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

📄 transportselector.cxx

📁 一个著名的SIP协议栈
💻 CXX
📖 第 1 页 / 共 4 页
字号:
#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/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::TRANSPORT

TransportSelector::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()
{
   deleteMap(mExactTransports);
   deleteMap(mAnyInterfaceTransports);
   deleteMap(mV4TlsTransports);
   deleteMap(mV4DtlsTransports);
#ifdef USE_IPV6
   deleteMap(mV6TlsTransports);
   deleteMap(mV6DtlsTransports);
#endif
#ifdef USE_SIGCOMP
   delete mSigcompStack;
#endif
}

void
TransportSelector::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();
   }
}

bool
TransportSelector::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;
}


void
TransportSelector::addTransport( std::auto_ptr<Transport> tAuto)
{
   Transport* transport = tAuto.release();   
   mDns.addTransportType(transport->transport(), transport->ipVersion());
   switch (transport->transport())
   {
      case UDP:
      case TCP:
      {
         Tuple key(transport->interfaceName(), transport->port(), 
                   transport->ipVersion(), transport->transport());
         
         assert(mExactTransports.find(key) == mExactTransports.end() &&
                mAnyInterfaceTransports.find(key) == mAnyInterfaceTransports.end());

         DebugLog (<< "Adding transport: " << key);

         // 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[key] = transport;
            mAnyPortAnyInterfaceTransports[key] = transport;
         }
         else
         {
            mExactTransports[key] = transport;
            mAnyPortTransports[key] = transport;
         }
      }
      break;
      case TLS:
      {
         if(transport->ipVersion()==V4)
         {
            mV4TlsTransports[transport->tlsDomain()] = transport;
         }
         else if(transport->ipVersion()==V6)
         {
#ifdef USE_IPV6
            mV6TlsTransports[transport->tlsDomain()] = transport;
#endif
         }
         else
         {
            assert(0);
         }
      }
      break;
#ifdef USE_DTLS
      case DTLS:
      {
         if(transport->ipVersion()==V4)
         {
            mV4DtlsTransports[transport->tlsDomain()] = transport;
         }
         else if(transport->ipVersion()==V6)
         {
#ifdef USE_IPV6
            mV6DtlsTransports[transport->tlsDomain()] = transport;
#endif
         }
         else
         {
            assert(0);
         }
      }
      break;
#endif
      default:
         assert(0);
         break;
   }

   if (transport->shareStackProcessAndSelect())
   {
      mSharedProcessTransports.push_back(transport);
   }
   else
   {
      mHasOwnProcessTransports.push_back(transport);
      transport->startOwnProcessing();
   }
}
  
void
TransportSelector::buildFdSet(FdSet& fdset)
{
   mDns.buildFdSet(fdset);
   for(TransportList::iterator it = mSharedProcessTransports.begin(); 
       it != mSharedProcessTransports.end(); it++)
   {
      (*it)->buildFdSet(fdset);
   }
}

void
TransportSelector::process(FdSet& fdset)
{
   mDns.process(fdset);
   for(TransportList::iterator it = mSharedProcessTransports.begin(); 
       it != mSharedProcessTransports.end(); it++)
   {
      try
      {
         (*it)->process(fdset);
      }
      catch (BaseException& e)
      {
         InfoLog (<< "Exception thrown from Transport::process: " << e);
      }
   }
}

bool
TransportSelector::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 this
DnsResult*
TransportSelector::createDnsResult(DnsHandler* handler)
{
   return mDns.createDnsResult(handler);
}

void
TransportSelector::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.
   }
}

Tuple
TransportSelector::getFirstInterface(bool is_v4, TransportType type)
{
// !kh! both getaddrinfo() and IPv6 are not supported by cygwin, yet.
#ifdef __CYGWIN__
   assert(0);
   return Tuple();
#else

⌨️ 快捷键说明

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