Exemple #1
0
        public void Execute(
            DialPlanContext dialPlanContext,
            ISIPServerUserAgent uas,
            SIPCallDirection callDirection,
            DialogueBridgeCreatedDelegate createBridgeDelegate,
            ISIPCallManager callManager)
        {
            if (dialPlanContext == null)
            {
                throw new ArgumentNullException("The DialPlanContext parameter cannot be null when attempting to execute a dialplan.");
            }

            if (uas.IsUASAnswered)
            {
                // This can occur if the call is cancelled by the caller between when the INVITE was received and when the dialplan execution was ready.
                logger.Warn("Dialplan execution for " + dialPlanContext.SIPDialPlan.DialPlanName + " for " + uas.CallDirection + " call to " + uas.CallDestination + " did not proceed as call already answered.");
                dialPlanContext.DialPlanExecutionFinished();
            }
            else
            {
                if (dialPlanContext.ContextType == DialPlanContextsEnum.Line)
                {
                    ThreadPool.QueueUserWorkItem(delegate { ExecuteDialPlanLine((DialPlanLineContext)dialPlanContext, uas, callDirection, createBridgeDelegate, callManager); });
                }
                else
                {
                    ExecuteDialPlanScript((DialPlanScriptContext)dialPlanContext, uas, callDirection, createBridgeDelegate, callManager);
                }
            }
        }
Exemple #2
0
 private void ExecuteScript(
     DialPlanExecutingScript executingScript,
     DialPlanContext dialPlanContext,
     DialPlanScriptFacade planFacade,
     string script)
 {
     try
     {
         Thread.CurrentThread.Name = "dialplanscript-" + executingScript.ScriptNumber;
         if (m_impersonationUsername != null && m_impersonationPassword != null)
         {
             WrapperImpersonationContext impersonationConext = new WrapperImpersonationContext(null, m_impersonationUsername, m_impersonationPassword);
             impersonationConext.Enter();
         }
         //logger.Debug(Thread.CurrentThread.Name + " identity=" + WindowsIdentity.GetCurrent().Name + ".");
         FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dial plan execution starting on thread " + Thread.CurrentThread.Name + " for " + dialPlanContext.Owner + ".", null));
         executingScript.DialPlanScriptEngine.Execute(script, executingScript.DialPlanScriptScope);
         //FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dial plan execution finished after full script run on thread " + Thread.CurrentThread.Name + " for " + dialPlanContext.Owner + ".", null));
     }
     catch (ApplicationException appExcp)
     {
         if (appExcp.Message != "Script was halted by external intervention.")
         {
             logger.Error("ApplicationException ExecuteScript. " + appExcp.Message);
             FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "There was an exception executing your dial plan script: " + appExcp.Message, executingScript.Owner));
             FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "ApplicationException on user " + executingScript.Owner + "'s dial plan script. " + appExcp.Message, null));
             executingScript.ExecutionError = appExcp.Message;
         }
         else
         {
             FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dial plan execution finished after being halted due to execution interrupt on thread " + Thread.CurrentThread.Name + " for " + dialPlanContext.Owner + ".", null));
         }
     }
     //catch (System.Scripting.SyntaxErrorException)
     catch (SyntaxErrorException syntaxExcp)
     {
         logger.Warn("SyntaxErrorException. Owner=" + dialPlanContext.Owner + ", DialPlanName=" + dialPlanContext.SIPDialPlan.DialPlanName + ", Line=" + syntaxExcp.Line + ".");
         FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "There was a syntax error in your dial plan on line " + syntaxExcp.Line + ", please check.", executingScript.Owner));
         executingScript.ExecutionError = "Dial plan syntax error";
     }
     catch (MissingMethodException missingExcp)
     {
         logger.Warn("MissingMethodException. " + missingExcp.Message);
         FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "There was a missing method exception in your dial plan: " + missingExcp.Message + ".", executingScript.Owner));
         executingScript.ExecutionError = "Dial plan missing method";
     }
     catch (ThreadAbortException) { }
     catch (Exception excp)
     {
         logger.Error("Exception ExecuteScript (" + excp.GetType() + "). " + excp.Message);
         FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "There was an exception executing your dial plan script: " + excp.Message, executingScript.Owner));
         FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Exception on user " + executingScript.Owner + "'s dial plan script (" + excp.GetType() + "). " + excp.Message, null));
         executingScript.ExecutionError = "Dial plan exception";
     }
     finally
     {
         executingScript.StopExecution();
     }
 }
 public void Initialise(DialPlanContext dialPlanContext)
 {
     ExecutingDialPlanContext = dialPlanContext;
     Owner             = ExecutingDialPlanContext.Owner;
     StartTime         = DateTime.Now;
     EndTime           = StartTime.AddSeconds(MAX_SCRIPTPROCESSING_SECONDS);
     Complete          = false;
     ExecutionError    = null;
     LastFailureStatus = SIPResponseStatusCodesEnum.None;
     LastFailureReason = null;
 }
