reSIProcate/stack  9694
TransportSelector.cxx
Go to the documentation of this file.
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  */