public DialPlanScriptContext(           
     SIPMonitorLogDelegate monitorLogDelegate,
     SIPTransport sipTransport,
     DialogueBridgeCreatedDelegate createBridge,
     SIPEndPoint outboundProxy,
     ISIPServerUserAgent sipServerUserAgent,
     SIPDialPlan dialPlan,
     List<SIPProvider> sipProviders,
     string traceDirectory,
     string callersNetworkId,
     Guid customerId)
     : base(monitorLogDelegate, sipTransport, createBridge, outboundProxy, sipServerUserAgent, dialPlan, sipProviders, traceDirectory, callersNetworkId, customerId)
 {
     ContextType = DialPlanContextsEnum.Script;
 }
 public DialPlanLineContext(
     SIPMonitorLogDelegate monitorLogDelegate,
     SIPTransport sipTransport,
     DialogueBridgeCreatedDelegate createBridge,
     SIPEndPoint outboundProxy,
     ISIPServerUserAgent sipServerUserAgent,
     SIPDialPlan dialPlan,
     List<SIPProvider> sipProviders,
     string traceDirectory,
     string callersNetworkId,
     Customer customer)
     : base(monitorLogDelegate, sipTransport, createBridge, outboundProxy, sipServerUserAgent, dialPlan, sipProviders, traceDirectory, callersNetworkId, customer, null, null)
 {
     ContextType = DialPlanContextsEnum.Line;
      string[] dialPlanEntries = dialPlan.DialPlanScript.Split(new char[] { '\n' });
      ParseDialPlan(dialPlanEntries);
 }
        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);
            }
        }
        private List<ISIPClientUserAgent> m_uacWaitingForCallDetails = new List<ISIPClientUserAgent>(); // UACs can indicate they would like the call details when available.

        #endregion Fields

        #region Constructors

        public DialPlanContext(
            SIPMonitorLogDelegate monitorLogDelegate,
            SIPTransport sipTransport,
            DialogueBridgeCreatedDelegate createBridge,
            SIPEndPoint outboundProxy,
            ISIPServerUserAgent sipServerUserAgent,
            SIPDialPlan dialPlan,
            List<SIPProvider> sipProviders,
            string traceDirectory,
            string callersNetworkId,
            Guid customerId)
        {
            Log_External = monitorLogDelegate;
            CreateBridge_External = createBridge;
            m_sipTransport = sipTransport;
            m_outboundProxy = outboundProxy;
            m_sipServerUserAgent = sipServerUserAgent;
            m_dialPlan = dialPlan;
            m_sipProviders = sipProviders;
            m_traceDirectory = traceDirectory;
            CallersNetworkId = callersNetworkId;
            CustomerId = customerId;

            m_sipServerUserAgent.CallCancelled += ClientCallCancelled;
            m_sipServerUserAgent.NoRingTimeout += ClientCallNoRingTimeout;
            m_sipServerUserAgent.TransactionComplete += ClientTransactionRemoved;
            m_sipServerUserAgent.SetTraceDelegate(TransactionTraceMessage);
        }
Example #5
0
        /// <summary>
        /// Processes a dialplan script (currently Ruby scripts only) for a received SIP INVITE request.
        /// </summary>
        /// <param name="coreLogDelegate">A function delegate that passes log/diagnostics events back to the SIP Proxy Core.</param>
        /// <param name="createBridgeDelegate">A function delegate that is called in the event that the dial plan command results in a call being answered and a bridge needing to be created.</param>
        /// <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="clientTransaction">The SIP Invite transaction that initiated the dial plan processing.</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 ExecuteDialPlanScript(
            DialPlanScriptContext dialPlanContext,
            ISIPServerUserAgent uas,
            SIPCallDirection callDirection,
            DialogueBridgeCreatedDelegate createBridgeDelegate,
            ISIPCallManager callManager)
        {
            try
            {
                if (uas == null)
                {
                    throw new ArgumentNullException("The ISIPServerUserAgent parameter cannot be null when attempting to execute a dialplan script.");
                }

                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.NewCall, "Executing script dial plan for call to " + uas.CallDestination + ".", dialPlanContext.Owner));

                if (!dialPlanContext.DialPlanScript.IsNullOrBlank())
                {
                    DialPlanExecutingScript dialPlanExecutionScript = null;
                    int runningScriptCount = (from script in m_runningScripts where !script.Complete select script).Count();

                    if (runningScriptCount < MAX_ALLOWED_SCRIPTSCOPES)
                    {
                        m_dialPlanScriptContextsCreated++;
                        //FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Creating DialPlanExecutingScript number " + m_dialPlanScriptContextsCreated + " for dialplan execution for script owned by " + dialPlanContext.Owner + ".", null));
                        dialPlanExecutionScript = new DialPlanExecutingScript(FireProxyLogEvent);
                    }
                    else
                    {
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "Running script limit of " + MAX_ALLOWED_SCRIPTSCOPES + " reached.", null));
                        lock (m_runningScripts)
                        {
                            foreach (DialPlanExecutingScript runningScript in m_runningScripts)
                            {
                                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, " running script owner=" + runningScript.Owner + ", dialplan name=" + runningScript.ExecutingDialPlanContext.SIPDialPlan.DialPlanName + ", start time=" + runningScript.StartTime.ToString("dd MMM yyyy HH:mm:ss") + ", is complete=" + runningScript.Complete + ".", null));
                            }
                        }
                    }

                    if (dialPlanExecutionScript != null)
                    {
                        dialPlanExecutionScript.Initialise(dialPlanContext);

                        DialPlanScriptFacade planFacade = new DialPlanScriptFacade(
                            m_sipTransport,
                            dialPlanExecutionScript,
                            FireProxyLogEvent,
                            createBridgeDelegate,
                            (uas.CallRequest != null) ? uas.CallRequest.Copy() : null,      // A different copy to the req object. Stops inadvertent changes in the dialplan.
                            callDirection,
                            dialPlanContext,
                            GetCanonicalDomainDelegate_External,
                            callManager,
                            m_sipSorceryPersistor,
                            m_outboundProxySocket,
                            this);

                        DialPlanCRMFacade crmFacade = new DialPlanCRMFacade(FireProxyLogEvent, dialPlanContext);
                        DialPlanLookupFacade lookupFacade = new DialPlanLookupFacade(FireProxyLogEvent, dialPlanContext.Owner);

                        ScriptScope rubyScope = dialPlanExecutionScript.DialPlanScriptScope;
                        rubyScope.SetVariable(SCRIPT_HELPEROBJECT_NAME, planFacade);
                        rubyScope.SetVariable(SCRIPT_CRMOBJECT_NAME, crmFacade);
                        rubyScope.SetVariable(SCRIPT_LOOKUPOBJECT_NAME, lookupFacade);
                        if (uas.CallRequest != null)
                        {
                            rubyScope.SetVariable(SCRIPT_REQUESTOBJECT_NAME, uas.CallRequest.Copy());
                        }

                        dialPlanExecutionScript.DialPlanScriptThread = new Thread(new ParameterizedThreadStart(delegate { ExecuteScript(dialPlanExecutionScript, dialPlanContext, planFacade, m_rubyScriptCommon + dialPlanContext.DialPlanScript); }));

                        lock (m_runningScripts)
                        {
                            m_runningScripts.Add(dialPlanExecutionScript);
                        }

                        dialPlanExecutionScript.DialPlanScriptThread.Start();
                    }
                    else
                    {
                        FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.Error, "Error processing call " + uas.CallDestination + " there were no script slots available, script could not be executed.", dialPlanContext.Owner));
                        dialPlanContext.CallFailed(SIPResponseStatusCodesEnum.InternalServerError, "Dial plan script engine was overloaded", null);
                    }
                }
                else
                {
                    FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.DialPlan, "A script dial plan was empty, execution cannot continue.", dialPlanContext.Owner));
                    dialPlanContext.CallFailed(SIPResponseStatusCodesEnum.InternalServerError, "Dial plan script was empty", null);
                }
            }
            catch (Exception excp)
            {
                FireProxyLogEvent(new SIPMonitorConsoleEvent(SIPMonitorServerTypesEnum.AppServer, SIPMonitorEventTypesEnum.Error, "Error executing script dialplan for " + uas.CallDestination + ". " + excp.Message, dialPlanContext.Owner));
                dialPlanContext.CallFailed(SIPResponseStatusCodesEnum.InternalServerError, "Dial plan exception starting script", null);
            }
        }
Example #6
0
        /// <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();
            }
        }
Example #7
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);
                }
            }
        }