/// <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; } }
/// <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; } }
/// <summary> /// Used to send a SIP request received from an external user agent to an internal SIP server agent. /// </summary> /// <param name="receivedFromEP">The SIP end point the proxy received the request from.</param> /// <param name="receivedOnEP">The SIP end point the proxy received the request on.</param> /// <param name="dstSocket">The internal socket to send the request to.</param> /// <param name="sipRequest">The SIP request to send.</param> /// <param name="proxyBranch">The branch to set on the Via header when sending the request. The branch should be calculated /// by the proxy core so that looped requests can be detected.</param> /// <param name="sendFromSocket">The proxy socket to send the request from.</param> public void SendInternal(SIPEndPoint receivedFromEP, SIPEndPoint receivedOnEP, string dstSocket, SIPRequest sipRequest, string proxyBranch, string sendFromSocket) { try { if (!IsDestinationValid(sipRequest, dstSocket)) { logger.Debug("SendInternal failed destination check."); return; } sipRequest.Header.ProxyReceivedFrom = receivedFromEP.ToString(); sipRequest.Header.ProxyReceivedOn = receivedOnEP.ToString(); SIPEndPoint dstSIPEndPoint = SIPEndPoint.ParseSIPEndPoint(dstSocket); SIPEndPoint localSIPEndPoint = SIPEndPoint.ParseSIPEndPoint(sendFromSocket); 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 topVia = new SIPViaHeader(localSIPEndPoint, proxyBranch); sipRequest.Header.Vias.PushViaHeader(topVia); } 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); } sipRequest.LocalSIPEndPoint = localSIPEndPoint; m_sipTransport.SendRequest(dstSIPEndPoint, sipRequest); } catch (Exception excp) { logger.Error("Exception SIPRequest SendInternal. " + excp.Message); logger.Error(sipRequest.ToString()); throw; } }
private void SIPTransportRequestReceived(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) { if (sipRequest.Method == SIPMethodsEnum.BYE) { if (m_uac != null && m_uac.SIPDialogue != null && sipRequest.Header.CallId == m_uac.SIPDialogue.CallId) { // Call has been hungup by remote end. AppendTraceMessage("Call hungup by server: " + localSIPEndPoint + "<-" + remoteEndPoint + " " + sipRequest.URI.ToString() + ".\n"); AppendSIPTraceMessage("Request Received " + localSIPEndPoint + "<-" + remoteEndPoint + "\n" + sipRequest.ToString()); m_uac.SIPDialogue.Hangup(m_sipTransport, null); ResetToCallStartState(); } else if (m_uas != null && m_uas.SIPDialogue != null && sipRequest.Header.CallId == m_uas.SIPDialogue.CallId) { // Call has been hungup by remote end. AppendTraceMessage("Call hungup by client: " + localSIPEndPoint + "<-" + remoteEndPoint + " " + sipRequest.URI.ToString() + ".\n"); AppendSIPTraceMessage("Request Received " + localSIPEndPoint + "<-" + remoteEndPoint + "\n" + sipRequest.ToString()); m_uas.SIPDialogue.Hangup(m_sipTransport, null); ResetToCallStartState(); } else { AppendTraceMessage("Unmatched BYE request received for " + sipRequest.URI.ToString() + ".\n"); SIPResponse noCallLegResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.CallLegTransactionDoesNotExist, null); m_sipTransport.SendResponse(noCallLegResponse); } } else if (sipRequest.Method == SIPMethodsEnum.INVITE) { ResetToCallStartState(); ClearTraces(); AppendTraceMessage("Incoming call request: " + localSIPEndPoint + "<-" + remoteEndPoint + " " + sipRequest.URI.ToString() + ".\n"); SetVisibility(m_uacGrid, Visibility.Collapsed); SetVisibility(m_uasGrid, Visibility.Visible); UASInviteTransaction uasTransaction = m_sipTransport.CreateUASTransaction(sipRequest, remoteEndPoint, localSIPEndPoint, null); m_uas = new SIPServerUserAgent(m_sipTransport, null, null, null, SIPCallDirection.In, null, null, LogTraceMessage, uasTransaction); m_uas.CallCancelled += UASCallCancelled; } else if (sipRequest.Method == SIPMethodsEnum.CANCEL) { UASInviteTransaction inviteTransaction = (UASInviteTransaction)m_sipTransport.GetTransaction(SIPTransaction.GetRequestTransactionId(sipRequest.Header.Vias.TopViaHeader.Branch, SIPMethodsEnum.INVITE)); if (inviteTransaction != null) { AppendTraceMessage("Matching CANCEL request received " + sipRequest.URI.ToString() + ".\n"); SIPCancelTransaction cancelTransaction = m_sipTransport.CreateCancelTransaction(sipRequest, remoteEndPoint, localSIPEndPoint, inviteTransaction); cancelTransaction.GotRequest(localSIPEndPoint, remoteEndPoint, sipRequest); } else { AppendTraceMessage("No matching transaction was found for CANCEL to " + sipRequest.URI.ToString() + ".\n"); SIPResponse noCallLegResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.CallLegTransactionDoesNotExist, null); m_sipTransport.SendResponse(noCallLegResponse); } } else { AppendTraceMessage("SIP " + sipRequest.Method + " request received but no processing has been set up for it, rejecting.\n"); SIPResponse notAllowedResponse = SIPTransport.GetResponse(sipRequest, SIPResponseStatusCodesEnum.MethodNotAllowed, null); m_sipTransport.SendResponse(notAllowedResponse); } }
void transport_SIPRequestInTraceEvent(SIPEndPoint localEndPoint, SIPEndPoint fromEndPoint, SIPRequest sipRequest) { Console.WriteLine("Request In: " + localEndPoint + "<-" + fromEndPoint.ToString() + "\n" + sipRequest.ToString()); }
public void SendRequest(SIPRequest sipRequest) { SIPEndPoint dstEndPoint = m_sipTransport.GetRequestEndPoint(sipRequest, OutboundProxy, true).GetSIPEndPoint(); if (dstEndPoint != null) { FireTransactionTraceMessage($"Send Request {LocalSIPEndPoint.ToString()}->{dstEndPoint.ToString()}: {sipRequest.StatusLine}"); if (sipRequest.Method == SIPMethodsEnum.ACK) { m_ackRequest = sipRequest; m_ackRequestIPEndPoint = dstEndPoint; } else { RemoteEndPoint = dstEndPoint; } m_sipTransport.SendRequest(dstEndPoint, sipRequest); } else { throw new ApplicationException("Could not send Transaction Request as request end point could not be determined.\r\n" + sipRequest.ToString()); } }
public void SendRequest(SIPRequest sipRequest) { if (m_sipChannels.Count == 0) { throw new ApplicationException("No channels are configured in the SIP transport layer. The request could not be sent."); } SIPDNSLookupResult dnsResult = GetRequestEndPoint(sipRequest, null, true); if (dnsResult.LookupError != null) { SIPResponse unresolvableResponse = GetResponse(sipRequest, SIPResponseStatusCodesEnum.AddressIncomplete, "DNS resolution for " + dnsResult.URI.Host + " failed " + dnsResult.LookupError); SendResponse(unresolvableResponse); } else if (dnsResult.Pending) { // The DNS lookup is still in progress, ignore this request and rely on the fact that the transaction retransmit mechanism will send another request. return; } else { SIPEndPoint requestEndPoint = dnsResult.GetSIPEndPoint(); if (requestEndPoint != null && requestEndPoint.Address.Equals(BlackholeAddress)) { // Ignore packet, it's destined for the blackhole. return; } else if (requestEndPoint != null) { SendRequest(requestEndPoint, sipRequest); } else { throw new ApplicationException("SIP Transport could not send request as end point could not be determined.\r\n" + sipRequest.ToString()); } } }
public void SendRequest(SIPRequest sipRequest) { var lookupResult = m_sipTransport.GetRequestEndPoint(sipRequest, OutboundProxy, true); if (lookupResult != null && lookupResult.LookupError == null) { SendRequest(lookupResult.GetSIPEndPoint(), sipRequest).Wait(); } else { throw new ApplicationException("Could not send Transaction Request as request end point could not be determined.\r\n" + sipRequest.ToString()); } }
public void GotRequest(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) { FireTransactionTraceMessage("Received Request " + localSIPEndPoint.ToString() + "<-" + remoteEndPoint.ToString() + m_crLF + sipRequest.ToString()); if (TransactionRequestReceived != null) { TransactionRequestReceived(localSIPEndPoint, remoteEndPoint, this, sipRequest); } }
void transport_SIPRequestOutTraceEvent(SIPEndPoint localEndPoint, SIPEndPoint toEndPoint, SIPRequest sipRequest) { Console.WriteLine("Request Out: " + localEndPoint + "->" + toEndPoint.ToString() + "\n" + sipRequest.ToString()); }
public void SendRequest(SIPRequest sipRequest) { SIPEndPoint dstEndPoint = m_sipTransport.GetRequestEndPoint(sipRequest, OutboundProxy, true).GetSIPEndPoint(); if (dstEndPoint != null) { FireTransactionTraceMessage("Send Request " + LocalSIPEndPoint.ToString() + "->" + dstEndPoint.ToString() + m_crLF + sipRequest.ToString()); if (sipRequest.Method == SIPMethodsEnum.ACK) { m_ackRequest = sipRequest; m_ackRequestIPEndPoint = dstEndPoint; } else { RemoteEndPoint = dstEndPoint; } m_sipTransport.SendRequest(dstEndPoint, sipRequest); } else { throw new ApplicationException("Could not send Transaction Request as request end point could not be determined.\r\n" + sipRequest.ToString()); } }
public void SendRequest(SIPEndPoint dstEndPoint, SIPRequest sipRequest) { FireTransactionTraceMessage("Send Request " + LocalSIPEndPoint.ToString() + "->" + dstEndPoint + m_crLF + sipRequest.ToString()); if (sipRequest.Method == SIPMethodsEnum.ACK) { m_ackRequest = sipRequest; m_ackRequestIPEndPoint = dstEndPoint; } m_sipTransport.SendRequest(dstEndPoint, sipRequest); }
void sipTransport1_SIPRequestOutTraceEvent(SIPEndPoint localEndPoint, SIPEndPoint toEndPoint, SIPRequest sipRequest) { Console.WriteLine("Request Sent: " + localEndPoint.ToString() + "<-" + toEndPoint.ToString() + "\r\n" + sipRequest.ToString()); }
void sipTransport2_SIPRequestInTraceEvent(SIPEndPoint localEndPoint, SIPEndPoint fromEndPoint, SIPRequest sipRequest) { Console.WriteLine("Request Received: " + localEndPoint.ToString() + "<-" + fromEndPoint.ToString() + "\r\n" + sipRequest.ToString()); }
private static void SIPRequestOutTraceEvent(SIPEndPoint localSIPEndPoint, SIPEndPoint remoteEndPoint, SIPRequest sipRequest) { logger.DebugFormat("REQUEST OUT {0}->{1}", localSIPEndPoint.ToString(), remoteEndPoint.ToString()); logger.Debug(sipRequest.ToString()); }
private void SendRequest(SIPChannel sipChannel, SIPEndPoint dstEndPoint, SIPRequest sipRequest) { try { if (dstEndPoint != null && dstEndPoint.Address.Equals(BlackholeAddress)) { // Ignore packet, it's destined for the blackhole. return; } if (m_sipChannels.Count == 0) { throw new ApplicationException("No channels are configured in the SIP transport layer. The request could not be sent."); } sipRequest.Header.ContentLength = (sipRequest.Body.NotNullOrBlank()) ? Encoding.UTF8.GetByteCount(sipRequest.Body) : 0; if (sipChannel.IsTLS) { sipChannel.Send(dstEndPoint.GetIPEndPoint(), Encoding.UTF8.GetBytes(sipRequest.ToString()), sipRequest.URI.Host); } else { sipChannel.Send(dstEndPoint.GetIPEndPoint(), Encoding.UTF8.GetBytes(sipRequest.ToString())); } if (SIPRequestOutTraceEvent != null) { FireSIPRequestOutTraceEvent(sipChannel.SIPChannelEndPoint, dstEndPoint, sipRequest); } } catch (ApplicationException appExcp) { logger.Warn("ApplicationException SIPTransport SendRequest. " + appExcp.Message); SIPResponse errorResponse = GetResponse(sipRequest, SIPResponseStatusCodesEnum.InternalServerError, appExcp.Message); // Remove any Via headers, other than the last one, that are for sockets hosted by this process. while (errorResponse.Header.Vias.Length > 0) { if (IsLocalSIPEndPoint(SIPEndPoint.ParseSIPEndPoint(errorResponse.Header.Vias.TopViaHeader.ReceivedFromAddress))) { errorResponse.Header.Vias.PopTopViaHeader(); } else { break; } } if (errorResponse.Header.Vias.Length == 0) { logger.Warn("Could not send error response for " + appExcp.Message + " as no non-local Via headers were available."); } else { SendResponse(errorResponse); } } }
private void LogSIPRequestOut(SIPEndPoint localSIPEndPoint, SIPEndPoint endPoint, SIPRequest sipRequest) { string message = "App Svr Sent: " + localSIPEndPoint.ToString() + "->" + endPoint.ToString() + "\r\n" + sipRequest.ToString(); //logger.Debug("as: request out " + sipRequest.Method + " " + localSIPEndPoint.ToString() + "->" + endPoint.ToString() + ", callid=" + sipRequest.Header.CallId + "."); string fromUser = (sipRequest.Header.From != null && sipRequest.Header.From.FromURI != null) ? sipRequest.Header.From.FromURI.User : "******"; FireSIPMonitorEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.FullSIPTrace, message, fromUser, localSIPEndPoint, endPoint)); }
private void LogSIPRequestIn(SIPEndPoint localSIPEndPoint, SIPEndPoint endPoint, SIPRequest sipRequest) { string message = "Proxy Request Received: " + localSIPEndPoint.ToString() + "<-" + endPoint.ToString() + "\r\n" + sipRequest.ToString(); //logger.Debug("pr: request in " + sipRequest.Method + " " + localSIPEndPoint.ToString() + "<-" + endPoint.ToString() + ", callid=" + sipRequest.Header.CallId + "."); string fromUser = (sipRequest.Header.From != null && sipRequest.Header.From.FromURI != null) ? sipRequest.Header.From.FromURI.User : "******"; FireSIPMonitorEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.SIPProxy, SIPMonitorEventTypesEnum.FullSIPTrace, message, fromUser, localSIPEndPoint, endPoint)); }