⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transportselector.cxx

📁 这是国外的resip协议栈
💻 CXX
📖 第 1 页 / 共 3 页
字号:
#if defined(HAVE_CONFIG_H)#include "resip/stack/config.hxx"#endif#ifdef WIN32#include <winsock2.h> #include <ws2tcpip.h> #include <wspiapi.h>   // Required for freeaddrinfo implementation in Windows 2000, NT, Me/95/98#else#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netdb.h>#endif#include "resip/stack/NameAddr.hxx"#include "resip/stack/Uri.hxx"#include "resip/stack/ExtensionParameter.hxx"#include "resip/stack/Security.hxx"#include "resip/stack/Compression.hxx"#include "resip/stack/SipMessage.hxx"#include "resip/stack/TransactionState.hxx"#include "resip/stack/TransportFailure.hxx"#include "resip/stack/TransportSelector.hxx"#include "resip/stack/InternalTransport.hxx"#include "resip/stack/TcpBaseTransport.hxx"#include "resip/stack/TcpTransport.hxx"#include "resip/stack/TlsTransport.hxx"#include "resip/stack/UdpTransport.hxx"#include "resip/stack/DtlsTransport.hxx"#include "resip/stack/Uri.hxx"#include "rutil/DataStream.hxx"#include "rutil/DnsUtil.hxx"#include "rutil/Inserter.hxx"#include "rutil/Logger.hxx"#include "rutil/Socket.hxx"#include "rutil/WinLeakCheck.hxx"#include "rutil/dns/DnsStub.hxx"#ifdef USE_SIGCOMP#include <osc/Stack.h>#include <osc/SigcompMessage.h>#endif#ifdef WIN32#include "rutil/WinCompat.hxx"#endif#ifdef __MINGW32__#define gai_strerror strerror#endif#include <sys/types.h>using namespace resip;#define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORTTransportSelector::TransportSelector(Fifo<TransactionMessage>& fifo, Security* security, DnsStub& dnsStub, Compression &compression) :   mDns(dnsStub),   mStateMacFifo(fifo),   mSecurity(security),   mSocket( INVALID_SOCKET ),   mSocket6( INVALID_SOCKET ),   mCompression(compression),   mSigcompStack (0){   memset(&mUnspecified.v4Address, 0, sizeof(sockaddr_in));   mUnspecified.v4Address.sin_family = AF_UNSPEC;#ifdef USE_IPV6   memset(&mUnspecified6.v6Address, 0, sizeof(sockaddr_in6));   mUnspecified6.v6Address.sin6_family = AF_UNSPEC;#endif#ifdef USE_SIGCOMP   if (mCompression.isEnabled())   {      DebugLog (<< "Compression enabled for Transport Selector");      mSigcompStack = new osc::Stack(mCompression.getStateHandler());      mCompression.addCompressorsToStack(mSigcompStack);   }   else   {      DebugLog (<< "Compression disabled for Transport Selector");   }#else   DebugLog (<< "No compression library available");#endif}template<class T> void deleteMap(T& m){   for (typename T::iterator it = m.begin(); it != m.end(); it++)   {      delete it->second;   }   m.clear();}TransportSelector::~TransportSelector(){   mConnectionlessMap.clear();   deleteMap(mExactTransports);   deleteMap(mAnyInterfaceTransports);   deleteMap(mTlsTransports);#ifdef USE_SIGCOMP   delete mSigcompStack;#endif}voidTransportSelector::shutdown(){    //!dcm! repeat shutodwn template pattern in all loop over all tranport functions, refactor to functor?    for (ExactTupleMap::iterator i=mExactTransports.begin(); i!=mExactTransports.end(); ++i)   {      i->second->shutdown();   }   for (AnyInterfaceTupleMap::iterator i=mAnyInterfaceTransports.begin(); i!=mAnyInterfaceTransports.end(); ++i)   {      i->second->shutdown();   }}boolTransportSelector::isFinished() const{   for (ExactTupleMap::const_iterator i=mExactTransports.begin(); i!=mExactTransports.end(); ++i)   {      if (!i->second->isFinished()) return false;   }   for (AnyInterfaceTupleMap::const_iterator i=mAnyInterfaceTransports.begin(); i!=mAnyInterfaceTransports.end(); ++i)   {      if (!i->second->isFinished()) return false;   }   return true;}voidTransportSelector::addTransport(std::auto_ptr<Transport> autoTransport){   Transport* transport = autoTransport.release();   mDns.addTransportType(transport->transport(), transport->ipVersion());   // !bwc! This is a multimap from TransportType/IpVersion to Transport*.   // Make _extra_ sure that no garbage goes in here.   if(transport->transport()==TCP)   {      assert(dynamic_cast<TcpTransport*>(transport));   }   else if(transport->transport()==TLS)   {      assert(dynamic_cast<TlsTransport*>(transport));   }   else if(transport->transport()==UDP)   {      assert(dynamic_cast<UdpTransport*>(transport));   }#if USE_DTLS   else if(transport->transport()==DTLS)   {      assert(dynamic_cast<DtlsTransport*>(transport));   }#endif   else   {      assert(0);   }      Tuple tuple(transport->interfaceName(), transport->port(),                    transport->ipVersion(), transport->transport());   mTypeToTransportMap.insert(std::make_pair(tuple,transport));      switch (transport->transport())   {      case UDP:      case TCP:      {         assert(mExactTransports.find(tuple) == mExactTransports.end() &&                mAnyInterfaceTransports.find(tuple) == mAnyInterfaceTransports.end());         DebugLog (<< "Adding transport: " << tuple);                  // Store the transport in the ANY interface maps if the tuple specifies ANY         // interface. Store the transport in the specific interface maps if the tuple         // specifies an interface. See TransportSelector::findTransport.         if (transport->interfaceName().empty() ||             transport->hasSpecificContact() )         {            mAnyInterfaceTransports[tuple] = transport;            mAnyPortAnyInterfaceTransports[tuple] = transport;         }         else         {            mExactTransports[tuple] = transport;            mAnyPortTransports[tuple] = transport;         }      }      break;      case TLS:      case DTLS:      {         TlsTransportKey key(transport->tlsDomain(),transport->transport(),transport->ipVersion());         mTlsTransports[key]=transport;      }         break;      default:         assert(0);         break;   }   if(transport->transport()==UDP || transport->transport()==DTLS)   {      mConnectionlessMap[transport->getTuple().mFlowKey]=transport;   }   if (transport->shareStackProcessAndSelect())   {      mSharedProcessTransports.push_back(transport);   }   else   {      mHasOwnProcessTransports.push_back(transport);      mHasOwnProcessTransports.back()->startOwnProcessing();   }}  voidTransportSelector::buildFdSet(FdSet& fdset){   mDns.buildFdSet(fdset);   for(TransportList::iterator it = mSharedProcessTransports.begin();        it != mSharedProcessTransports.end(); it++)   {      (*it)->buildFdSet(fdset);   }}voidTransportSelector::process(FdSet& fdset){   mDns.process(fdset);   for(TransportList::iterator it = mSharedProcessTransports.begin();        it != mSharedProcessTransports.end(); it++)   {      try      {         (*it)->process(fdset);      }      catch (BaseException& e)      {         ErrLog (<< "Exception thrown from Transport::process: " << e);      }   }}boolTransportSelector::hasDataToSend() const{   for(TransportList::const_iterator it = mSharedProcessTransports.begin();       it != mSharedProcessTransports.end(); it++)   {      if ((*it)->hasDataToSend())      {         return true;      }   }   return false;}//!jf! the problem here is that DnsResult is returned after looking//mDns.lookup() but this can result in a synchronous call to handle() which//assumes that dnsresult has been assigned to the TransactionState//!dcm! -- now 2-phase to fix thisDnsResult*TransportSelector::createDnsResult(DnsHandler* handler){   return mDns.createDnsResult(handler);}voidTransportSelector::dnsResolve(DnsResult* result,                              SipMessage* msg){   // Picking the target destination:   //   - for request, use forced target if set   //     otherwise use loose routing behaviour (route or, if none, request-uri)   //   - for response, use forced target if set, otherwise look at via   if (msg->isRequest())   {      // If this is an ACK we need to fix the tid to reflect that      if (msg->hasForceTarget())      {         //DebugLog(<< "!ah! RESOLVING request with force target : " << msg->getForceTarget() );         mDns.lookup(result, msg->getForceTarget());      }      else if (msg->exists(h_Routes) && !msg->header(h_Routes).empty())      {         // put this into the target, in case the send later fails, so we don't         // lose the target         msg->setForceTarget(msg->header(h_Routes).front().uri());         DebugLog (<< "Looking up dns entries (from route) for " << msg->getForceTarget());         mDns.lookup(result, msg->getForceTarget());      }      else      {         DebugLog (<< "Looking up dns entries for " << msg->header(h_RequestLine).uri());         mDns.lookup(result, msg->header(h_RequestLine).uri());      }   }   else if (msg->isResponse())   {      ErrLog(<<"unimplemented response dns");      assert(0);   }   else   {      assert(0);   }}bool isDgramTransport (TransportType type){   static const bool unknown_transport = false;   switch(type)   {      case UDP:      case DTLS:      case DCCP:      case SCTP:         return   true;      case TCP:      case TLS:         return   false;      default:         assert(unknown_transport);         return unknown_transport;  // !kh! just to make it compile wo/warning.   }}TupleTransportSelector::getFirstInterface(bool is_v4, TransportType type){// !kh! both getaddrinfo() and IPv6 are not supported by cygwin, yet.#ifdef __CYGWIN__   assert(0);   return Tuple();#else   // !kh!   // 1. Query local hostname.   char hostname[256] = "";   if(gethostname(hostname, sizeof(hostname)) != 0)   {      int e = getErrno();      Transport::error( e );      InfoLog(<< "Can't query local hostname : [" << e << "] " << strerror(e) );      throw Transport::Exception("Can't query local hostname", __FILE__, __LINE__);   }   InfoLog(<< "Local hostname is [" << hostname << "]");   // !kh!   // 2. Resolve address(es) of local hostname for specified transport.   const bool is_dgram = isDgramTransport(type);   addrinfo hint;   memset(&hint, 0, sizeof(hint));   hint.ai_family    = is_v4 ? PF_INET : PF_INET6;   hint.ai_flags     = AI_PASSIVE;   hint.ai_socktype  = is_dgram ? SOCK_DGRAM : SOCK_STREAM;   addrinfo* results;   int ret = getaddrinfo(      hostname,      0,      &hint,      &results);   if(ret != 0)   {      Transport::error( ret ); // !kh! is this the correct sematics? ret is not errno.      InfoLog(<< "Can't resolve " << hostname << "'s address : [" << ret << "] " << gai_strerror(ret) );      throw Transport::Exception("Can't resolve hostname", __FILE__,__LINE__);   }   // !kh!   // 3. Use first address resolved if there are more than one.   // What should I do if there are more than one address?   // i.e. results->ai_next != 0.   Tuple source(*(results->ai_addr), type);   InfoLog(<< "Local address is " << source);   addrinfo* ai = results->ai_next;   for(; ai; ai = ai->ai_next)   {      Tuple addr(*(ai->ai_addr), type);      InfoLog(<<"Additional address " << addr);   }   freeaddrinfo(results);      return source;#endif}TupleTransportSelector::determineSourceInterface(SipMessage* msg, const Tuple& target) const{   assert(msg->exists(h_Vias));   assert(!msg->header(h_Vias).empty());   const Via& via = msg->header(h_Vias).front();   if (msg->isRequest() && !via.sentHost().empty())      // hint provided in sent-by of via by application   {      DebugLog( << "hint provided by app: " <<  msg->header(h_Vias).front());            return Tuple(via.sentHost(), via.sentPort(), target.ipVersion(), target.getType());   }   else   {      Tuple source(target);#if defined(WIN32) && !defined(NO_IPHLPAPI)      try      {         GenericIPAddress addr = WinCompat::determineSourceInterface(target.toGenericIPAddress());         source.setSockaddr(addr);      }      catch (WinCompat::Exception&)      {         ErrLog (<< "Can't find source interface to use");         throw Transport::Exception("Can't find source interface", __FILE__, __LINE__);      }#else      // !kh!      // The connected UDP technique doesn't work all the time.      // 1. Might not work on all implementaions as stated in UNP vol.1 8.14.      // 2. Might not work under unspecified condition on Windows,      //    search "getsockname" in MSDN library.      // 3. We've experienced this issue on our production software.            // this process will determine which interface the kernel would use to      // send a packet to the target by making a connect call on a udp socket.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -