/// <summary> /// Attempts to place a new outgoing call. /// </summary> /// <param name="sipCallDescriptor">A call descriptor containing the information about how /// and where to place the call.</param> /// <param name="mediaSession">The media session used for this call</param> public async Task InitiateCall(SIPCallDescriptor sipCallDescriptor, IMediaSession mediaSession) { m_uac = new SIPClientUserAgent(m_transport); m_uac.CallTrying += ClientCallTryingHandler; m_uac.CallRinging += ClientCallRingingHandler; m_uac.CallAnswered += ClientCallAnsweredHandler; m_uac.CallFailed += ClientCallFailedHandler; SIPEndPoint serverEndPoint = m_uac.GetCallDestination(sipCallDescriptor); if (serverEndPoint != null) { MediaSession = mediaSession; MediaSession.SessionMediaChanged += MediaSessionOnSessionMediaChanged; var sdp = await MediaSession.CreateOffer(serverEndPoint.Address).ConfigureAwait(false); sipCallDescriptor.Content = sdp; m_uac.Call(sipCallDescriptor); } else { ClientCallFailed?.Invoke(m_uac, $"Could not resolve destination when placing call to {sipCallDescriptor.Uri}."); CallEnded(); } }
/// <summary> /// Attempts to place a new outgoing call. /// </summary> /// <param name="dst">The destination SIP URI to call.</param> /// <param name="username">Optional Username if authentication is required.</param> /// <param name="password">Optional. Password if authentication is required.</param> /// <param name="mediaSession">The RTP session for the call.</param> public async Task <bool> Call(string dst, string username, string password, IMediaSession mediaSession) { if (!SIPURI.TryParse(dst, out var dstUri)) { throw new ApplicationException("The destination was not recognised as a valid SIP URI."); } SIPCallDescriptor callDescriptor = new SIPCallDescriptor( username ?? SIPConstants.SIP_DEFAULT_USERNAME, password, dstUri.ToString(), SIPConstants.SIP_DEFAULT_FROMURI, dstUri.CanonicalAddress, null, null, null, SIPCallDirection.Out, SDP.SDP_MIME_CONTENTTYPE, null, null); await InitiateCall(callDescriptor, mediaSession); TaskCompletionSource <bool> callResult = new TaskCompletionSource <bool>(); ClientCallAnswered += (uac, resp) => Task.Run(() => callResult.SetResult(true)); ClientCallFailed += (uac, errorMessage) => Task.Run(() => callResult.SetResult(false)); return(await callResult.Task); }
/// <summary> /// Attempts to place a new outgoing call. /// </summary> /// <param name="sipCallDescriptor">A call descriptor containing the information about how and where to place the call.</param> public void Call(SIPCallDescriptor sipCallDescriptor) { m_uac = new SIPClientUserAgent(m_transport); m_uac.CallTrying += ClientCallTryingHandler; m_uac.CallRinging += ClientCallRingingHandler; m_uac.CallAnswered += ClientCallAnsweredHandler; m_uac.CallFailed += ClientCallFailedHandler; m_uac.Call(sipCallDescriptor); }
public SIPNonInviteClientUserAgent( SIPTransport sipTransport, SIPEndPoint outboundProxy, SIPCallDescriptor callDescriptor) { m_sipTransport = sipTransport; m_outboundProxy = outboundProxy; m_callDescriptor = callDescriptor; }
/// <summary> /// Attempts to place a new outgoing call. /// </summary> /// <param name="sipCallDescriptor">A call descriptor containing the information about how /// and where to place the call.</param> /// <param name="mediaSession">The media session used for this call</param> public async Task InitiateCallAsync(SIPCallDescriptor sipCallDescriptor, IMediaSession mediaSession) { m_cts = new CancellationTokenSource(); m_uac = new SIPClientUserAgent(m_transport); m_uac.CallTrying += ClientCallTryingHandler; m_uac.CallRinging += ClientCallRingingHandler; m_uac.CallAnswered += ClientCallAnsweredHandler; m_uac.CallFailed += ClientCallFailedHandler; // Can be DNS lookups involved in getting the call destination. SIPEndPoint serverEndPoint = await Task.Run <SIPEndPoint>(() => { return(m_uac.GetCallDestination(sipCallDescriptor)); }).ConfigureAwait(false); if (serverEndPoint != null) { MediaSession = mediaSession; MediaSession.OnRtpEvent += OnRemoteRtpEvent; //MediaSession.OnRtpClosed += (reason) => Hangup(); MediaSession.OnRtpClosed += (reason) => { if (!MediaSession.IsClosed) { logger.LogWarning($"RTP channel was closed with reason {reason}."); } }; RTCOfferOptions offerOptions = new RTCOfferOptions { RemoteSignallingAddress = serverEndPoint.Address }; var sdp = await mediaSession.createOffer(offerOptions).ConfigureAwait(false); mediaSession.setLocalDescription(new RTCSessionDescription { sdp = sdp, type = RTCSdpType.offer }); if (mediaSession.localDescription == null) { ClientCallFailed?.Invoke(m_uac, $"Could not create a local SDP offer."); CallEnded(); } else { sipCallDescriptor.Content = mediaSession.localDescription.sdp.ToString(); // This initiates the call but does not wait for an answer. m_uac.Call(sipCallDescriptor); } } else { ClientCallFailed?.Invoke(m_uac, $"Could not resolve destination when placing call to {sipCallDescriptor.Uri}."); CallEnded(); } }
public SIPRequest Call(SIPCallDescriptor sipCallDescriptor, SIPEndPoint serverEndPoint) { m_uacCallDescriptor = sipCallDescriptor; m_uac = new SIPClientUserAgent(m_sipTransport, m_outboundProxy); m_uac.CallFailed += ClientCallFailed; m_uac.CallTrying += (uac, resp) => CallTrying?.Invoke(uac, resp); m_uac.CallRinging += (uac, resp) => CallRinging?.Invoke(uac, resp); m_uac.CallAnswered += ClientCallAnswered; return(m_uac.Call(m_uacCallDescriptor)); }
private SIPRequest GetInviteRequest(string callURI, SIPCallDescriptor sipCallDescriptor) { SIPFromHeader fromHeader = sipCallDescriptor.GetFromHeader(); SIPRequest inviteRequest = new SIPRequest(SIPMethodsEnum.INVITE, SIPURI.ParseSIPURI(callURI)); inviteRequest.LocalSIPEndPoint = m_blackhole; SIPHeader inviteHeader = new SIPHeader(fromHeader, new SIPToHeader(null, inviteRequest.URI, null), 1, CallProperties.CreateNewCallId()); inviteHeader.From.FromTag = CallProperties.CreateNewTag(); // For incoming calls forwarded via the dial plan the username needs to go into the Contact header. inviteHeader.Contact = new List <SIPContactHeader>() { new SIPContactHeader(null, new SIPURI(inviteRequest.URI.Scheme, m_blackhole)) }; inviteHeader.CSeqMethod = SIPMethodsEnum.INVITE; inviteRequest.Header = inviteHeader; SIPViaHeader viaHeader = new SIPViaHeader(m_blackhole, CallProperties.CreateBranchId()); inviteRequest.Header.Vias.PushViaHeader(viaHeader); try { if (sipCallDescriptor.CustomHeaders != null && sipCallDescriptor.CustomHeaders.Count > 0) { foreach (string customHeader in sipCallDescriptor.CustomHeaders) { if (customHeader.IsNullOrBlank()) { continue; } else if (customHeader.Trim().StartsWith(SIPHeaders.SIP_HEADER_USERAGENT)) { inviteRequest.Header.UserAgent = customHeader.Substring(customHeader.IndexOf(":") + 1).Trim(); } else { inviteRequest.Header.UnknownHeaders.Add(customHeader); } } } } catch (Exception excp) { logger.LogError("Exception Parsing CustomHeader for GetInviteRequest. " + excp.Message + sipCallDescriptor.CustomHeaders); } return(inviteRequest); }
public void Call(SIPCallDescriptor sipCallDescriptor) { try { m_uacCallDescriptor = sipCallDescriptor; SIPRequest uacInviteRequest = GetInviteRequest(m_uacCallDescriptor.Uri, sipCallDescriptor); if (sipCallDescriptor.MangleResponseSDP && sipCallDescriptor.MangleIPAddress != null) { uacInviteRequest.Header.ProxyReceivedFrom = sipCallDescriptor.MangleIPAddress.ToString(); } uacInviteRequest.Body = sipCallDescriptor.Content; uacInviteRequest.Header.ContentType = sipCallDescriptor.ContentType; uacInviteRequest.LocalSIPEndPoint = m_blackhole; uacInviteRequest.RemoteSIPEndPoint = m_blackhole; // Now that we have a destination socket create a new UAC transaction for forwarded leg of the call. m_uacTransaction = m_sipTransport.CreateUACTransaction(uacInviteRequest, m_blackhole, m_blackhole, null); if (m_uacTransaction.CDR != null) { m_uacTransaction.CDR.Owner = m_uacOwner; m_uacTransaction.CDR.AdminMemberId = m_uacAdminMemberId; m_uacTransaction.CDR.DialPlanContextID = (m_uacCallDescriptor != null) ? m_uacCallDescriptor.DialPlanContextID : Guid.Empty; } //uacTransaction.UACInviteTransactionInformationResponseReceived += ServerInformationResponseReceived; //uacTransaction.UACInviteTransactionFinalResponseReceived += ServerFinalResponseReceived; //uacTransaction.UACInviteTransactionTimedOut += ServerTimedOut; //uacTransaction.TransactionTraceMessage += TransactionTraceMessage; m_uacTransaction.SendInviteRequest(m_blackhole, m_uacTransaction.TransactionRequest); SIPRequest uasInviteRequest = uacInviteRequest.Copy(); uasInviteRequest.LocalSIPEndPoint = m_blackhole; uasInviteRequest.RemoteSIPEndPoint = m_blackhole; uasInviteRequest.Header.Vias.TopViaHeader.Branch = CallProperties.CreateBranchId(); m_uasTransaction = m_sipTransport.CreateUASTransaction(uasInviteRequest, m_blackhole, m_blackhole, null); SetOwner(sipCallDescriptor.ToSIPAccount.Owner, sipCallDescriptor.ToSIPAccount.AdminMemberId); //m_uasTransaction.TransactionTraceMessage += TransactionTraceMessage; //m_uasTransaction.UASInviteTransactionTimedOut += ClientTimedOut; //m_uasTransaction.UASInviteTransactionCancelled += (t) => { }; QueueNewCall_External(this); } catch (Exception excp) { logger.LogError("Exception SIPB2BUserAgent Call. " + excp.Message); } }
public void Call(SIPCallDescriptor sipCallDescriptor) { CallDescriptor = sipCallDescriptor; m_xmppClient = new XMPPClient("talk.google.com", 5222, "google.com", null, null); m_xmppClient.IsBound += IsBound; m_xmppClient.Answered += Answered; IPEndPoint sdpEndPoint = SDP.GetSDPRTPEndPoint(CallDescriptor.Content); if (IPSocket.IsPrivateAddress(sdpEndPoint.Address.ToString())) { bool wasSDPMangled; CallDescriptor.Content = SIPPacketMangler.MangleSDP(CallDescriptor.Content, CallDescriptor.MangleIPAddress.ToString(), out wasSDPMangled); } ThreadPool.QueueUserWorkItem(delegate { m_xmppClient.Connect(); }); }
public SIPNonInviteClientUserAgent( SIPTransport sipTransport, SIPEndPoint outboundProxy, SIPCallDescriptor callDescriptor, string owner, string adminMemberID, SIPMonitorLogDelegate logDelegate) { m_sipTransport = sipTransport; m_outboundProxy = outboundProxy; m_callDescriptor = callDescriptor; m_owner = owner; m_adminMemberID = adminMemberID; Log_External = logDelegate; }
/// <summary> /// Attempts to place a new outgoing call. /// </summary> /// <param name="sipCallDescriptor">A call descriptor containing the information about how /// and where to place the call.</param> /// <param name="mediaSession">The media session used for this call</param> public async Task InitiateCallAsync(SIPCallDescriptor sipCallDescriptor, IMediaSession mediaSession) { m_cts = new CancellationTokenSource(); m_uac = new SIPClientUserAgent(m_transport); m_uac.CallTrying += ClientCallTryingHandler; m_uac.CallRinging += ClientCallRingingHandler; m_uac.CallAnswered += ClientCallAnsweredHandler; m_uac.CallFailed += ClientCallFailedHandler; // Can be DNS lookups involved in getting the call destination. SIPEndPoint serverEndPoint = await Task.Run <SIPEndPoint>(() => { return(m_uac.GetCallDestination(sipCallDescriptor)); }).ConfigureAwait(false); if (serverEndPoint != null) { MediaSession = mediaSession; MediaSession.OnRtpEvent += OnRemoteRtpEvent; //MediaSession.OnRtpClosed += (reason) => Hangup(); MediaSession.OnRtpClosed += (reason) => { if (!MediaSession.IsClosed) { logger.LogWarning($"RTP channel was closed with reason {reason}."); } }; var sdpAnnounceAddress = NetServices.GetLocalAddressForRemote(serverEndPoint.Address); var sdp = mediaSession.CreateOffer(sdpAnnounceAddress); if (sdp == null) { ClientCallFailed?.Invoke(m_uac, $"Could not generate an offer.", null); CallEnded(); } else { sipCallDescriptor.Content = sdp.ToString(); // This initiates the call but does not wait for an answer. m_uac.Call(sipCallDescriptor); } } else { ClientCallFailed?.Invoke(m_uac, $"Could not resolve destination when placing call to {sipCallDescriptor.Uri}.", null); CallEnded(); } }
/// <summary> /// Attempts to place a new outgoing call AND waits for the call to be answered or fail. /// Use <see cref="InitiateCallAsync(SIPCallDescriptor, IMediaSession)"/> to start a call without /// waiting for it to complete and monitor <see cref="ClientCallAnsweredHandler"/> and /// <see cref="ClientCallFailedHandler"/> to detect an answer or failure. /// </summary> /// <param name="callDescriptor">The full descriptor for the call destination. Allows customising /// of additional options above the standard username, password and destination URI.</param> /// <param name="mediaSession">The RTP session for the call.</param> public async Task <bool> Call(SIPCallDescriptor callDescriptor, IMediaSession mediaSession) { TaskCompletionSource <bool> callResult = new TaskCompletionSource <bool>(TaskCreationOptions.RunContinuationsAsynchronously); await InitiateCallAsync(callDescriptor, mediaSession).ConfigureAwait(false); ClientCallAnswered += (uac, resp) => { callResult.TrySetResult(true); }; ClientCallFailed += (uac, errorMessage) => { callResult.TrySetResult(false); }; return(callResult.Task.Result); }
/// <summary> /// Attempts to place a new outgoing call AND waits for the call to be answered or fail. /// Use <see cref="InitiateCallAsync(SIPCallDescriptor, IMediaSession)"/> to start a call without /// waiting for it to complete and monitor <see cref="ClientCallAnsweredHandler"/> and /// <see cref="ClientCallFailedHandler"/> to detect an answer or failure. /// </summary> /// <param name="dst">The destination SIP URI to call.</param> /// <param name="username">Optional Username if authentication is required.</param> /// <param name="password">Optional. Password if authentication is required.</param> /// <param name="mediaSession">The RTP session for the call.</param> public Task <bool> Call(string dst, string username, string password, IMediaSession mediaSession) { if (!SIPURI.TryParse(dst, out var dstUri)) { throw new ApplicationException("The destination was not recognised as a valid SIP URI."); } SIPCallDescriptor callDescriptor = new SIPCallDescriptor( username ?? SIPConstants.SIP_DEFAULT_USERNAME, password, dstUri.ToString(), SIPConstants.SIP_DEFAULT_FROMURI, dstUri.CanonicalAddress, null, null, null, SIPCallDirection.Out, SDP.SDP_MIME_CONTENTTYPE, null, null); return(Call(callDescriptor, mediaSession)); }
public override void Start() { try { base.Start(); m_activeAppServerEntry = GetActiveAppServer(); if (m_activeAppServerEntry != null) { while (!m_stop) { Thread.Sleep(Convert.ToInt32(m_interval.TotalMilliseconds % Int32.MaxValue)); logger.Debug("AppServerDispatcher executing."); m_startCheckTime.Reset(); m_startCheckTime.Start(); SIPClientUserAgent uac = new SIPClientUserAgent(m_sipTransport, null, null, null, LogMonitorEvent); SIPCallDescriptor callDescriptor = new SIPCallDescriptor(null, null, m_activeAppServerEntry.AppServerURI.ToString(), null, null, null, null, null, SIPCallDirection.Out, null, null, null); callDescriptor.MangleResponseSDP = false; uac.CallFailed += CallFailed; uac.CallAnswered += CallAnswered; uac.Call(callDescriptor); uac.ServerTransaction.CDR = null; } } else { logger.Warn("No active app server could be set in AppServerDispatcher.Start, job stopping."); } } catch (Exception excp) { logger.Error("Exception AppServerDispatcher StartJob. " + excp.Message); } }
public SIPCallDescriptor CopyOf() { List <string> copiedCustomHeaders = null; if (CustomHeaders != null) { copiedCustomHeaders = new List <string>(); copiedCustomHeaders.InsertRange(0, CustomHeaders); } SIPCallDescriptor copy = new SIPCallDescriptor( Username, Password, Uri, From, To, RouteSet, copiedCustomHeaders, AuthUsername, CallDirection, ContentType, Content, (MangleIPAddress != null) ? new IPAddress(MangleIPAddress.GetAddressBytes()) : null); // Options. copy.DelaySeconds = DelaySeconds; copy.RedirectMode = RedirectMode; copy.CallDurationLimit = CallDurationLimit; copy.MangleResponseSDP = MangleResponseSDP; copy.FromDisplayName = FromDisplayName; copy.FromURIUsername = FromURIUsername; copy.FromURIHost = FromURIHost; copy.TransferMode = TransferMode; copy.ToSIPAccount = ToSIPAccount; return(copy); }
public void Call(SIPCallDescriptor descriptor) { try { CallDescriptor = descriptor; SIPURI destinationURI = SIPURI.ParseSIPURIRelaxed(descriptor.Uri); SIPDialogue = m_googleVoiceCall.InitiateCall(descriptor.Username, descriptor.Password, descriptor.CallbackNumber, destinationURI.User, descriptor.CallbackPattern, descriptor.CallbackPhoneType, MAX_CALLBACK_WAIT_TIME, descriptor.ContentType, descriptor.Content); if (SIPDialogue != null) { CallAnswered(this, null); } else { CallFailed(this, "Google Voice call failed."); } } catch (Exception excp) { logger.Error("Exception GoogleVoiceCallAgent Call. " + excp.Message); CallFailed(this, excp.Message); } }
//private SIPDNSLookupResult ResolveSIPEndPoint(SIPURI uri, bool async) //{ // logger.Debug("Resolving SIP URI " + uri.ToParameterlessString() + "."); // return null; //} /// <summary> /// Places an outgoing SIP call. /// </summary> /// <param name="destination">The SIP URI to place a call to. The destination can be a full SIP URI in which case the all will /// be placed anonymously directly to that URI. Alternatively it can be just the user portion of a URI in which case it will /// be sent to the configured SIP server.</param> public void Call(string destination, IPEndPoint rtpEndPoint, string sipUsername, string sipPassword, string realm) { // Determine if this is a direct anonymous call or whether it should be placed using the pre-configured SIP server account. SIPURI callURI = null; //string sipUsername = null; //string sipPassword = null; string fromHeader = null; //if (destination.Contains("@") || m_sipServer == null) //{ // Anonymous call direct to SIP server specified in the URI. callURI = SIPURI.ParseSIPURIRelaxed(destination); //} //else //{ // // This call will use the pre-configured SIP account. // callURI = SIPURI.ParseSIPURIRelaxed(destination + "@" + m_sipServer); // sipUsername = m_sipUsername; // sipPassword = m_sipPassword; fromHeader = (new SIPFromHeader(sipUsername, new SIPURI(sipUsername, realm, null), null)).ToString(); //} StatusMessage("Starting call to " + callURI.ToString() + "."); m_uac = new SIPClientUserAgent(m_sipTransport, null, null, null, null); m_uac.CallTrying += CallTrying; m_uac.CallRinging += CallRinging; m_uac.CallAnswered += CallAnswered; m_uac.CallFailed += CallFailed; _audioChannel = new AudioChannel(rtpEndPoint); // Get the SDP requesting that the public IP address be used if the host on the call destination is not a private IP address. SDP sdp = _audioChannel.GetSDP(); SIPCallDescriptor callDescriptor = new SIPCallDescriptor(sipUsername, sipPassword, callURI.ToString(), fromHeader, null, null, null, null, SIPCallDirection.Out, SDP.SDP_MIME_CONTENTTYPE, sdp.ToString(), null); m_uac.Call(callDescriptor); }
private void StartNewCallAsync(SIPCallDescriptor callDescriptor) { try { callDescriptor.DialPlanContextID = (m_dialPlanContext != null) ? m_dialPlanContext.DialPlanContextID : Guid.Empty; if (Thread.CurrentThread.Name == null) { Thread.CurrentThread.Name = THEAD_NAME + DateTime.Now.ToString("HHmmss") + "-" + Crypto.GetRandomString(3); } StartNewCallSync(callDescriptor); } catch (Exception excp) { logger.Error("Exception StartNewCallAsync. " + excp.Message); } }
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); } }
public void Call(SIPCallDescriptor sipCallDescriptor) { try { m_sipCallDescriptor = sipCallDescriptor; SIPURI callURI = SIPURI.ParseSIPURI(sipCallDescriptor.Uri); SIPRouteSet routeSet = null; if (!m_callCancelled) { // 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 (!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(sipCallDescriptor.ProxySendFrom); m_outboundProxy = new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(outboundProxyEndPoint.Address, m_defaultSIPPort)); m_serverEndPoint = m_outboundProxy; Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "SIPClientUserAgent Call 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.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Error an outbound proxy value was not recognised in SIPClientUserAgent Call. " + 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.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Attempting to resolve " + callURI.Host + ".", Owner)); lookupResult = m_sipTransport.GetURIEndPoint(callURI, false); } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Route set for call " + routeSet.ToString() + ".", Owner)); lookupResult = m_sipTransport.GetURIEndPoint(routeSet.TopRoute.URI, false); } if (lookupResult.LookupError != null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "DNS error resolving " + callURI.Host + ", " + lookupResult.LookupError + ". Call cannot proceed.", Owner)); } else { m_serverEndPoint = lookupResult.GetSIPEndPoint(); } } if (m_serverEndPoint != null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "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 call could not locate an appropriate SIP transport channel for protocol " + callURI.Protocol + "."); } string content = sipCallDescriptor.Content; if (content.IsNullOrBlank()) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Body on UAC call was empty.", Owner)); } else if (m_sipCallDescriptor.ContentType == m_sdpContentType) { if (!m_sipCallDescriptor.MangleResponseSDP) { IPEndPoint sdpEndPoint = SDP.GetSDPRTPEndPoint(content); Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC call was set to NOT mangle, RTP socket " + sdpEndPoint.ToString() + ".", Owner)); } else { IPEndPoint sdpEndPoint = SDP.GetSDPRTPEndPoint(content); if (sdpEndPoint != null) { if (!IPSocket.IsPrivateAddress(sdpEndPoint.Address.ToString())) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC call had public IP not mangled, RTP socket " + sdpEndPoint.ToString() + ".", Owner)); } else { bool wasSDPMangled = false; if (sipCallDescriptor.MangleIPAddress != null) { if (sdpEndPoint != null) { content = SIPPacketMangler.MangleSDP(content, sipCallDescriptor.MangleIPAddress.ToString(), out wasSDPMangled); } } if (wasSDPMangled) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC call had RTP socket mangled from " + sdpEndPoint.ToString() + " to " + sipCallDescriptor.MangleIPAddress.ToString() + ":" + sdpEndPoint.Port + ".", Owner)); } else if (sdpEndPoint != null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC could not be mangled, using original RTP socket of " + sdpEndPoint.ToString() + ".", Owner)); } } } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP RTP socket on UAC call could not be determined.", Owner)); } } } SIPRequest switchServerInvite = GetInviteRequest(m_sipCallDescriptor, CallProperties.CreateBranchId(), CallProperties.CreateNewCallId(), m_localSIPEndPoint, routeSet, content, sipCallDescriptor.ContentType); // Now that we have a destination socket create a new UAC transaction for forwarded leg of the call. m_serverTransaction = m_sipTransport.CreateUACTransaction(switchServerInvite, m_serverEndPoint, m_localSIPEndPoint, m_outboundProxy); if (m_serverTransaction.CDR != null) { m_serverTransaction.CDR.Owner = Owner; m_serverTransaction.CDR.AdminMemberId = AdminMemberId; } m_serverTransaction.UACInviteTransactionInformationResponseReceived += ServerInformationResponseReceived; m_serverTransaction.UACInviteTransactionFinalResponseReceived += ServerFinalResponseReceived; m_serverTransaction.UACInviteTransactionTimedOut += ServerTimedOut; m_serverTransaction.TransactionTraceMessage += TransactionTraceMessage; m_serverTransaction.SendInviteRequest(m_serverEndPoint, m_serverTransaction.TransactionRequest); } else { if (routeSet == null || routeSet.Length == 0) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Forward leg failed, could not resolve URI host " + callURI.Host, Owner)); FireCallFailed(this, "unresolvable destination " + callURI.Host); } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Forward leg failed, could not resolve top Route host " + routeSet.TopRoute.Host, Owner)); FireCallFailed(this, "unresolvable destination " + routeSet.TopRoute.Host); } } } } catch (ApplicationException appExcp) { FireCallFailed(this, appExcp.Message); } catch (Exception excp) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Exception UserAgentClient Call. " + excp.Message, Owner)); FireCallFailed(this, excp.Message); } }
private SIPRequest GetInviteRequest(string callURI, SIPCallDescriptor sipCallDescriptor) { SIPFromHeader fromHeader = sipCallDescriptor.GetFromHeader(); SIPRequest inviteRequest = new SIPRequest(SIPMethodsEnum.INVITE, SIPURI.ParseSIPURI(callURI)); inviteRequest.LocalSIPEndPoint = m_blackhole; SIPHeader inviteHeader = new SIPHeader(fromHeader, new SIPToHeader(null, inviteRequest.URI, null), 1, CallProperties.CreateNewCallId()); inviteHeader.From.FromTag = CallProperties.CreateNewTag(); // For incoming calls forwarded via the dial plan the username needs to go into the Contact header. inviteHeader.Contact = new List<SIPContactHeader>() { new SIPContactHeader(null, new SIPURI(inviteRequest.URI.Scheme, m_blackhole)) }; inviteHeader.CSeqMethod = SIPMethodsEnum.INVITE; inviteRequest.Header = inviteHeader; SIPViaHeader viaHeader = new SIPViaHeader(m_blackhole, CallProperties.CreateBranchId()); inviteRequest.Header.Vias.PushViaHeader(viaHeader); try { if (sipCallDescriptor.CustomHeaders != null && sipCallDescriptor.CustomHeaders.Count > 0) { foreach (string customHeader in sipCallDescriptor.CustomHeaders) { if (customHeader.IsNullOrBlank()) { continue; } else if (customHeader.Trim().StartsWith(SIPHeaders.SIP_HEADER_USERAGENT)) { inviteRequest.Header.UserAgent = customHeader.Substring(customHeader.IndexOf(":") + 1).Trim(); } else { inviteRequest.Header.UnknownHeaders.Add(customHeader); } } } } catch (Exception excp) { logger.Error("Exception Parsing CustomHeader for GetInviteRequest. " + excp.Message + sipCallDescriptor.CustomHeaders); } return inviteRequest; }
/// <summary> /// Gets the destination of the remote SIP end point for this call. /// </summary> /// <param name="sipCallDescriptor">The call descriptor containing the settings to use to place the call.</param> /// <returns>The server end point for the call.</returns> public async Task <SIPEndPoint> GetCallDestination(SIPCallDescriptor sipCallDescriptor) { SIPURI callURI = SIPURI.ParseSIPURI(sipCallDescriptor.Uri); SIPEndPoint serverEndPoint = null; // 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)) { serverEndPoint = m_outboundProxy; } else if (!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(sipCallDescriptor.ProxySendFrom); //m_outboundProxy = new SIPEndPoint(SIPProtocolsEnum.udp, outboundProxyEndPoint.Address, SIPConstants.DEFAULT_SIP_PORT); //m_serverEndPoint = m_outboundProxy; m_outboundProxy = SIPEndPoint.ParseSIPEndPoint(sipCallDescriptor.ProxySendFrom); serverEndPoint = m_outboundProxy; logger.LogDebug($"SIPClientUserAgent Call using alternate outbound proxy of {serverEndPoint}."); } else if (m_outboundProxy != null) { // Using the system outbound proxy only, no additional user routing requirements. serverEndPoint = m_outboundProxy; } // No outbound proxy, determine the forward destination based on the SIP request. if (serverEndPoint == null) { //SIPDNSLookupResult lookupResult = null; SIPEndPoint lookupResult = null; double lookupDurationMilliseconds = 0; if (sipCallDescriptor.RouteSet != null && sipCallDescriptor.RouteSet.IndexOf(OUTBOUNDPROXY_AS_ROUTESET_CHAR) != -1) { var routeSet = new SIPRouteSet(); routeSet.PushRoute(new SIPRoute(sipCallDescriptor.RouteSet, true)); logger.LogDebug("Route set for call " + routeSet.ToString() + "."); //lookupResult = m_sipTransport.GetURIEndPoint(routeSet.TopRoute.URI, false); lookupResult = await m_sipTransport.ResolveSIPUriAsync(routeSet.TopRoute.URI).ConfigureAwait(false); } else { logger.LogDebug("SIPClientUserAgent attempting to resolve " + callURI.Host + "."); //lookupResult = m_sipTransport.GetURIEndPoint(callURI, false); DateTime lookupStartedAt = DateTime.Now; lookupResult = await m_sipTransport.ResolveSIPUriAsync(callURI).ConfigureAwait(false); lookupDurationMilliseconds = DateTime.Now.Subtract(lookupStartedAt).TotalMilliseconds; } if (lookupResult == null) { logger.LogDebug($"SIPClientUserAgent DNS failure resolving {callURI.Host} in {lookupDurationMilliseconds:0.##}ms. Call cannot proceed."); } else { logger.LogDebug($"SIPClientUserAgent resolved {callURI.Host} to {lookupResult} in {lookupDurationMilliseconds:0.##}ms."); serverEndPoint = lookupResult; } } return(serverEndPoint); }
/// <summary> /// Sends the SIP INVITE probe request. /// </summary> public void SendProbe() { try { if (WorkerProcess == null) { logger.Debug("When attempting to send probe the worker process was null. Marking for immediate restart."); NeedsImmediateRestart = true; } else if (WorkerProcess.HasExited) { logger.Debug("When attempting to send probe the worker had exited. Marking for immediate restart."); NeedsImmediateRestart = true; } else if (m_probeUAC != null && !m_probeUAC.IsUACAnswered) { // A probe call has timed out. m_probeUAC.Cancel(); m_missedProbes++; if (m_missedProbes >= m_missedProbesLimit) { logger.Warn(m_missedProbes + " probes missed for " + AppServerEndpoint.ToString() + ". Marking for immediate restart."); NeedsImmediateRestart = true; } } if(!NeedsImmediateRestart && !NeedsToRestart) { m_probeCount++; //logger.Debug("Sending probe " + m_probeCount + " to " + AppServerEndpoint.GetIPEndPoint().ToString() + "."); DateTime probeSentAt = DateTime.Now; SIPCallDescriptor callDescriptor = new SIPCallDescriptor(m_dispatcherUsername, null, "sip:" + m_dispatcherUsername + "@" + AppServerEndpoint.GetIPEndPoint().ToString(), "sip:" + m_dispatcherUsername + "@sipcalldispatcher", "sip:" + AppServerEndpoint.GetIPEndPoint().ToString(), null, null, null, SIPCallDirection.Out, null, null, null); m_probeUAC = new SIPClientUserAgent(m_sipTransport, null, null, null, null); m_probeUAC.CallAnswered += (call, sipResponse) => { //logger.Debug("Probe response received for " + AppServerEndpoint.ToString() + "."); if (sipResponse.Status != SIPResponseStatusCodesEnum.BadExtension) //if (sipResponse.Status != SIPResponseStatusCodesEnum.InternalServerError) { logger.Warn("Probe to " + AppServerEndpoint.ToString() + " answered incorrectly on probe number " + m_probeCount + " after " + DateTime.Now.Subtract(probeSentAt).TotalSeconds.ToString("0.##") + "s, unexpected response of " + ((int)sipResponse.StatusCode) + "."); NeedsImmediateRestart = true; } else { m_gotInitialProbeResponse = true; } if (m_initialResponseMRE != null) { m_initialResponseMRE.Set(); } }; m_probeUAC.Call(callDescriptor); } } catch (Exception excp) { logger.Error("Exception SendProbe. " + excp.Message); } }
/// <summary> /// Sends the SIP INVITE probe request. /// </summary> private void ProbeWorker(SIPAppServerWorker worker, bool isInitialProbe) { try { if (isInitialProbe) { worker.InitialProbeCount++; } int workerProcessID = worker.WorkerProcess.Id; SIPEndPoint workerEndPoint = worker.AppServerEndpoint; DateTime probeSentAt = DateTime.Now; SIPCallDescriptor callDescriptor = new SIPCallDescriptor(m_dispatcherUsername, null, "sip:" + m_dispatcherUsername + "@" + workerEndPoint.GetIPEndPoint().ToString(), "sip:" + m_dispatcherUsername + "@sipcalldispatcher", "sip:" + workerEndPoint.GetIPEndPoint().ToString(), null, null, null, SIPCallDirection.Out, null, null, null); SIPClientUserAgent uac = new SIPClientUserAgent(m_sipTransport, null, null, null, null); uac.CallFailed += (failedUAC, errorMessage) => { AppServerCallFailed(failedUAC, errorMessage, workerProcessID, probeSentAt, isInitialProbe); }; uac.CallAnswered += (call, sipResponse) => { if (sipResponse.Status != SIPResponseStatusCodesEnum.BadExtension) { //logger.Warn("Probe call answered with unexpected response code of " + sipResponse.StatusCode + "."); AppServerCallFailed(call, "Unexpected response of " + ((int)sipResponse.StatusCode) + " on probe call.", workerProcessID, probeSentAt, isInitialProbe); } else { AppServerCallSucceeded(call); } }; uac.Call(callDescriptor); } catch (Exception excp) { logger.Error("Exception SIPAppServerManager ProberWorker. " + excp.Message); } }
//private void ByeFinalResponseReceived(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, SIPTransaction sipTransaction, SIPResponse sipResponse) //{ // Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "BYE response " + sipResponse.StatusCode + " " + sipResponse.ReasonPhrase + ".", Owner)); //} private SIPRequest GetInviteRequest(SIPCallDescriptor sipCallDescriptor, string branchId, string callId, SIPEndPoint localSIPEndPoint, SIPRouteSet routeSet, string content, string contentType) { SIPRequest inviteRequest = new SIPRequest(SIPMethodsEnum.INVITE, sipCallDescriptor.Uri); inviteRequest.LocalSIPEndPoint = localSIPEndPoint; SIPHeader inviteHeader = new SIPHeader(sipCallDescriptor.GetFromHeader(), SIPToHeader.ParseToHeader(sipCallDescriptor.To), 1, callId); inviteHeader.From.FromTag = CallProperties.CreateNewTag(); // For incoming calls forwarded via the dial plan the username needs to go into the Contact header. inviteHeader.Contact = new List<SIPContactHeader>() { new SIPContactHeader(null, new SIPURI(inviteRequest.URI.Scheme, localSIPEndPoint)) }; inviteHeader.Contact[0].ContactURI.User = sipCallDescriptor.Username; inviteHeader.CSeqMethod = SIPMethodsEnum.INVITE; inviteHeader.UserAgent = m_userAgent; inviteHeader.Routes = routeSet; inviteRequest.Header = inviteHeader; if (!sipCallDescriptor.ProxySendFrom.IsNullOrBlank()) { inviteHeader.ProxySendFrom = sipCallDescriptor.ProxySendFrom; } SIPViaHeader viaHeader = new SIPViaHeader(localSIPEndPoint, branchId); inviteRequest.Header.Vias.PushViaHeader(viaHeader); inviteRequest.Body = content; inviteRequest.Header.ContentLength = (inviteRequest.Body != null) ? inviteRequest.Body.Length : 0; inviteRequest.Header.ContentType = contentType; // Add custom switchboard headers. if (CallDescriptor.SwitchboardHeaders != null) { inviteHeader.SwitchboardOriginalCallID = CallDescriptor.SwitchboardHeaders.SwitchboardOriginalCallID; //inviteHeader.SwitchboardCallerDescription = CallDescriptor.SwitchboardHeaders.SwitchboardCallerDescription; inviteHeader.SwitchboardLineName = CallDescriptor.SwitchboardHeaders.SwitchboardLineName; //inviteHeader.SwitchboardOwner = CallDescriptor.SwitchboardHeaders.SwitchboardOwner; //inviteHeader.SwitchboardOriginalFrom = CallDescriptor.SwitchboardHeaders.SwitchboardOriginalFrom; } // Add custom CRM headers. if (CallDescriptor.CRMHeaders != null) { inviteHeader.CRMPersonName = CallDescriptor.CRMHeaders.PersonName; inviteHeader.CRMCompanyName = CallDescriptor.CRMHeaders.CompanyName; inviteHeader.CRMPictureURL = CallDescriptor.CRMHeaders.AvatarURL; } try { if (sipCallDescriptor.CustomHeaders != null && sipCallDescriptor.CustomHeaders.Count > 0) { foreach (string customHeader in sipCallDescriptor.CustomHeaders) { if (customHeader.IsNullOrBlank()) { continue; } else if (customHeader.Trim().StartsWith(SIPHeaders.SIP_HEADER_USERAGENT)) { inviteRequest.Header.UserAgent = customHeader.Substring(customHeader.IndexOf(":") + 1).Trim(); } else { inviteRequest.Header.UnknownHeaders.Add(customHeader); } } } } catch (Exception excp) { logger.Error("Exception Parsing CustomHeader for GetInviteRequest. " + excp.Message + sipCallDescriptor.CustomHeaders); } return inviteRequest; }
public void Call(SIPCallDescriptor sipCallDescriptor) { try { m_sipCallDescriptor = sipCallDescriptor; SIPURI callURI = SIPURI.ParseSIPURI(sipCallDescriptor.Uri); SIPRouteSet routeSet = null; if (!m_callCancelled) { // 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 (!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(sipCallDescriptor.ProxySendFrom); m_outboundProxy = new SIPEndPoint(SIPProtocolsEnum.udp, new IPEndPoint(outboundProxyEndPoint.Address, m_defaultSIPPort)); m_serverEndPoint = m_outboundProxy; Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "SIPClientUserAgent Call 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.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Error an outbound proxy value was not recognised in SIPClientUserAgent Call. " + 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.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Attempting to resolve " + callURI.Host + ".", Owner)); lookupResult = m_sipTransport.GetURIEndPoint(callURI, false); } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Route set for call " + routeSet.ToString() + ".", Owner)); lookupResult = m_sipTransport.GetURIEndPoint(routeSet.TopRoute.URI, false); } if (lookupResult.LookupError != null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "DNS error resolving " + callURI.Host + ", " + lookupResult.LookupError + ". Call cannot proceed.", Owner)); } else { m_serverEndPoint = lookupResult.GetSIPEndPoint(); } } if (m_callCancelled) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Call was cancelled during DNS resolution of " + callURI.Host, Owner)); FireCallFailed(this, "Cancelled by caller"); } else if (m_serverEndPoint != null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "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 call could not locate an appropriate SIP transport channel for protocol " + callURI.Protocol + "."); } string content = sipCallDescriptor.Content; if (content.IsNullOrBlank()) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Body on UAC call was empty.", Owner)); } else if (m_sipCallDescriptor.ContentType == m_sdpContentType) { if (!m_sipCallDescriptor.MangleResponseSDP) { IPEndPoint sdpEndPoint = SDP.GetSDPRTPEndPoint(content); if (sdpEndPoint != null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC call was set to NOT mangle, RTP socket " + sdpEndPoint.ToString() + ".", Owner)); } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC call was set to NOT mangle, RTP socket could not be determined.", Owner)); } } else { IPEndPoint sdpEndPoint = SDP.GetSDPRTPEndPoint(content); if (sdpEndPoint != null) { if (!IPSocket.IsPrivateAddress(sdpEndPoint.Address.ToString())) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC call had public IP not mangled, RTP socket " + sdpEndPoint.ToString() + ".", Owner)); } else { bool wasSDPMangled = false; if (sipCallDescriptor.MangleIPAddress != null) { if (sdpEndPoint != null) { content = SIPPacketMangler.MangleSDP(content, sipCallDescriptor.MangleIPAddress.ToString(), out wasSDPMangled); } } if (wasSDPMangled) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC call had RTP socket mangled from " + sdpEndPoint.ToString() + " to " + sipCallDescriptor.MangleIPAddress.ToString() + ":" + sdpEndPoint.Port + ".", Owner)); } else if (sdpEndPoint != null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on UAC could not be mangled, using original RTP socket of " + sdpEndPoint.ToString() + ".", Owner)); } } } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP RTP socket on UAC call could not be determined.", Owner)); } } } SIPRequest switchServerInvite = GetInviteRequest(m_sipCallDescriptor, CallProperties.CreateBranchId(), CallProperties.CreateNewCallId(), m_localSIPEndPoint, routeSet, content, sipCallDescriptor.ContentType); // Now that we have a destination socket create a new UAC transaction for forwarded leg of the call. m_serverTransaction = m_sipTransport.CreateUACTransaction(switchServerInvite, m_serverEndPoint, m_localSIPEndPoint, m_outboundProxy); m_serverTransaction.CDR.DialPlanContextID = m_sipCallDescriptor.DialPlanContextID; #region Real-time call control processing. string rtccError = null; if (m_serverTransaction.CDR != null) { m_serverTransaction.CDR.Owner = Owner; m_serverTransaction.CDR.AdminMemberId = AdminMemberId; m_serverTransaction.CDR.Updated(); #if !SILVERLIGHT && !MIN_BUILD if (m_sipCallDescriptor.AccountCode != null) { var customerAccount = m_customerAccountDataLayer.CheckAccountCode(Owner, m_sipCallDescriptor.AccountCode); if (customerAccount == null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "A billable call could not proceed as no account exists for account code or number " + m_sipCallDescriptor.AccountCode + ".", Owner)); rtccLogger.Debug("A billable call could not proceed as no account exists for account code or number " + m_sipCallDescriptor.AccountCode + " and owner " + Owner + "."); rtccError = "Real-time call control invalid account code"; } else { AccountCode = customerAccount.AccountCode; string rateDestination = m_sipCallDescriptor.Uri; if (SIPURI.TryParse(m_sipCallDescriptor.Uri)) { rateDestination = SIPURI.ParseSIPURIRelaxed(m_sipCallDescriptor.Uri).User; } var rate = m_customerAccountDataLayer.GetRate(Owner, m_sipCallDescriptor.RateCode, rateDestination, customerAccount.RatePlan); if (rate == null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "A billable call could not proceed as no rate could be determined for destination " + rateDestination + ".", Owner)); rtccLogger.Debug("A billable call could not proceed as no rate could be determined for destination " + rateDestination + " and owner " + Owner + "."); rtccError = "Real-time call control no rate"; } else { Rate = rate.Rate1; if (rate.Rate1 == 0 && rate.SetupCost == 0) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "The rate and setup cost for the " + rateDestination + "were both zero. The call will be allowed to proceed with no RTCC reservation.", Owner)); } else { decimal balance = m_customerAccountDataLayer.GetBalance(AccountCode); if (balance < Rate) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "A billable call could not proceed as the available credit for " + AccountCode + " was not sufficient for 60 seconds to destination " + rateDestination + ".", Owner)); rtccLogger.Debug("A billable call could not proceed as the available credit for " + AccountCode + " was not sufficient for 60 seconds to destination " + rateDestination + " and owner " + Owner + "."); rtccError = "Real-time call control insufficient credit"; } else { int intialSeconds = 0; var reservationCost = m_customerAccountDataLayer.ReserveInitialCredit(AccountCode, rate, m_serverTransaction.CDR, out intialSeconds); if (reservationCost == Decimal.MinusOne) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call will not proceed as the intial real-time call control credit reservation failed.", Owner)); rtccLogger.Debug("Call will not proceed as the intial real-time call control credit reservation failed for owner " + Owner + "."); rtccError = "Real-time call control initial reservation failed"; } else { ReservedCredit = reservationCost; ReservedSeconds = intialSeconds; } } } } } } #endif } // If this is a billable call attempt to reserve the first chunk of credit. //if (m_serverTransaction.CDR != null && AccountCode.NotNullOrBlank()) //{ // m_serverTransaction.CDR.AccountCode = AccountCode; // m_serverTransaction.CDR.Rate = Rate; // //m_serverTransaction.CDR.Cost = ReservedCredit; // //m_serverTransaction.CDR.SecondsReserved = ReservedSeconds; // var reservationCost = m_customerAccountDataLayer.ReserveInitialCredit(AccountCode, Rate, m_rtccInitialReservationSeconds); // if (reservationCost == Decimal.MinusOne) // { // Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call will not proceed as the intial real-time call control credit reservation failed.", Owner)); // } // else // { // m_serverTransaction.CDR.SecondsReserved = m_rtccInitialReservationSeconds; // m_serverTransaction.CDR.Cost = reservationCost; // } //} #endregion if (rtccError == null) { m_serverTransaction.UACInviteTransactionInformationResponseReceived += ServerInformationResponseReceived; m_serverTransaction.UACInviteTransactionFinalResponseReceived += ServerFinalResponseReceived; m_serverTransaction.UACInviteTransactionTimedOut += ServerTimedOut; m_serverTransaction.TransactionTraceMessage += TransactionTraceMessage; m_serverTransaction.SendInviteRequest(m_serverEndPoint, m_serverTransaction.TransactionRequest); } else { m_serverTransaction.CancelCall(rtccError); FireCallFailed(this, rtccError); } } else { if (routeSet == null || routeSet.Length == 0) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Forward leg failed, could not resolve URI host " + callURI.Host, Owner)); m_serverTransaction.CancelCall("Unresolvable destination " + callURI.Host); FireCallFailed(this, "unresolvable destination " + callURI.Host); } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Forward leg failed, could not resolve top Route host " + routeSet.TopRoute.Host, Owner)); m_serverTransaction.CancelCall("Unresolvable destination " + routeSet.TopRoute.Host); FireCallFailed(this, "unresolvable destination " + routeSet.TopRoute.Host); } } } } catch (ApplicationException appExcp) { if (m_serverTransaction != null) { m_serverTransaction.CancelCall(appExcp.Message); } FireCallFailed(this, appExcp.Message); } catch (Exception excp) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.UserAgentClient, SIPMonitorEventTypesEnum.DialPlan, "Exception UserAgentClient Call. " + excp.Message, Owner)); if (m_serverTransaction != null) { m_serverTransaction.CancelCall("Unknown exception"); } FireCallFailed(this, excp.Message); } }
private void StartNewCallSync(SIPCallDescriptor callDescriptor) { try { // A call will not be delayed if there are no other calls being attempted. if (callDescriptor.DelaySeconds != 0 && m_switchCalls.Count > 0) { callDescriptor.DelayMRE = new ManualResetEvent(false); lock (m_delayedCalls) { m_delayedCalls.Add(callDescriptor); } int delaySeconds = (callDescriptor.DelaySeconds > MAX_DELAY_SECONDS) ? MAX_DELAY_SECONDS : callDescriptor.DelaySeconds; FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Delaying call leg to " + callDescriptor.Uri + " by " + delaySeconds + "s.", m_username)); callDescriptor.DelayMRE.WaitOne(delaySeconds * 1000); } lock (m_delayedCalls) { m_delayedCalls.Remove(callDescriptor); } if (!m_callAnswered && !m_commandCancelled) { ISIPClientUserAgent uacCall = null; if (callDescriptor.ToSIPAccount == null) { if (callDescriptor.IsGoogleVoiceCall) { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Creating Google Voice user agent for " + callDescriptor.Uri + ".", m_username)); uacCall = new GoogleVoiceUserAgent(m_sipTransport, m_callManager, m_statefulProxyLogEvent, m_username, m_adminMemberId, m_outboundProxySocket); } else { uacCall = new SIPClientUserAgent(m_sipTransport, m_outboundProxySocket, m_username, m_adminMemberId, m_statefulProxyLogEvent); } } else { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Creating B2B call for " + callDescriptor.Uri + ".", m_username)); uacCall = new SIPB2BUserAgent(m_statefulProxyLogEvent, QueueNewCall_External, m_sipTransport, m_username, m_adminMemberId); } //ISIPClientUserAgent uacCall = new JingleUserAgent(m_username, m_adminMemberId, m_statefulProxyLogEvent); lock (m_switchCalls) { m_switchCalls.Add(uacCall); } uacCall.CallAnswered += UACCallAnswered; uacCall.CallFailed += UACCallFailed; uacCall.CallRinging += UACCallProgress; //uacCall.CallTrying += UACCallTrying; uacCall.Call(callDescriptor); } } catch (Exception excp) { logger.Error("Exception ForkCall StartNewCall. " + excp.Message); } }
public void Call(SIPCallDescriptor sipCallDescriptor) { try { m_uacCallDescriptor = sipCallDescriptor; SIPRequest uacInviteRequest = GetInviteRequest(m_uacCallDescriptor.Uri, sipCallDescriptor.GetFromHeader()); if (sipCallDescriptor.MangleResponseSDP && sipCallDescriptor.MangleIPAddress != null) { uacInviteRequest.Header.ProxyReceivedFrom = sipCallDescriptor.MangleIPAddress.ToString(); } uacInviteRequest.Body = sipCallDescriptor.Content; uacInviteRequest.Header.ContentType = sipCallDescriptor.ContentType; uacInviteRequest.LocalSIPEndPoint = m_blackhole; uacInviteRequest.RemoteSIPEndPoint = m_blackhole; // Now that we have a destination socket create a new UAC transaction for forwarded leg of the call. m_uacTransaction = m_sipTransport.CreateUACTransaction(uacInviteRequest, m_blackhole, m_blackhole, null); if (m_uacTransaction.CDR != null) { m_uacTransaction.CDR.Owner = m_uacOwner; m_uacTransaction.CDR.AdminMemberId = m_uacAdminMemberId; } //uacTransaction.UACInviteTransactionInformationResponseReceived += ServerInformationResponseReceived; //uacTransaction.UACInviteTransactionFinalResponseReceived += ServerFinalResponseReceived; //uacTransaction.UACInviteTransactionTimedOut += ServerTimedOut; //uacTransaction.TransactionTraceMessage += TransactionTraceMessage; m_uacTransaction.SendInviteRequest(m_blackhole, m_uacTransaction.TransactionRequest); SIPRequest uasInviteRequest = uacInviteRequest.Copy(); uasInviteRequest.LocalSIPEndPoint = m_blackhole; uasInviteRequest.RemoteSIPEndPoint = m_blackhole; uasInviteRequest.Header.Vias.TopViaHeader.Branch = CallProperties.CreateBranchId(); m_uasTransaction = m_sipTransport.CreateUASTransaction(uasInviteRequest, m_blackhole, m_blackhole, null); SetOwner(sipCallDescriptor.ToSIPAccount.Owner, sipCallDescriptor.ToSIPAccount.AdminMemberId); //m_uasTransaction.TransactionTraceMessage += TransactionTraceMessage; //m_uasTransaction.UASInviteTransactionTimedOut += ClientTimedOut; //m_uasTransaction.UASInviteTransactionCancelled += (t) => { }; QueueNewCall_External(this); } catch (Exception excp) { logger.Error("Exception SIPB2BUserAgent Call. " + excp.Message); } }
public SIPCallDescriptor CopyOf() { List<string> copiedCustomHeaders = null; if (CustomHeaders != null) { copiedCustomHeaders = new List<string>(); copiedCustomHeaders.InsertRange(0, CustomHeaders); } SIPCallDescriptor copy = new SIPCallDescriptor( Username, Password, Uri, From, To, RouteSet, copiedCustomHeaders, AuthUsername, CallDirection, ContentType, Content, (MangleIPAddress != null) ? new IPAddress(MangleIPAddress.GetAddressBytes()) : null); // Options. copy.DelaySeconds = DelaySeconds; copy.RedirectMode = RedirectMode; copy.CallDurationLimit = CallDurationLimit; copy.MangleResponseSDP = MangleResponseSDP; copy.FromDisplayName = FromDisplayName; copy.FromURIUsername = FromURIUsername; copy.FromURIHost = FromURIHost; copy.TransferMode = TransferMode; copy.ToSIPAccount = ToSIPAccount; return copy; }
private void ProbeWorkers() { try { while (!m_exit) { try { SIPEndPoint activeWorkerEndPoint = GetFirstHealthyEndPoint(); SIPCallDescriptor callDescriptor = new SIPCallDescriptor(m_dispatcherUsername, null, "sip:" + m_dispatcherUsername + "@" + activeWorkerEndPoint.SocketEndPoint.ToString(), "sip:" + m_dispatcherUsername + "@sipcalldispatcher", "sip:" + activeWorkerEndPoint.SocketEndPoint.ToString(), null, null, null, SIPCallDirection.Out, null, null, null); SIPClientUserAgent uac = new SIPClientUserAgent(m_sipTransport, null, null, null, null); uac.CallAnswered += DispatcherCallAnswered; uac.CallFailed += new SIPCallFailedDelegate(DispatcherCallFailed); uac.Call(callDescriptor); } catch (Exception probeExcp) { dispatcherLogger.Error("Exception SIPCallDispatcher Sending Probe. " + probeExcp.Message); } Thread.Sleep(PROBE_WORKER_CALL_PERIOD); } } catch (Exception excp) { logger.Error("Exception SIPCallDispatcher ProberWorkers. " + excp.Message); } }
/// <summary> /// Initiates the call to the remote user agent server. /// </summary> /// <param name="sipCallDescriptor">The descriptor for the call that describes how to reach the user agent server and other properties.</param> /// <param name="serverEndPoint">Optional. If the server end point for the call is known or has been resolved in advance. If /// not set the SIP transport layer will attempt to resolve the destination at sending time.</param> public SIPRequest Call(SIPCallDescriptor sipCallDescriptor, SIPEndPoint serverEndPoint) { try { m_sipCallDescriptor = sipCallDescriptor; SIPURI callURI = SIPURI.ParseSIPURI(sipCallDescriptor.Uri); SIPRouteSet routeSet = null; logger.LogDebug($"UAC commencing call to {SIPURI.ParseSIPURI(m_sipCallDescriptor.Uri).CanonicalAddress}."); // 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 { logger.LogDebug("Error an outbound proxy value was not recognised in SIPClientUserAgent Call. " + m_sipCallDescriptor.RouteSet + "."); } } string content = sipCallDescriptor.Content; if (content.IsNullOrBlank()) { logger.LogDebug("Body on UAC call was empty."); } if (this.m_sipCallDescriptor.BranchId.IsNullOrBlank()) { this.m_sipCallDescriptor.BranchId = CallProperties.CreateBranchId(); } if (this.m_sipCallDescriptor.CallId.IsNullOrBlank()) { this.m_sipCallDescriptor.CallId = CallProperties.CreateNewCallId(); } SIPRequest inviteRequest = GetInviteRequest(m_sipCallDescriptor, m_sipCallDescriptor.BranchId, m_sipCallDescriptor.CallId, routeSet, content, sipCallDescriptor.ContentType); // Now that we have a destination socket create a new UAC transaction for forwarded leg of the call. m_serverTransaction = new UACInviteTransaction(m_sipTransport, inviteRequest, m_outboundProxy); m_serverTransaction.UACInviteTransactionInformationResponseReceived += ServerInformationResponseReceived; m_serverTransaction.UACInviteTransactionFinalResponseReceived += ServerFinalResponseReceived; m_serverTransaction.UACInviteTransactionFailed += ServerTransactionFailed; m_serverTransaction.SendInviteRequest(); return(inviteRequest); } catch (ApplicationException appExcp) { m_serverTransaction?.CancelCall(appExcp.Message); CallFailed?.Invoke(this, appExcp.Message, null); return(null); } catch (Exception excp) { logger.LogError("Exception UserAgentClient Call. " + excp); m_serverTransaction?.CancelCall("Unknown exception"); CallFailed?.Invoke(this, excp.Message, null); return(null); } }
/// <summary> /// Places an outgoing SIP call. /// </summary> /// <param name="destination">The SIP URI to place a call to. The destination can be a full SIP URI in which case the all will /// be placed anonymously directly to that URI. Alternatively it can be just the user portion of a URI in which case it will /// be sent to the configured SIP server.</param> public void Call(MediaManager mediaManager, string destination) { _mediaManager = mediaManager; _mediaManager.NewCall(); // Determine if this is a direct anonymous call or whether it should be placed using the pre-configured SIP server account. SIPURI callURI = null; string sipUsername = null; string sipPassword = null; string fromHeader = null; if (destination.Contains("@") || m_sipServer == null) { // Anonymous call direct to SIP server specified in the URI. callURI = SIPURI.ParseSIPURIRelaxed(destination); } else { // This call will use the pre-configured SIP account. callURI = SIPURI.ParseSIPURIRelaxed(destination + "@" + m_sipServer); sipUsername = m_sipUsername; sipPassword = m_sipPassword; fromHeader = (new SIPFromHeader(m_sipFromName, new SIPURI(m_sipUsername, m_sipServer, null), null)).ToString(); } StatusMessage("Starting call to " + callURI.ToString() + "."); m_uac = new SIPClientUserAgent(m_sipTransport, null, null, null, null); m_uac.CallTrying += CallTrying; m_uac.CallRinging += CallRinging; m_uac.CallAnswered += CallAnswered; m_uac.CallFailed += CallFailed; // Get the SDP requesting that the public IP address be used if the host on the call destination is not a private IP address. SDP sdp = _mediaManager.GetSDP(!(IPSocket.IsIPAddress(callURI.Host) && IPSocket.IsPrivateAddress(callURI.Host))); System.Diagnostics.Debug.WriteLine(sdp.ToString()); SIPCallDescriptor callDescriptor = new SIPCallDescriptor(sipUsername, sipPassword, callURI.ToString(), fromHeader, null, null, null, null, SIPCallDirection.Out, _sdpMimeContentType, sdp.ToString(), null); m_uac.Call(callDescriptor); }
public void Call(SIPCallDescriptor descriptor) { try { CallDescriptor = descriptor; SIPURI destinationURI = SIPURI.ParseSIPURIRelaxed(descriptor.Uri); bool wasSDPMangled = false; IPEndPoint sdpEndPoint = null; if (descriptor.MangleIPAddress != null) { sdpEndPoint = SDP.GetSDPRTPEndPoint(descriptor.Content); if (sdpEndPoint != null) { descriptor.Content = SIPPacketMangler.MangleSDP(descriptor.Content, descriptor.MangleIPAddress.ToString(), out wasSDPMangled); } } if (wasSDPMangled) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on Google Voice call had RTP socket mangled from " + sdpEndPoint.ToString() + " to " + descriptor.MangleIPAddress.ToString() + ":" + sdpEndPoint.Port + ".", Owner)); } else if (sdpEndPoint != null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SDP on Google Voice call could not be mangled, using original RTP socket of " + sdpEndPoint.ToString() + ".", Owner)); } SIPDialogue = m_googleVoiceCall.InitiateCall(descriptor.Username, descriptor.Password, descriptor.CallbackNumber, destinationURI.User, descriptor.CallbackPattern, descriptor.CallbackPhoneType, MAX_CALLBACK_WAIT_TIME, descriptor.ContentType, descriptor.Content); if (SIPDialogue != null) { CallAnswered(this, null); } else { CallFailed(this, "Google Voice call failed."); } } catch (Exception excp) { logger.Error("Exception GoogleVoiceCallAgent Call. " + excp.Message); CallFailed(this, excp.Message); } }
/// <summary> /// Builds the call list based on the original dial plan SwitchCall format. This will result in only a single call leg with a single forward /// destination. Examples of the dial string in a dial plan command are: /// /// exten = number,priority,Switch(username,password,new number[,From[,SendTo[,Trace]]]) /// or /// sys.Dial("username,password,${dst}@provider") /// </summary> private SIPCallDescriptor ParseAsteriskDialString(string data, SIPRequest sipRequest) { try { string username = null; string password = null; string sendToSocket = null; bool traceReqd = false; string forwardURIStr = null; string fromHeaderStr = null; SIPURI forwardURI = null; string[] dataFields = data.Split(new char[] { ',' }); username = dataFields[0].Trim().Trim(new char[] { '"', '\'' }); password = dataFields[1].Trim().Trim(new char[] { '"', '\'' }); forwardURIStr = dataFields[2].Trim().Trim(new char[] { '"', '\'' }); if (dataFields.Length > 3 && dataFields[3] != null) { fromHeaderStr = dataFields[3].Trim(); } if (dataFields.Length > 4 && dataFields[4] != null) { sendToSocket = dataFields[4].Trim().Trim(new char[] { '"', '\'' }); } if (dataFields.Length > 5 && dataFields[5] != null) { Boolean.TryParse(dataFields[5].Trim(), out traceReqd); } forwardURI = SIPURI.ParseSIPURIRelaxed(SubstituteRequestVars(sipRequest, forwardURIStr)); if (forwardURI != null) { if (forwardURI.User == null) { forwardURI.User = sipRequest.URI.User; } SIPFromHeader callFromHeader = ParseFromHeaderOption(fromHeaderStr, sipRequest, username, forwardURI.Host); string socket = (sendToSocket != null && sendToSocket.Trim().Length > 0) ? sendToSocket : null; string content = sipRequest.Body; string remoteUAStr = sipRequest.Header.ProxyReceivedFrom; SIPEndPoint remoteUAAddress = (!remoteUAStr.IsNullOrBlank()) ? SIPEndPoint.ParseSIPEndPoint(remoteUAStr) : sipRequest.RemoteSIPEndPoint; SIPCallDescriptor switchCallStruct = new SIPCallDescriptor(username, password, forwardURI.ToString(), callFromHeader.ToString(), forwardURI.ToString(), socket, null, null, SIPCallDirection.Out, sipRequest.Header.ContentType, content, remoteUAAddress.Address); return switchCallStruct; } else { logger.Warn("Could not parse SIP URI from " + forwardURIStr + " in ParseAsteriskDialString."); return null; } } catch (Exception excp) { logger.Error("Exception ParseAsteriskDialString. " + excp.Message); return null; } }
public List<SIPCallDescriptor> GetForwardsForRedirect(SIPURI redirectURI, SIPCallDescriptor callDescriptor) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Getting forwards for redirect to " + redirectURI.ToString() + ".", m_username)); List<SIPCallDescriptor> redirectCalls = new List<SIPCallDescriptor>(); string localDomain = GetCanonicalDomain_External(redirectURI.Host, false); if (localDomain != null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Redirect is for local SIP account " + redirectURI.User + " and canonical domain " + localDomain + ", looking up bindings.", m_username)); SIPAccount sipAccount = GetSIPAccount_External(s => s.SIPUsername == redirectURI.User && s.SIPDomain == localDomain); List<SIPRegistrarBinding> bindings = GetRegistrarBindings_External(b => b.SIPAccountId == sipAccount.Id, null, 0, Int32.MaxValue); if (bindings != null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, bindings.Count + " bindings found for local SIP account " + sipAccount.SIPUsername + "@" + sipAccount.SIPDomain + " when processing redirect.", m_username)); // Build list of registered contacts. for (int index = 0; index < bindings.Count; index++) { SIPRegistrarBinding binding = bindings[index]; SIPURI contactURI = binding.MangledContactSIPURI; SIPCallDescriptor redirectCallDescriptor = callDescriptor.CopyOf(); redirectCallDescriptor.Uri = contactURI.ToString(); redirectCalls.Add(redirectCallDescriptor); } } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "No bindings were found for local SIP account " + sipAccount.SIPUsername + "@" + sipAccount.SIPDomain + " when processing redirect.", m_username)); } } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Redirect destination " + redirectURI.ToString() + " was determined as an external URI.", m_username)); SIPCallDescriptor redirectCallDescriptor = callDescriptor.CopyOf(); redirectCallDescriptor.Uri = redirectURI.ToString(); redirectCalls.Add(redirectCallDescriptor); } return redirectCalls; }
/// <summary> /// Processes dial strings using the multi-legged format. Each leg is separated from the proceeding one by the | character and each subsequent leg /// will only be used if all the forwards in the preceeding one fail. Within each leg the forwards are separated by the & character. /// /// Example: /// Dial(123@provider1&provider2|[email protected]|provider4&456@provider5[,trace]) /// </summary> private Queue<List<SIPCallDescriptor>> ParseScriptDialString( SIPRequest sipRequest, string command, List<string> customHeaders, string customContentType, string customContent, string callersNetworkId, string fromDisplayName, string fromUsername, string fromHost, CRMHeaders contact) { try { Queue<List<SIPCallDescriptor>> callsQueue = new Queue<List<SIPCallDescriptor>>(); string[] followonLegs = command.Split(CALLLEG_FOLLOWON_SEPARATOR); foreach (string followOnLeg in followonLegs) { List<SIPCallDescriptor> switchCalls = new List<SIPCallDescriptor>(); string[] callLegs = followOnLeg.Split(CALLLEG_SIMULTANEOUS_SEPARATOR); foreach (string callLeg in callLegs) { if (!callLeg.IsNullOrBlank()) { // Strip off the options string if present. string options = null; string callLegDestination = callLeg; int optionsStartIndex = callLeg.IndexOf(CALLLEG_OPTIONS_START_CHAR); int optionsEndIndex = callLeg.IndexOf(CALLLEG_OPTIONS_END_CHAR); if (optionsStartIndex != -1) { callLegDestination = callLeg.Substring(0, optionsStartIndex); options = callLeg.Substring(optionsStartIndex, optionsEndIndex - optionsStartIndex); } // Determine whether the call forward is for a local domain or not. SIPURI callLegSIPURI = SIPURI.ParseSIPURIRelaxed(SubstituteRequestVars(sipRequest, callLegDestination)); if (callLegSIPURI != null && callLegSIPURI.User == null) { callLegSIPURI.User = sipRequest.URI.User; } if (callLegSIPURI != null) { string localDomain = GetCanonicalDomain_External(callLegSIPURI.Host, false); if (localDomain != null) { SIPAccount calledSIPAccount = GetSIPAccount_External(s => s.SIPUsername == callLegSIPURI.User && s.SIPDomain == localDomain); if (calledSIPAccount == null && callLegSIPURI.User.Contains(".")) { // A full lookup failed. Now try a partial lookup if the incoming username is in a dotted domain name format. string sipUsernameSuffix = callLegSIPURI.User.Substring(callLegSIPURI.User.LastIndexOf(".") + 1); calledSIPAccount = GetSIPAccount_External(s => s.SIPUsername == sipUsernameSuffix && s.SIPDomain == localDomain); } if (calledSIPAccount != null) { // An incoming dialplan won't be used if it's invoked from itself. if (calledSIPAccount.InDialPlanName.IsNullOrBlank() || (m_username == calledSIPAccount.Owner && m_dialPlanName == calledSIPAccount.InDialPlanName)) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call leg is for local domain looking up bindings for " + callLegSIPURI.User + "@" + localDomain + " for call leg " + callLegDestination + ".", m_username)); switchCalls.AddRange(GetForwardsForLocalLeg(sipRequest, calledSIPAccount, customHeaders, customContentType, customContent, options, callersNetworkId, fromDisplayName, fromUsername, fromHost, contact)); } else { // An incoming call for a SIP account that has an incoming dialplan specified. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call leg is for local domain forwarding to incoming dialplan for " + callLegSIPURI.User + "@" + localDomain + ".", m_username)); string sipUsername = (m_sipAccount != null) ? m_sipAccount.SIPUsername : m_username; string sipDomain = (m_sipAccount != null) ? m_sipAccount.SIPDomain : GetCanonicalDomain_External(SIPDomainManager.DEFAULT_LOCAL_DOMAIN, false); SIPFromHeader fromHeader = ParseFromHeaderOption(null, sipRequest, sipUsername, sipDomain); string content = customContent; string contentType = customContentType; if (contentType.IsNullOrBlank()) { contentType = sipRequest.Header.ContentType; } if (content.IsNullOrBlank()) { content = sipRequest.Body; } SIPCallDescriptor loopbackCall = new SIPCallDescriptor(calledSIPAccount, callLegSIPURI.ToString(), fromHeader.ToString(), contentType, content); loopbackCall.SetGeneralFromHeaderFields(fromDisplayName, fromUsername, fromHost); loopbackCall.MangleIPAddress = (PublicIPAddress != null) ? PublicIPAddress : SIPPacketMangler.GetRequestIPAddress(sipRequest); loopbackCall.ParseCallOptions(options); switchCalls.Add(loopbackCall); } } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "No sip account could be found for local call leg " + callLeg + ".", m_username)); } } else { // Construct a call forward for a remote destination. SIPCallDescriptor sipCallDescriptor = GetForwardsForExternalLeg(sipRequest, callLegSIPURI, customContentType, customContent, fromDisplayName, fromUsername, fromHost, contact); if (sipCallDescriptor != null) { // Add and provided custom headers to those already present in the call descriptor and overwrite if an existing // header is already present. if (customHeaders != null && customHeaders.Count > 0) { foreach (string customHeader in customHeaders) { string customHeaderValue = SubstituteRequestVars(sipRequest, customHeader); sipCallDescriptor.CustomHeaders.Add(customHeaderValue); } } sipCallDescriptor.ParseCallOptions(options); switchCalls.Add(sipCallDescriptor); } } } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Could not parse a SIP URI from " + callLeg + " in ParseMultiDialString.", m_username)); } } } // Calls will not be added if the URI is already in the queue! List<SIPCallDescriptor> callList = new List<SIPCallDescriptor>(); callsQueue.Enqueue(callList); foreach (SIPCallDescriptor callToAdd in switchCalls) { if (!IsURIInQueue(callsQueue, callToAdd.Uri)) { callList.Add(callToAdd); } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call leg " + callToAdd.Uri.ToString() + " already added duplicate ignored.", m_username)); } } } return callsQueue; } catch (Exception excp) { logger.Error("Exception ParseScriptDialString. " + excp.Message); throw excp; } }
public SIPRequest Call(SIPCallDescriptor sipCallDescriptor) { return(Call(sipCallDescriptor, null)); }
/// <summary> /// Creates a list of calls based on the registered contacts for a user registration. /// </summary> /// <param name="user"></param> /// <param name="domain"></param> /// <param name="from">The From header that will be set on the forwarded call leg.</param> /// <returns></returns> public List<SIPCallDescriptor> GetForwardsForLocalLeg( SIPRequest sipRequest, SIPAccount sipAccount, List<string> customHeaders, string customContentType, string customContent, string options, string callersNetworkId, string fromDisplayName, string fromUsername, string fromHost, CRMHeaders contact) { List<SIPCallDescriptor> localUserSwitchCalls = new List<SIPCallDescriptor>(); try { if (sipAccount == null) { throw new ApplicationException("Cannot lookup forwards for a null SIP account."); } List<SIPRegistrarBinding> bindings = GetRegistrarBindings_External(b => b.SIPAccountId == sipAccount.Id, null, 0, Int32.MaxValue); if (bindings != null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, bindings.Count + " found for " + sipAccount.SIPUsername + "@" + sipAccount.SIPDomain + ".", m_username)); // Build list of registered contacts. for (int index = 0; index < bindings.Count; index++) { SIPRegistrarBinding binding = bindings[index]; SIPURI contactURI = binding.MangledContactSIPURI; // Determine the content based on a custom request, caller's network id and whether mangling is required. string contentType = (sipRequest != null) ? sipRequest.Header.ContentType : null; string content = (sipRequest != null) ? sipRequest.Body : null; if (!customContentType.IsNullOrBlank()) { contentType = customContentType; } if (!customContent.IsNullOrBlank()) { content = customContent; } IPAddress publicSDPAddress = PublicIPAddress; if (publicSDPAddress == null && sipRequest != null) { publicSDPAddress = SIPPacketMangler.GetRequestIPAddress(sipRequest); } string fromHeader = (sipRequest != null) ? sipRequest.Header.From.ToString() : m_anonymousFromURI; SIPCallDescriptor switchCall = new SIPCallDescriptor( null, null, contactURI.ToString(), fromHeader, new SIPToHeader(null, SIPURI.ParseSIPURIRelaxed(sipAccount.SIPUsername + "@" + sipAccount.SIPDomain), null).ToString(), null, customHeaders, null, SIPCallDirection.In, contentType, content, publicSDPAddress); switchCall.CRMHeaders = contact; // If the binding for the call is a switchboard add the custom switchboard headers. if (!sipRequest.Header.SwitchboardFrom.IsNullOrBlank()) { switchCall.SwitchboardHeaders.SwitchboardFrom = sipRequest.Header.SwitchboardFrom; } // If the binding has a proxy socket defined set the header to ask the upstream proxy to use it. if (binding.ProxySIPEndPoint != null) { switchCall.ProxySendFrom = binding.ProxySIPEndPoint.ToString(); } switchCall.ParseCallOptions(options); if (sipAccount != null && !sipAccount.NetworkId.IsNullOrBlank() && sipAccount.NetworkId == callersNetworkId) { switchCall.MangleResponseSDP = false; } switchCall.SetGeneralFromHeaderFields(fromDisplayName, fromUsername, fromHost); localUserSwitchCalls.Add(switchCall); } } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "No current bindings found for local SIP account " + sipAccount.SIPUsername + "@" + sipAccount.SIPDomain + ".", m_username)); } return localUserSwitchCalls; } catch (Exception excp) { logger.Error("Exception GetForwardsForLocalLeg. " + excp); return localUserSwitchCalls; } }
private void PlaceCall(object state) { string callURI = (string)state; /*m_dnsLookupComplete.Reset(); ThreadPool.QueueUserWorkItem(new WaitCallback(DNSLookup), callURI); if (!m_dnsLookupComplete.WaitOne(DNS_LOOKUP_TIMEOUT)) { AppendTraceMessage("DNS lookup for " + callURI + " timed out.\n"); ResetToCallStartState(); } else {*/ AppendTraceMessage("Starting call to " + callURI + ".\n"); m_uac = new SIPClientUserAgent(m_sipTransport, null, null, null, LogTraceMessage); m_uac.CallTrying += CallTrying; m_uac.CallRinging += CallRinging; m_uac.CallAnswered += CallAnswered; m_uac.CallFailed += CallFailed; SIPCallDescriptor callDescriptor = new SIPCallDescriptor("anonymous", null, callURI, null, null, null, null, null, SIPCallDirection.Out, null, null, null); m_uac.Call(callDescriptor); //} }
/// <summary> /// Can't be used for local destinations! /// </summary> /// <param name="sipRequest"></param> /// <param name="command"></param> /// <returns></returns> private SIPCallDescriptor GetForwardsForExternalLeg( SIPRequest sipRequest, SIPURI callLegURI, string customContentType, string customContent, string fromDisplayName, string fromUsername, string fromHost, CRMHeaders contact) { try { SIPCallDescriptor sipCallDescriptor = null; Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Attempting to locate a provider for call leg: " + callLegURI.ToString() + ".", m_username)); bool providerFound = false; string contentType = (sipRequest != null) ? sipRequest.Header.ContentType : null; string content = (sipRequest != null) ? sipRequest.Body : null; if (!customContentType.IsNullOrBlank()) { contentType = customContentType; } if (!customContent.IsNullOrBlank()) { content = customContent; } IPAddress publicSDPAddress = PublicIPAddress; if (publicSDPAddress == null && sipRequest != null) { publicSDPAddress = SIPPacketMangler.GetRequestIPAddress(sipRequest); } if (m_sipProviders != null) { foreach (SIPProvider provider in m_sipProviders) { if (callLegURI.Host.ToUpper() == provider.ProviderName.ToUpper()) { if (provider.ProviderType == ProviderTypes.GoogleVoice) { sipCallDescriptor = new SIPCallDescriptor( provider.ProviderUsername, provider.ProviderPassword, callLegURI.User + "@" + provider.ProviderName, provider.GVCallbackNumber, provider.GVCallbackPattern, (provider.GVCallbackType != null) ? (int)provider.GVCallbackType.Value : DEFAULT_GVCALLBACK_TYPE, content, contentType); sipCallDescriptor.CRMHeaders = contact; providerFound = true; break; } else { SIPURI providerURI = SIPURI.ParseSIPURI(provider.ProviderServer); if (providerURI != null) { providerURI.User = callLegURI.User; if (callLegURI.Parameters.Count > 0) { foreach (string parameterName in callLegURI.Parameters.GetKeys()) { if (!providerURI.Parameters.Has(parameterName)) { providerURI.Parameters.Set(parameterName, callLegURI.Parameters.Get(parameterName)); } } } if (callLegURI.Headers.Count > 0) { foreach (string headerName in callLegURI.Headers.GetKeys()) { if (!providerURI.Headers.Has(headerName)) { providerURI.Headers.Set(headerName, callLegURI.Headers.Get(headerName)); } } } SIPFromHeader fromHeader = ParseFromHeaderOption(provider.ProviderFrom, sipRequest, provider.ProviderUsername, providerURI.Host); sipCallDescriptor = new SIPCallDescriptor( provider.ProviderUsername, provider.ProviderPassword, providerURI.ToString(), fromHeader.ToString(), providerURI.ToString(), null, SIPCallDescriptor.ParseCustomHeaders(SubstituteRequestVars(sipRequest, provider.CustomHeaders)), provider.ProviderAuthUsername, SIPCallDirection.Out, contentType, content, publicSDPAddress); sipCallDescriptor.CRMHeaders = contact; if (!provider.ProviderOutboundProxy.IsNullOrBlank()) { sipCallDescriptor.ProxySendFrom = provider.ProviderOutboundProxy.Trim(); } providerFound = true; if (provider.ProviderFrom.IsNullOrBlank()) { // If there is already a custom From header set on the provider that overrides the general settings. sipCallDescriptor.SetGeneralFromHeaderFields(fromDisplayName, fromUsername, fromHost); } break; } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Could not parse SIP URI from Provider Server " + provider.ProviderServer + " in GetForwardsForExternalLeg.", m_username)); } } } } } if (!providerFound) { // Treat as an anonymous SIP URI. // Copy the From header so the tag can be removed before adding to the forwarded request. string fromHeaderStr = (sipRequest != null) ? sipRequest.Header.From.ToString() : m_anonymousFromURI; SIPFromHeader forwardedFromHeader = SIPFromHeader.ParseFromHeader(fromHeaderStr); forwardedFromHeader.FromTag = null; sipCallDescriptor = new SIPCallDescriptor( m_anonymousUsername, null, callLegURI.ToString(), forwardedFromHeader.ToString(), callLegURI.ToString(), null, null, null, SIPCallDirection.Out, contentType, content, publicSDPAddress); sipCallDescriptor.CRMHeaders = contact; sipCallDescriptor.SetGeneralFromHeaderFields(fromDisplayName, fromUsername, fromHost); } return sipCallDescriptor; } catch (Exception excp) { logger.Error("Exception GetForwardsForExternalLeg. " + excp.Message); return null; } }
private void ProbeWorkers() { try { while (!m_exit) { Thread.Sleep(PROBE_WORKER_CALL_PERIOD); try { SIPEndPoint activeWorkerEndPoint = GetFirstHealthyEndPoint(); if (activeWorkerEndPoint != null) { SIPCallDescriptor callDescriptor = new SIPCallDescriptor(m_dispatcherUsername, null, "sip:" + m_dispatcherUsername + "@" + activeWorkerEndPoint.GetIPEndPoint().ToString(), "sip:" + m_dispatcherUsername + "@sipcalldispatcher", "sip:" + activeWorkerEndPoint.GetIPEndPoint().ToString(), null, null, null, SIPCallDirection.Out, null, null, null); SIPClientUserAgent uac = new SIPClientUserAgent(m_sipTransport, null, null, null, null); uac.CallFailed += new SIPCallFailedDelegate(AppServerCallFailed); uac.CallAnswered += (call, sipResponse) => { if (sipResponse.Status != SIPResponseStatusCodesEnum.BadExtension) { logger.Warn("Probe call answered with unexpected response code of " + sipResponse.StatusCode + "."); AppServerCallFailed(call, "Unexpected response of " + ((int)sipResponse.StatusCode) + " on probe call."); } }; uac.Call(callDescriptor); } else { logger.Warn("SIPAppServerManager was not able to find a healthy app server endpoint."); } } catch (Exception probeExcp) { logger.Error("Exception SIPAppServerManager Sending Probe. " + probeExcp.Message); } } } catch (Exception excp) { logger.Error("Exception SIPAppServerManager ProberWorkers. " + excp.Message); } }
private SIPRequest GetInviteRequest(SIPCallDescriptor sipCallDescriptor, string branchId, string callId, SIPRouteSet routeSet, string content, string contentType) { SIPRequest inviteRequest = new SIPRequest(SIPMethodsEnum.INVITE, sipCallDescriptor.Uri); SIPHeader inviteHeader = new SIPHeader(sipCallDescriptor.GetFromHeader(), SIPToHeader.ParseToHeader(sipCallDescriptor.To), 1, callId); inviteHeader.From.FromTag = CallProperties.CreateNewTag(); inviteHeader.Contact = new List <SIPContactHeader>() { SIPContactHeader.GetDefaultSIPContactHeader(inviteRequest.URI.Scheme) }; inviteHeader.Contact[0].ContactURI.User = sipCallDescriptor.Username; inviteHeader.CSeqMethod = SIPMethodsEnum.INVITE; inviteHeader.UserAgent = SIPConstants.SipUserAgentVersionString; inviteHeader.Routes = routeSet; inviteHeader.Supported = SIPExtensionHeaders.REPLACES + ", " + SIPExtensionHeaders.NO_REFER_SUB + ((PrackSupported == true) ? ", " + SIPExtensionHeaders.PRACK : ""); inviteRequest.Header = inviteHeader; if (!sipCallDescriptor.ProxySendFrom.IsNullOrBlank()) { inviteHeader.ProxySendFrom = sipCallDescriptor.ProxySendFrom; } SIPViaHeader viaHeader = new SIPViaHeader(new IPEndPoint(IPAddress.Any, 0), branchId); inviteRequest.Header.Vias.PushViaHeader(viaHeader); inviteRequest.Body = content; inviteRequest.Header.ContentLength = (inviteRequest.Body != null) ? inviteRequest.Body.Length : 0; inviteRequest.Header.ContentType = contentType; try { if (sipCallDescriptor.CustomHeaders != null && sipCallDescriptor.CustomHeaders.Count > 0) { foreach (string customHeader in sipCallDescriptor.CustomHeaders) { if (customHeader.IsNullOrBlank()) { continue; } else if (customHeader.Trim().StartsWith(SIPHeaders.SIP_HEADER_USERAGENT)) { inviteRequest.Header.UserAgent = customHeader.Substring(customHeader.IndexOf(":") + 1).Trim(); } else if (customHeader.Trim().StartsWith(SIPHeaders.SIP_HEADER_TO + ":")) { var customToHeader = SIPUserField.ParseSIPUserField(customHeader.Substring(customHeader.IndexOf(":") + 1).Trim()); if (customToHeader != null) { inviteRequest.Header.To.ToUserField = customToHeader; } } else { inviteRequest.Header.UnknownHeaders.Add(customHeader); } } } } catch (Exception excp) { logger.LogError("Exception Parsing CustomHeader for GetInviteRequest. " + excp.Message + sipCallDescriptor.CustomHeaders); } if (AdjustInvite != null) { inviteRequest = AdjustInvite(inviteRequest); } return(inviteRequest); }
private void StartNewCallSync(SIPCallDescriptor callDescriptor) { try { callDescriptor.DialPlanContextID = (m_dialPlanContext != null) ? m_dialPlanContext.DialPlanContextID : Guid.Empty; if (callDescriptor.DelaySeconds != 0) { callDescriptor.DelayMRE = new ManualResetEvent(false); lock (m_delayedCalls) { m_delayedCalls.Add(callDescriptor); } int delaySeconds = (callDescriptor.DelaySeconds > MAX_DELAY_SECONDS) ? MAX_DELAY_SECONDS : callDescriptor.DelaySeconds; FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Delaying call leg to " + callDescriptor.Uri + " by " + delaySeconds + "s.", m_username)); callDescriptor.DelayMRE.WaitOne(delaySeconds * 1000); } lock (m_delayedCalls) { m_delayedCalls.Remove(callDescriptor); } if (!m_callAnswered && !m_commandCancelled) { ISIPClientUserAgent uacCall = null; if (callDescriptor.ToSIPAccount == null) { if (callDescriptor.IsGoogleVoiceCall) { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Creating Google Voice user agent for " + callDescriptor.Uri + ".", m_username)); uacCall = new GoogleVoiceUserAgent(m_sipTransport, m_callManager, m_statefulProxyLogEvent, m_username, m_adminMemberId, m_outboundProxySocket); } else { uacCall = new SIPClientUserAgent(m_sipTransport, m_outboundProxySocket, m_username, m_adminMemberId, m_statefulProxyLogEvent, m_customerAccountDataLayer.GetRtccCustomer, m_customerAccountDataLayer.GetRtccRate, m_customerAccountDataLayer.GetBalance, m_customerAccountDataLayer.ReserveInitialCredit, m_customerAccountDataLayer.UpdateRealTimeCallControlCDRID); } } else { if (QueueNewCall_External == null) { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "B2B calls are not supported in this dialplan manifestation.", m_username)); } else { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Creating B2B call for " + callDescriptor.Uri + ".", m_username)); uacCall = new SIPB2BUserAgent(m_statefulProxyLogEvent, QueueNewCall_External, m_sipTransport, m_username, m_adminMemberId); } } //ISIPClientUserAgent uacCall = new JingleUserAgent(m_username, m_adminMemberId, m_statefulProxyLogEvent); if (uacCall != null) { lock (m_switchCalls) { m_switchCalls.Add(uacCall); } uacCall.CallAnswered += UACCallAnswered; uacCall.CallFailed += UACCallFailed; uacCall.CallRinging += UACCallProgress; //uacCall.CallTrying += UACCallTrying; uacCall.Call(callDescriptor); } } } catch (Exception excp) { logger.Error("Exception ForkCall StartNewCall. " + excp.Message); } }