|
reSIProcate/stack
9694
|
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 */
1.7.5.1