📄 turnsocket.cxx
字号:
mRequestedIpAddress = UnspecifiedIpAddress; return refreshAllocation(); } else { return asio::error_code(reTurn::NoAllocation, asio::error::misc_category); }}StunTuple& TurnSocket::getRelayTuple(){ return mRelayTuple;}StunTuple& TurnSocket::getReflexiveTuple(){ return mReflexiveTuple;}unsigned int TurnSocket::getLifetime(){ return mLifetime;}unsigned int TurnSocket::getBandwidth(){ return mBandwidth;}asio::error_code TurnSocket::setActiveDestination(const asio::ip::address& address, unsigned short port){ asio::error_code errorCode; resip::Lock lock(mMutex); // ensure there is an allocation if(!mHaveAllocation) { if(mConnected) { // TODO - Disconnect } return connect(address.to_string(), port); //return asio::error_code(reTurn::NoAllocation, asio::error::misc_category); } // Ensure Connected if(!mConnected) { return asio::error_code(reTurn::NotConnected, asio::error::misc_category); } // Setup Remote Peer StunTuple remoteTuple(mRelayTuple.getTransportType(), address, port); RemotePeer* remotePeer = mChannelManager.findRemotePeerByPeerAddress(remoteTuple); if(remotePeer) { mActiveDestination = remotePeer; } else { // No remote peer yet (ie. not data sent or received from remote peer) - so create one mActiveDestination = mChannelManager.createRemotePeer(remoteTuple, mChannelManager.getNextChannelNumber(), 0); assert(mActiveDestination); } return errorCode;}asio::error_code TurnSocket::clearActiveDestination(){ asio::error_code errorCode; resip::Lock lock(mMutex); // ensure there is an allocation if(!mHaveAllocation) { return asio::error_code(reTurn::NoAllocation, asio::error::misc_category); } mActiveDestination = 0; return errorCode;}asio::error_code TurnSocket::send(const char* buffer, unsigned int size){ // Allow raw data to be sent if there is no allocation if(!mHaveAllocation) { return rawWrite(buffer, size); } if(!mActiveDestination) { return asio::error_code(reTurn::NoActiveDestination, asio::error::misc_category); } return sendTo(*mActiveDestination, buffer, size);}asio::error_code TurnSocket::sendTo(const asio::ip::address& address, unsigned short port, const char* buffer, unsigned int size){ resip::Lock lock(mMutex); // ensure there is an allocation if(!mHaveAllocation) { return asio::error_code(reTurn::NoAllocation, asio::error::misc_category); } // Setup Remote Peer StunTuple remoteTuple(mRelayTuple.getTransportType(), address, port); RemotePeer* remotePeer = mChannelManager.findRemotePeerByPeerAddress(remoteTuple); if(!remotePeer) { // No remote peer yet (ie. not data sent or received from remote peer) - so create one remotePeer = mChannelManager.createRemotePeer(remoteTuple, mChannelManager.getNextChannelNumber(), 0); assert(remotePeer); } return sendTo(*remotePeer, buffer, size);}asio::error_code TurnSocket::sendTo(RemotePeer& remotePeer, const char* buffer, unsigned int size){ resip::Lock lock(mMutex); // Check to see if an allocation refresh is required - if so send it and make sure it was sucessful asio::error_code ret = checkIfAllocationRefreshRequired(); if(ret) { return ret; } if(remotePeer.isClientToServerChannelConfirmed()) { // send framed data to active destination char framing[4]; unsigned short channelNumber = remotePeer.getClientToServerChannel(); channelNumber = htons(channelNumber); memcpy(&framing[0], &channelNumber, 2); if(mLocalBinding.getTransportType() == StunTuple::UDP) { // No size in header for UDP framing[2] = 0x00; framing[3] = 0x00; } else { UInt16 turnDataSize = size; turnDataSize = htons(turnDataSize); memcpy((void*)&framing[2], &turnDataSize, 2); } std::vector<asio::const_buffer> bufs; bufs.push_back(asio::buffer(framing, sizeof(framing))); bufs.push_back(asio::buffer(buffer, size)); return rawWrite(bufs); } else { // Data must be wrapped in a Send Indication // Wrap data in a SendInd StunMessage ind; ind.createHeader(StunMessage::StunClassIndication, StunMessage::TurnSendMethod); ind.mHasTurnPeerAddress = true; ind.mTurnPeerAddress.port = remotePeer.getPeerTuple().getPort(); if(remotePeer.getPeerTuple().getAddress().is_v6()) { ind.mTurnPeerAddress.family = StunMessage::IPv6Family; memcpy(&ind.mTurnPeerAddress.addr.ipv6, remotePeer.getPeerTuple().getAddress().to_v6().to_bytes().c_array(), sizeof(ind.mTurnPeerAddress.addr.ipv6)); } else { ind.mTurnPeerAddress.family = StunMessage::IPv4Family; ind.mTurnPeerAddress.addr.ipv4 = remotePeer.getPeerTuple().getAddress().to_v4().to_ulong(); } ind.mHasTurnChannelNumber = true; ind.mTurnChannelNumber = remotePeer.getClientToServerChannel(); if(size > 0) { ind.setTurnData(buffer, size); } // If not using UDP - then mark channel as confirmed if(mLocalBinding.getTransportType() != StunTuple::UDP) { remotePeer.setClientToServerChannelConfirmed(); } // Send indication to Turn Server unsigned int msgsize = ind.stunEncodeFramedMessage(mWriteBuffer, sizeof(mWriteBuffer)); return rawWrite(mWriteBuffer, msgsize); }}asio::error_code TurnSocket::receive(char* buffer, unsigned int& size, unsigned int timeout, asio::ip::address* sourceAddress, unsigned short* sourcePort){ asio::error_code errorCode; resip::Lock lock(mMutex); bool done = false; // TODO - rethink this scheme so that we don't need to copy recieved data // TODO - if we loop around more than once - timeout needs to be adjusted while(!done) { done = true; // Wait for response unsigned int readSize; errorCode = rawRead(timeout, &readSize, sourceAddress, sourcePort); // Note: SourceAddress and sourcePort may be overwritten below if from Turn Relay if(errorCode) { return errorCode; } // Note if this is a UDP RFC3489 back compat socket, then allocations are not allowed and handleRawData will always be used if(!mHaveAllocation) { return handleRawData(mReadBuffer, readSize, readSize, buffer, size); } // Check Channel if(readSize > 4) { unsigned short channelNumber; memcpy(&channelNumber, &mReadBuffer[0], 2); channelNumber = ntohs(channelNumber); if(channelNumber > 0) { RemotePeer* remotePeer = mChannelManager.findRemotePeerByServerToClientChannel(channelNumber); if(remotePeer) { UInt16 dataLen; memcpy(&dataLen, &mReadBuffer[2], 2); dataLen = ntohs(dataLen); if(sourceAddress) { *sourceAddress = remotePeer->getPeerTuple().getAddress(); } if(sourcePort) { *sourcePort = remotePeer->getPeerTuple().getPort(); } errorCode = handleRawData(&mReadBuffer[4], readSize-4, dataLen, buffer, size); } else { // Invalid ServerToClient Channel - teardown? errorCode = asio::error_code(reTurn::InvalidChannelNumberReceived, asio::error::misc_category); done = true; } } else // We have received a Stun/Turn Message { // StunMessage StunMessage* stunMsg = new StunMessage(mLocalBinding, mConnectedTuple, &mReadBuffer[4], readSize-4); unsigned int tempsize = size; errorCode = handleStunMessage(*stunMsg, buffer, tempsize, sourceAddress, sourcePort); if(!errorCode && tempsize == 0) // Signifies that a Stun/Turn request was received and there is nothing to return to receive caller { done = false; } else { size = tempsize; } } } else { // Less data than frame size received errorCode = asio::error_code(reTurn::FrameError, asio::error::misc_category); done = true; } } return errorCode;}asio::error_code TurnSocket::receiveFrom(const asio::ip::address& address, unsigned short port, char* buffer, unsigned int& size, unsigned int timeout){ asio::ip::address sourceAddress; unsigned short sourcePort; bool done = false; asio::error_code errorCode; resip::Lock lock(mMutex); while(!done) { done = true; errorCode = receive(buffer, size, timeout, &sourceAddress, &sourcePort); if(!errorCode) { if(sourceAddress != address || sourcePort != port) { WarningLog(<< "Recevied message but not from requested address/port - Discarding."); done = false; } } } return errorCode;}asio::error_code TurnSocket::handleRawData(char* data, unsigned int dataSize, unsigned int expectedSize, char* buffer, unsigned int& bufferSize){ asio::error_code errorCode; if(dataSize != expectedSize) { // TODO - fix read logic so that we can read in chuncks WarningLog(<< "Did not read entire message: read=" << dataSize << " wanted=" << expectedSize); return asio::error_code(reTurn::ReadError, asio::error::misc_category); } if(dataSize > bufferSize) { // Passed in buffer is not large enough WarningLog(<< "Passed in buffer not large enough."); return asio::error_code(reTurn::BufferTooSmall, asio::error::misc_category); } // Copy data to return buffer memcpy(buffer, data, dataSize); bufferSize = dataSize; return errorCode;}asio::error_code TurnSocket::handleStunMessage(StunMessage& stunMessage, char* buffer, unsigned int& size, asio::ip::address* sourceAddress, unsigned short* sourcePort){ asio::error_code errorCode; if(stunMessage.isValid()) { if(stunMessage.mClass == StunMessage::StunClassIndication && stunMessage.mMethod == StunMessage::TurnDataMethod) { if(!stunMessage.mHasTurnPeerAddress || !stunMessage.mHasTurnChannelNumber)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -