public void SingleZMatchDialPlanTest() { Console.WriteLine("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); string testDialPlan = "exten => _3Z.,1,Switch(anon, password, [email protected])"; SIPDialPlan dialPlan = new SIPDialPlan(null, null, null, testDialPlan, SIPDialPlanScriptTypesEnum.Asterisk); SIPRequest request = new SIPRequest(SIPMethodsEnum.INVITE, SIPURI.ParseSIPURI("sip:[email protected]")); DialPlanLineContext dialPlanContext = new DialPlanLineContext(null, null, null, null, null, dialPlan, null, null, null); DialPlanCommand commandMatch = dialPlanContext.GetDialPlanMatch(request); Assert.IsNotNull(commandMatch, "The dial plan should have returned a match."); Console.WriteLine("---------------------------------"); }
private void ProcessNewCall(ISIPServerUserAgent uas) { //bool wasExecutionCountIncremented = false; Customer customer = null; SIPDialPlan dialPlan = null; try { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call Manager processing new call on thread " + Thread.CurrentThread.Name + " for " + uas.CallRequest.Method + " to " + uas.CallRequest.URI.ToString() + ".", null)); #region Do some pre-flight checks on the SIP account to determine if the call should be processed. if (uas.SIPAccount == null) { if (uas.CallRequest.URI.User == DISPATCHER_SIPACCOUNT_NAME) { // This is a call from the monitoring system allow to proceed. } else if (uas.CallDirection == SIPCallDirection.Out) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SIP account " + uas.CallRequest.Header.From.FromURI.ToParameterlessString() + " not found for outgoing call to " + uas.CallRequest.URI.ToString() + ".", null)); uas.Reject(SIPResponseStatusCodesEnum.Forbidden, null, null); return; } else if (uas.CallDirection == SIPCallDirection.In) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SIP account " + uas.CallRequest.URI.ToParameterlessString() + " not found for incoming call.", null)); uas.Reject(SIPResponseStatusCodesEnum.NotFound, null, null); return; } } else { if (uas.SIPAccount.IsDisabled) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SIP account " + uas.SIPAccount.SIPUsername + "@" + uas.SIPAccount.SIPDomain + " is disabled for " + uas.CallDirection + " call.", uas.SIPAccount.Owner)); uas.Reject(SIPResponseStatusCodesEnum.Forbidden, "SIP account disabled", null); return; } else if (uas.SIPAccount.IsIncomingOnly && uas.CallDirection == SIPCallDirection.Out) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "SIP account " + uas.SIPAccount.SIPUsername + "@" + uas.SIPAccount.SIPDomain + " is not permitted to make outgoing calls", uas.SIPAccount.Owner)); uas.Reject(SIPResponseStatusCodesEnum.Forbidden, "SIP account not permitted to make outgoing calls", null); return; } } #endregion SIPURI callURI = (uas.CallRequest != null) ? uas.CallRequest.URI : null; SIPAccount sipAccount = uas.SIPAccount; if (uas.CallDirection == SIPCallDirection.In && callURI.User == DISPATCHER_SIPACCOUNT_NAME) { uas.NoCDR(); #region Create a pseudo-dialplan to process the monitoring process call. string pseudoScript = //"sys.Log(\"Dispatcher Call.\")\n" + "result = sys.DoesSIPAccountExist(\"" + DISPATCHER_SIPACCOUNT_NAME + "\")\n" + // Allows the test call to check the database connectivity. //"sys.Log(\"DoesSIPAccountExist result=#{result}.\")\n" + "sys.Respond(420, nil, \"DialPlanEngine-ExecutionCount: " + m_dialPlanEngine.ScriptCount + "\")\n"; SIPDialPlan dispatcherDialPlan = new SIPDialPlan(null, null, null, pseudoScript, SIPDialPlanScriptTypesEnum.Ruby); dispatcherDialPlan.Id = Guid.Empty; // Prevents the increment and decrement on the execution counts. DialPlanScriptContext scriptContext = new DialPlanScriptContext( Log_External, m_sipTransport, CreateDialogueBridge, m_outboundProxy, uas, dispatcherDialPlan, null, null, null, null, null, null); m_dialPlanEngine.Execute(scriptContext, uas, uas.CallDirection, null, this); #endregion } else { string dialPlanName = (uas.CallDirection == SIPCallDirection.Out) ? sipAccount.OutDialPlanName : sipAccount.InDialPlanName; string owner = (uas.IsB2B) ? uas.SIPAccount.Owner : uas.Owner; if (GetDialPlanAndCustomer(owner, dialPlanName, uas, out customer, out dialPlan)) { //IncrementDialPlanExecutionCount(dialPlan, customer, originalExecutionCount + 1); //IncrementCustomerExecutionCount(customer); //wasExecutionCountIncremented = true; if (dialPlan != null) { if (!uas.IsInvite && !dialPlan.AcceptNonInvite) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "A " + uas.CallRequest.Method + " was rejected for dialplan " + dialPlanName + " as it does not accept non-INVITE requests.", owner)); uas.Reject(SIPResponseStatusCodesEnum.MethodNotAllowed, "User has chosen not to accept request type", null); return; } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Using dialplan " + dialPlanName + " for " + uas.CallDirection + " call to " + callURI.ToString() + ".", owner)); if (dialPlan.ScriptType == SIPDialPlanScriptTypesEnum.Asterisk) { DialPlanLineContext lineContext = new DialPlanLineContext( Log_External, m_sipTransport, CreateDialogueBridge, m_outboundProxy, uas, dialPlan, GetSIPProviders_External(p => p.Owner == owner, null, 0, Int32.MaxValue), m_traceDirectory, (uas.CallDirection == SIPCallDirection.Out) ? sipAccount.NetworkId : null, customer); //lineContext.DialPlanComplete += () => { DecrementCustomerExecutionCount(customer);} ; m_dialPlanEngine.Execute(lineContext, uas, uas.CallDirection, CreateDialogueBridge, this); } else { dialPlan.AuthorisedApps = customer.AuthorisedApps + ";" + dialPlan.AuthorisedApps; DialPlanScriptContext scriptContext = new DialPlanScriptContext( Log_External, m_sipTransport, CreateDialogueBridge, m_outboundProxy, uas, dialPlan, GetSIPProviders_External(p => p.Owner == owner, null, 0, Int32.MaxValue), m_traceDirectory, (uas.CallDirection == SIPCallDirection.Out) ? sipAccount.NetworkId : null, customer, m_dialPlanEngine, GetCanonicalDomain_External); uas.SetDialPlanContextID(scriptContext.DialPlanContextID); //scriptContext.DialPlanComplete += () => { DecrementCustomerExecutionCount(customer);}; m_dialPlanEngine.Execute(scriptContext, uas, uas.CallDirection, CreateDialogueBridge, this); } } } else if (uas.CallDirection == SIPCallDirection.In) { if (uas.IsB2B) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dialplan could not be loaded for incoming B2B call to " + callURI.ToString() + ".", owner)); uas.Reject(SIPResponseStatusCodesEnum.InternalServerError, "Error loading incoming dial plan for B2B call", null); //DecrementCustomerExecutionCount(customer); } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "No dialplan specified for incoming call to " + sipAccount.SIPUsername + "@" + sipAccount.SIPDomain + ", registered bindings will be used.", owner)); // The SIP account has no dialplan for an incoming call therefore send to the SIP account's bindings. List<SIPRegistrarBinding> bindings = GetSIPAccountBindings_External(b => b.SIPAccountId == sipAccount.Id, null, 0, MAX_FORWARD_BINDINGS); if (bindings != null && bindings.Count > 0) { // Create a pseudo-dialplan to process the incoming call. string pseudoScript = "sys.Dial(\"" + sipAccount.SIPUsername + "@" + sipAccount.SIPDomain + "\")\n"; Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Forwarding incoming call for " + sipAccount.SIPUsername + "@" + sipAccount.SIPDomain + " to " + bindings.Count + " bindings.", owner)); SIPDialPlan incomingDialPlan = new SIPDialPlan(sipAccount.Owner, null, null, pseudoScript, SIPDialPlanScriptTypesEnum.Ruby); incomingDialPlan.Id = Guid.Empty; // Prevents the increment and decrement on the execution counts. DialPlanScriptContext scriptContext = new DialPlanScriptContext( Log_External, m_sipTransport, CreateDialogueBridge, m_outboundProxy, uas, incomingDialPlan, null, m_traceDirectory, null, customer, null, GetCanonicalDomain_External); //scriptContext.DialPlanComplete += () => { DecrementCustomerExecutionCount(customer); }; m_dialPlanEngine.Execute(scriptContext, uas, uas.CallDirection, CreateDialogueBridge, this); } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "No bindings available for " + sipAccount.SIPUsername + "@" + sipAccount.SIPDomain + " returning temporarily not available.", owner)); uas.Reject(SIPResponseStatusCodesEnum.TemporarilyUnavailable, null, null); //DecrementDialPlanExecutionCount(null, customer.Id); //DecrementCustomerExecutionCount(customer); } } } else { // Couldn't load a dialplan for an outgoing call. Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dialplan could not be loaded for " + uas.CallDirection + " call to " + callURI.ToString() + ".", owner)); uas.Reject(SIPResponseStatusCodesEnum.InternalServerError, "Error loading dial plan", null); //DecrementDialPlanExecutionCount(null, customer.Id); //DecrementCustomerExecutionCount(customer); } } } } catch (Exception excp) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.Error, "Exception SIPCallManager ProcessNewCall. " + excp.Message, null)); uas.Reject(SIPResponseStatusCodesEnum.InternalServerError, "Exception ProcessNewCall", null); //if (wasExecutionCountIncremented) //{ //DecrementDialPlanExecutionCount(dialPlan, customer.Id); // DecrementCustomerExecutionCount(customer); //} } }
public void RegexWithNoCommaMatchDialPlanTest() { Console.WriteLine("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); string testDialPlan = @"exten =~ \d{3},1,Switch(anon,,${dst}@sip.blueface.ie, ""sip switch"" <sip:[email protected]>, 194.213.29.100)"; SIPDialPlan dialPlan = new SIPDialPlan(null, null, null, testDialPlan, SIPDialPlanScriptTypesEnum.Asterisk); SIPRequest request = new SIPRequest(SIPMethodsEnum.INVITE, SIPURI.ParseSIPURI("sip:[email protected]")); DialPlanLineContext dialPlanContext = new DialPlanLineContext(null, null, null, null, null, dialPlan, null, null, null); DialPlanCommand commandMatch = dialPlanContext.GetDialPlanMatch(request); Assert.IsNotNull(commandMatch, "The dial plan should have returned a match."); Console.WriteLine("---------------------------------"); }
public void SimpleDialPlanTest() { Console.WriteLine("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); string testDialPlan = @" exten => 100,1,Switch(""anonymous.invalid"", ""password"", ""*****@*****.**"") exten => 101,1,Switch(""username"", ""password"", ""*****@*****.**"") "; SIPDialPlan dialPlan = new SIPDialPlan(null, null, null, testDialPlan, SIPDialPlanScriptTypesEnum.Asterisk); DialPlanLineContext dialPlanContext = new DialPlanLineContext(null, null, null, null, null, dialPlan, null, null, null); Console.WriteLine("dst=" + dialPlanContext.m_commands[0].Destination + ", data=" + dialPlanContext.m_commands[0].Data + "."); Console.WriteLine("dst=" + dialPlanContext.m_commands[1].Destination + ", data=" + dialPlanContext.m_commands[1].Data + "."); Assert.IsTrue(dialPlanContext.m_commands.Count == 2, "The dial plan was not correctly parsed."); Assert.IsTrue(dialPlanContext.m_commands[0].Operation == DialPlanOpsEnum.Equals, "Command 1 oeration not correct."); Assert.IsTrue(dialPlanContext.m_commands[1].Operation == DialPlanOpsEnum.Equals, "Command 2 oeration not correct."); Assert.IsTrue(dialPlanContext.m_commands[0].Destination == "100", "Command 1 destination not correct."); Assert.IsTrue(dialPlanContext.m_commands[1].Destination == "101", "Command 2 destination not correct."); Assert.IsTrue(dialPlanContext.m_commands[0].Command == "Switch", "Command 1 command not correct."); Assert.IsTrue(dialPlanContext.m_commands[1].Command == "Switch", "Command 2 command not correct."); Assert.IsTrue(dialPlanContext.m_commands[0].Data == "\"anonymous.invalid\", \"password\", \"[email protected]\"", "Command 1 data not correct."); Assert.IsTrue(dialPlanContext.m_commands[1].Data == "\"username\", \"password\", \"[email protected]\"", "Command 2 data not correct."); Console.WriteLine("---------------------------------"); }
public void NoMatchDialPlanTest() { Console.WriteLine("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); string testDialPlan = @" exten => _3100,1,Switch(anon, password, [email protected]) exten => _3300,1,Switch(anon, password, [email protected]) exten => _3000,1,Switch(anon, password, [email protected]) "; SIPDialPlan dialPlan = new SIPDialPlan(null, null, null, testDialPlan, SIPDialPlanScriptTypesEnum.Asterisk); SIPRequest request = new SIPRequest(SIPMethodsEnum.INVITE, SIPURI.ParseSIPURI("sip:[email protected]")); DialPlanLineContext dialPlanContext = new DialPlanLineContext(null, null, null, null, null, dialPlan, null, null, null); DialPlanCommand commandMatch = dialPlanContext.GetDialPlanMatch(request); Assert.IsTrue(dialPlanContext.m_commands.Count == 3, "The dial plan was not correctly parsed."); Assert.IsNull(commandMatch, "The dial plan produced a match when it should not have."); Console.WriteLine("---------------------------------"); }
public void DifferentOperatorsDialPlanTest() { Console.WriteLine("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); string testDialPlan = @" exten == 100,1,Switch(""anonymous.invalid"", ""password"", ""*****@*****.**"") exten =~ 101,1,Switch(""username"", ""password"", ""*****@*****.**"") exten = 103,1,Switch(""username"", ""password"", ""[email protected]) "; SIPDialPlan dialPlan = new SIPDialPlan(null, null, null, testDialPlan, SIPDialPlanScriptTypesEnum.Asterisk); DialPlanLineContext dialPlanContext = new DialPlanLineContext(null, null, null, null, null, dialPlan, null, null, null); Assert.IsTrue(dialPlanContext.m_commands.Count == 3, "The dial plan was not correctly parsed."); Assert.IsTrue(dialPlanContext.m_commands[0].Operation == DialPlanOpsEnum.Equals, "Command 1 operation was incorrect."); Assert.IsTrue(dialPlanContext.m_commands[1].Operation == DialPlanOpsEnum.Regex, "Command 2 operation was incorrect."); Assert.IsTrue(dialPlanContext.m_commands[2].Operation == DialPlanOpsEnum.Equals, "Command 3 operation was incorrect."); Console.WriteLine("---------------------------------"); }
public void CommentOnLineTest() { Console.WriteLine("--> " + System.Reflection.MethodBase.GetCurrentMethod().Name); string testDialPlan = @" exten => 100,1,Switch(anonymous.invalid, password, [email protected]) ; Comment exten => 101,1,Switch(""username"", ""password"", ""[email protected]) "; SIPDialPlan dialPlan = new SIPDialPlan(null, null, null, testDialPlan, SIPDialPlanScriptTypesEnum.Asterisk); DialPlanLineContext dialPlanContext = new DialPlanLineContext(null, null, null, null, null, dialPlan, null, null, null); Console.WriteLine("dst=" + dialPlanContext.m_commands[0].Destination + ", data=" + dialPlanContext.m_commands[0].Data + "."); Console.WriteLine("dst=" + dialPlanContext.m_commands[1].Destination + ", data=" + dialPlanContext.m_commands[1].Data + "."); Assert.IsTrue(dialPlanContext.m_commands.Count == 2, "The dial plan was not correctly parsed."); Assert.IsTrue(dialPlanContext.m_commands[0].Command == "Switch", "The dial plan command was not correct."); Assert.IsTrue(dialPlanContext.m_commands[0].Data == "anonymous.invalid, password, [email protected]", "The dial plan data was not correct."); Console.WriteLine("---------------------------------"); }
/// <summary> /// Processes the matched dial plan command for an outgoing call request. This method is used for "exten =>" formatted dial plans. In addition if the dial /// plan owner has requested that their dialplan be used for incoming calls it will process those as well. /// </summary> /// <param name="localEndPoint">The SIP Proxy socket the request was received on.</param> /// <param name="remoteEndPoint">The socket the request was recevied from.</param> /// <param name="transaction">The SIP Invite transaction that initiated the dial plan processing.</param> /// <param name="manglePrivateAddresses">If true private IP addresses will be subtituted for the remote socket.</param> /// <param name="canonicalFromDomain">If (and only if) the call is an outgoing call this will be set to the canonical domain of the host in the SIP From /// header. An outgoing call is one from an authenticated user destined for an external SIP URI. If the call is an incoming this will be null.</param> /// <param name="canonicalToDomain">If (and only if) the call is an incoming call this will be set to the canonical domain of the host in the SIP URI /// request. An incoming call is one from an external caller to a URI corresponding to a hosted domain on this SIP Proxy.</param> private void ExecuteDialPlanLine( DialPlanLineContext dialPlanContext, ISIPServerUserAgent uas, SIPCallDirection callDirection, DialogueBridgeCreatedDelegate createBridgeDelegate, ISIPCallManager callManager) { try { //SIPRequest sipRequest = uas.CallRequest; FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Executing line dial plan for call to " + uas.CallDestination + ".", dialPlanContext.Owner)); DialPlanCommand matchedCommand = dialPlanContext.GetDialPlanMatch(uas.CallDestination); if (matchedCommand == null) { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Destination " + uas.CallDestination + " not found in line dial plan " + dialPlanContext.SIPDialPlan.DialPlanName + ".", dialPlanContext.Owner)); dialPlanContext.CallFailed(SIPResponseStatusCodesEnum.NotFound, null, null); } else if (Regex.Match(matchedCommand.Command, "Switch|Dial", RegexOptions.IgnoreCase).Success) { if (matchedCommand.Data != null && matchedCommand.Data.Trim().Length > 0) { DialStringParser dialStringParser = new DialStringParser(m_sipTransport, dialPlanContext.Owner, dialPlanContext.SIPAccount, dialPlanContext.SIPProviders, m_sipSorceryPersistor.SIPAccountsPersistor.Get, m_sipSorceryPersistor.SIPRegistrarBindingPersistor.Get, GetCanonicalDomainDelegate_External, LogDelegate_External, dialPlanContext.SIPDialPlan.DialPlanName); ForkCall ForkCall = new ForkCall(m_sipTransport, FireProxyLogEvent, callManager.QueueNewCall, dialStringParser, dialPlanContext.Owner, dialPlanContext.AdminMemberId, m_outboundProxySocket, null, null); ForkCall.CallProgress += dialPlanContext.CallProgress; ForkCall.CallFailed += dialPlanContext.CallFailed; ForkCall.CallAnswered += dialPlanContext.CallAnswered; Queue<List<SIPCallDescriptor>> calls = dialStringParser.ParseDialString(DialPlanContextsEnum.Line, uas.CallRequest.Copy(), matchedCommand.Data, null, null, null, dialPlanContext.CallersNetworkId, null, null, null, null, CustomerServiceLevels.None); ForkCall.Start(calls); } else { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Error processing dialplan Dial command the dial string was empty.", dialPlanContext.Owner)); } } //else if (Regex.Match(matchedCommand.Command, "RTSP", RegexOptions.IgnoreCase).Success) //{ // RTSPApp rtspCall = new RTSPApp(FireProxyLogEvent, (UASInviteTransaction)transaction, dialPlanContext.Owner); // rtspCall.Start(matchedCommand.Data); //} else if (Regex.Match(matchedCommand.Command, "SIPReply", RegexOptions.IgnoreCase).Success) { string[] replyFields = matchedCommand.Data.Split(','); string statusMessage = (replyFields.Length > 1 && replyFields[1] != null) ? replyFields[1].Trim() : null; SIPResponseStatusCodesEnum status = SIPResponseStatusCodes.GetStatusTypeForCode(Convert.ToInt32(replyFields[0])); if ((int)status >= 300) { dialPlanContext.CallFailed(status, statusMessage, null); } else if ((int)status < 200) { dialPlanContext.CallProgress(status, statusMessage, null, null, null, null); } } else { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.Error, "Command " + matchedCommand.Command + " is not a valid dial plan command.", dialPlanContext.Owner)); dialPlanContext.CallFailed(SIPResponseStatusCodesEnum.InternalServerError, "Invalid dialplan command " + matchedCommand.Command, null); } } catch (Exception excp) { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.Error, "Error executing line dialplan for " + uas.CallRequest.URI.ToString() + ". " + excp.Message, dialPlanContext.Owner)); dialPlanContext.DialPlanExecutionFinished(); } }
/// <summary> /// Processes the matched dial plan command for an outgoing call request. This method is used for "exten =>" formatted dial plans. In addition if the dial /// plan owner has requested that their dialplan be used for incoming calls it will process those as well. /// </summary> /// <param name="localEndPoint">The SIP Proxy socket the request was received on.</param> /// <param name="remoteEndPoint">The socket the request was recevied from.</param> /// <param name="transaction">The SIP Invite transaction that initiated the dial plan processing.</param> /// <param name="manglePrivateAddresses">If true private IP addresses will be subtituted for the remote socket.</param> /// <param name="canonicalFromDomain">If (and only if) the call is an outgoing call this will be set to the canonical domain of the host in the SIP From /// header. An outgoing call is one from an authenticated user destined for an external SIP URI. If the call is an incoming this will be null.</param> /// <param name="canonicalToDomain">If (and only if) the call is an incoming call this will be set to the canonical domain of the host in the SIP URI /// request. An incoming call is one from an external caller to a URI corresponding to a hosted domain on this SIP Proxy.</param> private void ExecuteDialPlanLine( DialPlanLineContext dialPlanContext, ISIPServerUserAgent uas, SIPCallDirection callDirection, DialogueBridgeCreatedDelegate createBridgeDelegate, ISIPCallManager callManager) { try { //SIPRequest sipRequest = uas.CallRequest; FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Executing line dial plan for call to " + uas.CallDestination + ".", dialPlanContext.Owner)); DialPlanCommand matchedCommand = dialPlanContext.GetDialPlanMatch(uas.CallDestination); if (matchedCommand == null) { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Destination " + uas.CallDestination + " not found in line dial plan " + dialPlanContext.SIPDialPlan.DialPlanName + ".", dialPlanContext.Owner)); dialPlanContext.CallFailed(SIPResponseStatusCodesEnum.NotFound, null, null); } else if (Regex.Match(matchedCommand.Command, "Switch|Dial", RegexOptions.IgnoreCase).Success) { if (matchedCommand.Data != null && matchedCommand.Data.Trim().Length > 0) { DialStringParser dialStringParser = new DialStringParser(m_sipTransport, dialPlanContext.Owner, dialPlanContext.SIPAccount, dialPlanContext.SIPProviders, m_sipSorceryPersistor.SIPAccountsPersistor.Get, m_sipSorceryPersistor.SIPRegistrarBindingPersistor.Get, GetCanonicalDomainDelegate_External, LogDelegate_External, dialPlanContext.SIPDialPlan.DialPlanName); ForkCall ForkCall = new ForkCall(m_sipTransport, FireProxyLogEvent, callManager.QueueNewCall, dialStringParser, dialPlanContext.Owner, dialPlanContext.AdminMemberId, m_outboundProxySocket, null, null); ForkCall.CallProgress += dialPlanContext.CallProgress; ForkCall.CallFailed += dialPlanContext.CallFailed; ForkCall.CallAnswered += dialPlanContext.CallAnswered; Queue <List <SIPCallDescriptor> > calls = dialStringParser.ParseDialString(DialPlanContextsEnum.Line, uas.CallRequest.Copy(), matchedCommand.Data, null, null, null, dialPlanContext.CallersNetworkId, null, null, null, null, CustomerServiceLevels.None); ForkCall.Start(calls); } else { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Error processing dialplan Dial command the dial string was empty.", dialPlanContext.Owner)); } } //else if (Regex.Match(matchedCommand.Command, "RTSP", RegexOptions.IgnoreCase).Success) //{ // RTSPApp rtspCall = new RTSPApp(FireProxyLogEvent, (UASInviteTransaction)transaction, dialPlanContext.Owner); // rtspCall.Start(matchedCommand.Data); //} else if (Regex.Match(matchedCommand.Command, "SIPReply", RegexOptions.IgnoreCase).Success) { string[] replyFields = matchedCommand.Data.Split(','); string statusMessage = (replyFields.Length > 1 && replyFields[1] != null) ? replyFields[1].Trim() : null; SIPResponseStatusCodesEnum status = SIPResponseStatusCodes.GetStatusTypeForCode(Convert.ToInt32(replyFields[0])); if ((int)status >= 300) { dialPlanContext.CallFailed(status, statusMessage, null); } else if ((int)status < 200) { dialPlanContext.CallProgress(status, statusMessage, null, null, null, null); } } else { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.Error, "Command " + matchedCommand.Command + " is not a valid dial plan command.", dialPlanContext.Owner)); dialPlanContext.CallFailed(SIPResponseStatusCodesEnum.InternalServerError, "Invalid dialplan command " + matchedCommand.Command, null); } } catch (Exception excp) { FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.Error, "Error executing line dialplan for " + uas.CallRequest.URI.ToString() + ". " + excp.Message, dialPlanContext.Owner)); dialPlanContext.DialPlanExecutionFinished(); } }