Exemple #4
0
 /// <summary>
 /// See overload.
 /// </summary>
 /// <param name="switchCallTransactions">An empty list that will be filled with transactions that the ForkCall creates and that each
 /// represent an outgoing call. The calling object can use the list to check response codes to determine the result of each leg in the
 /// ForkCall.</param>
 public ForkCall(
     SIPTransport sipTransport,
     SIPMonitorLogDelegate statefulProxyLogEvent,
     QueueNewCallDelegate queueNewCall,
     DialStringParser dialStringParser,
     string username,
     string adminMemberId,
     SIPEndPoint outboundProxy,
     ISIPCallManager callManager,
     DialPlanContext dialPlanContext,
     out List <SIPTransaction> switchCallTransactions) :
     this(sipTransport, statefulProxyLogEvent, queueNewCall, dialStringParser, username, adminMemberId, outboundProxy, callManager, dialPlanContext)
 {
     switchCallTransactions = m_switchCallTransactions;
 }
Exemple #5
0
 /// <remarks>
 /// The ForkCall allows a SIP call to be forked to multiple destinations. To do this it utilises multiple
 /// simultaneous SIPCallDescriptor objects and consolidates their responses to work out what should and shouldn't
 /// be forwarded onto the client that initiated the call. The ForkCall acts as a classic SIP forking proxy.
 ///
 /// The ForkCall is capable of both multiple forwards and also of follow on forwarding in the event of a call
 /// leg of multiple forwards not succeeding. As an example:
 ///
 ///     Dial(provider1&provider2|provider3&provider4|provider5&provider6)
 ///
 /// The handling of this call would be:
 /// 1. The call would be simultaneously forwarded to provider1 and provider2,
 /// 2. If the call was not successfully answered in step 1 the  call would be simultaneously forwarded to provider3 and provider4,
 /// 3. If the call was not successfully answered in step 2 the  call would be simultaneously forwarded to provider5 and provider6,
 /// 4. If the call was not successfully answered in step 3 the client call would be sent an error response.
 /// 5. If the client cancels the call at any time during the call all forwarding operations will halt.
 /// </remarks>
 /// <param name="sipTransport">The SIP transport layer that will handle the forked calls.</param>
 /// <param name="statefulProxyLogEvent">A delegate that allows the owning object to receive notifications from the ForkCall.</param>
 /// <param name="queueNewCall">A delegate that can be used to queue a new call with the SIP application server call manager. This
 /// delegate is used when a fork call generates a B2B call that requires the incoming dialplan for a called user to be processed.</param>
 /// <param name="dialStringParser">The dial string parser is used when a redirect response is received on a forked call leg. The
 /// parser can then be applied to the redirect SIP URI to generate new call legs to be added to the ForkCall.</param>
 /// <param name="username">The username of the call owner.</param>
 /// <param name="adminMemberId">The admin ID of the call owner.</param>
 /// <param name="outboundProxy">The outbound proxy to use for all SIP traffic originated. Can be null if an outbound proxy is not
 /// being used.</param>
 public ForkCall(
     SIPTransport sipTransport,
     SIPMonitorLogDelegate statefulProxyLogEvent,
     QueueNewCallDelegate queueNewCall,
     DialStringParser dialStringParser,
     string username,
     string adminMemberId,
     SIPEndPoint outboundProxy,
     ISIPCallManager callManager,
     DialPlanContext dialPlanContext)
 {
     m_sipTransport          = sipTransport;
     m_statefulProxyLogEvent = statefulProxyLogEvent;
     QueueNewCall_External   = queueNewCall;
     m_dialStringParser      = dialStringParser;
     m_username            = username;
     m_adminMemberId       = adminMemberId;
     m_outboundProxySocket = outboundProxy;
     m_callManager         = callManager;
     m_dialPlanContext     = dialPlanContext;
 }
Exemple #6
0
 /// <summary>
 /// See overload.
 /// </summary>
 /// <param name="switchCallTransactions">An empty list that will be filled with transactions that the ForkCall creates and that each
 /// represent an outgoing call. The calling object can use the list to check response codes to determine the result of each leg in the
 /// ForkCall.</param>
 public ForkCall(
     SIPTransport sipTransport,
     SIPMonitorLogDelegate statefulProxyLogEvent,
     QueueNewCallDelegate queueNewCall,
     DialStringParser dialStringParser,
     string username,
     string adminMemberId,
     SIPEndPoint outboundProxy,
     ISIPCallManager callManager,
     DialPlanContext dialPlanContext,
     out List<SIPTransaction> switchCallTransactions)
     : this(sipTransport, statefulProxyLogEvent, queueNewCall, dialStringParser, username, adminMemberId, outboundProxy, callManager, dialPlanContext)
 {
     switchCallTransactions = m_switchCallTransactions;
 }
Exemple #7
0
        private QueueNewCallDelegate QueueNewCall_External; // Function delegate to allow new calls to be placed on the call manager and run through the dialplan logic.

        #endregion Fields

        #region Constructors

        /// <remarks>
        /// The ForkCall allows a SIP call to be forked to multiple destinations. To do this it utilises multiple
        /// simultaneous SIPCallDescriptor objects and consolidates their responses to work out what should and shouldn't
        /// be forwarded onto the client that initiated the call. The ForkCall acts as a classic SIP forking proxy.
        /// 
        /// The ForkCall is capable of both multiple forwards and also of follow on forwarding in the event of a call 
        /// leg of multiple forwards not succeeding. As an example:
        /// 
        ///     Dial(provider1&provider2|provider3&provider4|provider5&provider6)
        ///     
        /// The handling of this call would be:
        /// 1. The call would be simultaneously forwarded to provider1 and provider2,
        /// 2. If the call was not successfully answered in step 1 the  call would be simultaneously forwarded to provider3 and provider4,
        /// 3. If the call was not successfully answered in step 2 the  call would be simultaneously forwarded to provider5 and provider6,
        /// 4. If the call was not successfully answered in step 3 the client call would be sent an error response.
        /// 5. If the client cancels the call at any time during the call all forwarding operations will halt.
        /// </remarks>
        /// <param name="sipTransport">The SIP transport layer that will handle the forked calls.</param>
        /// <param name="statefulProxyLogEvent">A delegate that allows the owning object to receive notifications from the ForkCall.</param>
        /// <param name="queueNewCall">A delegate that can be used to queue a new call with the SIP application server call manager. This
        /// delegate is used when a fork call generates a B2B call that requires the incoming dialplan for a called user to be processed.</param>
        /// <param name="dialStringParser">The dial string parser is used when a redirect response is received on a forked call leg. The
        /// parser can then be applied to the redirect SIP URI to generate new call legs to be added to the ForkCall.</param>
        /// <param name="username">The username of the call owner.</param>
        /// <param name="adminMemberId">The admin ID of the call owner.</param>
        /// <param name="outboundProxy">The outbound proxy to use for all SIP traffic originated. Can be null if an outbound proxy is not 
        /// being used.</param>
        public ForkCall(
            SIPTransport sipTransport,
            SIPMonitorLogDelegate statefulProxyLogEvent,
            QueueNewCallDelegate queueNewCall,
            DialStringParser dialStringParser,
            string username,
            string adminMemberId,
            SIPEndPoint outboundProxy,
            ISIPCallManager callManager,
            DialPlanContext dialPlanContext)
        {
            m_sipTransport = sipTransport;
            m_statefulProxyLogEvent = statefulProxyLogEvent;
            QueueNewCall_External = queueNewCall;
            m_dialStringParser = dialStringParser;
            m_username = username;
            m_adminMemberId = adminMemberId;
            m_outboundProxySocket = outboundProxy;
            m_callManager = callManager;
            m_dialPlanContext = dialPlanContext;
        }
        public DialPlanScriptFacade(
            SIPTransport sipTransport,
            DialPlanExecutingScript executingScript,
            SIPMonitorLogDelegate logDelegate,
            DialogueBridgeCreatedDelegate createBridge,
            SIPRequest sipRequest,
            SIPCallDirection callDirection,
            DialPlanContext dialPlanContext,
            GetCanonicalDomainDelegate getCanonicalDomain,
            ISIPCallManager callManager,
            //SIPAssetPersistor<SIPAccount> sipAccountPersistor,
            //SIPAssetPersistor<SIPDialPlan> sipDialPlanPersistor,
            //SIPAssetPersistor<SIPDialogueAsset> sipDialoguePersistor,
            //SIPAssetGetListDelegate<SIPRegistrarBinding> getSIPAccountBindings,
            SIPSorceryPersistor sipSorceryPersistor,
            SIPEndPoint outboundProxySocket,
            DialPlanEngine dialPlanEngine
            )
        {
            m_sipTransport = sipTransport;
            m_executingScript = executingScript;
            m_dialPlanLogDelegate = logDelegate;
            CreateBridge_External = createBridge;
            m_sipRequest = sipRequest;
            m_callDirection = callDirection;
            m_dialPlanContext = dialPlanContext;
            m_getCanonicalDomainDelegate = getCanonicalDomain;
            m_callManager = callManager;
            //m_sipAccountPersistor = sipAccountPersistor;
            //m_sipDialPlanPersistor = sipDialPlanPersistor;
            //m_sipDialoguePersistor = sipDialoguePersistor;
            //GetSIPAccountBindings_External = getSIPAccountBindings;
            m_sipSorceryPersistor = sipSorceryPersistor;
            m_outboundProxySocket = outboundProxySocket;

            m_executingScript.Cleanup = CleanupDialPlanScript;

            if (m_dialPlanContext != null)
            {
                m_username = dialPlanContext.Owner;
                m_adminMemberId = dialPlanContext.AdminMemberId;
                m_sipProviders = dialPlanContext.SIPProviders;

                m_dialPlanContext.TraceLog.AppendLine("DialPlan=> Dialplan trace commenced at " + DateTime.Now.ToString("dd MMM yyyy HH:mm:ss:fff") + ".");
                m_dialPlanContext.CallCancelledByClient += ClientCallTerminated;

                SIPAssetGetDelegate<SIPAccount> getSIPAccount = null;
                if (m_sipSorceryPersistor != null && m_sipSorceryPersistor.SIPAccountsPersistor != null)
                {
                    getSIPAccount = m_sipSorceryPersistor.SIPAccountsPersistor.Get;
                }
                m_dialStringParser = new DialStringParser(m_sipTransport, m_dialPlanContext.Owner, m_dialPlanContext.SIPAccount, m_sipProviders, getSIPAccount, m_sipSorceryPersistor.SIPRegistrarBindingPersistor.Get, m_getCanonicalDomainDelegate, logDelegate, m_dialPlanContext.SIPDialPlan.DialPlanName);
            }
        }
