reSIProcate/stack  9694
Public Member Functions | Static Public Attributes | Protected Member Functions | Protected Attributes | Private Attributes
resip::UdpTransport Class Reference

A Transport based on UDP. More...

#include <UdpTransport.hxx>

Inheritance diagram for resip::UdpTransport:
Inheritance graph
[legend]
Collaboration diagram for resip::UdpTransport:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 RESIP_HeapCount (UdpTransport)
 UdpTransport (Fifo< TransactionMessage > &fifo, int portNum, IpVersion version, StunSetting stun, const Data &interfaceObj, AfterSocketCreationFuncPtr socketFunc=0, Compression &compression=Compression::Disabled, unsigned transportFlags=0)
virtual ~UdpTransport ()
virtual TransportType transport () const
virtual bool isReliable () const
virtual bool isDatagram () const
virtual void process (FdSet &fdset)
 If there is work to do, this is the method that does it.
virtual void process ()
 Called after a message is added.
virtual bool hasDataToSend () const
 If we return true, the TransactionController will set the timeout to zero so that process() is called immediately.
virtual void buildFdSet (FdSet &fdset)
 Adds the Transport's socket FD to the appropriate read or write sets as applicable.
virtual void setPollGrp (FdPollGrp *grp)
virtual void setRcvBufLen (int buflen)
virtual void processPollEvent (FdPollEventMask mask)
bool stunSendTest (const Tuple &dest)
bool stunResult (Tuple &mappedAddress)
void setExternalUnknownDatagramHandler (ExternalUnknownDatagramHandler *handler)
 Installs a handler for the unknown datagrams arriving on the udp transport.

Static Public Attributes

static const int MaxBufferSize = 8192

Protected Member Functions

void processRxAll ()
 Add options RXALL (to try receive all readable data) and KEEP_BUFFER.
int processRxRecv (char *&buffer, Tuple &sender)
bool processRxParse (char *buffer, int len, Tuple &sender)
 Parse the contents of {buffer} and do something with it.
void processTxAll ()
 Added support for TXNOW and TXALL.
void processTxOne (SendData *data)
void updateEvents ()

Protected Attributes

osc::Stack * mSigcompStack
unsigned mPollEventCnt
unsigned mTxTryCnt
unsigned mTxMsgCnt
unsigned mTxFailCnt
unsigned mRxTryCnt
unsigned mRxMsgCnt
unsigned mRxKeepaliveCnt
unsigned mRxTransactionCnt

Private Attributes

char * mRxBuffer
MsgHeaderScanner mMsgHeaderScanner
resip::Mutex myMutex
Tuple mStunMappedAddress
bool mStunSuccess
ExternalUnknownDatagramHandlermExternalUnknownDatagramHandler
bool mInWritable
bool mInActiveWrite

Detailed Description

A Transport based on UDP.

Used in test cases, TransportSelector (which is itself internal), DtlsTransport as a base class and in SipStack::addTransport(...). Not expected to be used in an API.

Definition at line 40 of file UdpTransport.hxx.


Constructor & Destructor Documentation

UdpTransport::UdpTransport ( Fifo< TransactionMessage > &  fifo,
int  portNum,
IpVersion  version,
StunSetting  stun,
const Data interfaceObj,
AfterSocketCreationFuncPtr  socketFunc = 0,
Compression compression = Compression::Disabled,
unsigned  transportFlags = 0 
)
Parameters:
fifothe TransactionMessage Fifo that will receive any ConnectionTerminated or TransportFailure messages.
interfaceObja "presentation format" representation of the IP address of this transport
See also:
Tuple::inet_ntop() for information about "presentation format"
Parameters:
portNumis the port to receive and/or send on
socketFuncFunctor (defined in rutil/Socket.hxx) that is called when a socket is created; allows app to log fd creation, tweak sockopts, and so forth.

Definition at line 30 of file UdpTransport.cxx.

