diff --git a/src/include/switch_types.h b/src/include/switch_types.h index bf9d88b895..6818f67aa7 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -941,7 +941,8 @@ typedef uint32_t switch_frame_flag_t; typedef enum { SAF_NONE = 0, - SAF_SUPPORT_NOMEDIA = (1 << 0) + SAF_SUPPORT_NOMEDIA = (1 << 0), + SAF_ROUTING_EXEC = (1 << 1) } switch_application_flag_enum_t; typedef uint32_t switch_application_flag_t; diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 8b6aae0fef..e11d2b6b07 100644 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -2722,29 +2722,29 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "transfer", "Transfer a channel", TRANSFER_LONG_DESC, transfer_function, " [ ]", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "check_acl", "Check an ip against an ACL list", "Check an ip against an ACL list", check_acl_function, - " []", SAF_SUPPORT_NOMEDIA); - SWITCH_ADD_APP(app_interface, "verbose_events", "Make ALL Events verbose.", "Make ALL Events verbose.", verbose_events_function, "", SAF_SUPPORT_NOMEDIA); + " []", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + SWITCH_ADD_APP(app_interface, "verbose_events", "Make ALL Events verbose.", "Make ALL Events verbose.", verbose_events_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); SWITCH_ADD_APP(app_interface, "sleep", "Pause a channel", SLEEP_LONG_DESC, sleep_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "delay_echo", "echo audio at a specified delay", "Delay n ms", delay_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "strftime", "strftime", "strftime", strftime_function, "[|]", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "phrase", "Say a Phrase", "Say a Phrase", phrase_function, ",", SAF_NONE); - SWITCH_ADD_APP(app_interface, "eval", "Do Nothing", "Do Nothing", eval_function, "", SAF_SUPPORT_NOMEDIA); + SWITCH_ADD_APP(app_interface, "eval", "Do Nothing", "Do Nothing", eval_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); SWITCH_ADD_APP(app_interface, "pre_answer", "Pre-Answer the call", "Pre-Answer the call for a channel.", pre_answer_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "answer", "Answer the call", "Answer the call for a channel.", answer_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "hangup", "Hangup the call", "Hangup the call for a channel.", hangup_function, "[]", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "set_name", "Name the channel", "Name the channel", set_name_function, "", SAF_SUPPORT_NOMEDIA); - SWITCH_ADD_APP(app_interface, "presence", "Send Presence", "Send Presence.", presence_function, " []", SAF_SUPPORT_NOMEDIA); - SWITCH_ADD_APP(app_interface, "log", "Logs to the logger", LOG_LONG_DESC, log_function, " ", SAF_SUPPORT_NOMEDIA); - SWITCH_ADD_APP(app_interface, "info", "Display Call Info", "Display Call Info", info_function, "", SAF_SUPPORT_NOMEDIA); - SWITCH_ADD_APP(app_interface, "event", "Fire an event", "Fire an event", event_function, "", SAF_SUPPORT_NOMEDIA); + SWITCH_ADD_APP(app_interface, "presence", "Send Presence", "Send Presence.", presence_function, " []", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + SWITCH_ADD_APP(app_interface, "log", "Logs to the logger", LOG_LONG_DESC, log_function, " ", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + SWITCH_ADD_APP(app_interface, "info", "Display Call Info", "Display Call Info", info_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + SWITCH_ADD_APP(app_interface, "event", "Fire an event", "Fire an event", event_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); SWITCH_ADD_APP(app_interface, "sound_test", "Analyze Audio", "Analyze Audio", sound_test_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "export", "Export a channel variable across a bridge", EXPORT_LONG_DESC, export_function, "=", - SAF_SUPPORT_NOMEDIA); - SWITCH_ADD_APP(app_interface, "set", "Set a channel variable", SET_LONG_DESC, set_function, "=", SAF_SUPPORT_NOMEDIA); + SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + SWITCH_ADD_APP(app_interface, "set", "Set a channel variable", SET_LONG_DESC, set_function, "=", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); SWITCH_ADD_APP(app_interface, "set_global", "Set a global variable", SET_GLOBAL_LONG_DESC, set_global_function, "=", - SAF_SUPPORT_NOMEDIA); + SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); SWITCH_ADD_APP(app_interface, "set_profile_var", "Set a caller profile variable", SET_PROFILE_VAR_LONG_DESC, set_profile_var_function, - "=", SAF_SUPPORT_NOMEDIA); + "=", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); SWITCH_ADD_APP(app_interface, "unset", "Unset a channel variable", UNSET_LONG_DESC, unset_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "ring_ready", "Indicate Ring_Ready", "Indicate Ring_Ready on a channel.", ring_ready_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "remove_bugs", "Remove media bugs", "Remove all media bugs from a channel.", remove_bugs_function, "", SAF_NONE); diff --git a/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c b/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c index 1f6743eda5..aa862007a1 100644 --- a/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c +++ b/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c @@ -45,6 +45,40 @@ typedef enum { } break_t; +static switch_status_t exec_app(switch_core_session_t *session, const char *app, const char *arg) +{ + switch_application_interface_t *application_interface; + switch_status_t status = SWITCH_STATUS_SUCCESS; + switch_channel_t *channel = switch_core_session_get_channel(session); + + switch_assert(channel); + + if ((application_interface = switch_loadable_module_get_application_interface(app)) == 0) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Application %s\n", app); + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + return SWITCH_STATUS_FALSE; + } + + if (!application_interface->application_function) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No Function for %s\n", app); + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + switch_goto_status(SWITCH_STATUS_FALSE, done); + } + + if (!switch_test_flag(application_interface, SAF_ROUTING_EXEC)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "This application cannot be executed inline\n"); + switch_goto_status(SWITCH_STATUS_FALSE, done); + } + + switch_core_session_exec(session, application_interface, arg); + +done: + + UNPROTECT_INTERFACE(application_interface); + + return status; +} + static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *caller_profile, switch_xml_t xexten, switch_caller_extension_t **extension) { switch_xml_t xcond, xaction, xexpression; @@ -95,63 +129,63 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t * int test = tm.tm_year + 1900; time_match = switch_number_cmp(xyear, test); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, - "Dialplan: year[%d] =~ %s %s\n", test, xyear, time_match ? "PASS" : "FAIL"); + "Dialplan: year[%d] =~ %s (%s)\n", test, xyear, time_match ? "PASS" : "FAIL"); } if (time_match && xyday) { int test = tm.tm_yday + 1; time_match = switch_number_cmp(xyday, test); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, - "Dialplan: day of year[%d] =~ %s %s\n", test, xyday, time_match ? "PASS" : "FAIL"); + "Dialplan: day of year[%d] =~ %s (%s)\n", test, xyday, time_match ? "PASS" : "FAIL"); } if (time_match && xmon) { int test = tm.tm_mon + 1; time_match = switch_number_cmp(xmon, test); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, - "Dialplan: month[%d] =~ %s %s\n", test, xmon, time_match ? "PASS" : "FAIL"); + "Dialplan: month[%d] =~ %s (%s)\n", test, xmon, time_match ? "PASS" : "FAIL"); } if (time_match && xmday) { int test = tm.tm_mday; time_match = switch_number_cmp(xmday, test); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, - "Dialplan: day of month[%d] =~ %s %s\n", test, xmday, time_match ? "PASS" : "FAIL"); + "Dialplan: day of month[%d] =~ %s (%s)\n", test, xmday, time_match ? "PASS" : "FAIL"); } if (time_match && xweek) { int test = (int) (tm.tm_yday + 1 / 7); time_match = switch_number_cmp(xweek, test); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, - "Dialplan: week of year[%d] =~ %s %s\n", test, xweek, time_match ? "PASS" : "FAIL"); + "Dialplan: week of year[%d] =~ %s (%s)\n", test, xweek, time_match ? "PASS" : "FAIL"); } if (time_match && xwday) { int test = tm.tm_wday + 1; time_match = switch_number_cmp(xwday, test); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, - "Dialplan: day of week[%d] =~ %s %s\n", test, xwday, time_match ? "PASS" : "FAIL"); + "Dialplan: day of week[%d] =~ %s (%s)\n", test, xwday, time_match ? "PASS" : "FAIL"); } if (time_match && xhour) { int test = tm.tm_hour; time_match = switch_number_cmp(xhour, test); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, - "Dialplan: hour[%d] =~ %s %s\n", test, xhour, time_match ? "PASS" : "FAIL"); + "Dialplan: hour[%d] =~ %s (%s)\n", test, xhour, time_match ? "PASS" : "FAIL"); } if (time_match && xminute) { int test = tm.tm_min; time_match = switch_number_cmp(xminute, test); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, - "Dialplan: minute[%d] =~ %s %s\n", test, xminute, time_match ? "PASS" : "FAIL"); + "Dialplan: minute[%d] =~ %s (%s)\n", test, xminute, time_match ? "PASS" : "FAIL"); } if (time_match && xminday) { int test = (tm.tm_hour * 60) + (tm.tm_min + 1); time_match = switch_number_cmp(xminday, test); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, - "Dialplan: minute of day[%d] =~ %s %s\n", test, xminday, time_match ? "PASS" : "FAIL"); + "Dialplan: minute of day[%d] =~ %s (%s)\n", test, xminday, time_match ? "PASS" : "FAIL"); } field = (char *) switch_xml_attr(xcond, "field"); @@ -227,12 +261,14 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t * if (anti_action) { for (xaction = switch_xml_child(xcond, "anti-action"); xaction; xaction = xaction->next) { - char *application = (char *) switch_xml_attr_soft(xaction, "application"); - char *data = (char *) switch_xml_attr_soft(xaction, "data"); + const char *application = switch_xml_attr_soft(xaction, "application"); + const char *data = switch_xml_attr_soft(xaction, "data"); + const char *inline_ = switch_xml_attr_soft(xaction, "inline"); + int xinline = switch_true(inline_); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, - "Dialplan: %s ANTI-Action %s(%s)\n", - switch_channel_get_name(channel), application, data); + "Dialplan: %s ANTI-Action %s(%s) %s\n", + switch_channel_get_name(channel), application, data, xinline ? "INLINE" : ""); if (!*extension) { if ((*extension = switch_caller_extension_new(session, exten_name, caller_profile->destination_number)) == 0) { @@ -242,7 +278,11 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t * } } - switch_caller_extension_add_application(session, *extension, application, data); + if (xinline) { + exec_app(session, application, data); + } else { + switch_caller_extension_add_application(session, *extension, application, data); + } proceed = 1; } } else { @@ -252,6 +292,8 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t * char *substituted = NULL; uint32_t len = 0; char *app_data = NULL; + const char *inline_ = switch_xml_attr_soft(xaction, "inline"); + int xinline = switch_true(inline_); if (!switch_strlen_zero(xaction->txt)) { data = xaction->txt; @@ -282,16 +324,24 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t * } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG_CLEAN(session), SWITCH_LOG_DEBUG, - "Dialplan: %s Action %s(%s)\n", - switch_channel_get_name(channel), application, app_data); + "Dialplan: %s Action %s(%s) %s\n", + switch_channel_get_name(channel), application, app_data, xinline ? "INLINE" : ""); + + + if (xinline) { + exec_app(session, application, app_data); + } else { + switch_caller_extension_add_application(session, *extension, application, app_data); + } - switch_caller_extension_add_application(session, *extension, application, app_data); switch_safe_free(substituted); } } switch_regex_safe_free(re); - if (do_break_i == BREAK_ON_TRUE || do_break_i == BREAK_ALWAYS) { + if (((anti_action == SWITCH_FALSE && do_break_i == BREAK_ON_TRUE) || + (anti_action == SWITCH_TRUE && do_break_i == BREAK_ON_FALSE)) || + do_break_i == BREAK_ALWAYS) { break; } }