/// <summary> /// Forwards a SIP request through the Proxy. This method differs from the standard Send in that irrespective of whether the Proxy is /// receiving and sending on different sockets only a single Via header will ever be allowed on the request. It is then up to the /// response processing logic to determine from which Proxy socket to forward the request and to add back on the Via header for the /// end agent. This method is only ever used for requests destined for EXTERNAL SIP end points. /// </summary> /// <param name="dstSIPEndPoint">The destination SIP socket to send the request to.</param> /// <param name="sipRequest">The SIP request to send.</param> /// default channel that matches the destination end point should be used.</param> public void SendTransparent(SIPEndPoint dstSIPEndPoint, SIPRequest sipRequest, IPAddress publicIPAddress) { try { if (!IsDestinationValid(sipRequest, dstSIPEndPoint)) { logger.Debug("SendTransparent failed destination check."); return; } // Determine the external SIP endpoint that the proxy will use to send this request. SIPEndPoint localSIPEndPoint = null; if (!sipRequest.Header.ProxySendFrom.IsNullOrBlank()) { SIPChannel proxyChannel = m_sipTransport.FindSIPChannel(SIPEndPoint.ParseSIPEndPoint(sipRequest.Header.ProxySendFrom)); localSIPEndPoint = (proxyChannel != null) ? proxyChannel.SIPChannelEndPoint : null; } localSIPEndPoint = localSIPEndPoint ?? m_sipTransport.GetDefaultSIPEndPoint(dstSIPEndPoint); // Create the single Via header for the outgoing request. It uses the passed in branchid which has been taken from the // request that's being forwarded. If this proxy is behind a NAT and the public IP is known that's also set on the Via. string proxyBranch = sipRequest.Header.Vias.PopTopViaHeader().Branch; sipRequest.Header.Vias = new SIPViaSet(); SIPViaHeader via = new SIPViaHeader(localSIPEndPoint, proxyBranch); if (publicIPAddress != null) { via.Host = publicIPAddress.ToString(); } sipRequest.Header.Vias.PushViaHeader(via); if (sipRequest.Method != SIPMethodsEnum.REGISTER) { AdjustContactHeader(sipRequest.Header, localSIPEndPoint, publicIPAddress); } // If dispatcher is being used record the transaction so responses are sent to the correct internal socket. if (m_dispatcher != null && sipRequest.Method != SIPMethodsEnum.REGISTER && sipRequest.Method != SIPMethodsEnum.ACK && sipRequest.Method != SIPMethodsEnum.NOTIFY) { //Log("RecordDispatch for " + sipRequest.Method + " " + sipRequest.URI.ToString() + " to " + sipRequest.RemoteSIPEndPoint.ToString() + "."); m_dispatcher.RecordDispatch(sipRequest, sipRequest.RemoteSIPEndPoint); } // Proxy sepecific headers that don't need to be seen by external UAs. sipRequest.Header.ProxyReceivedOn = null; sipRequest.Header.ProxyReceivedFrom = null; sipRequest.Header.ProxySendFrom = null; sipRequest.LocalSIPEndPoint = localSIPEndPoint; m_sipTransport.SendRequest(dstSIPEndPoint, sipRequest); } catch (Exception excp) { logger.Error("Exception SendTransparent. " + excp.Message); logger.Error(sipRequest.ToString()); throw; } }