|
reSIProcate/stack
9694
|
00001 #if defined(HAVE_CONFIG_H) 00002 #include "config.h" 00003 #endif 00004 00005 #ifdef WIN32 00006 #include <winsock2.h> 00007 #include <ws2tcpip.h> 00008 #include <wspiapi.h> // Required for freeaddrinfo implementation in Windows 2000, NT, Me/95/98 00009 #else 00010 #include <sys/types.h> 00011 #include <sys/socket.h> 00012 #include <arpa/inet.h> 00013 #include <netdb.h> 00014 #endif 00015 00016 #include "resip/stack/NameAddr.hxx" 00017 #include "resip/stack/Uri.hxx" 00018 00019 #include "resip/stack/ExtensionParameter.hxx" 00020 #include "resip/stack/Compression.hxx" 00021 #include "resip/stack/SipMessage.hxx" 00022 #include "resip/stack/TransactionState.hxx" 00023 #include "resip/stack/TransportFailure.hxx" 00024 #include "resip/stack/TransportSelector.hxx" 00025 #include "resip/stack/InternalTransport.hxx" 00026 #include "resip/stack/TcpBaseTransport.hxx" 00027 #include "resip/stack/TcpTransport.hxx" 00028 #include "resip/stack/UdpTransport.hxx" 00029 #include "resip/stack/Uri.hxx" 00030 00031 #include "rutil/DataStream.hxx" 00032 #include "rutil/DnsUtil.hxx" 00033 #include "rutil/Inserter.hxx" 00034 #include "rutil/Logger.hxx" 00035 #include "rutil/Socket.hxx" 00036 #include "rutil/FdPoll.hxx" 00037 #include "rutil/WinLeakCheck.hxx" 00038 #include "rutil/dns/DnsStub.hxx" 00039 00040 #ifdef USE_SIGCOMP 00041 #include <osc/Stack.h> 00042 #include <osc/SigcompMessage.h> 00043 #endif 00044 00045 #ifdef USE_SSL 00046 #include "resip/stack/ssl/DtlsTransport.hxx" 00047 #include "resip/stack/ssl/Security.hxx" 00048 #include "resip/stack/ssl/TlsTransport.hxx" 00049 #endif 00050 00051 #ifdef WIN32 00052 #include "rutil/WinCompat.hxx" 00053 #endif 00054 00055 #ifdef __MINGW32__ 00056 #define gai_strerror strerror 00057 #endif 00058 00059 #include <sys/types.h> 00060 00061 using namespace resip; 00062 00063 #define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT 00064 00065 TransportSelector::TransportSelector(Fifo<TransactionMessage>& fifo, Security* security, DnsStub& dnsStub, Compression &compression) : 00066 mDns(dnsStub), 00067 mStateMacFifo(fifo), 00068 mSecurity(security), 00069 mSocket( INVALID_SOCKET ), 00070 mSocket6( INVALID_SOCKET ), 00071 mCompression(compression), 00072 mSigcompStack (0), 00073 mPollGrp(0), 00074 mAvgBufferSize(1024), 00075 mInterruptorHandle(0) 00076 { 00077 memset(&mUnspecified.v4Address, 0, sizeof(sockaddr_in)); 00078 mUnspecified.v4Address.sin_family = AF_UNSPEC; 00079 00080 #ifdef USE_IPV6 00081 memset(&mUnspecified6.v6Address, 0, sizeof(sockaddr_in6)); 00082 mUnspecified6.v6Address.sin6_family = AF_UNSPEC; 00083 #endif 00084 00085 #ifdef USE_SIGCOMP 00086 if (mCompression.isEnabled()) 00087 { 00088 DebugLog (<< "Compression enabled for Transport Selector"); 00089 mSigcompStack = new osc::Stack(mCompression.getStateHandler()); 00090 mCompression.addCompressorsToStack(mSigcompStack); 00091 } 00092 else 00093 { 00094 DebugLog (<< "Compression disabled for Transport Selector"); 00095 } 00096 #else 00097 DebugLog (<< "No compression library available"); 00098 #endif 00099 } 00100 00101 TransportSelector::~TransportSelector() 00102 { 00103 mExactTransports.clear(); 00104 mAnyInterfaceTransports.clear(); 00105 mAnyPortTransports.clear(); 00106 mAnyPortAnyInterfaceTransports.clear(); 00107 mTlsTransports.clear(); 00108 mSharedProcessTransports.clear(); 00109 mHasOwnProcessTransports.clear(); 00110 mTypeToTransportMap.clear(); 00111 while(!mTransports.empty()) 00112 { 00113 delete mTransports.back(); 00114 mTransports.pop_back(); 00115 } 00116 #ifdef USE_SIGCOMP 00117 delete mSigcompStack; 00118 #endif 00119 00120 if ( mSocket != INVALID_SOCKET ) 00121 closeSocket( mSocket ); 00122 if ( mSocket6 != INVALID_SOCKET ) 00123 closeSocket( mSocket6 ); 00124 00125 setPollGrp(0); 00126 } 00127 00128 void 00129 TransportSelector::shutdown() 00130 { 00132 for (ExactTupleMap::iterator i=mExactTransports.begin(); i!=mExactTransports.end(); ++i) 00133 { 00134 i->second->shutdown(); 00135 } 00136 for (AnyInterfaceTupleMap::iterator i=mAnyInterfaceTransports.begin(); i!=mAnyInterfaceTransports.end(); ++i) 00137 { 00138 i->second->shutdown(); 00139 } 00140 for (TlsTransportMap::iterator i=mTlsTransports.begin(); i!=mTlsTransports.end(); ++i) 00141 { 00142 i->second->shutdown(); 00143 } 00144 } 00145 00146 bool 00147 TransportSelector::isFinished() const 00148 { 00149 for (ExactTupleMap::const_iterator i=mExactTransports.begin(); i!=mExactTransports.end(); ++i) 00150 { 00151 if (!i->second->isFinished()) return false; 00152 } 00153 for (AnyInterfaceTupleMap::const_iterator i=mAnyInterfaceTransports.begin(); i!=mAnyInterfaceTransports.end(); ++i) 00154 { 00155 if (!i->second->isFinished()) return false; 00156 } 00157 for (TlsTransportMap::const_iterator i=mTlsTransports.begin(); i!=mTlsTransports.end(); ++i) 00158 { 00159 if (!i->second->isFinished()) return false; 00160 } 00161 return true; 00162 } 00163 00164 void 00165 TransportSelector::addTransport(std::auto_ptr<Transport> autoTransport, 00166 bool immediate) 00167 { 00168 if(immediate) 00169 { 00170 addTransportInternal(autoTransport); 00171 } 00172 else 00173 { 00174 mTransportsToAdd.add(autoTransport.release()); 00175 } 00176 } 00177 00178 void 00179 TransportSelector::addTransportInternal(std::auto_ptr<Transport> autoTransport) 00180 { 00181 Transport* transport = autoTransport.release(); 00182 mDns.addTransportType(transport->transport(), transport->ipVersion()); 00183 00184 // !bwc! This is a multimap from TransportType/IpVersion to Transport*. 00185 // Make _extra_ sure that no garbage goes in here. 00186 if(transport->transport()==TCP) 00187 { 00188 assert(dynamic_cast<TcpTransport*>(transport)); 00189 } 00190 #ifdef USE_SSL 00191 else if(transport->transport()==TLS) 00192 { 00193 assert(dynamic_cast<TlsTransport*>(transport)); 00194 } 00195 #endif 00196 else if(transport->transport()==UDP) 00197 { 00198 assert(dynamic_cast<UdpTransport*>(transport)); 00199 } 00200 #ifdef USE_DTLS 00201 #ifdef USE_SSL 00202 else if(transport->transport()==DTLS) 00203 { 00204 assert(dynamic_cast<DtlsTransport*>(transport)); 00205 } 00206 #endif 00207 #endif 00208 else 00209 { 00210 assert(0); 00211 } 00212 00213 Tuple tuple(transport->interfaceName(), transport->port(), 00214 transport->ipVersion(), transport->transport()); 00215 mTypeToTransportMap.insert(TypeToTransportMap::value_type(tuple,transport)); 00216 00217 switch (transport->transport()) 00218 { 00219 case UDP: 00220 case TCP: 00221 { 00222 assert(mExactTransports.find(tuple) == mExactTransports.end() && 00223 mAnyInterfaceTransports.find(tuple) == mAnyInterfaceTransports.end()); 00224 00225 DebugLog (<< "Adding transport: " << tuple); 00226 00227 // Store the transport in the ANY interface maps if the tuple specifies ANY 00228 // interface. Store the transport in the specific interface maps if the tuple 00229 // specifies an interface. See TransportSelector::findTransport. 00230 if (transport->interfaceName().empty() || 00231 transport->getTuple().isAnyInterface() || 00232 transport->hasSpecificContact() ) 00233 { 00234 mAnyInterfaceTransports[tuple] = transport; 00235 mAnyPortAnyInterfaceTransports[tuple] = transport; 00236 } 00237 else 00238 { 00239 mExactTransports[tuple] = transport; 00240 mAnyPortTransports[tuple] = transport; 00241 } 00242 } 00243 break; 00244 case TLS: 00245 case DTLS: 00246 { 00247 TlsTransportKey key(transport->tlsDomain(),transport->transport(),transport->ipVersion()); 00248 mTlsTransports[key]=transport; 00249 } 00250 break; 00251 default: 00252 assert(0); 00253 break; 00254 } 00255 00256 if (transport->shareStackProcessAndSelect()) 00257 { 00258 if ( mPollGrp ) 00259 { 00260 transport->setPollGrp(mPollGrp); 00261 } 00262 mSharedProcessTransports.push_back(transport); 00263 } 00264 else 00265 { 00266 mHasOwnProcessTransports.push_back(transport); 00267 mHasOwnProcessTransports.back()->startOwnProcessing(); 00268 } 00269 00270 mTransports.push_back(transport); 00271 transport->setKey((unsigned int)mTransports.size()); 00272 } 00273 00274 void 00275 TransportSelector::setPollGrp(FdPollGrp *grp) 00276 { 00277 if(mPollGrp && mInterruptorHandle) 00278 { 00279 // unregister our select interruptor 00280 mPollGrp->delPollItem(mInterruptorHandle); 00281 mInterruptorHandle=0; 00282 } 00283 00284 mPollGrp = grp; 00285 00286 if(mPollGrp && mSelectInterruptor.get()) 00287 { 00288 mInterruptorHandle = mPollGrp->addPollItem(mSelectInterruptor->getReadSocket(), FPEM_Read, mSelectInterruptor.get()); 00289 } 00290 00291 for(TransportList::iterator t=mSharedProcessTransports.begin(); 00292 t!=mSharedProcessTransports.end(); ++t) 00293 { 00294 (*t)->setPollGrp(mPollGrp); 00295 } 00296 } 00297 00298 void 00299 TransportSelector::createSelectInterruptor() 00300 { 00301 if(!mSelectInterruptor.get()) 00302 { 00303 mSelectInterruptor.reset(new SelectInterruptor); 00304 if(mPollGrp) 00305 { 00306 mInterruptorHandle = mPollGrp->addPollItem(mSelectInterruptor->getReadSocket(), FPEM_Read, mSelectInterruptor.get()); 00307 } 00308 } 00309 } 00310 00311 void 00312 TransportSelector::buildFdSet(FdSet& fdset) 00313 { 00314 for(TransportList::iterator it = mSharedProcessTransports.begin(); 00315 it != mSharedProcessTransports.end(); it++) 00316 { 00317 (*it)->buildFdSet(fdset); 00318 } 00319 if(mSelectInterruptor.get()) 00320 { 00321 mSelectInterruptor->buildFdSet(fdset); 00322 } 00323 } 00324 00325 void 00326 TransportSelector::process(FdSet& fdset) 00327 { 00328 checkTransportAddQueue(); 00329 00330 for(TransportList::iterator it = mSharedProcessTransports.begin(); 00331 it != mSharedProcessTransports.end(); it++) 00332 { 00333 try 00334 { 00335 (*it)->process(fdset); 00336 } 00337 catch (BaseException& e) 00338 { 00339 ErrLog (<< "Exception thrown from Transport::process: " << e); 00340 } 00341 } 00342 00343 if(mSelectInterruptor.get()) 00344 { 00345 mSelectInterruptor->process(fdset); 00346 } 00347 } 00348 00349 void 00350 TransportSelector::process() 00351 { 00352 // This function will only be sufficient if these Transports are hooked into 00353 // a FdPollGrp. 00354 checkTransportAddQueue(); 00355 00356 for(TransportList::iterator it = mSharedProcessTransports.begin(); 00357 it != mSharedProcessTransports.end(); it++) 00358 { 00359 try 00360 { 00361 (*it)->process(); 00362 } 00363 catch (BaseException& e) 00364 { 00365 ErrLog (<< "Exception thrown from Transport::process: " << e); 00366 } 00367 } 00368 } 00369 00370 void 00371 TransportSelector::checkTransportAddQueue() 00372 { 00373 std::auto_ptr<Transport> t(mTransportsToAdd.getNext(-1)); 00374 while(t.get()) 00375 { 00376 addTransportInternal(t); 00377 t.reset(mTransportsToAdd.getNext(0)); 00378 } 00379 } 00380 00381 void 00382 TransportSelector::poke() 00383 { 00384 for(TransportList::iterator it = mHasOwnProcessTransports.begin(); 00385 it != mHasOwnProcessTransports.end(); it++) 00386 { 00387 try 00388 { 00389 (*it)->poke(); 00390 } 00391 catch (BaseException& e) 00392 { 00393 ErrLog (<< "Exception thrown from Transport::process: " << e); 00394 } 00395 } 00396 00397 if(mSelectInterruptor.get() && hasDataToSend()) 00398 { 00399 mSelectInterruptor->handleProcessNotification(); 00400 } 00401 } 00402 00403 bool 00404 TransportSelector::hasDataToSend() const 00405 { 00406 for(TransportList::const_iterator it = mSharedProcessTransports.begin(); 00407 it != mSharedProcessTransports.end(); it++) 00408 { 00409 if ((*it)->hasDataToSend()) 00410 { 00411 return true; 00412 } 00413 } 00414 return false; 00415 } 00416 00418 //mDns.lookup() but this can result in a synchronous call to handle() which 00419 //assumes that dnsresult has been assigned to the TransactionState 00421 DnsResult* 00422 TransportSelector::createDnsResult(DnsHandler* handler) 00423 { 00424 return mDns.createDnsResult(handler); 00425 } 00426 00427 void 00428 TransportSelector::dnsResolve(DnsResult* result, 00429 SipMessage* msg) 00430 { 00431 // Picking the target destination: 00432 // - for request, use forced target if set 00433 // otherwise use loose routing behaviour (route or, if none, request-uri) 00434 // - for response, use forced target if set, otherwise look at via 00435 00436 if (msg->isRequest()) 00437 { 00438 // If this is an ACK we need to fix the tid to reflect that 00439 if (msg->hasForceTarget()) 00440 { 00441 //DebugLog(<< "!ah! RESOLVING request with force target : " << msg->getForceTarget() ); 00442 mDns.lookup(result, msg->getForceTarget()); 00443 } 00444 else if (msg->exists(h_Routes) && !msg->const_header(h_Routes).empty()) 00445 { 00446 // put this into the target, in case the send later fails, so we don't 00447 // lose the target 00448 msg->setForceTarget(msg->const_header(h_Routes).front().uri()); 00449 DebugLog (<< "Looking up dns entries (from route) for " << msg->getForceTarget()); 00450 mDns.lookup(result, msg->getForceTarget()); 00451 } 00452 else 00453 { 00454 DebugLog (<< "Looking up dns entries for " << msg->const_header(h_RequestLine).uri()); 00455 mDns.lookup(result, msg->const_header(h_RequestLine).uri()); 00456 } 00457 } 00458 else if (msg->isResponse()) 00459 { 00460 ErrLog(<<"unimplemented response dns"); 00461 assert(0); 00462 } 00463 else 00464 { 00465 assert(0); 00466 } 00467 } 00468 00469 bool isDgramTransport (TransportType type) 00470 { 00471 static const bool unknown_transport = false; 00472 switch(type) 00473 { 00474 case UDP: 00475 case DTLS: 00476 case DCCP: 00477 case SCTP: 00478 return true; 00479 00480 case TCP: 00481 case TLS: 00482 return false; 00483 00484 default: 00485 assert(unknown_transport); 00486 return unknown_transport; // !kh! just to make it compile wo/warning. 00487 } 00488 } 00489 00490 Tuple 00491 TransportSelector::getFirstInterface(bool is_v4, TransportType type) 00492 { 00493 // !kh! both getaddrinfo() and IPv6 are not supported by cygwin, yet. 00494 #ifdef __CYGWIN__ 00495 assert(0); 00496 return Tuple(); 00497 #else 00498 // !kh! 00499 // 1. Query local hostname. 00500 char hostname[256] = ""; 00501 if(gethostname(hostname, sizeof(hostname)) != 0) 00502 { 00503 int e = getErrno(); 00504 Transport::error( e ); 00505 InfoLog(<< "Can't query local hostname : [" << e << "] " << strerror(e) ); 00506 throw Transport::Exception("Can't query local hostname", __FILE__, __LINE__); 00507 } 00508 InfoLog(<< "Local hostname is [" << hostname << "]"); 00509 00510 // !kh! 00511 // 2. Resolve address(es) of local hostname for specified transport. 00512 const bool is_dgram = isDgramTransport(type); 00513 addrinfo hint; 00514 memset(&hint, 0, sizeof(hint)); 00515 hint.ai_family = is_v4 ? PF_INET : PF_INET6; 00516 hint.ai_flags = AI_PASSIVE; 00517 hint.ai_socktype = is_dgram ? SOCK_DGRAM : SOCK_STREAM; 00518 00519 addrinfo* results; 00520 int ret = getaddrinfo( 00521 hostname, 00522 0, 00523 &hint, 00524 &results); 00525 00526 if(ret != 0) 00527 { 00528 Transport::error( ret ); // !kh! is this the correct sematics? ret is not errno. 00529 InfoLog(<< "Can't resolve " << hostname << "'s address : [" << ret << "] " << gai_strerror(ret) ); 00530 throw Transport::Exception("Can't resolve hostname", __FILE__,__LINE__); 00531 } 00532 00533 // !kh! 00534 // 3. Use first address resolved if there are more than one. 00535 // What should I do if there are more than one address? 00536 // i.e. results->ai_next != 0. 00537 Tuple source(*(results->ai_addr), type); 00538 InfoLog(<< "Local address is " << source); 00539 addrinfo* ai = results->ai_next; 00540 for(; ai; ai = ai->ai_next) 00541 { 00542 Tuple addr(*(ai->ai_addr), type); 00543 InfoLog(<<"Additional address " << addr); 00544 } 00545 freeaddrinfo(results); 00546 00547 return source; 00548 #endif 00549 } 00550 00551 00558 Transport* 00559 TransportSelector::findTransportByVia(SipMessage* msg, const Tuple& target, 00560 Tuple& source) const 00561 { 00562 assert(msg->exists(h_Vias)); 00563 assert(!msg->const_header(h_Vias).empty()); 00564 const Via& via = msg->const_header(h_Vias).front(); 00565 00566 if (via.sentHost().empty() && via.transport().empty()) 00567 { 00568 return 0; 00569 } 00570 00571 // XXX: Is there better way to do below (without the copy)? 00572 source = Tuple(via.sentHost(), via.sentPort(), target.ipVersion(), 00573 via.transport().empty() ? target.getType() : toTransportType(via.transport())); // Transport type is pre-populated in via, lock to it 00574 00575 if ( target.mFlowKey!=0 && (source.getPort()==0 || source.isAnyInterface()) ) 00576 { 00577 WarningLog(<< "Sending request with incomplete Via header and FlowKey." 00578 <<" This code no smart enough to pick the correct Transport." 00579 <<" Via=" << via); 00580 assert(0); 00581 } 00582 if ( source.isAnyInterface() ) 00583 { 00584 // INADDR_ANY cannot go out on the wire, so remove it from 00585 // via header now. 00586 // transmit() will later use determineSourceInterface() to 00587 // get the actual interface to populate the Contact & Via headers. 00588 // Not sure if we should support this case or just assert. 00589 // .gh. This should be supported, in case only the transport part of the Via is set 00590 msg->header(h_Vias).front().sentHost().clear(); 00591 } 00592 00593 Transport *trans; 00594 if ( (trans = findTransportBySource(source, msg)) == NULL ) 00595 { 00596 return NULL; 00597 } 00598 if(source.getPort()==0) 00599 { 00600 source.setPort(trans->port()); 00601 } 00602 return trans; 00603 } 00604 00605 Tuple 00606 TransportSelector::determineSourceInterface(SipMessage* msg, const Tuple& target) const 00607 { 00608 assert(msg->exists(h_Vias)); 00609 assert(!msg->header(h_Vias).empty()); 00610 const Via& via = msg->header(h_Vias).front(); 00611 00612 // this case should be handled already for UDP and TCP targets 00613 assert( (!(msg->isRequest() && !via.sentHost().empty())) || (target.getType() == TLS || target.getType() == DTLS) ); 00614 if (1) 00615 { 00616 Tuple source(target); 00617 #if defined(WIN32) && !defined(NO_IPHLPAPI) 00618 try 00619 { 00620 GenericIPAddress addr = WinCompat::determineSourceInterface(target.toGenericIPAddress()); 00621 source.setSockaddr(addr); 00622 } 00623 catch (WinCompat::Exception&) 00624 { 00625 ErrLog (<< "Can't find source interface to use"); 00626 throw Transport::Exception("Can't find source interface", __FILE__, __LINE__); 00627 } 00628 #else 00629 // !kh! 00630 // The connected UDP technique doesn't work all the time. 00631 // 1. Might not work on all implementaions as stated in UNP vol.1 8.14. 00632 // 2. Might not work under unspecified condition on Windows, 00633 // search "getsockname" in MSDN library. 00634 // 3. We've experienced this issue on our production software. 00635 00636 // this process will determine which interface the kernel would use to 00637 // send a packet to the target by making a connect call on a udp socket. 00638 Socket tmp = INVALID_SOCKET; 00639 if (target.isV4()) 00640 { 00641 if (mSocket == INVALID_SOCKET) 00642 { 00643 mSocket = InternalTransport::socket(UDP, V4); // may throw 00644 } 00645 tmp = mSocket; 00646 } 00647 else 00648 { 00649 if (mSocket6 == INVALID_SOCKET) 00650 { 00651 mSocket6 = InternalTransport::socket(UDP, V6); // may throw 00652 } 00653 tmp = mSocket6; 00654 } 00655 00656 int ret = connect(tmp,&target.getSockaddr(), target.length()); 00657 if (ret < 0) 00658 { 00659 int e = getErrno(); 00660 Transport::error( e ); 00661 InfoLog(<< "Unable to route to " << target << " : [" << e << "] " << strerror(e) ); 00662 throw Transport::Exception("Can't find source address for Via", __FILE__,__LINE__); 00663 } 00664 00665 socklen_t len = source.length(); 00666 ret = getsockname(tmp,&source.getMutableSockaddr(), &len); 00667 if (ret < 0) 00668 { 00669 int e = getErrno(); 00670 Transport::error(e); 00671 InfoLog(<< "Can't determine name of socket " << target << " : " << strerror(e) ); 00672 throw Transport::Exception("Can't find source address for Via", __FILE__,__LINE__); 00673 } 00674 00675 // !kh! test if connected UDP technique results INADDR_ANY, i.e. 0.0.0.0. 00676 // if it does, assume the first avaiable interface. 00677 if(source.isV4()) 00678 { 00679 long src = (reinterpret_cast<const sockaddr_in*>(&source.getSockaddr())->sin_addr.s_addr); 00680 if(src == INADDR_ANY) 00681 { 00682 InfoLog(<< "Connected UDP failed to determine source address, use first address instaed."); 00683 source = getFirstInterface(true, target.getType()); 00684 } 00685 } 00686 else // IPv6 00687 { 00688 //should never reach here in WIN32 w/ V6 support 00689 #if defined(USE_IPV6) && !defined(WIN32) 00690 if (source.isAnyInterface()) 00691 { 00692 source = getFirstInterface(false, target.getType()); 00693 } 00694 # endif 00695 } 00696 // Unconnect. 00697 // !jf! This is necessary, but I am not sure what we can do if this 00698 // fails. I'm not sure the stack can recover from this error condition. 00699 if (target.isV4()) 00700 { 00701 ret = connect(mSocket, 00702 (struct sockaddr*)&mUnspecified.v4Address, 00703 sizeof(mUnspecified.v4Address)); 00704 } 00705 #ifdef USE_IPV6 00706 else 00707 { 00708 ret = connect(mSocket6, 00709 (struct sockaddr*)&mUnspecified6.v6Address, 00710 sizeof(mUnspecified6.v6Address)); 00711 } 00712 #else 00713 else 00714 { 00715 assert(0); 00716 } 00717 #endif 00718 00719 if ( ret<0 ) 00720 { 00721 int e = getErrno(); 00722 //.dcm. OS X 10.5 workaround, we could #ifdef for specific OS X version. 00723 if (!(e ==EAFNOSUPPORT || e == EADDRNOTAVAIL)) 00724 { 00725 ErrLog(<< "Can't disconnect socket : " << strerror(e) ); 00726 Transport::error(e); 00727 throw Transport::Exception("Can't disconnect socket", __FILE__,__LINE__); 00728 } 00729 } 00730 #endif 00731 00732 // This is the port that the request will get sent out from. By default, 00733 // this value will be 0, since the Helper that creates the request will not 00734 // assign it. In this case, the stack will pick an arbitrary (but appropriate) 00735 // transport. If it is non-zero, it will only match transports that are bound to 00736 // the specified port (and fail if none are available) 00737 00738 if(msg->isRequest()) 00739 { 00740 source.setPort(via.sentPort()); 00741 } 00742 else 00743 { 00744 source.setPort(0); 00745 } 00746 00747 DebugLog (<< "Looked up source for destination: " << target 00748 << " -> " << source 00749 << " sent-by=" << via.sentHost() 00750 << " sent-port=" << via.sentPort()); 00751 00752 return source; 00753 } 00754 } 00755 00756 // !jf! there may be an extra copy of a tuple here. can probably get rid of it 00757 // but there are some const issues. 00758 bool 00759 TransportSelector::transmit(SipMessage* msg, Tuple& target, SendData* sendData) 00760 { 00761 assert(msg); 00762 00763 if(msg->mIsDecorated) 00764 { 00765 msg->rollbackOutboundDecorators(); 00766 } 00767 00768 try 00769 { 00770 TransportFailure::FailureReason transportFailureReason = TransportFailure::NoTransport; 00771 00772 // !ah! You NEED to do this for responses too -- the transport doesn't 00773 // !ah! know it's IP addres(es) in all cases, AND it's function of the dest. 00774 // (imagine a synthetic message...) 00775 00776 Tuple source; 00777 // .bwc. We need 3 things here: 00778 // 1) A Transport* to call send() on. 00779 // 2) A complete Tuple to pass in this call (target). 00780 // 3) A host, port, and protocol for filling out the topmost via, and 00781 // possibly stuff like Contact, Referred-By, and other headers that 00782 // must specify a hostname that the TU was unable to supply, because 00783 // it didn't know what interface/port the message would be sent on. 00784 // (source) 00785 /* 00786 Our Transport* might be found in target. If so, we can skip this block 00787 of stuff. 00788 Alternatively, we might not have the transport to start with. However, 00789 given a connection id, we will be able to find the Connection we 00790 should use, we can get the Transport we want. If we have no connection 00791 id, but we know we are using TLS or DTLS and have a tls hostname, we 00792 can use the hostname to find the appropriate transport. If all else 00793 fails, we must resort to the connected UDP trick to fill out source, 00794 which in turn is used to look up a matching transport. 00795 00796 Given the transport, it is always possible to get the port/protocol, 00797 and usually possible to get the host (if it is bound to INADDR_ANY, we 00798 can't tell). However, if we had to fill out source in order to find 00799 the transport in the first place, this is not an issue. 00800 */ 00801 00802 Data remoteSigcompId; 00803 00804 Transport* transport=0; 00805 00806 if (msg->isRequest()) 00807 { 00808 transport = findTransportByVia(msg, target, source); 00809 if (!transport) 00810 { 00811 if ((transport = findTransportByDest(target)) != NULL) 00812 { 00813 source = transport->getTuple(); 00814 } 00815 } 00816 00817 if(!transport && target.mFlowKey && target.onlyUseExistingConnection) 00818 { 00819 // .bwc. Connection info was specified, and use of this connection 00820 // was mandatory, but connection is no longer around. We fail. 00821 transportFailureReason = TransportFailure::TransportNoExistConn; 00822 } 00823 else if (transport)// .bwc. Here we use transport to find source. 00824 { 00825 assert( source.getType()!=0 ); 00826 00827 // .bwc. If the transport has an ambiguous interface, we need to 00828 //look a little closer. 00829 if(source.isAnyInterface()) 00830 { 00831 Tuple temp = determineSourceInterface(msg,target); 00832 00833 // .bwc. determineSourceInterface() can give us a port, if the TU 00834 // put one in the topmost Via. 00835 assert(source.ipVersion()==temp.ipVersion() && 00836 source.getType()==temp.getType()); 00837 source=temp; 00838 00839 /* determineSourceInterface might return an arbitrary port 00840 here, so use the port specified in transport->port(). 00841 */ 00842 if(source.getPort()==0) 00843 { 00844 source.setPort(transport->port()); 00845 } 00846 } 00847 } 00848 // .bwc. Here we use source to find transport. 00849 else 00850 { 00851 source = determineSourceInterface(msg, target); 00852 transport = findTransportBySource(source, msg); 00853 00854 // .bwc. determineSourceInterface might give us a port 00855 if(transport && source.getPort()==0) 00856 { 00857 source.setPort(transport->port()); 00858 } 00859 } 00860 00861 target.transportKey=transport ? transport->getKey() : 0; 00862 00863 // .bwc. Topmost Via is only filled out in the request case. Also, if 00864 // we don't have a transport at this point, we're going to fail, 00865 // so don't bother doing the work. 00866 if(target.transportKey) 00867 { 00868 Via& topVia(msg->header(h_Vias).front()); 00869 topVia.remove(p_maddr); // !jf! why do this? 00870 00871 // insert the via 00872 if (topVia.transport().empty()) 00873 { 00874 topVia.transport() = Tuple::toData(source.getType()); 00875 } 00876 if (!topVia.sentHost().size()) 00877 { 00878 topVia.sentHost() = Tuple::inet_ntop(source); 00879 } 00880 if (!topVia.sentPort()) 00881 { 00882 topVia.sentPort() = source.getPort(); 00883 } 00884 00885 if (mCompression.isEnabled()) 00886 { 00887 // Indicate support for SigComp, if appropriate. 00888 if (!topVia.exists(p_comp)) 00889 { 00890 topVia.param(p_comp) = "sigcomp"; 00891 } 00892 if (!topVia.exists(p_sigcompId)) 00893 { 00894 topVia.param(p_sigcompId) = mCompression.getSigcompId(); 00895 } 00896 00897 // Figure out remote identifier (from Route header 00898 // field, if present; otherwise, from Request-URI). 00899 // XXX rohc-sip-sigcomp-03 says to use +sip.instance, 00900 // but this is impossible to actually do if you're 00901 // not actually the registrar, and really hard even 00902 // if you are. 00903 Uri destination;// (*reinterpret_cast<Uri*>(0)); // !bwc! What? 00904 00905 if(msg->exists(h_Routes) && 00906 !msg->const_header(h_Routes).empty()) 00907 { 00908 destination = msg->const_header(h_Routes).front().uri(); 00909 } 00910 else 00911 { 00912 destination = msg->const_header(h_RequestLine).uri(); 00913 } 00914 00915 if (destination.exists(p_comp) && 00916 destination.param(p_comp) == "sigcomp") 00917 { 00918 if (destination.exists(p_sigcompId)) 00919 { 00920 remoteSigcompId = destination.param(p_sigcompId); 00921 } 00922 else 00923 { 00924 remoteSigcompId = destination.host(); 00925 } 00926 } 00927 // Squirrel the compartment away in the branch so that 00928 // we can figure out (pre-transaction-matching) what 00929 // compartment incoming requests are associated with. 00930 topVia.param(p_branch).setSigcompCompartment(remoteSigcompId); 00931 } 00932 } 00933 00934 } 00935 else if (msg->isResponse()) 00936 { 00937 // We assume that all stray responses have been discarded, so we always 00938 // know the transport that the corresponding request was received on 00939 // and this has been copied by TransactionState::sendToWire into transport 00940 transport=findTransportByDest(target); 00941 00942 // !bwc! May eventually remove this once we allow transports to be 00943 // removed while running. 00944 assert(transport); 00945 00946 source = transport->getTuple(); 00947 00948 // .bwc. If the transport has an ambiguous interface, we need to 00949 //look a little closer. 00950 if(source.isAnyInterface()) 00951 { 00952 Tuple temp = source; 00953 source = determineSourceInterface(msg,target); 00954 assert(source.ipVersion()==temp.ipVersion() && 00955 source.getType()==temp.getType()); 00956 00957 /* determineSourceInterface might return an arbitrary port here, 00958 so use the port specified in transport->port(). 00959 */ 00960 if(source.getPort()==0) 00961 { 00962 source.setPort(transport->port()); 00963 } 00964 } 00965 if (mCompression.isEnabled()) 00966 { 00967 // Figure out remote identifier (from Via header field). 00968 Via& topVia(msg->header(h_Vias).front()); 00969 00970 if(topVia.exists(p_comp) && 00971 topVia.param(p_comp) == "sigcomp") 00972 { 00973 if (topVia.exists(p_sigcompId)) 00974 { 00975 remoteSigcompId = topVia.param(p_sigcompId); 00976 } 00977 else 00978 { 00979 // XXX rohc-sigcomp-sip-03 says "sent-by", 00980 // but this should probably be "received" if present, 00981 // and "sent-by" otherwise. 00982 // XXX Also, the spec is ambiguous about whether 00983 // to include the port in this identifier. 00984 remoteSigcompId = topVia.sentHost(); 00985 } 00986 } 00987 } 00988 } 00989 else 00990 { 00991 assert(0); 00992 } 00993 00994 // .bwc. At this point, source, transport, and target should be 00995 // _fully_ specified. 00996 00997 if (transport) 00998 { 00999 // !bwc! TODO This filling in of stuff really should be handled with 01000 // the callOutboundDecorators() callback. (Or, at the very least, 01001 // we should allow this code to be turned off through configuration. 01002 // There are plenty of cases where this stuff is not at all necessary.) 01003 // There is a contact header and it contains exactly one entry 01004 if (msg->exists(h_Contacts) && msg->header(h_Contacts).size()==1) 01005 { 01006 for (NameAddrs::iterator i=msg->header(h_Contacts).begin(); i != msg->header(h_Contacts).end(); i++) 01007 { 01008 const NameAddr& c_contact = *i; 01009 NameAddr& contact = *i; 01010 // No host specified, so use the ip address and port of the 01011 // transport used. Otherwise, leave it as is. 01012 if (c_contact.uri().host().empty()) 01013 { 01014 contact.uri().host() = (transport->hasSpecificContact() ? 01015 transport->interfaceName() : 01016 Tuple::inet_ntop(source) ); 01017 contact.uri().port() = transport->port(); 01018 01019 if (transport->transport() != UDP && !contact.uri().exists(p_gr)) 01020 { 01021 contact.uri().param(p_transport) = Tuple::toDataLower(transport->transport()); 01022 } 01023 01024 // Add comp=sigcomp to contact URI 01025 // Also, If no +sip.instance on contact HEADER, 01026 // add sigcomp-id="<urn>" to contact URI. 01027 if (mCompression.isEnabled()) 01028 { 01029 if (!contact.uri().exists(p_comp)) 01030 { 01031 contact.uri().param(p_comp) = "sigcomp"; 01032 } 01033 if (!contact.exists(p_Instance) && 01034 !contact.uri().exists(p_sigcompId)) 01035 { 01036 contact.uri().param(p_sigcompId) 01037 = mCompression.getSigcompId(); 01038 } 01039 } 01040 } 01041 else 01042 { 01043 if (c_contact.uri().exists(p_addTransport)) 01044 { 01045 if (target.getType() != UDP) 01046 { 01047 contact.uri().param(p_transport) = Tuple::toDataLower(target.getType()); 01048 } 01049 contact.uri().remove(p_addTransport); 01050 } 01051 } 01052 01053 } 01054 } 01055 01056 // !bwc! TODO make this configurable 01057 // Fix the Referred-By header if no host specified. 01058 // If malformed, leave it alone. 01059 if (msg->exists(h_ReferredBy) 01060 && msg->const_header(h_ReferredBy).isWellFormed()) 01061 { 01062 if (msg->const_header(h_ReferredBy).uri().host().empty()) 01063 { 01064 msg->header(h_ReferredBy).uri().host() = Tuple::inet_ntop(source); 01065 msg->header(h_ReferredBy).uri().port() = transport->port(); 01066 } 01067 } 01068 01069 // !bwc! TODO make this configurable 01070 // .bwc. Only try fiddling with this is if the Record-Route is well- 01071 // formed. If the topmost Record-Route is malformed, we have no idea 01072 // whether it came from something the TU synthesized or from the wire. 01073 // We shouldn't touch it. Frankly, I take issue with the method we have 01074 // chosen to signal to the stack that we want it to fill out various 01075 // header-field-values. 01076 if (msg->exists(h_RecordRoutes) 01077 && !msg->const_header(h_RecordRoutes).empty() 01078 && msg->const_header(h_RecordRoutes).front().isWellFormed()) 01079 { 01080 const NameAddr& c_rr = msg->const_header(h_RecordRoutes).front(); 01081 NameAddr& rr = msg->header(h_RecordRoutes).front(); 01082 if (c_rr.uri().host().empty()) 01083 { 01084 rr.uri().host() = Tuple::inet_ntop(source); 01085 rr.uri().port() = transport->port(); 01086 if (target.getType() != UDP && !rr.uri().exists(p_transport)) 01087 { 01088 rr.uri().param(p_transport) = Tuple::toDataLower(target.getType()); 01089 } 01090 // Add comp=sigcomp and sigcomp-id="<urn>" to Record-Route 01091 // XXX This isn't quite right -- should be set only 01092 // on routes facing the client. Doing this correctly 01093 // requires double-record-routing 01094 if (mCompression.isEnabled()) 01095 { 01096 if (!rr.uri().exists(p_comp)) 01097 { 01098 rr.uri().param(p_comp) = "sigcomp"; 01099 } 01100 if (!rr.uri().exists(p_sigcompId)) 01101 { 01102 rr.uri().param(p_sigcompId) = mCompression.getSigcompId(); 01103 } 01104 } 01105 } 01106 } 01107 01108 // !bwc! TODO make this configurable 01109 // See draft-ietf-sip-identity 01110 if (mSecurity && msg->exists(h_Identity) && msg->const_header(h_Identity).value().empty()) 01111 { 01112 DateCategory now; 01113 msg->header(h_Date) = now; 01114 #if defined(USE_SSL) 01115 try 01116 { 01117 const Data& domain = msg->const_header(h_From).uri().host(); 01118 msg->header(h_Identity).value() = mSecurity->computeIdentity( domain, 01119 msg->getCanonicalIdentityString()); 01120 } 01121 catch (Security::Exception& e) 01122 { 01123 InfoLog (<< "Couldn't add identity header: " << e); 01124 msg->remove(h_Identity); 01125 if (msg->exists(h_IdentityInfo)) 01126 { 01127 msg->remove(h_IdentityInfo); 01128 } 01129 } 01130 #endif 01131 } 01132 01133 target.transportKey=transport->getKey(); 01134 01135 // !bwc! Deprecated. Stop doing this eventually. 01136 target.transport=transport; 01137 01138 // Call back anyone who wants to perform outbound decoration 01139 msg->callOutboundDecorators(source, target,remoteSigcompId); 01140 01141 std::auto_ptr<SendData> send(new SendData(target, 01142 resip::Data::Empty, 01143 msg->getTransactionId(), 01144 remoteSigcompId)); 01145 01146 send->data.reserve(mAvgBufferSize + mAvgBufferSize/4); 01147 01148 DataStream str(send->data); 01149 msg->encode(str); 01150 str.flush(); 01151 01152 // !bwc! Moving average of message size. (Used to intelligently 01153 // predict how much space to reserve in the buffer, to minimize 01154 // dynamic resizing.) 01155 mAvgBufferSize = (255*mAvgBufferSize + send->data.size()+128)/256; 01156 01157 assert(!send->data.empty()); 01158 DebugLog (<< "Transmitting to " << target 01159 << " tlsDomain=" << msg->getTlsDomain() 01160 << " via " << source 01161 << std::endl << std::endl << send->data.escaped() 01162 << "sigcomp id=" << remoteSigcompId); 01163 01164 if(sendData) 01165 { 01166 *sendData = *send; 01167 } 01168 01169 transport->send(send); 01170 return true; 01171 } 01172 else 01173 { 01174 InfoLog (<< "tid=" << msg->getTransactionId() << " failed to find a transport to " << target); 01175 mStateMacFifo.add(new TransportFailure(msg->getTransactionId(), transportFailureReason)); 01176 return false; 01177 } 01178 01179 } 01180 catch (Transport::Exception& ) 01181 { 01182 InfoLog (<< "tid=" << msg->getTransactionId() << " no route to target: " << target); 01183 mStateMacFifo.add(new TransportFailure(msg->getTransactionId(), TransportFailure::NoRoute)); 01184 return false; 01185 } 01186 } 01187 01188 void 01189 TransportSelector::retransmit(const SendData& data) 01190 { 01191 assert(data.destination.transportKey); 01192 Transport* transport = findTransportByDest(data.destination); 01193 01194 // !jf! The previous call to transmit may have blocked or failed (It seems to 01195 // block in windows when the network is disconnected - don't know why just 01196 // yet. 01197 01198 // !kh! 01199 // My speculation for blocking is; when network is disconnected, WinSock sets 01200 // a timer (to give up) and tries to defer reporting the error, in hope of 01201 // the network would be recovered. Before the timer fires, applications could 01202 // still select() (or the likes) their socket descriptors and find they are 01203 // writable if there is still room in buffer (per socket). If the send()s or 01204 // sendto()s made during this time period overflows the buffer, it blocks. 01205 // But I somewhat doubt this would be noticed, because block would be brief, 01206 // once the timer fires, the blocked call would return error. 01207 // Note that the block applies to both UDP and TCP sockets. 01208 // Quote from Linux man page: 01209 // When the message does not fit into the send buffer of the socket, send 01210 // normally blocks, unless the socket has been placed in non-blocking I/O 01211 // mode. In non-blocking mode it would return EAGAIN in this case. 01212 // Quote from MSDN library: 01213 // If no buffer space is available within the transport system to hold the 01214 // data to be transmitted, sendto will block unless the socket has been 01215 // placed in a nonblocking mode. 01216 01217 if(transport) 01218 { 01219 // If this is not true, it means the transport has been removed. 01220 transport->send(std::auto_ptr<SendData>(data.clone())); 01221 } 01222 } 01223 01224 void 01225 TransportSelector::closeConnection(const Tuple& peer) 01226 { 01227 Transport* t = findTransportByDest(peer); 01228 if(t) 01229 { 01230 SendData* close=new SendData(peer, 01231 resip::Data::Empty, 01232 resip::Data::Empty, 01233 resip::Data::Empty); 01234 close->command = SendData::CloseConnection; 01235 t->send(std::auto_ptr<SendData>(close)); 01236 } 01237 } 01238 01239 unsigned int 01240 TransportSelector::sumTransportFifoSizes() const 01241 { 01242 unsigned int sum = 0; 01243 01244 for (AnyPortTupleMap::const_iterator i = mAnyPortTransports.begin(); 01245 i != mAnyPortTransports.end(); ++i) 01246 { 01247 sum += i->second->getFifoSize(); 01248 } 01249 01250 for (AnyPortAnyInterfaceTupleMap::const_iterator i = mAnyPortAnyInterfaceTransports.begin(); 01251 i != mAnyPortAnyInterfaceTransports.end(); ++i) 01252 { 01253 sum += i->second->getFifoSize(); 01254 } 01255 01256 for (TlsTransportMap::const_iterator i = mTlsTransports.begin(); 01257 i != mTlsTransports.end(); ++i) 01258 { 01259 sum += i->second->getFifoSize(); 01260 } 01261 01262 return sum; 01263 } 01264 01265 void 01266 TransportSelector::terminateFlow(const resip::Tuple& flow) 01267 { 01268 closeConnection(flow); 01269 } 01270 01271 void 01272 TransportSelector::enableFlowTimer(const resip::Tuple& flow) 01273 { 01274 Transport* t = findTransportByDest(flow); 01275 if(t) 01276 { 01277 SendData* enableFlowTimer=new SendData(flow, 01278 resip::Data::Empty, 01279 resip::Data::Empty, 01280 resip::Data::Empty); 01281 enableFlowTimer->command = SendData::EnableFlowTimer; 01282 t->send(std::auto_ptr<SendData>(enableFlowTimer)); 01283 } 01284 } 01285 01286 Transport* 01287 TransportSelector::findTransportByDest(const Tuple& target) 01288 { 01289 if(target.transportKey) 01290 { 01291 if(target.transportKey <= mTransports.size()) 01292 { 01293 return mTransports[target.transportKey-1]; 01294 } 01295 } 01296 else 01297 { 01298 std::pair<TypeToTransportMap::iterator, TypeToTransportMap::iterator> range(mTypeToTransportMap.equal_range(target)); 01299 01300 if(range.first != range.second) // At least one match 01301 { 01302 TypeToTransportMap::iterator i=range.first; 01303 ++i; 01304 if(i==range.second) // Exactly one match 01305 { 01306 return range.first->second; 01307 } 01308 } 01309 } 01310 01311 // .bwc. No luck here. Maybe findTransportBySource will end up working. 01312 return 0; 01313 } 01314 01319 Transport* 01320 TransportSelector::findLoopbackTransportBySource(bool ignorePort, Tuple& search) const 01321 { 01322 //When we are sending to a loopback address, the kernel makes an 01323 //(effectively) arbitrary choice of which loopback address to send 01324 //from. (Since any loopback address can be used to send to any other 01325 //loopback address) This choice may not agree with our idea of what 01326 //address we should be sending from, so we need to just choose the 01327 //loopback address we like, and ignore what the kernel told us to do. 01328 ExactTupleMap::const_iterator i; 01329 for (i=mExactTransports.begin();i != mExactTransports.end();i++) 01330 { 01331 DebugLog(<<"search: " << search << " elem: " << i->first); 01332 if(i->first.ipVersion()==V4) 01333 { 01334 //Compare only the first byte (the 127) 01335 if(i->first.isEqualWithMask(search,8,ignorePort)) 01336 { 01337 search=i->first; 01338 DebugLog(<<"Match!"); 01339 return i->second; 01340 } 01341 } 01342 #ifdef USE_IPV6 01343 else if(i->first.ipVersion()==V6) 01344 { 01345 //What to do? 01346 } 01347 #endif 01348 else 01349 { 01350 assert(0); 01351 } 01352 } 01353 01354 return 0; 01355 } // of findLoopbackTransport 01356 01357 Transport* 01358 TransportSelector::findTransportBySource(Tuple& search, const SipMessage* msg) const 01359 { 01360 DebugLog(<< "findTransportBySource(" << search << ")"); 01361 01362 if(msg && 01363 !msg->getTlsDomain().empty() && 01364 (search.getType()==TLS || search.getType()==DTLS)) 01365 { 01366 // We should not be willing to attempt sending on a TLS/DTLS transport 01367 // that does not have the cert we're attempting to use, even if the 01368 // IP/port/proto match. If we have not specified which identity we want 01369 // to use, then proceed with the code below. 01370 return findTlsTransport(msg->getTlsDomain(),search.getType(),search.ipVersion()); 01371 } 01372 01373 bool ignorePort = (search.getPort() == 0); 01374 DebugLog(<< "should port be ignored: " << ignorePort); 01375 01376 if (!ignorePort) 01377 { 01378 // 1. search for matching port on a specific interface 01379 { 01380 ExactTupleMap::const_iterator i = mExactTransports.find(search); 01381 if (i != mExactTransports.end()) 01382 { 01383 DebugLog(<< "findTransport (exact) => " << *(i->second)); 01384 return i->second; 01385 } 01386 } 01387 01388 // 2. search for matching port on any loopback interface 01389 if (search.isLoopback()) 01390 { 01391 Transport *trans=findLoopbackTransportBySource( /*ignorePort*/false, search); 01392 if (trans) 01393 { 01394 return trans; 01395 } 01396 } 01397 01398 // 3. search for specific port on ANY interface 01399 { 01400 AnyInterfaceTupleMap::const_iterator i = mAnyInterfaceTransports.find(search); 01401 if (i != mAnyInterfaceTransports.end()) 01402 { 01403 DebugLog(<< "findTransport (any interface) => " << *(i->second)); 01404 return i->second; 01405 } 01406 } 01407 } 01408 else 01409 { 01410 // 1. search for ANY port on specific interface 01411 { 01412 AnyPortTupleMap::const_iterator i = mAnyPortTransports.find(search); 01413 if (i != mAnyPortTransports.end()) 01414 { 01415 DebugLog(<< "findTransport (any port, specific interface) => " << *(i->second)); 01416 return i->second; 01417 } 01418 } 01419 01420 // 2. search for ANY port on any loopback interface 01421 if (search.isLoopback()) 01422 { 01423 Transport *trans = findLoopbackTransportBySource( /*ignorePort*/true, search); 01424 if (trans) 01425 { 01426 return trans; 01427 } 01428 } 01429 01430 // 3. search for ANY port on ANY interface 01431 { 01432 //CerrLog(<< "Trying AnyPortAnyInterfaceTupleMap " << mAnyPortAnyInterfaceTransports.size()); 01433 AnyPortAnyInterfaceTupleMap::const_iterator i = mAnyPortAnyInterfaceTransports.find(search); 01434 if (i != mAnyPortAnyInterfaceTransports.end()) 01435 { 01436 DebugLog(<< "findTransport (any port, any interface) => " << *(i->second)); 01437 return i->second; 01438 } 01439 } 01440 } 01441 01442 DebugLog (<< "Exact interface / Specific port: " << Inserter(mExactTransports)); 01443 DebugLog (<< "Any interface / Specific port: " << Inserter(mAnyInterfaceTransports)); 01444 DebugLog (<< "Exact interface / Any port: " << Inserter(mAnyPortTransports)); 01445 DebugLog (<< "Any interface / Any port: " << Inserter(mAnyPortAnyInterfaceTransports)); 01446 01447 WarningLog(<< "Can't find matching transport " << search); 01448 return 0; 01449 } 01450 01451 01452 Transport* 01453 TransportSelector::findTlsTransport(const Data& domainname,resip::TransportType type,resip::IpVersion version) const 01454 { 01455 assert(type==TLS || type==DTLS); 01456 DebugLog (<< "Searching for " << ((type==TLS) ? "TLS" : "DTLS") << " transport for domain='" 01457 << domainname << "'" << " have " << mTlsTransports.size()); 01458 01459 if (domainname == Data::Empty) 01460 { 01461 for(TlsTransportMap::const_iterator i=mTlsTransports.begin(); 01462 i!=mTlsTransports.end();++i) 01463 { 01464 if(i->first.mType==type && i->first.mVersion==version) 01465 { 01466 DebugLog(<<"Found a default transport."); 01467 return i->second; 01468 } 01469 } 01470 } 01471 else 01472 { 01473 TlsTransportKey key(domainname,type,version); 01474 01475 TlsTransportMap::const_iterator i=mTlsTransports.find(key); 01476 01477 if(i!=mTlsTransports.end()) 01478 { 01479 DebugLog(<< "Found a transport."); 01480 return i->second; 01481 } 01482 } 01483 01484 DebugLog(<<"No transport found."); 01485 return 0; 01486 } 01487 01488 unsigned int 01489 TransportSelector::getTimeTillNextProcessMS() 01490 { 01491 return hasDataToSend() ? 0 : INT_MAX; 01492 } 01493 01494 void 01495 TransportSelector::registerMarkListener(MarkListener* listener) 01496 { 01497 mDns.getMarkManager().registerMarkListener(listener); 01498 } 01499 01500 void TransportSelector::unregisterMarkListener(MarkListener* listener) 01501 { 01502 mDns.getMarkManager().unregisterMarkListener(listener); 01503 } 01504 01505 01506 /* ==================================================================== 01507 * The Vovida Software License, Version 1.0 01508 * 01509 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 01510 * 01511 * Redistribution and use in source and binary forms, with or without 01512 * modification, are permitted provided that the following conditions 01513 * are met: 01514 * 01515 * 1. Redistributions of source code must retain the above copyright 01516 * notice, this list of conditions and the following disclaimer. 01517 * 01518 * 2. Redistributions in binary form must reproduce the above copyright 01519 * notice, this list of conditions and the following disclaimer in 01520 * the documentation and/or other materials provided with the 01521 * distribution. 01522 * 01523 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 01524 * and "Vovida Open Communication Application Library (VOCAL)" must 01525 * not be used to endorse or promote products derived from this 01526 * software without prior written permission. For written 01527 * permission, please contact vocal@vovida.org. 01528 * 01529 * 4. Products derived from this software may not be called "VOCAL", nor 01530 * may "VOCAL" appear in their name, without prior written 01531 * permission of Vovida Networks, Inc. 01532 * 01533 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 01534 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 01535 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 01536 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 01537 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 01538 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 01539 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 01540 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 01541 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 01542 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 01543 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 01544 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 01545 * DAMAGE. 01546 * 01547 * ==================================================================== 01548 * 01549 * This software consists of voluntary contributions made by Vovida 01550 * Networks, Inc. and many individuals on behalf of Vovida Networks, 01551 * Inc. For more information on Vovida Networks, Inc., please see 01552 * <http://www.vovida.org/>. 01553 * 01554 * vi: set shiftwidth=3 expandtab: 01555 */
1.7.5.1