References resip::Compression::addCompressorsToStack(), resip::InternalTransport::bind(), DebugLog, resip::Tuple::getPort(), resip::Compression::getStateHandler(), InfoLog, resip::Compression::isEnabled(), resip::Transport::mCompression, resip::InternalTransport::mFd, resip::Tuple::mFlowKey, mPollEventCnt, mRxKeepaliveCnt, mRxMsgCnt, mRxTransactionCnt, mRxTryCnt, mSigcompStack, resip::Transport::mTuple, mTxFailCnt, resip::InternalTransport::mTxFifo, mTxMsgCnt, mTxTryCnt, resip::FifoStatsInterface::setDescription(), resip::Tuple::setType(), resip::InternalTransport::socket(), transport(), and resip::V4.

   : InternalTransport(fifo, portNum, version, pinterface, socketFunc, compression, transportFlags),
     mSigcompStack(0),
     mRxBuffer(0),
     mExternalUnknownDatagramHandler(0),
     mInWritable(false)
{
   mPollEventCnt = 0;
   mTxTryCnt = mTxMsgCnt = mTxFailCnt = 0;
   mRxTryCnt = mRxMsgCnt = mRxKeepaliveCnt = mRxTransactionCnt = 0;
   mTuple.setType(transport());
   mFd = InternalTransport::socket(transport(), version);
   mTuple.mFlowKey=(FlowKey)mFd;
   bind();      // also makes it non-blocking

   InfoLog (<< "Creating UDP transport host=" << pinterface
            << " port=" << mTuple.getPort()
            << " ipv4=" << bool(version==V4) );

#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
   mTxFifo.setDescription("UdpTransport::mTxFifo");
}

Here is the call graph for this function:

UdpTransport::~UdpTransport ( ) [virtual]

Definition at line 73 of file UdpTransport.cxx.

References InfoLog, mPollEventCnt, resip::InternalTransport::mPollGrp, mRxBuffer, mRxKeepaliveCnt, mRxMsgCnt, mRxTransactionCnt, mRxTryCnt, mSigcompStack, resip::Transport::mTransportFlags, resip::Transport::mTuple, mTxFailCnt, mTxMsgCnt, mTxTryCnt, and setPollGrp().

{
   InfoLog(<< "Shutting down " << mTuple
           <<" tf="<<mTransportFlags<<" evt="<<(mPollGrp?1:0)
           <<" stats:"
           <<" poll="<<mPollEventCnt
           <<" txtry="<<mTxTryCnt
           <<" txmsg="<<mTxMsgCnt
           <<" txfail="<<mTxFailCnt
           <<" rxtry="<<mRxTryCnt
           <<" rxmsg="<<mRxMsgCnt
           <<" rxka="<<mRxKeepaliveCnt
           <<" rxtr="<<mRxTransactionCnt
           );
#ifdef USE_SIGCOMP
   delete mSigcompStack;
#endif
   if ( mRxBuffer )
   {
      delete[] mRxBuffer;
   }
   setPollGrp(0);
}

Here is the call graph for this function:


Member Function Documentation

void UdpTransport::buildFdSet ( FdSet fdset) [virtual]

Adds the Transport's socket FD to the appropriate read or write sets as applicable.

Implements resip::Transport.

Definition at line 185 of file UdpTransport.cxx.

References resip::ConsumerFifoBuffer< class >::messageAvailable(), resip::InternalTransport::mFd, resip::InternalTransport::mTxFifoOutBuffer, resip::FdSet::setRead(), and resip::FdSet::setWrite().

Referenced by main(), and Loadgen::Transceiver::receive().

{
   fdset.setRead(mFd);

   if (mTxFifoOutBuffer.messageAvailable())
   {
      fdset.setWrite(mFd);
   }
}

Here is the call graph for this function:

bool UdpTransport::hasDataToSend ( ) const [virtual]

If we return true, the TransactionController will set the timeout to zero so that process() is called immediately.

We don't want this; instead, we depend upon the writable-socket callback (fdset or poll).

Reimplemented from resip::InternalTransport.

Definition at line 179 of file UdpTransport.cxx.

{
   return false;
}
virtual bool resip::UdpTransport::isDatagram ( ) const [inline, virtual]

Implements resip::Transport.

Definition at line 71 of file UdpTransport.hxx.

{ return true; }
virtual bool resip::UdpTransport::isReliable ( ) const [inline, virtual]

Implements resip::Transport.

Definition at line 70 of file UdpTransport.hxx.

Referenced by processTxOne().

{ return false; }
void UdpTransport::process ( FdSet fdset) [virtual]

If there is work to do, this is the method that does it.

If the socket is readable, it is read. If the socket is writable and there are outgoing messages to be sent, they are sent.

