private void NatKeepAliveChannelMessageReceived(SIPChannel sipChannel, SIPEndPoint remoteEndPoint, byte[] buffer) { try { NATKeepAliveMessage keepAliveMessage = NATKeepAliveMessage.ParseNATKeepAliveMessage(buffer); if (keepAliveMessage != null) { if (keepAliveMessage.LocalSIPEndPoint.Protocol == SIPProtocolsEnum.udp) { FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.NATKeepAlive, SIPMonitorEventTypesEnum.NATKeepAliveRelay, "Relaying NAT keep-alive from proxy socket " + keepAliveMessage.LocalSIPEndPoint + " to " + keepAliveMessage.RemoteEndPoint + ".", null)); m_sipTransport.SendRaw(keepAliveMessage.LocalSIPEndPoint, new SIPEndPoint(keepAliveMessage.RemoteEndPoint), m_sendBuffer); } else { // For connection oriented protocols check whether a connection exists. NAT keep alives shouldn't cause a connection to be initiated. SIPChannel sendFromChannel = m_sipTransport.FindSIPChannel(keepAliveMessage.LocalSIPEndPoint); if (sendFromChannel != null && sendFromChannel.IsConnectionEstablished(keepAliveMessage.RemoteEndPoint)) { FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.NATKeepAlive, SIPMonitorEventTypesEnum.NATKeepAliveRelay, "Relaying NAT keep-alive from proxy socket " + keepAliveMessage.LocalSIPEndPoint + " to " + keepAliveMessage.RemoteEndPoint + ".", null)); m_sipTransport.SendRaw(keepAliveMessage.LocalSIPEndPoint, new SIPEndPoint(keepAliveMessage.RemoteEndPoint), m_sendBuffer); } else { FireSIPMonitorLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.NATKeepAlive, SIPMonitorEventTypesEnum.NATKeepAliveRelay, "No established connection was found to relay NAT keep-alive from proxy socket " + keepAliveMessage.LocalSIPEndPoint + " to " + keepAliveMessage.RemoteEndPoint + ".", null)); } } } } catch (Exception excp) { logger.Error("Exception NatKeepAliveChannelMessageReceived. " + excp.Message); } }
/// <summary> /// Used to send a request from an internal server agent to an external SIP user agent. The difference between this method and /// the SendTransparent method is that this one will set Via headers in accordance with RFC3261. /// </summary> /// <param name="receivedOnEP">The proxy SIP end point the request was received on.</param> /// <param name="dstSocket">The SIP end point the request is being sent to.</param> /// <param name="sipRequest">The SIP request to send.</param> /// <param name="proxyBranch">The branch parameter for the top Via header that has been pre-calculated by the proxy core.</param> /// <param name="sendFromSocket">The proxy SIP end point to send this request from. If the SIP request has its ProxySendFrom header /// value set that will overrule this parameter.</param> public void SendExternal(SIPEndPoint receivedOnEP, SIPEndPoint dstSIPEndPoint, SIPRequest sipRequest, string proxyBranch, IPAddress publicIPAddress) { try { if (!IsDestinationValid(sipRequest, dstSIPEndPoint)) { logger.Debug("SendExternal failed destination check."); return; } // Determine the external SIP endpoint that the proxy will use to send this request. SIPEndPoint localSIPEndPoint = m_sipTransport.GetDefaultSIPEndPoint(dstSIPEndPoint); if (!sipRequest.Header.ProxySendFrom.IsNullOrBlank()) { SIPChannel proxyChannel = m_sipTransport.FindSIPChannel(SIPEndPoint.ParseSIPEndPoint(sipRequest.Header.ProxySendFrom)); if (proxyChannel == null) { logger.Warn("No SIP channel could be found for\n" + sipRequest.ToString()); } localSIPEndPoint = (proxyChannel != null) ? proxyChannel.SIPChannelEndPoint : localSIPEndPoint; } if (receivedOnEP != localSIPEndPoint) { // The proxy is being requested to send the request on a different socket to the one it was received on. // A second Via header is added to ensure the response can navigate back the same path. The calculated branch // parameter needs to go on the top Via header so that whichever internal socket the request is being sent to can // determine re-transmits. SIPViaHeader via = new SIPViaHeader(receivedOnEP, CallProperties.CreateBranchId()); sipRequest.Header.Vias.PushViaHeader(via); SIPViaHeader externalVia = new SIPViaHeader(localSIPEndPoint, proxyBranch); sipRequest.Header.Vias.PushViaHeader(externalVia); } else { // Only a single Via header is required as any response to this request will be sent from the same socket it gets received on. SIPViaHeader via = new SIPViaHeader(localSIPEndPoint, proxyBranch); sipRequest.Header.Vias.PushViaHeader(via); } if (sipRequest.Method != SIPMethodsEnum.REGISTER) { AdjustContactHeader(sipRequest.Header, localSIPEndPoint, publicIPAddress); } sipRequest.LocalSIPEndPoint = localSIPEndPoint; // 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; m_sipTransport.SendRequest(dstSIPEndPoint, sipRequest); } catch (Exception excp) { logger.Error("Exception SIPRequest SendExternal. " + excp.Message); logger.Error(sipRequest.ToString()); throw; } }