Exemple #9
0
 public DialPlanCRMFacade(SIPMonitorLogDelegate logDelegate, DialPlanContext context)
 {
     LogToMonitor = logDelegate;
     m_context    = context;
 }
 private void ExecuteScript(
     DialPlanExecutingScript executingScript,
     DialPlanContext dialPlanContext,
     DialPlanScriptFacade planFacade,
     string script)
 {
     try
     {
         Thread.CurrentThread.Name = "dialplanscript-" + executingScript.ScriptNumber;
         if (m_impersonationUsername != null && m_impersonationPassword != null)
         {
             WrapperImpersonationContext impersonationConext = new WrapperImpersonationContext(null, m_impersonationUsername, m_impersonationPassword);
             impersonationConext.Enter();
         }
         //logger.Debug(Thread.CurrentThread.Name + " identity=" + WindowsIdentity.GetCurrent().Name + ".");
         FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dial plan execution starting on thread " + Thread.CurrentThread.Name + " for " + dialPlanContext.Owner + ".", null));
         executingScript.DialPlanScriptEngine.Execute(script, executingScript.DialPlanScriptScope);
         //FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dial plan execution finished after full script run on thread " + Thread.CurrentThread.Name + " for " + dialPlanContext.Owner + ".", null));
     }
     catch (ApplicationException appExcp)
     {
         if (appExcp.Message != "Script was halted by external intervention.")
         {
             logger.Error("ApplicationException ExecuteScript. " + appExcp.Message);
             FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "There was an exception executing your dial plan script: " + appExcp.Message, executingScript.Owner));
             FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "ApplicationException on user " + executingScript.Owner + "'s dial plan script. " + appExcp.Message, null));
             executingScript.ExecutionError = appExcp.Message;
         }
         else
         {
             FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dial plan execution finished after being halted due to execution interrupt on thread " + Thread.CurrentThread.Name + " for " + dialPlanContext.Owner + ".", null));
         }
     }
     //catch (System.Scripting.SyntaxErrorException)
     catch (SyntaxErrorException syntaxExcp)
     {
         logger.Warn("SyntaxErrorException. Owner=" + dialPlanContext.Owner + ", DialPlanName=" + dialPlanContext.SIPDialPlan.DialPlanName + ", Line=" + syntaxExcp.Line + ".");
         FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "There was a syntax error in your dial plan on line " + syntaxExcp.Line + ", please check.", executingScript.Owner));
         executingScript.ExecutionError = "Dial plan syntax error";
     }
     catch (MissingMethodException missingExcp)
     {
         logger.Warn("MissingMethodException. " + missingExcp.Message);
         FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "There was a missing method exception in your dial plan: " + missingExcp.Message + ".", executingScript.Owner));
         executingScript.ExecutionError = "Dial plan missing method";
     }
     catch (ThreadAbortException) { }
     catch (Exception excp)
     {
         logger.Error("Exception ExecuteScript (" + excp.GetType() + "). " + excp.Message);
         FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "There was an exception executing your dial plan script: " + excp.Message, executingScript.Owner));
         FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Exception on user " + executingScript.Owner + "'s dial plan script (" + excp.GetType() + "). " + excp.Message, null));
         executingScript.ExecutionError = "Dial plan exception";
     }
     finally
     {
         executingScript.StopExecution();
     }
 }
        public void Execute(
            DialPlanContext dialPlanContext,
            ISIPServerUserAgent uas,
            SIPCallDirection callDirection,
            DialogueBridgeCreatedDelegate createBridgeDelegate,
            ISIPCallManager callManager)
        {
            if (dialPlanContext == null)
            {
                throw new ArgumentNullException("The DialPlanContext parameter cannot be null when attempting to execute a dialplan.");
            }

            if (uas.IsUASAnswered)
            {
                // This can occur if the call is cancelled by the caller between when the INVITE was received and when the dialplan execution was ready.
                logger.Warn("Dialplan execution for " + dialPlanContext.SIPDialPlan.DialPlanName + " for " + uas.CallDirection + " call to " + uas.CallDestination + " did not proceed as call already answered.");
                dialPlanContext.DialPlanExecutionFinished();
            }
            else
            {
                if (dialPlanContext.ContextType == DialPlanContextsEnum.Line)
                {
                    ThreadPool.QueueUserWorkItem(delegate { ExecuteDialPlanLine((DialPlanLineContext)dialPlanContext, uas, callDirection, createBridgeDelegate, callManager); });
                }
                else
                {
                    ExecuteDialPlanScript((DialPlanScriptContext)dialPlanContext, uas, callDirection, createBridgeDelegate, callManager);
                }
            }
        }
 public DialPlanCRMFacade(SIPMonitorLogDelegate logDelegate, DialPlanContext context)
 {
     LogToMonitor = logDelegate;
     m_context = context;
 }
 public void Initialise(DialPlanContext dialPlanContext)
 {
     ExecutingDialPlanContext = dialPlanContext;
     Owner = ExecutingDialPlanContext.Owner;
     StartTime = DateTime.Now;
     EndTime = StartTime.AddSeconds(MAX_SCRIPTPROCESSING_SECONDS);
     Complete = false;
     ExecutionError = null;
     LastFailureStatus = SIPResponseStatusCodesEnum.None;
     LastFailureReason = null;
 }