Incoming messages are parsed and dispatched to the relevant entity. SIP messages will be posted to the TransactionMessage Fifo.

See also:
sendData()
Parameters:
fdsetis the FdSet after select() has been called.
See also:
FdSet::select()

Implements resip::Transport.

Definition at line 196 of file UdpTransport.cxx.

References resip::ProducerFifoBuffer< class >::flush(), resip::InternalTransport::mFd, resip::Transport::mStateMachineFifo, processRxAll(), processTxAll(), resip::FdSet::readyToRead(), and resip::FdSet::readyToWrite().

Referenced by main(), Loadgen::Transceiver::receive(), and Loadgen::Transceiver::send().

{
   // pull buffers to send out of TxFifo
   // receive datagrams from fd
   // preparse and stuff into RxFifo

   if (fdset.readyToWrite(mFd))
   {
      processTxAll();
   }

   if ( fdset.readyToRead(mFd) )
   {
      processRxAll();
   }
   mStateMachineFifo.flush();
}

Here is the call graph for this function:

void UdpTransport::process ( ) [virtual]

Called after a message is added.

Could try writing it now.

Implements resip::Transport.

Definition at line 123 of file UdpTransport.cxx.

References resip::ProducerFifoBuffer< class >::flush(), resip::InternalTransport::mPollGrp, resip::Transport::mStateMachineFifo, resip::Transport::mTransportFlags, processTxAll(), RESIP_TRANSPORT_FLAG_TXNOW, and updateEvents().

                      {
   mStateMachineFifo.flush();
   if ( (mTransportFlags & RESIP_TRANSPORT_FLAG_TXNOW)!= 0 )
   {
       processTxAll();
       // FALLTHRU to code below in case queue not-empty
       // shouldn't ever happen (with current code)
       // but in future we may throttle transmits
   }
   if ( mPollGrp )
       updateEvents();
}

Here is the call graph for this function:

void UdpTransport::processPollEvent ( FdPollEventMask  mask) [virtual]

Implements resip::FdPollItemIf.

Definition at line 155 of file UdpTransport.cxx.

References FPEM_Error, FPEM_Read, FPEM_Write, mPollEventCnt, processRxAll(), processTxAll(), and updateEvents().

{
   ++mPollEventCnt;
   if ( mask & FPEM_Error )
   {
      assert(0);
   }
   if ( mask & FPEM_Write )
   {
      processTxAll();
      updateEvents();   // turn-off writability
   }
   if ( mask & FPEM_Read )
   {
      processRxAll();
   }
}

Here is the call graph for this function:

void UdpTransport::processRxAll ( ) [protected]

Add options RXALL (to try receive all readable data) and KEEP_BUFFER.

While each can be specified independently, generally should do both or neither. This is because with RXALL, every read cycle will have end with an EAGAIN read followed by buffer free (if no KEEP_BUFFER flag). Testing in very limited cases shows marginal (5%) performance improvements. Probably "real" traffic (that is bursty) would more impact.

Definition at line 308 of file UdpTransport.cxx.

References len, mRxBuffer, mRxMsgCnt, mRxTryCnt, resip::Transport::mTransportFlags, resip::Transport::mTuple, processRxParse(), processRxRecv(), RESIP_TRANSPORT_FLAG_KEEP_BUFFER, and RESIP_TRANSPORT_FLAG_RXALL.

Referenced by process(), and processPollEvent().

{
   char *buffer = mRxBuffer;
   mRxBuffer = NULL;
   ++mRxTryCnt;
   for (;;)
   {
      // TBD: check StateMac capacity
      Tuple sender(mTuple);
      int len = processRxRecv(buffer, sender);
      if ( len <= 0 )
         break;
      ++mRxMsgCnt;
      if ( processRxParse(buffer, len, sender) )
      {
         buffer = NULL;
      }
      if ( (mTransportFlags & RESIP_TRANSPORT_FLAG_RXALL)==0 )
         break;
   }
   if ( buffer && (mTransportFlags & RESIP_TRANSPORT_FLAG_KEEP_BUFFER)!=0 )
   {
      assert(mRxBuffer==NULL);
      mRxBuffer = buffer;
      buffer = NULL;
   }
   if ( buffer )
      delete[] buffer;
}

Here is the call graph for this function:

bool UdpTransport::processRxParse ( char *  buffer,
int  len,
Tuple sender 
) [protected]

Parse the contents of {buffer} and do something with it.

Return true iff {buffer} was consumed (absorbed into SipMessage to be free'd later). Note return code doesn't indicate "success" in parsing the message; rather, it just indicates who owns buffer.

Definition at line 399 of file UdpTransport.cxx.

References resip::Fifo< Msg >::add(), resip::ProducerFifoBuffer< class >::add(), resip::SipMessage::addBuffer(), StunAddress4::addr, resip::MsgHeaderScanner::allocateBuffer(), resip::Transport::basicCheck(), resip::Data::Borrow, resip::Transport::boundInterface(), resip::Symbols::CRLFCRLF, resip::Data::data(), DebugLog, dest, resip::Data::empty(), resip::Data::Empty, resip::Via::exists(), resip::Transport::getExpectedWaitForIncoming(), resip::Transport::getKey(), resip::Transport::getRejectionBehaviorForIncoming(), resip::Tuple::getSockaddr(), StunMessage::hasMappedAddress, StunMessage::hasXorMappedAddress, resip::SipMessage::header(), StunMsgHdr::id, InfoLog, StunAtrAddress4::ipv4, resip::Transport::ipVersion(), resip::Compression::isEnabled(), resip::SipMessage::isRequest(), len, resip::Transport::make503(), StunMessage::mappedAddress, MaxBufferSize, resip::Transport::mCompression, mExternalUnknownDatagramHandler, resip::Tuple::mFlowKey, mMsgHeaderScanner, mRxKeepaliveCnt, mRxTransactionCnt, StunMessage::msgHdr, mSigcompStack, resip::Transport::mStateMachineFifo, mStunMappedAddress, mStunSuccess, resip::Transport::mTuple, resip::InternalTransport::mTxFifo, myMutex, UInt128::octet, resip::ParserCategory::param(), StunAddress4::port, resip::MsgHeaderScanner::prepareForMessage(), resip::CongestionManager::REJECTING_NEW_WORK, resip::CongestionManager::REJECTING_NON_ESSENTIAL, resip::MsgHeaderScanner::scanChunk(), resip::MsgHeaderScanner::scrEnd, resip::InternalTransport::send(), resip::SipMessage::setBody(), resip::SipMessage::setSource(), resip::Data::size(), StunAtrString::sizeValue, StackLog, resip::Transport::stampReceived(), STUN_MAX_MESSAGE_SIZE, stunEncodeMessage(), stunParseMessage(), stunServerProcessMsg(), resip::Tuple::transport, resip::Tuple::transportKey, resip::UDP, resip::V4, and StunMessage::xorMappedAddress.

Referenced by processRxAll().

{
   bool origBufferConsumed = true;

   //handle incoming CRLFCRLF keep-alive packets
   if (len == 4 &&
       strncmp(buffer, Symbols::CRLFCRLF, len) == 0)
   {
      StackLog(<<"Throwing away incoming firewall keep-alive");
      ++mRxKeepaliveCnt;
      return false;
   }

   // 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;
         // Use XorMappedAddress if present - if not use MappedAddress
         if(resp.hasXorMappedAddress)
         {
            UInt16 id16 = resp.msgHdr.id.octet[0]<<8
                          | resp.msgHdr.id.octet[1];
            UInt32 id32 = resp.msgHdr.id.octet[0]<<24
                          | resp.msgHdr.id.octet[1]<<16
                          | resp.msgHdr.id.octet[2]<<8
                          | resp.msgHdr.id.octet[3];
            resp.xorMappedAddress.ipv4.port = resp.xorMappedAddress.ipv4.port^id16;
            resp.xorMappedAddress.ipv4.addr = resp.xorMappedAddress.ipv4.addr^id32;

#if defined(WIN32)
            sin_addr.S_un.S_addr = htonl(resp.xorMappedAddress.ipv4.addr);
#else
            sin_addr.s_addr = htonl(resp.xorMappedAddress.ipv4.addr);
#endif
            mStunMappedAddress = Tuple(sin_addr,resp.xorMappedAddress.ipv4.port, UDP);
            mStunSuccess = true;
         }
         else if(resp.hasMappedAddress)
         {
#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;
         }
      }
      return false;
   }

   // 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&)sender.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,
                                       false );
         SendData* stunResponse = new SendData(sender, response, rlen);
         mTxFifo.add(stunResponse);
      }
      return false;
   }

