reSIProcate/stack  9694
UdpTransport.cxx
Go to the documentation of this file.
00001 #if defined(HAVE_CONFIG_H)
00002 #include "config.h"
00003 #endif
00004 
00005 #include <memory>
00006 
00007 #include "resip/stack/Helper.hxx"
00008 #include "resip/stack/SendData.hxx"
00009 #include "resip/stack/SipMessage.hxx"
00010 #include "resip/stack/UdpTransport.hxx"
00011 #include "rutil/Data.hxx"
00012 #include "rutil/DnsUtil.hxx"
00013 #include "rutil/Logger.hxx"
00014 #include "rutil/Socket.hxx"
00015 #include "rutil/WinLeakCheck.hxx"
00016 #include "rutil/compat.hxx"
00017 #include "rutil/stun/Stun.hxx"
00018 
00019 #ifdef USE_SIGCOMP
00020 #include <osc/Stack.h>
00021 #include <osc/StateChanges.h>
00022 #include <osc/SigcompMessage.h>
00023 #endif
00024 
00025 #define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT
00026 
00027 using namespace std;
00028 using namespace resip;
00029 
00030 UdpTransport::UdpTransport(Fifo<TransactionMessage>& fifo,
00031                            int portNum,
00032                            IpVersion version,
00033                            StunSetting stun,
00034                            const Data& pinterface,
00035                            AfterSocketCreationFuncPtr socketFunc,
00036                            Compression &compression,
00037                            unsigned transportFlags)
00038    : InternalTransport(fifo, portNum, version, pinterface, socketFunc, compression, transportFlags),
00039      mSigcompStack(0),
00040      mRxBuffer(0),
00041      mExternalUnknownDatagramHandler(0),
00042      mInWritable(false)
00043 {
00044    mPollEventCnt = 0;
00045    mTxTryCnt = mTxMsgCnt = mTxFailCnt = 0;
00046    mRxTryCnt = mRxMsgCnt = mRxKeepaliveCnt = mRxTransactionCnt = 0;
00047    mTuple.setType(transport());
00048    mFd = InternalTransport::socket(transport(), version);
00049    mTuple.mFlowKey=(FlowKey)mFd;
00050    bind();      // also makes it non-blocking
00051 
00052    InfoLog (<< "Creating UDP transport host=" << pinterface
00053             << " port=" << mTuple.getPort()
00054             << " ipv4=" << bool(version==V4) );
00055 
00056 #ifdef USE_SIGCOMP
00057    if (mCompression.isEnabled())
00058    {
00059       DebugLog (<< "Compression enabled for transport: " << *this);
00060       mSigcompStack = new osc::Stack(mCompression.getStateHandler());
00061       mCompression.addCompressorsToStack(mSigcompStack);
00062    }
00063    else
00064    {
00065       DebugLog (<< "Compression disabled for transport: " << *this);
00066    }
00067 #else
00068    DebugLog (<< "No compression library available: " << *this);
00069 #endif
00070    mTxFifo.setDescription("UdpTransport::mTxFifo");
00071 }
00072 
00073 UdpTransport::~UdpTransport()
00074 {
00075    InfoLog(<< "Shutting down " << mTuple
00076            <<" tf="<<mTransportFlags<<" evt="<<(mPollGrp?1:0)
00077            <<" stats:"
00078            <<" poll="<<mPollEventCnt
00079            <<" txtry="<<mTxTryCnt
00080            <<" txmsg="<<mTxMsgCnt
00081            <<" txfail="<<mTxFailCnt
00082            <<" rxtry="<<mRxTryCnt
00083            <<" rxmsg="<<mRxMsgCnt
00084            <<" rxka="<<mRxKeepaliveCnt
00085            <<" rxtr="<<mRxTransactionCnt
00086            );
00087 #ifdef USE_SIGCOMP
00088    delete mSigcompStack;
00089 #endif
00090    if ( mRxBuffer )
00091    {
00092       delete[] mRxBuffer;
00093    }
00094    setPollGrp(0);
00095 }
00096 
00097 void
00098 UdpTransport::setPollGrp(FdPollGrp *grp)
00099 {
00100    if(mPollGrp)
00101    {
00102       mPollGrp->delPollItem(mPollItemHandle);
00103       mPollItemHandle=0;
00104    }
00105 
00106    if(mFd!=INVALID_SOCKET && grp)
00107    {
00108       mPollItemHandle = grp->addPollItem(mFd, FPEM_Read, this);
00109       // above released by InternalTransport destructor
00110       // ?bwc? Is this really a good idea? If the InternalTransport d'tor is
00111       // freeing this, shouldn't InternalTransport::setPollGrp() handle 
00112       // creating it?
00113    }
00114 
00115    InternalTransport::setPollGrp(grp);
00116 }
00117 
00118 
00122 void
00123 UdpTransport::process() {
00124    mStateMachineFifo.flush();
00125    if ( (mTransportFlags & RESIP_TRANSPORT_FLAG_TXNOW)!= 0 )
00126    {
00127        processTxAll();
00128        // FALLTHRU to code below in case queue not-empty
00129        // shouldn't ever happen (with current code)
00130        // but in future we may throttle transmits
00131    }
00132    if ( mPollGrp )
00133        updateEvents();
00134 }
00135 
00136 void
00137 UdpTransport::updateEvents()
00138 {
00139    //assert( mPollGrp );
00140    bool haveMsg = mTxFifoOutBuffer.messageAvailable();
00141    if ( !mInWritable && haveMsg )
00142    {
00143       mPollGrp->modPollItem(mPollItemHandle, FPEM_Read|FPEM_Write);
00144       mInWritable = true;
00145    }
00146    else if ( mInWritable && !haveMsg )
00147    {
00148       mPollGrp->modPollItem(mPollItemHandle, FPEM_Read);
00149       mInWritable = false;
00150    }
00151 }
00152 
00153 
00154 void
00155 UdpTransport::processPollEvent(FdPollEventMask mask)
00156 {
00157    ++mPollEventCnt;
00158    if ( mask & FPEM_Error )
00159    {
00160       assert(0);
00161    }
00162    if ( mask & FPEM_Write )
00163    {
00164       processTxAll();
00165       updateEvents();   // turn-off writability
00166    }
00167    if ( mask & FPEM_Read )
00168    {
00169       processRxAll();
00170    }
00171 }
00172 
00178 bool
00179 UdpTransport::hasDataToSend() const
00180 {
00181    return false;
00182 }
00183 
00184 void
00185 UdpTransport::buildFdSet( FdSet& fdset )
00186 {
00187    fdset.setRead(mFd);
00188 
00189    if (mTxFifoOutBuffer.messageAvailable())
00190    {
00191       fdset.setWrite(mFd);
00192    }
00193 }
00194 
00195 void
00196 UdpTransport::process(FdSet& fdset)
00197 {
00198    // pull buffers to send out of TxFifo
00199    // receive datagrams from fd
00200    // preparse and stuff into RxFifo
00201 
00202    if (fdset.readyToWrite(mFd))
00203    {
00204       processTxAll();
00205    }
00206 
00207    if ( fdset.readyToRead(mFd) )
00208    {
00209       processRxAll();
00210    }
00211    mStateMachineFifo.flush();
00212 }
00213 
00219 void
00220 UdpTransport::processTxAll()
00221 {
00222    SendData *msg;
00223    ++mTxTryCnt;
00224    while ( (msg=mTxFifoOutBuffer.getNext(RESIP_FIFO_NOWAIT)) != NULL )
00225    {
00226       processTxOne(msg);
00227       // With UDP we don't need to worry about write blocking (I hope)
00228       if ( (mTransportFlags & RESIP_TRANSPORT_FLAG_TXALL)==0 )
00229          break;
00230    }
00231 }
00232 
00233 void
00234 UdpTransport::processTxOne(SendData *data)
00235 {
00236    ++mTxMsgCnt;
00237    assert(data);
00238    std::auto_ptr<SendData> sendData(data);
00239    //DebugLog (<< "Sent: " <<  sendData->data);
00240    //DebugLog (<< "Sending message on udp.");
00241    assert( sendData->destination.getPort() != 0 );
00242 
00243    const sockaddr& addr = sendData->destination.getSockaddr();
00244    int expected;
00245    int count;
00246 
00247 #ifdef USE_SIGCOMP
00248    // If message needs to be compressed, compress it here.
00249    if (mSigcompStack &&
00250        sendData->sigcompId.size() > 0 &&
00251        !sendData->isAlreadyCompressed )
00252    {
00253        osc::SigcompMessage *sm = mSigcompStack->compressMessage
00254          (sendData->data.data(), sendData->data.size(),
00255           sendData->sigcompId.data(), sendData->sigcompId.size(),
00256           isReliable());
00257 
00258        DebugLog (<< "Compressed message from "
00259                  << sendData->data.size() << " bytes to "
00260                  << sm->getDatagramLength() << " bytes");
00261 
00262        expected = sm->getDatagramLength();
00263 
00264        count = sendto(mFd,
00265                       sm->getDatagramMessage(),
00266                       sm->getDatagramLength(),
00267                       0, // flags
00268                       &addr, sendData->destination.length());
00269        delete sm;
00270    }
00271    else
00272 #endif
00273    {
00274        expected = (int)sendData->data.size();
00275        count = sendto(mFd,
00276                       sendData->data.data(), (int)sendData->data.size(),
00277                       0, // flags
00278                       &addr, (int)sendData->destination.length());
00279    }
00280 
00281    if ( count == SOCKET_ERROR )
00282    {
00283       int e = getErrno();
00284       error(e);
00285       InfoLog (<< "Failed (" << e << ") sending to " << sendData->destination);
00286       fail(sendData->transactionId);
00287       ++mTxFailCnt;
00288    }
00289    else
00290    {
00291       if (count != expected)
00292       {
00293          ErrLog (<< "UDPTransport - send buffer full" );
00294          fail(sendData->transactionId);
00295       }
00296    }
00297 }
00298 
00307 void
00308 UdpTransport::processRxAll()
00309 {
00310    char *buffer = mRxBuffer;
00311    mRxBuffer = NULL;
00312    ++mRxTryCnt;
00313    for (;;)
00314    {
00315       // TBD: check StateMac capacity
00316       Tuple sender(mTuple);
00317       int len = processRxRecv(buffer, sender);
00318       if ( len <= 0 )
00319          break;
00320       ++mRxMsgCnt;
00321       if ( processRxParse(buffer, len, sender) )
00322       {
00323          buffer = NULL;
00324       }
00325       if ( (mTransportFlags & RESIP_TRANSPORT_FLAG_RXALL)==0 )
00326          break;
00327    }
00328    if ( buffer && (mTransportFlags & RESIP_TRANSPORT_FLAG_KEEP_BUFFER)!=0 )
00329    {
00330       assert(mRxBuffer==NULL);
00331       mRxBuffer = buffer;
00332       buffer = NULL;
00333    }
00334    if ( buffer )
00335       delete[] buffer;
00336 }
00337 
00338 /*
00339  * Receive from socket and store results into {buffer}. Updates
00340  * {buffer} with actual buffer (in case allocation required),
00341  * {len} with length of receive data, and {sender} with who
00342  * sent the packet.
00343  * Return length of data read:
00344  *  0 if no data read and no more data to read (EAGAIN)
00345  *  >0 if data read and may be more data to read
00346 **/
00347 int
00348 UdpTransport::processRxRecv(char*& buffer, Tuple& sender)
00349 {
00350    // !jf! this may have to change - when we read a message that is too big
00351    //should this buffer be allocated on the stack and then copied out, as it
00352    //needs to be deleted every time EWOULDBLOCK is encountered
00353    // .dlb. can we determine the size of the buffer before we allocate?
00354    // something about MSG_PEEK|MSG_TRUNC in Stevens..
00355    // .dlb. RFC3261 18.1.1 MUST accept 65K datagrams. would have to attempt to
00356    // adjust the UDP buffer as well...
00357    if (buffer==NULL)
00358    {
00359       buffer = MsgHeaderScanner::allocateBuffer(MaxBufferSize);
00360    }
00361 
00362    for (;;) {
00363       // !jf! how do we tell if it discarded bytes
00364       // !ah! we use the len-1 trick :-(
00365       socklen_t slen = sender.length();
00366       int len = recvfrom( mFd,
00367                           buffer,
00368                           MaxBufferSize,
00369                           0 /*flags */,
00370                           &sender.getMutableSockaddr(),
00371                           &slen);
00372       if ( len == SOCKET_ERROR )
00373       {
00374          int err = getErrno();
00375          if ( err != EWOULDBLOCK  )
00376          {
00377             error( err );
00378          }
00379          len = 0;
00380       }
00381       if (len+1 >= MaxBufferSize)
00382       {
00383          InfoLog(<<"Datagram exceeded max length "<<MaxBufferSize);
00384          continue;
00385       }
00386       return len;
00387    }
00388 }
00389 
00390 
00398 bool
00399 UdpTransport::processRxParse(char *buffer, int len, Tuple& sender)
00400 {
00401    bool origBufferConsumed = true;
00402 
00403    //handle incoming CRLFCRLF keep-alive packets
00404    if (len == 4 &&
00405        strncmp(buffer, Symbols::CRLFCRLF, len) == 0)
00406    {
00407       StackLog(<<"Throwing away incoming firewall keep-alive");
00408       ++mRxKeepaliveCnt;
00409       return false;
00410    }
00411 
00412    // this must be a STUN response (or garbage)
00413    if (buffer[0] == 1 && buffer[1] == 1 && ipVersion() == V4)
00414    {
00415       resip::Lock lock(myMutex);
00416       StunMessage resp;
00417       memset(&resp, 0, sizeof(StunMessage));
00418 
00419       if (stunParseMessage(buffer, len, resp, false))
00420       {
00421          in_addr sin_addr;
00422          // Use XorMappedAddress if present - if not use MappedAddress
00423          if(resp.hasXorMappedAddress)
00424          {
00425             UInt16 id16 = resp.msgHdr.id.octet[0]<<8
00426                           | resp.msgHdr.id.octet[1];
00427             UInt32 id32 = resp.msgHdr.id.octet[0]<<24
00428                           | resp.msgHdr.id.octet[1]<<16
00429                           | resp.msgHdr.id.octet[2]<<8
00430                           | resp.msgHdr.id.octet[3];
00431             resp.xorMappedAddress.ipv4.port = resp.xorMappedAddress.ipv4.port^id16;
00432             resp.xorMappedAddress.ipv4.addr = resp.xorMappedAddress.ipv4.addr^id32;
00433 
00434 #if defined(WIN32)
00435             sin_addr.S_un.S_addr = htonl(resp.xorMappedAddress.ipv4.addr);
00436 #else
00437             sin_addr.s_addr = htonl(resp.xorMappedAddress.ipv4.addr);
00438 #endif
00439             mStunMappedAddress = Tuple(sin_addr,resp.xorMappedAddress.ipv4.port, UDP);
00440             mStunSuccess = true;
00441          }
00442          else if(resp.hasMappedAddress)
00443          {
00444 #if defined(WIN32)
00445          sin_addr.S_un.S_addr = htonl(resp.mappedAddress.ipv4.addr);
00446 #else
00447          sin_addr.s_addr = htonl(resp.mappedAddress.ipv4.addr);
00448 #endif
00449          mStunMappedAddress = Tuple(sin_addr,resp.mappedAddress.ipv4.port, UDP);
00450          mStunSuccess = true;
00451          }
00452       }
00453       return false;
00454    }
00455 
00456    // this must be a STUN request (or garbage)
00457    if (buffer[0] == 0 && buffer[1] == 1 && ipVersion() == V4)
00458    {
00459       bool changePort = false;
00460       bool changeIp = false;
00461 
00462       StunAddress4 myAddr;
00463       const sockaddr_in& bi = (const sockaddr_in&)boundInterface();
00464       myAddr.addr = ntohl(bi.sin_addr.s_addr);
00465       myAddr.port = ntohs(bi.sin_port);
00466 
00467       StunAddress4 from; // packet source
00468       const sockaddr_in& fi = (const sockaddr_in&)sender.getSockaddr();
00469       from.addr = ntohl(fi.sin_addr.s_addr);
00470       from.port = ntohs(fi.sin_port);
00471 
00472       StunMessage resp;
00473       StunAddress4 dest;
00474       StunAtrString hmacPassword;
00475       hmacPassword.sizeValue = 0;
00476 
00477       StunAddress4 secondary;
00478       secondary.port = 0;
00479       secondary.addr = 0;
00480 
00481       bool ok = stunServerProcessMsg( buffer, len, // input buffer
00482                                       from,  // packet source
00483                                       secondary, // not used
00484                                       myAddr, // address to fill into response
00485                                       myAddr, // not used
00486                                       &resp, // stun response
00487                                       &dest, // where to send response
00488                                       &hmacPassword, // not used
00489                                       &changePort, // not used
00490                                       &changeIp, // not used
00491                                       false ); // logging
00492 
00493       if (ok)
00494       {
00495          DebugLog(<<"Got UDP STUN keepalive. Sending response...");
00496          char* response = new char[STUN_MAX_MESSAGE_SIZE];
00497          int rlen = stunEncodeMessage( resp,
00498                                        response,
00499                                        STUN_MAX_MESSAGE_SIZE,
00500                                        hmacPassword,
00501                                        false );
00502          SendData* stunResponse = new SendData(sender, response, rlen);
00503          mTxFifo.add(stunResponse);
00504       }
00505       return false;
00506    }
00507 
00508 #ifdef USE_SIGCOMP
00509    osc::StateChanges *sc = 0;
00510 #endif
00511 
00512    // Attempt to decode SigComp message, if appropriate.
00513    if ((buffer[0] & 0xf8) == 0xf8)
00514    {
00515      if (!mCompression.isEnabled())
00516      {
00517        InfoLog(<< "Discarding unexpected SigComp Message");
00518        return false;
00519      }
00520 #ifdef USE_SIGCOMP
00521      char* newBuffer = MsgHeaderScanner::allocateBuffer(MaxBufferSize);
00522      size_t uncompressedLength =
00523        mSigcompStack->uncompressMessage(buffer, len,
00524                                         newBuffer, MaxBufferSize, sc);
00525 
00526     DebugLog (<< "Uncompressed message from "
00527               << len << " bytes to "
00528               << uncompressedLength << " bytes");
00529 
00530 
00531      osc::SigcompMessage *nack = mSigcompStack->getNack();
00532 
00533      if (nack)
00534      {
00535        mTxFifo.add(new SendData(tuple,
00536                                 Data(nack->getDatagramMessage(),
00537                                      nack->getDatagramLength()),
00538                                 Data::Empty,
00539                                 Data::Empty,
00540                                 true)
00541                   );
00542        delete nack;
00543      }
00544 
00545      // delete[] buffer; NO: let caller do this if needed
00546      origBufferConsumed = false;
00547      buffer = newBuffer;
00548      len = uncompressedLength;
00549 #endif
00550    }
00551 
00552    buffer[len]=0; // null terminate the buffer string just to make debug easier and reduce errors
00553 
00554    //DebugLog ( << "UDP Rcv : " << len << " b" );
00555    //DebugLog ( << Data(buffer, len).escaped().c_str());
00556 
00557    SipMessage* message = new SipMessage(this);
00558 
00559    // set the received from information into the received= parameter in the
00560    // via
00561 
00562    // It is presumed that UDP Datagrams are arriving atomically and that
00563    // each one is a unique SIP message
00564 
00565 
00566    // Save all the info where this message came from
00567    sender.transport = this;
00568    sender.transportKey = getKey();
00569    sender.mFlowKey=mTuple.mFlowKey;
00570    message->setSource(sender);
00571    //DebugLog (<< "Received from: " << sender);
00572 
00573    // Tell the SipMessage about this datagram buffer.
00574    // WATCHOUT: below here buffer is consumed by message
00575    message->addBuffer(buffer);
00576 
00577    mMsgHeaderScanner.prepareForMessage(message);
00578 
00579    char *unprocessedCharPtr;
00580    if (mMsgHeaderScanner.scanChunk(buffer,
00581                                    len,
00582                                    &unprocessedCharPtr) !=
00583        MsgHeaderScanner::scrEnd)
00584    {
00585       StackLog(<<"Scanner rejecting datagram as unparsable / fragmented from " << sender);
00586       StackLog(<< Data(Data::Borrow, buffer, len));
00587       if(mExternalUnknownDatagramHandler)
00588       {
00589          auto_ptr<Data> datagram(new Data(buffer,len));
00590          (*mExternalUnknownDatagramHandler)(this,sender,datagram);
00591       }
00592 
00593       // Idea: consider backing buffer out of message and letting caller reuse it
00594       delete message;
00595       message=0;
00596       return origBufferConsumed;
00597    }
00598 
00599    // no pp error
00600    int used = int(unprocessedCharPtr - buffer);
00601 
00602    if (used < len)
00603    {
00604       // body is present .. add it up.
00605       // NB. The Sip Message uses an overlay (again)
00606       // for the body. It ALSO expects that the body
00607       // will be contiguous (of course).
00608       // it doesn't need a new buffer in UDP b/c there
00609       // will only be one datagram per buffer. (1:1 strict)
00610 
00611       message->setBody(buffer+used,len-used);
00612       //DebugLog(<<"added " << len-used << " byte body");
00613    }
00614 
00615    // .bwc. basicCheck takes up substantial CPU. Don't bother doing it
00616    // if we're overloaded.
00617    CongestionManager::RejectionBehavior behavior=getRejectionBehaviorForIncoming();
00618    if (behavior==CongestionManager::REJECTING_NON_ESSENTIAL
00619          || (behavior==CongestionManager::REJECTING_NEW_WORK
00620             && message->isRequest()))
00621    {
00622       // .bwc. If this fifo is REJECTING_NEW_WORK, we will drop
00623       // requests but not responses ( ?bwc? is this right for ACK?). 
00624       // If we are REJECTING_NON_ESSENTIAL, 
00625       // we reject all incoming work, since losing something from the 
00626       // wire will not cause instability or leaks (see 
00627       // CongestionManager.hxx)
00628 
00629       // .bwc. This handles all appropriate checking for whether
00630       // this is a response or an ACK.
00631       std::auto_ptr<SendData> tryLater(make503(*message, getExpectedWaitForIncoming()/1000));
00632       if(tryLater.get())
00633       {
00634          send(tryLater);
00635       }
00636      delete message; // dropping message due to congestion
00637      message = 0;
00638      return origBufferConsumed;
00639    }
00640 
00641    if (!basicCheck(*message))
00642    {
00643       delete message; // cannot use it, so, punt on it...
00644       // basicCheck queued any response required
00645       message = 0;
00646       return origBufferConsumed;
00647    }
00648 
00649    stampReceived(message);
00650 
00651 #ifdef USE_SIGCOMP
00652    if (mCompression.isEnabled() && sc)
00653    {
00654      const Via &via = message->header(h_Vias).front();
00655      if (message->isRequest())
00656      {
00657        // For requests, the compartment ID is read out of the
00658        // top via header field; if not present, we use the
00659        // TCP connection for identification purposes.
00660        if (via.exists(p_sigcompId))
00661        {
00662          Data compId = via.param(p_sigcompId);
00663          if(!compId.empty())
00664          {
00665             // .bwc. Crash was happening here. Why was there an empty sigcomp
00666             // id?
00667             mSigcompStack->provideCompartmentId(
00668                              sc, compId.data(), compId.size());
00669          }
00670        }
00671        else
00672        {
00673          mSigcompStack->provideCompartmentId(sc, this, sizeof(this));
00674        }
00675      }
00676      else
00677      {
00678        // For responses, the compartment ID is supposed to be
00679        // the same as the compartment ID of the request. We
00680        // *could* dig down into the transaction layer to try to
00681        // figure this out, but that's a royal pain, and a rather
00682        // severe layer violation. In practice, we're going to ferret
00683        // the ID out of the the Via header field, which is where we
00684        // squirreled it away when we sent this request in the first place.
00685        // !bwc! This probably shouldn't be going out over the wire.
00686        Data compId = via.param(p_branch).getSigcompCompartment();
00687        if(!compId.empty())
00688        {
00689          mSigcompStack->provideCompartmentId(sc, compId.data(), compId.size());
00690        }
00691      }
00692 
00693    }
00694 #endif
00695 
00696    mStateMachineFifo.add(message);
00697    ++mRxTransactionCnt;
00698    return origBufferConsumed;
00699 }
00700 
00701 
00702 
00703 bool
00704 UdpTransport::stunSendTest(const Tuple&  dest)
00705 {
00706    bool changePort=false;
00707    bool changeIP=false;
00708 
00709    StunAtrString username;
00710    StunAtrString password;
00711 
00712    username.sizeValue = 0;
00713    password.sizeValue = 0;
00714 
00715    StunMessage req;
00716    memset(&req, 0, sizeof(StunMessage));
00717 
00718    stunBuildReqSimple(&req, username, changePort , changeIP , 1);
00719 
00720    char* buf = new char[STUN_MAX_MESSAGE_SIZE];
00721    int len = STUN_MAX_MESSAGE_SIZE;
00722 
00723    int rlen = stunEncodeMessage(req, buf, len, password, false);
00724 
00725    SendData* stunRequest = new SendData(dest, buf, rlen);
00726    mTxFifo.add(stunRequest);
00727 
00728    mStunSuccess = false;
00729 
00730    return true;
00731 }
00732 
00733 bool
00734 UdpTransport::stunResult(Tuple& mappedAddress)
00735 {
00736    resip::Lock lock(myMutex);
00737 
00738    if (mStunSuccess)
00739    {
00740       mappedAddress = mStunMappedAddress;
00741    }
00742    return mStunSuccess;
00743 }
00744 
00745 void
00746 UdpTransport::setExternalUnknownDatagramHandler(ExternalUnknownDatagramHandler *handler)
00747 {
00748    mExternalUnknownDatagramHandler = handler;
00749 }
00750 
00751 void
00752 UdpTransport::setRcvBufLen(int buflen)
00753 {
00754    setSocketRcvBufLen(mFd, buflen);
00755 }
00756 
00757 /* ====================================================================
00758  * The Vovida Software License, Version 1.0
00759  *
00760  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00761  *
00762  * Redistribution and use in source and binary forms, with or without
00763  * modification, are permitted provided that the following conditions
00764  * are met:
00765  *
00766  * 1. Redistributions of source code must retain the above copyright
00767  *    notice, this list of conditions and the following disclaimer.
00768  *
00769  * 2. Redistributions in binary form must reproduce the above copyright
00770  *    notice, this list of conditions and the following disclaimer in
00771  *    the documentation and/or other materials provided with the
00772  *    distribution.
00773  *
00774  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00775  *    and "Vovida Open Communication Application Library (VOCAL)" must
00776  *    not be used to endorse or promote products derived from this
00777  *    software without prior written permission. For written
00778  *    permission, please contact vocal@vovida.org.
00779  *
00780  * 4. Products derived from this software may not be called "VOCAL", nor
00781  *    may "VOCAL" appear in their name, without prior written
00782  *    permission of Vovida Networks, Inc.
00783  *
00784  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00785  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00786  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00787  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00788  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00789  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00790  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00791  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00792  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00793  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00794  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00795  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00796  * DAMAGE.
00797  *
00798  * ====================================================================
00799  *
00800  * This software consists of voluntary contributions made by Vovida
00801  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00802  * Inc.  For more information on Vovida Networks, Inc., please see
00803  * <http://www.vovida.org/>.
00804  *
00805  * vi: set shiftwidth=3 expandtab:
00806  */