public SIPReferServerUserAgent(SIPTransport sipTransport, SIPMonitorLogDelegate logDelegate, SIPNonInviteTransaction sipTransaction) { m_sipTransport = sipTransport; Log_External = logDelegate; m_sipTransaction = sipTransaction; m_sipTransaction.TransactionTraceMessage += TransactionTraceMessage; m_sipTransaction.NonInviteTransactionTimedOut += ClientTimedOut; // If external logging is not required assign an empty handler to stop null reference exceptions. if (Log_External == null) { Log_External = (e) => { }; } var referTo = SIPURI.ParseSIPURI(m_sipTransaction.TransactionRequest.Header.ReferTo); var replacesParameter = SIPReplacesParameter.Parse(referTo.Headers.Get("Replaces")); ReplacedCall = new ReplacesCallDescriptor(); ReplacedCall.CallId = replacesParameter.CallID; ReplacedCall.FromTag = replacesParameter.FromTag; ReplacedCall.ToTag = replacesParameter.ToTag; ReferToUri = referTo.CopyOf(); ReferToUri.Headers.RemoveAll(); }
private SIPRequest GetReferRequest(SIPEndPoint localSIPEndPoint, SIPURI referTo, ReplacesCallDescriptor sipReplacesCallDescriptor) { SIPRequest referRequest = new SIPRequest(SIPMethodsEnum.REFER, m_sipCallDescriptor.Uri); SIPFromHeader referFromHeader = SIPFromHeader.ParseFromHeader(m_sipCallDescriptor.From); SIPToHeader referToHeader = SIPToHeader.ParseToHeader(m_sipCallDescriptor.Uri); int cseq = ++CSeq; CallId = CallProperties.CreateNewCallId(); SIPHeader referHeader = new SIPHeader(referFromHeader, referToHeader, cseq, CallId); referHeader.CSeqMethod = SIPMethodsEnum.REFER; referRequest.Header = referHeader; referRequest.Header.Routes = RouteSet; referRequest.Header.ProxySendFrom = m_sipCallDescriptor.ProxySendFrom; if (sipReplacesCallDescriptor != null) { referTo.Headers.Set("Replaces", sipReplacesCallDescriptor.GetUrlEncodedReplacesUriHeader()); referRequest.Header.ReferTo = referTo.ToString(); } else { referRequest.Header.ReferTo = referTo.ToString(); } // "Requires" Header referRequest.Header.Require = (String.IsNullOrWhiteSpace(referRequest.Header.Require)) ? "replaces" : referRequest.Header.Require + ",replaces"; SIPViaHeader viaHeader = new SIPViaHeader(localSIPEndPoint, CallProperties.CreateBranchId()); referRequest.Header.Vias.PushViaHeader(viaHeader); return referRequest; }
public void ReferOutOfDialog(SIPURI fromUri, SIPURI toUri, SIPURI referToUri, ReplacesCallDescriptor sipReplacesCallDescriptor) { try { m_sipCallDescriptor = new SIPCallDescriptor(null,toUri.ToString(),fromUri.ToString(),null,null); m_sipCallDescriptor.Gruu = toUri.Parameters.Get(SIPCallDescriptor.GRUU_KEY); m_sipCallDescriptor.ReplacesCall = sipReplacesCallDescriptor; SIPURI callURI = SIPURI.ParseSIPURI(m_sipCallDescriptor.Uri); // If the outbound proxy is a loopback address, as it will normally be for local deployments, then it cannot be overriden. if (m_outboundProxy != null && IPAddress.IsLoopback(m_outboundProxy.Address)) { m_serverEndPoint = m_outboundProxy; } else if (!m_sipCallDescriptor.ProxySendFrom.IsNullOrBlank()) { // If the binding has a specific proxy end point sent then the request needs to be forwarded to the proxy's default end point for it to take care of. SIPEndPoint outboundProxyEndPoint = SIPEndPoint.ParseSIPEndPoint(m_sipCallDescriptor.ProxySendFrom); m_outboundProxy = new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(outboundProxyEndPoint.Address, m_defaultSIPPort)); m_serverEndPoint = m_outboundProxy; Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "SIPReferClientUserAgent refer request using alternate outbound proxy of " + m_outboundProxy + ".", Owner)); } else if (m_outboundProxy != null) { // Using the system outbound proxy only, no additional user routing requirements. m_serverEndPoint = m_outboundProxy; } // A custom route set may have been specified for the call. if (m_sipCallDescriptor.RouteSet != null && m_sipCallDescriptor.RouteSet.IndexOf(OUTBOUNDPROXY_AS_ROUTESET_CHAR) != -1) { try { RouteSet = new SIPRouteSet(); RouteSet.PushRoute(new SIPRoute(m_sipCallDescriptor.RouteSet, true)); } catch { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Error an outbound proxy value was not recognised in SIPReferClientUserAgent refer request. " + m_sipCallDescriptor.RouteSet + ".", Owner)); } } // No outbound proxy, determine the forward destination based on the SIP request. if (m_serverEndPoint == null) { SIPDNSLookupResult lookupResult = null; if (RouteSet == null || RouteSet.Length == 0) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Attempting to resolve " + callURI.Host + ".", Owner)); lookupResult = m_sipTransport.GetURIEndPoint(callURI, false); } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Route set for refer request " + RouteSet.ToString() + ".", Owner)); lookupResult = m_sipTransport.GetURIEndPoint(RouteSet.TopRoute.URI, false); } if (lookupResult.LookupError != null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "DNS error resolving " + callURI.Host + ", " + lookupResult.LookupError + ". Refer request cannot proceed.", Owner)); } else { m_serverEndPoint = lookupResult.GetSIPEndPoint(); } } if (m_serverEndPoint != null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Switching to " + SIPURI.ParseSIPURI(m_sipCallDescriptor.Uri).CanonicalAddress + " via " + m_serverEndPoint + ".", Owner)); m_localSIPEndPoint = m_sipTransport.GetDefaultSIPEndPoint(m_serverEndPoint); if (m_localSIPEndPoint == null) { throw new ApplicationException("The refer request could not locate an appropriate SIP transport channel for protocol " + callURI.Protocol + "."); } SIPRequest referRequest = GetReferRequest(m_localSIPEndPoint,referToUri, sipReplacesCallDescriptor); // Now that we have a destination socket create a new UAC transaction for forwarded leg of the call. m_serverTransaction = m_sipTransport.CreateNonInviteTransaction(referRequest, m_serverEndPoint, m_localSIPEndPoint, m_outboundProxy); m_serverTransaction.NonInviteTransactionFinalResponseReceived += m_serverTransaction_NonInviteTransactionFinalResponseReceived; m_serverTransaction.NonInviteTransactionTimedOut += m_serverTransaction_NonInviteTransactionTimedOut; m_serverTransaction.TransactionTraceMessage += TransactionTraceMessage; m_serverTransaction.SendReliableRequest(); } else { if (RouteSet == null || RouteSet.Length == 0) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Forward leg failed, could not resolve URI host " + callURI.Host, Owner)); FireReferFailed(this, "unresolvable destination " + callURI.Host); } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Forward leg failed, could not resolve top Route host " + RouteSet.TopRoute.Host, Owner)); FireReferFailed(this, "unresolvable destination " + RouteSet.TopRoute.Host); } } } catch (ApplicationException appExcp) { FireReferFailed(this, appExcp.Message); } catch (Exception excp) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.ReferUserAgentClient, SIPMonitorEventTypesEnum.Refer, "Exception UserAgentClient Call. " + excp.Message, Owner)); FireReferFailed(this, excp.Message); } }