#ifdef USE_SIGCOMP
   osc::StateChanges *sc = 0;
#endif

   // Attempt to decode SigComp message, if appropriate.
   if ((buffer[0] & 0xf8) == 0xf8)
   {
     if (!mCompression.isEnabled())
     {
       InfoLog(<< "Discarding unexpected SigComp Message");
       return false;
     }
#ifdef USE_SIGCOMP
     char* newBuffer = MsgHeaderScanner::allocateBuffer(MaxBufferSize);
     size_t uncompressedLength =
       mSigcompStack->uncompressMessage(buffer, len,
                                        newBuffer, MaxBufferSize, sc);

    DebugLog (<< "Uncompressed message from "
              << len << " bytes to "
              << uncompressedLength << " bytes");


     osc::SigcompMessage *nack = mSigcompStack->getNack();

     if (nack)
     {
       mTxFifo.add(new SendData(tuple,
                                Data(nack->getDatagramMessage(),
                                     nack->getDatagramLength()),
                                Data::Empty,
                                Data::Empty,
                                true)
                  );
       delete nack;
     }

     // delete[] buffer; NO: let caller do this if needed
     origBufferConsumed = false;
     buffer = newBuffer;
     len = uncompressedLength;
#endif
   }

   buffer[len]=0; // null terminate the buffer string just to make debug easier and reduce errors

   //DebugLog ( << "UDP Rcv : " << len << " b" );
   //DebugLog ( << Data(buffer, len).escaped().c_str());

   SipMessage* message = new SipMessage(this);

   // set the received from information into the received= parameter in the
   // via

   // It is presumed that UDP Datagrams are arriving atomically and that
   // each one is a unique SIP message


   // Save all the info where this message came from
   sender.transport = this;
   sender.transportKey = getKey();
   sender.mFlowKey=mTuple.mFlowKey;
   message->setSource(sender);
   //DebugLog (<< "Received from: " << sender);

   // Tell the SipMessage about this datagram buffer.
   // WATCHOUT: below here buffer is consumed by message
   message->addBuffer(buffer);

   mMsgHeaderScanner.prepareForMessage(message);

   char *unprocessedCharPtr;
   if (mMsgHeaderScanner.scanChunk(buffer,
                                   len,
                                   &unprocessedCharPtr) !=
       MsgHeaderScanner::scrEnd)
   {
      StackLog(<<"Scanner rejecting datagram as unparsable / fragmented from " << sender);
      StackLog(<< Data(Data::Borrow, buffer, len));
      if(mExternalUnknownDatagramHandler)
      {
         auto_ptr<Data> datagram(new Data(buffer,len));
         (*mExternalUnknownDatagramHandler)(this,sender,datagram);
      }

      // Idea: consider backing buffer out of message and letting caller reuse it
      delete message;
      message=0;
      return origBufferConsumed;
   }

   // no pp error
   int used = int(unprocessedCharPtr - buffer);

   if (used < len)
   {
      // body is present .. add it up.
      // NB. The Sip Message uses an overlay (again)
      // for the body. It ALSO expects that the body
      // will be contiguous (of course).
      // it doesn't need a new buffer in UDP b/c there
      // will only be one datagram per buffer. (1:1 strict)

      message->setBody(buffer+used,len-used);
      //DebugLog(<<"added " << len-used << " byte body");
   }

   // .bwc. basicCheck takes up substantial CPU. Don't bother doing it
   // if we're overloaded.
   CongestionManager::RejectionBehavior behavior=getRejectionBehaviorForIncoming();
   if (behavior==CongestionManager::REJECTING_NON_ESSENTIAL
         || (behavior==CongestionManager::REJECTING_NEW_WORK
            && message->isRequest()))
   {
      // .bwc. If this fifo is REJECTING_NEW_WORK, we will drop
      // requests but not responses ( ?bwc? is this right for ACK?). 
      // If we are REJECTING_NON_ESSENTIAL, 
      // we reject all incoming work, since losing something from the 
      // wire will not cause instability or leaks (see 
      // CongestionManager.hxx)

      // .bwc. This handles all appropriate checking for whether
      // this is a response or an ACK.
      std::auto_ptr<SendData> tryLater(make503(*message, getExpectedWaitForIncoming()/1000));
      if(tryLater.get())
      {
         send(tryLater);
      }
     delete message; // dropping message due to congestion
     message = 0;
     return origBufferConsumed;
   }

   if (!basicCheck(*message))
   {
      delete message; // cannot use it, so, punt on it...
      // basicCheck queued any response required
      message = 0;
      return origBufferConsumed;
   }

   stampReceived(message);

#ifdef USE_SIGCOMP
   if (mCompression.isEnabled() && sc)
   {
     const Via &via = message->header(h_Vias).front();
     if (message->isRequest())
     {
       // For requests, the compartment ID is read out of the
       // top via header field; if not present, we use the
       // TCP connection for identification purposes.
       if (via.exists(p_sigcompId))
       {
         Data compId = via.param(p_sigcompId);
         if(!compId.empty())
         {
            // .bwc. Crash was happening here. Why was there an empty sigcomp
            // id?
            mSigcompStack->provideCompartmentId(
                             sc, compId.data(), compId.size());
         }
       }
       else
       {
         mSigcompStack->provideCompartmentId(sc, this, sizeof(this));
       }
     }
     else
     {
       // For responses, the compartment ID is supposed to be
       // the same as the compartment ID of the request. We
       // *could* dig down into the transaction layer to try to
       // figure this out, but that's a royal pain, and a rather
       // severe layer violation. In practice, we're going to ferret
       // the ID out of the the Via header field, which is where we
       // squirreled it away when we sent this request in the first place.
       // !bwc! This probably shouldn't be going out over the wire.
       Data compId = via.param(p_branch).getSigcompCompartment();
       if(!compId.empty())
       {
         mSigcompStack->provideCompartmentId(sc, compId.data(), compId.size());
       }
     }

   }
#endif

   mStateMachineFifo.add(message);
   ++mRxTransactionCnt;
   return origBufferConsumed;
}

Here is the call graph for this function:

int UdpTransport::processRxRecv ( char *&  buffer,
Tuple sender 
) [protected]

Definition at line 348 of file UdpTransport.cxx.

References resip::MsgHeaderScanner::allocateBuffer(), resip::Transport::error(), resip::getErrno(), resip::Tuple::getMutableSockaddr(), InfoLog, len, resip::Tuple::length(), MaxBufferSize, resip::InternalTransport::mFd, and SOCKET_ERROR.

Referenced by processRxAll().

{
   // !jf! this may have to change - when we read a message that is too big
   //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...
   if (buffer==NULL)
   {
      buffer = MsgHeaderScanner::allocateBuffer(MaxBufferSize);
   }

   for (;;) {
      // !jf! how do we tell if it discarded bytes
      // !ah! we use the len-1 trick :-(
      socklen_t slen = sender.length();
      int len = recvfrom( mFd,
                          buffer,
                          MaxBufferSize,
                          0 /*flags */,
                          &sender.getMutableSockaddr(),
                          &slen);
      if ( len == SOCKET_ERROR )
      {
         int err = getErrno();
         if ( err != EWOULDBLOCK  )
         {
            error( err );
         }
         len = 0;
      }
      if (len+1 >= MaxBufferSize)
      {
         InfoLog(<<"Datagram exceeded max length "<<MaxBufferSize);
         continue;
      }
      return len;
   }
}

Here is the call graph for this function:

void UdpTransport::processTxAll ( ) [protected]

Added support for TXNOW and TXALL.

Generally only makes sense to specify one of these. Limited testing shows limited performance gain from either of these: the socket-event overhead appears tiny.

Definition at line 220 of file UdpTransport.cxx.

References resip::ConsumerFifoBuffer< class >::getNext(), resip::Transport::mTransportFlags, resip::InternalTransport::mTxFifoOutBuffer, mTxTryCnt, processTxOne(), RESIP_FIFO_NOWAIT, and RESIP_TRANSPORT_FLAG_TXALL.

Referenced by process(), and processPollEvent().

{
   SendData *msg;
   ++mTxTryCnt;
   while ( (msg=mTxFifoOutBuffer.getNext(RESIP_FIFO_NOWAIT)) != NULL )
   {
      processTxOne(msg);
      // With UDP we don't need to worry about write blocking (I hope)
      if ( (mTransportFlags & RESIP_TRANSPORT_FLAG_TXALL)==0 )
         break;
   }
}

Here is the call graph for this function:

