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

📄 transportselector.cxx

📁 这是国外的resip协议栈
💻 CXX
📖 第 1 页 / 共 3 页
字号:
      Socket tmp = INVALID_SOCKET;      if (target.isV4())      {         if (mSocket == INVALID_SOCKET)         {            mSocket = InternalTransport::socket(UDP, V4); // may throw         }         tmp = mSocket;      }      else      {         if (mSocket6 == INVALID_SOCKET)         {            mSocket6 = InternalTransport::socket(UDP, V6); // may throw         }         tmp = mSocket6;      }      int ret = connect(tmp,&target.getSockaddr(), target.length());      if (ret < 0)      {         int e = getErrno();         Transport::error( e );         InfoLog(<< "Unable to route to " << target << " : [" << e << "] " << strerror(e) );         throw Transport::Exception("Can't find source address for Via", __FILE__,__LINE__);      }      socklen_t len = source.length();      ret = getsockname(tmp,&source.getMutableSockaddr(), &len);      if (ret < 0)      {         int e = getErrno();         Transport::error(e);         InfoLog(<< "Can't determine name of socket " << target << " : " << strerror(e) );         throw Transport::Exception("Can't find source address for Via", __FILE__,__LINE__);      }      // !kh! test if connected UDP technique results INADDR_ANY, i.e. 0.0.0.0.      // if it does, assume the first avaiable interface.      if(source.isV4())      {         long src = (reinterpret_cast<const sockaddr_in*>(&source.getSockaddr())->sin_addr.s_addr);         if(src == INADDR_ANY)         {            InfoLog(<< "Connected UDP failed to determine source address, use first address instaed.");            source = getFirstInterface(true, target.getType());         }      }      else  // IPv6      {//should never reach here in WIN32 w/ V6 support#if defined(USE_IPV6) && !defined(WIN32)          if (source.isAnyInterface())  //!dcm! -- when could this happen?         {            source = getFirstInterface(false, target.getType());         }# endif      }      // Unconnect.      // !jf! This is necessary, but I am not sure what we can do if this      // fails. I'm not sure the stack can recover from this error condition.      if (target.isV4())      {         ret = connect(mSocket,                       (struct sockaddr*)&mUnspecified.v4Address,                       sizeof(mUnspecified.v4Address));      }#ifdef USE_IPV6      else      {         ret = connect(mSocket6,                       (struct sockaddr*)&mUnspecified6.v6Address,                       sizeof(mUnspecified6.v6Address));      }#else      else      {         assert(0);      }#endif      if ( ret<0 )      {         int e =  getErrno();         //.dcm. OS X 10.5 workaround, we could #ifdef for specific OS X version.         if  (!(e ==EAFNOSUPPORT || e == EADDRNOTAVAIL))         {            ErrLog(<< "Can't disconnect socket :  " << strerror(e) );            Transport::error(e);            throw Transport::Exception("Can't disconnect socket", __FILE__,__LINE__);         }      }#endif            // This is the port that the request will get sent out from. By default,       // this value will be 0, since the Helper that creates the request will not      // assign it. In this case, the stack will pick an arbitrary (but appropriate)      // transport. If it is non-zero, it will only match transports that are bound to      // the specified port (and fail if none are available)      if(msg->isRequest())      {         source.setPort(via.sentPort());      }      else      {         source.setPort(0);      }       DebugLog (<< "Looked up source for destination: " << target                << " -> " << source                << " sent-by=" << via.sentHost()                << " sent-port=" << via.sentPort());            return source;   }}// !jf! there may be an extra copy of a tuple here. can probably get rid of it// but there are some const issues.voidTransportSelector::transmit(SipMessage* msg, Tuple& target){   assert(msg);   try   {      // !ah! You NEED to do this for responses too -- the transport doesn't      // !ah! know it's IP addres(es) in all cases, AND it's function of the dest.      // (imagine a synthetic message...)      Tuple source;      // .bwc. We need 3 things here:      // 1) A Transport* to call send() on.      // 2) A complete Tuple to pass in this call (target).      // 3) A host, port, and protocol for filling out the topmost via, and      //    possibly stuff like Contact, Referred-By, and other headers that      //    must specify a hostname that the TU was unable to supply, because      //    it didn't know what interface/port the message would be sent on.      //    (source)      /*         Our Transport* might be found in target. If so, we can skip this block         of stuff.         Alternatively, we might not have the transport to start with. However,         given a connection id, we will be able to find the Connection we         should use, we can get the Transport we want. If we have no connection         id, but we know we are using TLS or DTLS and have a tls hostname, we         can use the hostname to find the appropriate transport. If all else         fails, we must resort to the connected UDP trick to fill out source,         which in turn is used to look up a matching transport.         Given the transport, it is always possible to get the port/protocol,          and usually possible to get the host (if it is bound to INADDR_ANY, we         can't tell). However, if we had to fill out source in order to find          the transport in the first place, this is not an issue.      */      Data remoteSigcompId;      if (msg->isRequest())      {         Transport* transport=0;         transport = findTransportByDest(msg,target);                  if(!transport && target.mFlowKey && target.onlyUseExistingConnection)         {            // .bwc. Connection info was specified, and use of this connection             // was mandatory, but connection is no longer around. We fail.         }         else if (transport)// .bwc. Here we use transport to find source.         {            source = transport->getTuple();            // .bwc. If the transport has an ambiguous interface, we need to            //look a little closer.            if(source.isAnyInterface())            {               Tuple temp = determineSourceInterface(msg,target);               // .bwc. determineSourceInterface() can give us a port, if the TU               // put one in the topmost Via.               assert(source.ipVersion()==temp.ipVersion() &&                        source.getType()==temp.getType());               source=temp;               /* determineSourceInterface might return an arbitrary port                   here, so use the port specified in target.transport->port().               */               if(source.getPort()==0)               {                  source.setPort(transport->port());               }            }         }         // .bwc. Here we use source to find transport.         else         {            source = determineSourceInterface(msg, target);            transport = findTransportBySource(source);                        // .bwc. determineSourceInterface might give us a port            if(transport && source.getPort()==0)            {               source.setPort(transport->port());            }         }                           target.transport=transport;                  // .bwc. Topmost Via is only filled out in the request case. Also, if         // we don't have a transport at this point, we're going to fail,         // so don't bother doing the work.         if(target.transport)         {            Via& topVia(msg->header(h_Vias).front());            topVia.remove(p_maddr); // !jf! why do this?            // insert the via            if (topVia.transport().empty())            {               topVia.transport() = Tuple::toData(source.getType());            }            if (!topVia.sentHost().size())            {               msg->header(h_Vias).front().sentHost() = Tuple::inet_ntop(source);            }            if (!topVia.sentPort())            {               msg->header(h_Vias).front().sentPort() = source.getPort();            }            if (mCompression.isEnabled())            {               // Indicate support for SigComp, if appropriate.               if (!topVia.exists(p_comp))               {                  topVia.param(p_comp) = "sigcomp";               }               if (!topVia.exists(p_sigcompId))               {                  topVia.param(p_sigcompId) = mCompression.getSigcompId();               }               // Figure out remote identifier (from Route header               // field, if present; otherwise, from Request-URI).               // XXX rohc-sip-sigcomp-03 says to use +sip.instance,               // but this is impossible to actually do if you're               // not actually the registrar, and really hard even               // if you are.               Uri& destination(*reinterpret_cast<Uri*>(0));               if(msg->exists(h_Routes) &&                   !msg->header(h_Routes).empty())               {                  destination = msg->header(h_Routes).front().uri();               }               else               {                  destination = msg->header(h_RequestLine).uri();               }               if (destination.exists(p_comp) &&                   destination.param(p_comp) == "sigcomp")               {                  if (destination.exists(p_sigcompId))                  {                      remoteSigcompId = destination.param(p_sigcompId);                  }                  else                  {                      remoteSigcompId = destination.host();                  }               }               // Squirrel the compartment away in the branch so that               // we can figure out (pre-transaction-matching) what               // compartment incoming requests are associated with.               topVia.param(p_branch).setSigcompCompartment(remoteSigcompId);            }         }               }      else if (msg->isResponse())      {         // We assume that all stray responses have been discarded, so we always         // know the transport that the corresponding request was received on         // and this has been copied by TransactionState::sendToWire into target.transport         assert(target.transport);                  source = target.transport->getTuple();         // .bwc. If the transport has an ambiguous interface, we need to         //look a little closer.         if(source.isAnyInterface())         {            Tuple temp = source;            source = determineSourceInterface(msg,target);            assert(source.ipVersion()==temp.ipVersion() &&                     source.getType()==temp.getType());            /* determineSourceInterface might return an arbitrary port here,               so use the port specified in target.transport->port().            */            if(source.getPort()==0)            {               source.setPort(target.transport->port());            }         }         if (mCompression.isEnabled())         {            // Figure out remote identifier (from Via header field).            Via& topVia(msg->header(h_Vias).front());            if(topVia.exists(p_comp) &&               topVia.param(p_comp) == "sigcomp")            {               if (topVia.exists(p_sigcompId))               {                   remoteSigcompId = topVia.param(p_sigcompId);               }               else               {                   // XXX rohc-sigcomp-sip-03 says "sent-by",                   // but this should probably be "received" if present,                   // and "sent-by" otherwise.                   // XXX Also, the spec is ambiguous about whether                   // to include the port in this identifier.                   remoteSigcompId = topVia.sentHost();               }            }         }      }      else      {         assert(0);      }      // .bwc. At this point, source, target.transport, and target should be      // _fully_ specified.      if (target.transport)      {         // !bwc! TODO This filling in of stuff really should be handled with         // the callOutboundDecorators() callback. (Or, at the very least,         // we should allow this code to be turned off through configuration.         // There are plenty of cases where this stuff is not at all necessary.)         // There is a contact header and it contains exactly one entry         if (msg->exists(h_Contacts) && msg->header(h_Contacts).size()==1)         {            for (NameAddrs::iterator i=msg->header(h_Contacts).begin(); i != msg->header(h_Contacts).end(); i++)            {               NameAddr& contact = *i;               // No host specified, so use the ip address and port of the               // transport used. Otherwise, leave it as is.               if (contact.uri().host().empty())               {                  contact.uri().host() = (target.transport->hasSpecificContact() ?                                           target.transport->interfaceName() :                                           Tuple::inet_ntop(source) );                  contact.uri().port() = target.transport->port();                  if (target.transport->transport() != UDP)                  {                     contact.uri().param(p_transport) = Tuple::toData(target.transport->transport());                  }                  // Add comp=sigcomp to contact URI                  // Also, If no +sip.instance on contact HEADER,                  // add sigcomp-id="<urn>" to contact URI.                  if (mCompression.isEnabled())                  {                     if (!contact.uri().exists(p_comp))                     {                        contact.uri().param(p_comp) = "sigcomp";                     }                     if (!contact.exists(p_Instance) &&                         !contact.uri().exists(p_sigcompId))                     {                        contact.uri().param(p_sigcompId)                           = mCompression.getSigcompId();                     }                  }               }                else               {                  if (contact.uri().exists(p_addTransport))                  {                     if (target.getType() != UDP)                     {                        contact.uri().param(p_transport) = Tuple::toData(target.getType());                     }                     contact.uri().remove(p_addTransport);                  }               }            }         }         // Fix the Referred-By header if no host specified.         // If malformed, leave it alone.         if (msg->exists(h_ReferredBy)                && msg->header(h_ReferredBy).isWellFormed())         {            if (msg->header(h_ReferredBy).uri().host().empty())            {               msg->header(h_ReferredBy).uri().host() = Tuple::inet_ntop(source);               msg->header(h_ReferredBy).uri().port() = target.transport->port();            }         }         // .bwc. Only try fiddling with this is if the Record-Route is well-         // formed. If the topmost Record-Route is malformed, we have no idea         // whether it came from something the TU synthesized or from the wire.         // We shouldn't touch it. Frankly, I take issue with the method we have         // chosen to signal to the stack that we want it to fill out various         // header-field-values.          if (msg->exists(h_RecordRoutes)                && !msg->header(h_RecordRoutes).empty()                && msg->header(h_RecordRoutes).front().isWellFormed())         {            NameAddr& rr = msg->header(h_RecordRoutes).front();            if (rr.uri().host().empty())            {               rr.uri().host() = Tuple::inet_ntop(source);               rr.uri().port() = target.transport->port();               if (target.getType() != UDP && !rr.uri().exists(p_transport))               {                  rr.uri().param(p_transport) = Tuple::toData(target.getType());               }               // Add comp=sigcomp and sigcomp-id="<urn>" to Record-Route               // XXX This isn't quite right -- should be set only               // on routes facing the client. Doing this correctly               // requires double-record-routing               if (mCompression.isEnabled())               {                  if (!rr.uri().exists(p_comp))                  {                     rr.uri().param(p_comp) = "sigcomp";                  }                  if (!rr.uri().exists(p_sigcompId))                  {                     rr.uri().param(p_sigcompId) = mCompression.getSigcompId();                  }               }            }         }

⌨️ 快捷键说明

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