📄 udptransport.cxx
字号:
#if defined(HAVE_CONFIG_H)#include "resip/stack/config.hxx"#endif#include <memory>#include "resip/stack/Helper.hxx"#include "resip/stack/SendData.hxx"#include "resip/stack/SipMessage.hxx"#include "resip/stack/UdpTransport.hxx"#include "rutil/Data.hxx"#include "rutil/DnsUtil.hxx"#include "rutil/Logger.hxx"#include "rutil/Socket.hxx"#include "rutil/WinLeakCheck.hxx"#include "rutil/compat.hxx"#include "rutil/stun/Stun.hxx"#ifdef USE_SIGCOMP#include <osc/Stack.h>#include <osc/StateChanges.h>#include <osc/SigcompMessage.h>#endif#define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORTusing namespace std;using namespace resip;UdpTransport::UdpTransport(Fifo<TransactionMessage>& fifo, int portNum, IpVersion version, StunSetting stun, const Data& pinterface, AfterSocketCreationFuncPtr socketFunc, Compression &compression) : InternalTransport(fifo, portNum, version, pinterface, socketFunc, compression), mSigcompStack(0){ InfoLog (<< "Creating UDP transport host=" << pinterface << " port=" << portNum << " ipv4=" << bool(version==V4) ); mTuple.setType(transport()); mFd = InternalTransport::socket(transport(), version); mTuple.mFlowKey=mFd; bind();#ifdef USE_SIGCOMP if (mCompression.isEnabled()) { DebugLog (<< "Compression enabled for transport: " << *this); mSigcompStack = new osc::Stack(mCompression.getStateHandler()); mCompression.addCompressorsToStack(mSigcompStack); } else { DebugLog (<< "Compression disabled for transport: " << *this); }#else DebugLog (<< "No compression library available: " << *this);#endif}UdpTransport::~UdpTransport(){ InfoLog (<< "Shutting down " << mTuple);#ifdef USE_SIGCOMP delete mSigcompStack;#endif}void UdpTransport::process(FdSet& fdset){ // pull buffers to send out of TxFifo // receive datagrams from fd // preparse and stuff into RxFifo if (mTxFifo.messageAvailable() && fdset.readyToWrite(mFd)) { std::auto_ptr<SendData> sendData = std::auto_ptr<SendData>(mTxFifo.getNext()); //DebugLog (<< "Sent: " << sendData->data); //DebugLog (<< "Sending message on udp."); assert( &(*sendData) ); assert( sendData->destination.getPort() != 0 ); const sockaddr& addr = sendData->destination.getSockaddr(); int expected; int count;#ifdef USE_SIGCOMP // If message needs to be compressed, compress it here. if (mSigcompStack && sendData->sigcompId.size() > 0 && !sendData->isAlreadyCompressed ) { osc::SigcompMessage *sm = mSigcompStack->compressMessage (sendData->data.data(), sendData->data.size(), sendData->sigcompId.data(), sendData->sigcompId.size(), isReliable()); DebugLog (<< "Compressed message from " << sendData->data.size() << " bytes to " << sm->getDatagramLength() << " bytes"); expected = sm->getDatagramLength(); count = sendto(mFd, sm->getDatagramMessage(), sm->getDatagramLength(), 0, // flags &addr, sendData->destination.length()); delete sm; } else#endif { expected = sendData->data.size(); count = sendto(mFd, sendData->data.data(), sendData->data.size(), 0, // flags &addr, sendData->destination.length()); } if ( count == SOCKET_ERROR ) { int e = getErrno(); error(e); InfoLog (<< "Failed (" << e << ") sending to " << sendData->destination); fail(sendData->transactionId); } else { if (count != expected) { ErrLog (<< "UDPTransport - send buffer full" ); fail(sendData->transactionId); } } } // !jf! this may have to change - when we read a message that is too big if ( fdset.readyToRead(mFd) ) { //should this buffer be allocated on the stack and then copied out, as it //needs to be deleted every time EWOULDBLOCK is encountered // .dlb. can we determine the size of the buffer before we allocate? // something about MSG_PEEK|MSG_TRUNC in Stevens.. // .dlb. RFC3261 18.1.1 MUST accept 65K datagrams. would have to attempt to // adjust the UDP buffer as well... char* buffer = MsgHeaderScanner::allocateBuffer(MaxBufferSize); // !jf! how do we tell if it discarded bytes // !ah! we use the len-1 trick :-( Tuple tuple(mTuple); socklen_t slen = tuple.length(); int len = recvfrom( mFd, buffer, MaxBufferSize, 0 /*flags */, &tuple.getMutableSockaddr(), &slen); if ( len == SOCKET_ERROR ) { int err = getErrno(); if ( err != EWOULDBLOCK ) { error( err ); } } if (len == 0 || len == SOCKET_ERROR) { delete[] buffer; buffer=0; return; } if (len+1 >= MaxBufferSize) { InfoLog(<<"Datagram exceeded max length "<<MaxBufferSize); delete [] buffer; buffer=0; return; } //handle incoming CRLFCRLF keep-alive packets if (len == 4 && strncmp(buffer, Symbols::CRLFCRLF, len) == 0) { delete[] buffer; buffer = 0; StackLog(<<"Throwing away incoming firewall keep-alive"); return; } // this must be a STUN response (or garbage) if (buffer[0] == 1 && buffer[1] == 1 && ipVersion() == V4) { resip::Lock lock(myMutex); StunMessage resp; memset(&resp, 0, sizeof(StunMessage)); if (stunParseMessage(buffer, len, resp, false)) { in_addr sin_addr;#if defined(WIN32) sin_addr.S_un.S_addr = htonl(resp.mappedAddress.ipv4.addr);#else sin_addr.s_addr = htonl(resp.mappedAddress.ipv4.addr);#endif mStunMappedAddress = Tuple(sin_addr,resp.mappedAddress.ipv4.port, UDP); mStunSuccess = true; } delete[] buffer; buffer = 0; return; } // this must be a STUN request (or garbage) if (buffer[0] == 0 && buffer[1] == 1 && ipVersion() == V4) { bool changePort = false; bool changeIp = false; StunAddress4 myAddr; const sockaddr_in& bi = (const sockaddr_in&)boundInterface(); myAddr.addr = ntohl(bi.sin_addr.s_addr); myAddr.port = ntohs(bi.sin_port); StunAddress4 from; // packet source const sockaddr_in& fi = (const sockaddr_in&)tuple.getSockaddr(); from.addr = ntohl(fi.sin_addr.s_addr); from.port = ntohs(fi.sin_port); StunMessage resp; StunAddress4 dest; StunAtrString hmacPassword; hmacPassword.sizeValue = 0; StunAddress4 secondary; secondary.port = 0; secondary.addr = 0; bool ok = stunServerProcessMsg( buffer, len, // input buffer from, // packet source secondary, // not used myAddr, // address to fill into response myAddr, // not used &resp, // stun response &dest, // where to send response &hmacPassword, // not used &changePort, // not used &changeIp, // not used false ); // logging if (ok) { DebugLog(<<"Got UDP STUN keepalive. Sending response..."); char* response = new char[STUN_MAX_MESSAGE_SIZE]; int rlen = stunEncodeMessage( resp, response, STUN_MAX_MESSAGE_SIZE, hmacPassword,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -