📄 transportselector.cxx
字号:
#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 + -