void UdpTransport::processTxOne ( SendData data) [protected]

Definition at line 234 of file UdpTransport.cxx.

References DebugLog, ErrLog, resip::Transport::error(), resip::Transport::fail(), resip::getErrno(), InfoLog, isReliable(), resip::InternalTransport::mFd, mSigcompStack, mTxFailCnt, mTxMsgCnt, sendto(), and SOCKET_ERROR.

Referenced by processTxAll().

{
   ++mTxMsgCnt;
   assert(data);
   std::auto_ptr<SendData> sendData(data);
   //DebugLog (<< "Sent: " <<  sendData->data);
   //DebugLog (<< "Sending message on udp.");
   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 = (int)sendData->data.size();
       count = sendto(mFd,
                      sendData->data.data(), (int)sendData->data.size(),
                      0, // flags
                      &addr, (int)sendData->destination.length());
   }

   if ( count == SOCKET_ERROR )
   {
      int e = getErrno();
      error(e);
      InfoLog (<< "Failed (" << e << ") sending to " << sendData->destination);
      fail(sendData->transactionId);
      ++mTxFailCnt;
   }
   else
   {
      if (count != expected)
      {
         ErrLog (<< "UDPTransport - send buffer full" );
         fail(sendData->transactionId);
      }
   }
}

Here is the call graph for this function:

resip::UdpTransport::RESIP_HeapCount ( UdpTransport  )
void UdpTransport::setExternalUnknownDatagramHandler ( ExternalUnknownDatagramHandler handler)

Installs a handler for the unknown datagrams arriving on the udp transport.

Definition at line 746 of file UdpTransport.cxx.

References mExternalUnknownDatagramHandler.

void UdpTransport::setPollGrp ( FdPollGrp grp) [virtual]

Reimplemented from resip::InternalTransport.

Definition at line 98 of file UdpTransport.cxx.

References resip::FdPollGrp::addPollItem(), resip::FdPollGrp::delPollItem(), FPEM_Read, INVALID_SOCKET, resip::InternalTransport::mFd, resip::InternalTransport::mPollGrp, and resip::InternalTransport::mPollItemHandle.

Referenced by ~UdpTransport().

{
   if(mPollGrp)
   {
      mPollGrp->delPollItem(mPollItemHandle);
      mPollItemHandle=0;
   }

   if(mFd!=INVALID_SOCKET && grp)
   {
      mPollItemHandle = grp->addPollItem(mFd, FPEM_Read, this);
      // above released by InternalTransport destructor
      // ?bwc? Is this really a good idea? If the InternalTransport d'tor is
      // freeing this, shouldn't InternalTransport::setPollGrp() handle 
      // creating it?
   }

   InternalTransport::setPollGrp(grp);
}

Here is the call graph for this function:

void UdpTransport::setRcvBufLen ( int  buflen) [virtual]

Reimplemented from resip::Transport.

Definition at line 752 of file UdpTransport.cxx.

References resip::InternalTransport::mFd, and resip::setSocketRcvBufLen().

{
   setSocketRcvBufLen(mFd, buflen);
}

Here is the call graph for this function:

bool UdpTransport::stunResult ( Tuple mappedAddress)

Definition at line 734 of file UdpTransport.cxx.

References mStunMappedAddress, mStunSuccess, and myMutex.

{
   resip::Lock lock(myMutex);

   if (mStunSuccess)
   {
      mappedAddress = mStunMappedAddress;
   }
   return mStunSuccess;
}
bool UdpTransport::stunSendTest ( const Tuple dest)

Definition at line 704 of file UdpTransport.cxx.

References resip::Fifo< Msg >::add(), len, mStunSuccess, resip::InternalTransport::mTxFifo, StunAtrString::sizeValue, STUN_MAX_MESSAGE_SIZE, stunBuildReqSimple(), and stunEncodeMessage().

{
   bool changePort=false;
   bool changeIP=false;

   StunAtrString username;
   StunAtrString password;

   username.sizeValue = 0;
   password.sizeValue = 0;

   StunMessage req;
   memset(&req, 0, sizeof(StunMessage));

   stunBuildReqSimple(&req, username, changePort , changeIP , 1);

   char* buf = new char[STUN_MAX_MESSAGE_SIZE];
   int len = STUN_MAX_MESSAGE_SIZE;

   int rlen = stunEncodeMessage(req, buf, len, password, false);

   SendData* stunRequest = new SendData(dest, buf, rlen);
   mTxFifo.add(stunRequest);

   mStunSuccess = false;

   return true;
}