Exemple #14
0
        private void MonitorScripts()
        {
            try
            {
                while (!StopScriptMonitoring)
                {
                    DialPlanExecutingScript[] killScripts = null;

                    bool lockTaken = false;
                    Monitor.TryEnter(m_runningScripts, 100, ref lockTaken);
                    if (lockTaken)
                    {
                        try
                        {
                            killScripts = (from script in m_runningScripts
                                           where
                                           script.Complete ||
                                           DateTime.Now > script.EndTime ||
                                           DateTime.Now.Subtract(script.StartTime).TotalSeconds > ABSOLUTEMAX_SCRIPTPROCESSING_SECONDS
                                           select script).ToArray();
                        }
                        finally
                        {
                            Monitor.Exit(m_runningScripts);
                        }
                    }
                    else
                    {
                        logger.Warn("Dialplan engine monitoring thread could not acquire a lock on the running scripts list.");
                    }

                    if (killScripts != null)
                    {
                        for (int index = 0; index < killScripts.Length; index++)
                        {
                            DialPlanExecutingScript killScript      = killScripts[index];
                            DialPlanContext         dialPlanContext = killScript.ExecutingDialPlanContext;

                            if (!killScript.Complete)
                            {
                                killScript.LogDelegate(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Long running dialplan script is being forcefully terminated.", killScript.Owner));
                            }

                            try
                            {
                                if (dialPlanContext != null && !dialPlanContext.IsAnswered)
                                {
                                    // The dialplan script has finished but the client call has not been answered. There could have be an
                                    // error executing the script or the dialplan could have completed without getting an answer.
                                    if (!killScript.ExecutionError.IsNullOrBlank())
                                    {
                                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dial plan execution completed without answering and had an execution error message of " + killScript.ExecutionError + ".", killScript.Owner));
                                        dialPlanContext.CallFailed(SIPResponseStatusCodesEnum.InternalServerError, killScript.ExecutionError, null);
                                    }
                                    else if (killScript.LastFailureStatus != SIPResponseStatusCodesEnum.None)
                                    {
                                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dial plan execution completed without answering and a last failure status of " + killScript.LastFailureStatus + " " + killScript.LastFailureReason + ".", killScript.Owner));
                                        dialPlanContext.CallFailed(killScript.LastFailureStatus, killScript.LastFailureReason, null);
                                    }
                                    else
                                    {
                                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dial plan execution completed without answering and with no last failure status.", killScript.Owner));
                                        dialPlanContext.CallFailed(SIPResponseStatusCodesEnum.TemporarilyUnavailable, null, null);
                                    }
                                }
                                else
                                {
                                    FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dial plan execution completed with normal clearing.", killScript.Owner));
                                }

                                long gcMemory       = GC.GetTotalMemory(false);
                                long physicalMemory = System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64;

                                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Dial plan finished for " + killScript.Owner + ", gc memory=" + gcMemory + ", physical memory=" + physicalMemory + ", running script count=" + ScriptCount + ".", null));
                            }
                            catch (Exception finallyExcp)
                            {
                                logger.Error("Exception MonitorScripts Kill. " + finallyExcp.Message);
                            }
                            finally
                            {
                                try
                                {
                                    /*if (killScript.DialPlanScriptThread != null && killScript.DialPlanScriptThread.IsAlive)
                                     * {
                                     *  //logger.Debug("Aborting dialplan script thread.");
                                     *  killScript.DialPlanScriptThread.Abort();
                                     * }*/

                                    killScript.StopExecution();
                                }
                                catch (ThreadStateException) { } // This exception is thrown when aborting a thread in a suspended state and is expected behaviour.
                                catch (Exception killExcp)
                                {
                                    logger.Error("Exception MonitorScripts aborting thread (" + killExcp.GetType().ToString() + "). " + killExcp.Message);
                                }

                                lock (m_runningScripts)
                                {
                                    m_runningScripts.Remove(killScript);
                                }
                                logger.Debug("Executing script " + killScript.DialPlanScriptThread.Name + " removed from running scripts list, running script count=" + ScriptCount + ".");
                            }
                        }
                    }

                    Thread.Sleep(500);
                }

                if (StopScriptMonitoring)
                {
                    if (m_runningScripts.Count > 0)
                    {
                        for (int index = 0; index < m_runningScripts.Count; index++)
                        {
                            if (m_runningScripts[index].DialPlanScriptThread != null && m_runningScripts[index].DialPlanScriptThread.IsAlive)
                            {
                                try
                                {
                                    m_runningScripts[index].DialPlanScriptThread.Abort();
                                }
                                catch (Exception finalKill)
                                {
                                    logger.Debug("Exception on script final kill. " + finalKill.Message);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception excp)
            {
                logger.Error("Exception MonitorScripts. " + excp);
            }
        }