private void ParseDialPlan(string[] dialPlanEntries) { try { if (dialPlanEntries != null) { foreach (string line in dialPlanEntries) { if (line == null || line.Trim().Length == 0 || line.Trim().StartsWith(";")) { // Do nothing, blank or comment line. } else { if (line.Trim().StartsWith(DIALPLAN_LINESTART_KEY)) { // Split the line on the exten => data to get the data now that the line is recognised as a valid extension line. string op = Regex.Match(line, @"exten\s*(?<op>[=~>]+).+").Result("${op}"); DialPlanOpsEnum opType = DialPlanOpTypes.GetDialPlanOp(op); string[] lineFields = Regex.Split(line, op); if (lineFields == null || lineFields.Length <= 1) { logger.Warn("Dial plan line was invalid ignored: " + line); } else { string dstPattern = null; int priority = 1; string app = null; if (opType == DialPlanOpsEnum.Regex) { // Check for regex delimiter characters before splitting up the command line. If the regex contains commas it needs to be extracted first. if (lineFields[1].Trim().StartsWith(REGEX_DELIMITER_CHAR.ToString())) { int endDelimIndex = lineFields[1].Trim().Substring(1).IndexOf(REGEX_DELIMITER_CHAR); dstPattern = lineFields[1].Trim().Substring(1, endDelimIndex); string[] dataFields = lineFields[1].Trim().Substring(endDelimIndex + 3).Split(new char[] { ',' }, 2); priority = Convert.ToInt32(dataFields[0]); app = dataFields[1]; } } if (dstPattern == null) { string[] dataFields = lineFields[1].Trim().Split(new char[] { ',' }, 3); if (dataFields == null || dataFields.Length <= 2) { logger.Warn("Dial plan line was invalid ignored: " + line); } else { dstPattern = dataFields[0]; priority = Convert.ToInt32(dataFields[1]); app = dataFields[2]; } } if (dstPattern != null && app != null) { DialPlanCommand command = new DialPlanCommand(opType, dstPattern, priority, app, m_sipProviders); m_commands.Add(command); } } } else { logger.Warn("Unknown dial plan command ignored: " + line); } } } } } catch (Exception excp) { logger.Error("Exception ParseDialPlan. " + excp.Message); throw excp; } }
/// <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(); } }