Here is the call graph for this function:

virtual TransportType resip::UdpTransport::transport ( ) const [inline, virtual]
Returns:
This transport's TransportType.

Implements resip::Transport.

Definition at line 69 of file UdpTransport.hxx.

References resip::UDP.

Referenced by Loadgen::Transceiver::send(), Loadgen::Transceiver::Transceiver(), and UdpTransport().

{ return UDP; }
void UdpTransport::updateEvents ( ) [protected]

Definition at line 137 of file UdpTransport.cxx.

References FPEM_Read, FPEM_Write, resip::ConsumerFifoBuffer< class >::messageAvailable(), mInWritable, resip::FdPollGrp::modPollItem(), resip::InternalTransport::mPollGrp, resip::InternalTransport::mPollItemHandle, and resip::InternalTransport::mTxFifoOutBuffer.

Referenced by process(), and processPollEvent().

{
   //assert( mPollGrp );
   bool haveMsg = mTxFifoOutBuffer.messageAvailable();
   if ( !mInWritable && haveMsg )
   {
      mPollGrp->modPollItem(mPollItemHandle, FPEM_Read|FPEM_Write);
      mInWritable = true;
   }
   else if ( mInWritable && !haveMsg )
   {
      mPollGrp->modPollItem(mPollItemHandle, FPEM_Read);
      mInWritable = false;
   }
}

Here is the call graph for this function:


Member Data Documentation

const int resip::UdpTransport::MaxBufferSize = 8192 [static]

Definition at line 84 of file UdpTransport.hxx.

Referenced by processRxParse(), and processRxRecv().

Definition at line 119 of file UdpTransport.hxx.

Referenced by processRxParse(), and setExternalUnknownDatagramHandler().

Definition at line 121 of file UdpTransport.hxx.

Definition at line 120 of file UdpTransport.hxx.

Referenced by updateEvents().

Definition at line 115 of file UdpTransport.hxx.

Referenced by processRxParse().

unsigned resip::UdpTransport::mPollEventCnt [protected]

Definition at line 105 of file UdpTransport.hxx.

Referenced by processPollEvent(), UdpTransport(), and ~UdpTransport().

Definition at line 114 of file UdpTransport.hxx.

Referenced by processRxAll(), and ~UdpTransport().

Definition at line 111 of file UdpTransport.hxx.

Referenced by processRxParse(), UdpTransport(), and ~UdpTransport().

unsigned resip::UdpTransport::mRxMsgCnt [protected]

Definition at line 110 of file UdpTransport.hxx.

Referenced by processRxAll(), UdpTransport(), and ~UdpTransport().

Definition at line 112 of file UdpTransport.hxx.

Referenced by processRxParse(), UdpTransport(), and ~UdpTransport().

unsigned resip::UdpTransport::mRxTryCnt [protected]

Definition at line 109 of file UdpTransport.hxx.

Referenced by processRxAll(), UdpTransport(), and ~UdpTransport().

osc::Stack* resip::UdpTransport::mSigcompStack [protected]

Definition at line 102 of file UdpTransport.hxx.

Referenced by processRxParse(), processTxOne(), UdpTransport(), and ~UdpTransport().

Definition at line 117 of file UdpTransport.hxx.

Referenced by processRxParse(), and stunResult().

Definition at line 118 of file UdpTransport.hxx.

Referenced by processRxParse(), stunResult(), and stunSendTest().

unsigned resip::UdpTransport::mTxFailCnt [protected]

Definition at line 108 of file UdpTransport.hxx.

Referenced by processTxOne(), UdpTransport(), and ~UdpTransport().

unsigned resip::UdpTransport::mTxMsgCnt [protected]

Definition at line 107 of file UdpTransport.hxx.

Referenced by processTxOne(), UdpTransport(), and ~UdpTransport().

unsigned resip::UdpTransport::mTxTryCnt [protected]

Definition at line 106 of file UdpTransport.hxx.

Referenced by processTxAll(), UdpTransport(), and ~UdpTransport().

Definition at line 116 of file UdpTransport.hxx.

Referenced by processRxParse(), and stunResult().


The documentation for this class was generated from the following files: