📄 transportselector.cxx
字号:
// See draft-ietf-sip-identity if (mSecurity && msg->exists(h_Identity) && msg->header(h_Identity).value().empty()) { DateCategory now; msg->header(h_Date) = now;#if defined(USE_SSL) try { const Data& domain = msg->header(h_From).uri().host(); msg->header(h_Identity).value() = mSecurity->computeIdentity( domain, msg->getCanonicalIdentityString()); } catch (Security::Exception& e) { InfoLog (<< "Couldn't add identity header: " << e); msg->remove(h_Identity); if (msg->exists(h_IdentityInfo)) { msg->remove(h_IdentityInfo); } }#endif } // Call back anyone who wants to perform outbound decoration msg->callOutboundDecorators(source, target); Data& encoded = msg->getEncoded(); encoded.clear(); DataStream encodeStream(encoded); msg->encode(encodeStream); encodeStream.flush(); msg->getCompartmentId() = remoteSigcompId; assert(!msg->getEncoded().empty()); DebugLog (<< "Transmitting to " << target << " tlsDomain=" << msg->getTlsDomain() << " via " << source << std::endl << std::endl << encoded.escaped()); target.transport->send(target, encoded, msg->getTransactionId(), remoteSigcompId); } else { InfoLog (<< "tid=" << msg->getTransactionId() << " failed to find a transport to " << target); mStateMacFifo.add(new TransportFailure(msg->getTransactionId(), TransportFailure::NoTransport)); } } catch (Transport::Exception& ) { InfoLog (<< "tid=" << msg->getTransactionId() << " no route to target: " << target); mStateMacFifo.add(new TransportFailure(msg->getTransactionId(), TransportFailure::NoRoute)); return; }}voidTransportSelector::retransmit(SipMessage* msg, Tuple& target){ assert(target.transport); // !jf! The previous call to transmit may have blocked or failed (It seems to // block in windows when the network is disconnected - don't know why just // yet. // !kh! // My speculation for blocking is; when network is disconnected, WinSock sets // a timer (to give up) and tries to defer reporting the error, in hope of // the network would be recovered. Before the timer fires, applications could // still select() (or the likes) their socket descriptors and find they are // writable if there is still room in buffer (per socket). If the send()s or // sendto()s made during this time period overflows the buffer, it blocks. // But I somewhat doubt this would be noticed, because block would be brief, // once the timer fires, the blocked call would return error. // Note that the block applies to both UDP and TCP sockets. // Quote from Linux man page: // When the message does not fit into the send buffer of the socket, send // normally blocks, unless the socket has been placed in non-blocking I/O // mode. In non-blocking mode it would return EAGAIN in this case. // Quote from MSDN library: // If no buffer space is available within the transport system to hold the // data to be transmitted, sendto will block unless the socket has been // placed in a nonblocking mode. if(!msg->getEncoded().empty()) { //DebugLog(<<"!ah! retransmit to " << target); target.transport->send(target, msg->getEncoded(), msg->getTransactionId(), msg->getCompartmentId()); }}unsigned intTransportSelector::sumTransportFifoSizes() const{ unsigned int sum = 0; for (AnyPortTupleMap::const_iterator i = mAnyPortTransports.begin(); i != mAnyPortTransports.end(); ++i) { sum += i->second->getFifoSize(); } for (AnyPortAnyInterfaceTupleMap::const_iterator i = mAnyPortAnyInterfaceTransports.begin(); i != mAnyPortAnyInterfaceTransports.end(); ++i) { sum += i->second->getFifoSize(); } for (TlsTransportMap::const_iterator i = mTlsTransports.begin(); i != mTlsTransports.end(); ++i) { sum += i->second->getFifoSize(); } return sum;}boolTransportSelector::connectionAlive(const Tuple& target) const{ return (findConnection(target)!=0);}const Connection*TransportSelector::findConnection(const Tuple& target) const{ // !bwc! If we can find a match in the ConnectionManager, we can // determine what Transport this needs to be sent on. This may also let // us know immediately what our source needs to be. if(target.getType()==TCP || target.getType()==TLS) { TcpBaseTransport* tcpb=0; Connection* conn=0; TypeToTransportMap::const_iterator i; TypeToTransportMap::const_iterator l=mTypeToTransportMap.lower_bound(target); TypeToTransportMap::const_iterator u=mTypeToTransportMap.upper_bound(target); for(i=l;i!=u;++i) { tcpb=static_cast<TcpBaseTransport*>(i->second); conn = tcpb->getConnectionManager().findConnection(target); if(conn) { return conn; } } } return 0;}Transport*TransportSelector::findTransportByDest(SipMessage* msg, Tuple& target){ if(!target.transport) { if(target.getType()==UDP || target.getType()==DTLS) { if(target.mFlowKey) { std::map<FlowKey,Transport*>::iterator i=mConnectionlessMap.find(target.mFlowKey); if(i!=mConnectionlessMap.end()) { return i->second; } } } else if(target.getType()==TCP || target.getType()==TLS) { // .bwc. We might find a match by the cid, or maybe using the // tuple itself. const Connection* conn = findConnection(target); if(conn) // .bwc. Woohoo! Home free! { return conn->transport(); } else if(target.onlyUseExistingConnection) { // .bwc. Connection no longer exists, so we fail. return 0; } } // !bwc! No luck finding with a FlowKey. if(target.getType()==TLS || target.getType()==DTLS) { return findTlsTransport(msg->getTlsDomain(),target.getType(),target.ipVersion()); } } else // .bwc. Easy as pie. { return target.transport; } // .bwc. No luck here. Maybe findTransportBySource will end up working. return 0; }Transport*TransportSelector::findTransportBySource(Tuple& search){ DebugLog(<< "findTransportBySource(" << search << ")"); if (search.getPort() != 0) { //0. When we are sending to a loopback address, the kernel makes an //(effectively) arbitrary choice of which loopback address to send //from. (Since any loopback address can be used to send to any other //loopback address) This choice may not agree with our idea of what //address we should be sending from, so we need to just choose the //loopback address we like, and ignore what the kernel told us to do. if( search.isLoopback() ) { ExactTupleMap::const_iterator i; for (i=mExactTransports.begin();i != mExactTransports.end();i++) { DebugLog(<<"search: " << search << " elem: " << i->first); if(i->first.ipVersion()==V4) { //Compare only the first byte (the 127) if(i->first.isEqualWithMask(search,8,false)) { search=i->first; DebugLog(<<"Match!"); return i->second; } }#ifdef USE_IPV6 else if(i->first.ipVersion()==V6) { //What to do? }#endif else { assert(0); } } } // 1. search for matching port on a specific interface { ExactTupleMap::const_iterator i = mExactTransports.find(search); if (i != mExactTransports.end()) { DebugLog(<< "findTransport (exact) => " << *(i->second)); return i->second; } } // 2. search for specific port on ANY interface { AnyInterfaceTupleMap::const_iterator i = mAnyInterfaceTransports.find(search); if (i != mAnyInterfaceTransports.end()) { DebugLog(<< "findTransport (any interface) => " << *(i->second)); return i->second; } } } else { //0. When we are sending to a loopback address, the kernel makes an //(effectively) arbitrary choice of which loopback address to send //from. (Since any loopback address can be used to send to any other //loopback address) This choice may not agree with our idea of what //address we should be sending from, so we need to just choose the //loopback address we like, and ignore what the kernel told us to do. if( search.isLoopback() ) { ExactTupleMap::const_iterator i; for (i=mExactTransports.begin();i != mExactTransports.end();i++) { DebugLog(<<"search: " << search << " elem: " << i->first); if(i->first.ipVersion()==V4) { //Compare only the first byte (the 127) if(i->first.isEqualWithMask(search,8,true)) { search=i->first; DebugLog(<<"Match!"); return i->second; } }#ifdef USE_IPV6 else if(i->first.ipVersion()==V6) { //What to do? }#endif else { assert(0); } } } // 1. search for ANY port on specific interface { AnyPortTupleMap::const_iterator i = mAnyPortTransports.find(search); if (i != mAnyPortTransports.end()) { DebugLog(<< "findTransport (any port, specific interface) => " << *(i->second)); return i->second; } } // 2. search for ANY port on ANY interface { //CerrLog(<< "Trying AnyPortAnyInterfaceTupleMap " << mAnyPortAnyInterfaceTransports.size()); AnyPortAnyInterfaceTupleMap::const_iterator i = mAnyPortAnyInterfaceTransports.find(search); if (i != mAnyPortAnyInterfaceTransports.end()) { DebugLog(<< "findTransport (any port, any interface) => " << *(i->second)); return i->second; } } } DebugLog (<< "Exact interface / Specific port: " << Inserter(mExactTransports)); DebugLog (<< "Any interface / Specific port: " << Inserter(mAnyInterfaceTransports)); DebugLog (<< "Exact interface / Any port: " << Inserter(mAnyPortTransports)); DebugLog (<< "Any interface / Any port: " << Inserter(mAnyPortAnyInterfaceTransports)); WarningLog(<< "Can't find matching transport " << search); return 0;}Transport*TransportSelector::findTlsTransport(const Data& domainname,resip::TransportType type,resip::IpVersion version){ assert(type==TLS || type==DTLS); DebugLog (<< "Searching for" << ((type==TLS) ? "TLS" : "DTLS") << "transport for domain='" << domainname << "'" << " have " << mTlsTransports.size()); if (domainname == Data::Empty) { for(TlsTransportMap::iterator i=mTlsTransports.begin(); i!=mTlsTransports.end();++i) { if(i->first.mType==type && i->first.mVersion==version) { DebugLog(<<"Found a default transport."); return i->second; } } } else { TlsTransportKey key(domainname,type,version); TlsTransportMap::iterator i=mTlsTransports.find(key); if(i!=mTlsTransports.end()) { DebugLog(<< "Found a transport."); return i->second; } } DebugLog(<<"No transport found."); return 0;}unsigned int TransportSelector::getTimeTillNextProcessMS(){ if (mDns.requiresProcess()) { return 50; } else { return INT_MAX; }}voidTransportSelector::registerMarkListener(MarkListener* listener){ mDns.getMarkManager().registerMarkListener(listener);}void TransportSelector::unregisterMarkListener(MarkListener* listener){ mDns.getMarkManager().unregisterMarkListener(listener);}/* ==================================================================== * The Vovida Software License, Version 1.0 * * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The names "VOCAL", "Vovida Open Communication Application Library", * and "Vovida Open Communication Application Library (VOCAL)" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact vocal@vovida.org. * * 4. Products derived from this software may not be called "VOCAL", nor * may "VOCAL" appear in their name, without prior written * permission of Vovida Networks, Inc. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * ==================================================================== * * This software consists of voluntary contributions made by Vovida * Networks, Inc. and many individuals on behalf of Vovida Networks, * Inc. For more information on Vovida Networks, Inc., please see * <http://www.vovida.org/>. * */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -