public void CallFailed(SIPResponseStatusCodesEnum failureStatus, string reasonPhrase, string[] customHeaders) { try { if (m_sipServerUserAgent != null && !m_isAnswered) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call failed with a failure status of " + failureStatus + " and " + reasonPhrase + ".", Owner)); m_isAnswered = true; if ((int)failureStatus >= 300 && (int)failureStatus <= 399) { SIPURI redirectURI = SIPURI.ParseSIPURIRelaxed(customHeaders[0]); m_sipServerUserAgent.Redirect(failureStatus, redirectURI); } else { m_sipServerUserAgent.Reject(failureStatus, reasonPhrase, customHeaders); } } } catch (Exception excp) { logger.Error("Exception DialPlanContext CallFailed. " + excp.Message); } finally { DialPlanExecutionFinished(); } }
public void CallFailed(SIPResponseStatusCodesEnum failureStatus, string reasonPhrase, string[] customHeaders) { try { if (!m_isAnswered) { m_isAnswered = true; if ((int)failureStatus >= 300 && (int)failureStatus <= 399) { SIPURI redirectURI = SIPURI.ParseSIPURIRelaxed(customHeaders[0]); m_sipServerUserAgent.Redirect(failureStatus, redirectURI); } else { m_sipServerUserAgent.Reject(failureStatus, reasonPhrase, customHeaders); } } } catch (Exception excp) { logger.Error("Exception DialPlanContext CallFailed. " + excp.Message); } finally { DialPlanExecutionFinished(); } }
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); //} } }
private bool GetDialPlanAndCustomer(string owner, string dialPlanName, ISIPServerUserAgent uas, out Customer customer, out SIPDialPlan dialPlan) { try { dialPlan = null; customer = m_customerPersistor.Get(c => c.CustomerUsername == owner); if (customer == null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call rejected for customer " + owner + " as no matching account found.", null)); uas.Reject(SIPResponseStatusCodesEnum.DoesNotExistAnywhere, "No matching user was found", null); } else if (customer.Suspended) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call rejected for customer " + owner + " as account is suspended.", null)); uas.Reject(SIPResponseStatusCodesEnum.DoesNotExistAnywhere, "User account is suspended", null); } else if (customer.ServiceLevel == CustomerServiceLevels.PremiumPayReqd.ToString() || customer.ServiceLevel == CustomerServiceLevels.ProfessionalPayReqd.ToString() || customer.ServiceLevel == CustomerServiceLevels.SwitchboardPayReqd.ToString()) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call rejected for customer " + owner + " as payment is outstanding.", null)); uas.Reject(SIPResponseStatusCodesEnum.PaymentRequired, null, null); } else if (dialPlanName.IsNullOrBlank() && uas.CallDirection == SIPCallDirection.Out) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call rejected for customer " + owner + " as no dialplan is configured for an " + uas.CallDirection + " call.", null)); uas.Reject(SIPResponseStatusCodesEnum.TemporarilyUnavailable, "SIP account missing dialplan setting", null); } else { if (dialPlanName.IsNullOrBlank()) { // Incoming call with no dialplan. return true; } else { dialPlan = GetDialPlan_External(d => d.Owner == owner && d.DialPlanName == dialPlanName); if (dialPlan == null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call rejected, dialplan " + dialPlanName + " could not be found.", owner)); uas.Reject(SIPResponseStatusCodesEnum.InternalServerError, "Could not load dialplan " + dialPlanName, null); } else if (dialPlan != null && dialPlan.IsReadOnly) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call rejected for read only dialplan " + dialPlanName + ". Upgrade to a Premium service to enable.", owner)); uas.Reject(SIPResponseStatusCodesEnum.PaymentRequired, "Dial plan is readonly, upgrade to Premium service", null); } else if (customer.ServiceLevel == CustomerServiceLevels.Free.ToString() && dialPlan.ScriptType == SIPDialPlanScriptTypesEnum.Asterisk) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Your service level does not permit the use of Asterisk dial plans.", owner)); uas.Reject(SIPResponseStatusCodesEnum.PaymentRequired, "Free plans cannot use Asterisk dial plans", null); } else if (!IsDialPlanExecutionAllowed(dialPlan, customer)) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Execution of dial plan " + dialPlanName + " was not processed as maximum execution count has been reached.", owner)); uas.Reject(SIPResponseStatusCodesEnum.TemporarilyUnavailable, "Dial plan execution exceeded maximum allowed", null); } else { if (m_dailyCallLimit == -1) { return true; } else { // Check whether the number of CDR's exceeds the daily call limit. DateTime yesterday = DateTime.Now.AddDays(-1); int cdrCount = m_sipCDRPersistor.Count(x => x.Owner == owner && x.Created > yesterday); if (cdrCount >= m_dailyCallLimit) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Execution of call for " + owner + " was not processed as daily call limit reached.", owner)); uas.Reject(SIPResponseStatusCodesEnum.TemporarilyUnavailable, "Daily call limit reached", null); } else { return true; } } } } } return false; } catch (Exception excp) { logger.Error("Exception GetDialPlanAndCustomer. " + excp.Message); throw; } }
public void QueueNewCall(ISIPServerUserAgent serverUA) { try { // Attempt to queue the call. if (m_newCalls.Count < MAX_NEWCALL_QUEUE) { lock (m_newCalls) { m_newCalls.Enqueue(serverUA); m_newCallReady.Set(); } } else { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call Manager rejected call as new calls queue full.", null)); serverUA.Reject(SIPResponseStatusCodesEnum.TemporarilyUnavailable, "Call Manager overloaded", null); } } catch (Exception excp) { logger.Error("Exception SIPCallManager QueueNewCall. " + excp.Message); } }
private bool GetDialPlanAndCustomer(string owner, string dialPlanName, ISIPServerUserAgent uas, out Customer customer, out SIPDialPlan dialPlan) { try { dialPlan = null; customer = m_customerPersistor.Get(c => c.CustomerUsername == owner); if (customer == null) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call rejected for customer " + owner + " as no matching account found.", null)); uas.Reject(SIPResponseStatusCodesEnum.DoesNotExistAnywhere, "No matching user was found", null); } else if (customer.Suspended) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call rejected for customer " + owner + " as account is suspended.", null)); uas.Reject(SIPResponseStatusCodesEnum.DoesNotExistAnywhere, "User account is suspended", null); } else if (dialPlanName.IsNullOrBlank() && uas.CallDirection == SIPCallDirection.Out) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Call rejected for customer " + owner + " as no dialplan is configured for an " + uas.CallDirection + " call.", null)); uas.Reject(SIPResponseStatusCodesEnum.TemporarilyUnavailable, "SIP account missing dialplan setting", null); } else { dialPlan = GetDialPlan_External(d => d.Owner == owner && d.DialPlanName == dialPlanName); if (!IsDialPlanExecutionAllowed(dialPlan, customer)) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Execution of dial plan " + dialPlanName + " was not processed as maximum execution count has been reached.", owner)); uas.Reject(SIPResponseStatusCodesEnum.TemporarilyUnavailable, "Dial plan execution exceeded maximum allowed", null); } else { if (m_dailyCallLimit == -1) { return true; } else { // Check whether the number of CDR's exceeds the daily call limit. DateTime yesterday = DateTime.Now.AddDays(-1); int cdrCount = m_sipCDRPersistor.Count(x => x.Owner == owner && x.Created > yesterday); if (cdrCount >= m_dailyCallLimit) { Log_External(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Execution of call for " + owner + " was not processed as daily call limit reached.", owner)); uas.Reject(SIPResponseStatusCodesEnum.TemporarilyUnavailable, "Daily call limit reached", null); } else { return true; } } } } return false; } catch (Exception excp) { logger.Error("Exception GetDialPlanAndCustomer. " + excp.Message); throw; } }