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); } } }
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; }
/// <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; }
/// <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; }
/// <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; }
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); } }
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; }
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); } }