diff --git a/src/include/switch_core.h b/src/include/switch_core.h index ce57eef43f..ed444a2430 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -640,6 +640,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_exec(_In_ switch_core_sessio _In_ const switch_application_interface_t *application_interface, _In_opt_z_ const char *arg); +SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application(_In_ switch_core_session_t *session, + _In_ const char *app, + _In_opt_z_ const char *arg); + SWITCH_DECLARE(switch_status_t) switch_core_session_execute_exten(_In_ switch_core_session_t *session, _In_z_ const char *exten, _In_opt_z_ const char *dialplan, diff --git a/src/include/switch_types.h b/src/include/switch_types.h index d8244ce278..932d39d70d 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -102,6 +102,7 @@ SWITCH_BEGIN_EXTERN_C #define SWITCH_PATH_SEPARATOR "/" #endif #define SWITCH_URL_SEPARATOR "://" +#define SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE "execute_on_answer" #define SWITCH_CALL_TIMEOUT_VARIABLE "call_timeout" #define SWITCH_HOLDING_UUID_VARIABLE "holding_uuid" #define SWITCH_API_BRIDGE_END_VARIABLE "api_after_bridge" diff --git a/src/switch_channel.c b/src/switch_channel.c index c8e562cea0..04d204c4b5 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -1533,7 +1533,17 @@ SWITCH_DECLARE(switch_status_t) switch_channel_perform_answer(switch_channel_t * status = switch_core_session_receive_message(channel->session, &msg); if (status == SWITCH_STATUS_SUCCESS) { + const char *var = switch_channel_get_variable(channel, SWITCH_CHANNEL_EXECUTE_ON_ANSWER_VARIABLE); + char *app; switch_channel_perform_mark_answered(channel, file, func, line); + if (var) { + char *arg = NULL; + app = switch_core_session_strdup(channel->session, var); + if ((arg = strchr(app, ' '))) { + *arg++ = '\0'; + } + switch_core_session_execute_application(channel->session, app, arg); + } } else { switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION); } diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 974c4f2434..5cbaa42853 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -950,6 +950,57 @@ SWITCH_DECLARE(switch_app_log_t *) switch_core_session_get_app_log(switch_core_s return session->app_log; } +SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application(switch_core_session_t *session, const char *app, const char *arg) +{ + const switch_application_interface_t *application_interface; + char *expanded = NULL; + + if ((application_interface = switch_loadable_module_get_application_interface(app)) == 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Application %s\n", app); + switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + return SWITCH_STATUS_FALSE; + } + + if (!application_interface->application_function) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Function for %s\n", app); + switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + return SWITCH_STATUS_FALSE; + } + + if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) && !switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA)) { + switch_ivr_media(session->uuid_str, SMF_NONE); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Application %s Requires media on channel %s!\n", + app, switch_channel_get_name(session->channel)); + } else if (!switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA) && !switch_channel_media_ready(session->channel)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Application %s Requires media! pre_answering channel %s\n", + app, switch_channel_get_name(session->channel)); + if (switch_channel_pre_answer(session->channel) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Well, that didn't work very well did it? ...\n"); + return SWITCH_STATUS_FALSE; + } + } + + if ((expanded = switch_channel_expand_variables(session->channel, arg)) != arg) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Expanded String %s(%s)\n", switch_channel_get_name(session->channel), app, expanded); + } + + if (switch_channel_get_variable(session->channel, "presence_id")) { + char *arg = switch_mprintf("%s(%s)", app, expanded); + if (arg) { + switch_channel_presence(session->channel, "unknown", arg); + switch_safe_free(arg); + } + } + + switch_core_session_exec(session, application_interface, expanded); + + if (expanded != arg) { + switch_safe_free(expanded); + } + + return SWITCH_STATUS_SUCCESS; +} + SWITCH_DECLARE(switch_status_t) switch_core_session_exec(switch_core_session_t *session, const switch_application_interface_t *application_interface, const char *arg) { switch_app_log_t *log, *lp; @@ -1000,13 +1051,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_exten(switch_core_se char *dp[25]; char *dpstr; int argc, x, count = 0; - char *expanded = NULL; switch_caller_profile_t *profile, *new_profile, *pp = NULL; switch_channel_t *channel = switch_core_session_get_channel(session); switch_dialplan_interface_t *dialplan_interface = NULL; switch_caller_extension_t *extension = NULL; - const switch_application_interface_t *application_interface; - switch_event_t *event; switch_status_t status = SWITCH_STATUS_SUCCESS; if (!(profile = switch_channel_get_caller_profile(channel))) { @@ -1076,55 +1124,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_exten(switch_core_se while (switch_channel_ready(channel) && extension->current_application) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Execute %s(%s)\n", extension->current_application->application_name, switch_str_nil(extension->current_application->application_data)); - if ((application_interface = switch_loadable_module_get_application_interface(extension->current_application->application_name)) == 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Application %s\n", extension->current_application->application_name); - status = SWITCH_STATUS_FALSE; + + if (switch_core_session_execute_application(session, + extension->current_application->application_name, + extension->current_application->application_data) != SWITCH_STATUS_SUCCESS) { goto done; } - - if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) && !switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Application %s Cannot be used with NO_MEDIA mode!\n", - extension->current_application->application_name); - status = SWITCH_STATUS_FALSE; - goto done; - } - - if (!application_interface->application_function) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Function for %s\n", extension->current_application->application_name); - status = SWITCH_STATUS_FALSE; - goto done; - } - - if ((expanded = - switch_channel_expand_variables(session->channel, - extension->current_application->application_data)) != extension->current_application->application_data) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Expanded String %s(%s)\n", extension->current_application->application_name, - expanded); - } - - if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(session->channel, event); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application", "%s", extension->current_application->application_name); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data-Orig", "%s", extension->current_application->application_data); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Application-Data", "%s", expanded); - switch_event_fire(&event); - } - - - if (switch_channel_get_variable(session->channel, "presence_id")) { - char *arg = switch_mprintf("%s(%s)", extension->current_application->application_name, expanded); - if (arg) { - switch_channel_presence(session->channel, "unknown", arg); - switch_safe_free(arg); - } - } - - switch_core_session_exec(session, application_interface, expanded); - - if (expanded != extension->current_application->application_data) { - switch_safe_free(expanded); - } - + extension->current_application = extension->current_application->next; } diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index ad5fb7d28f..86e9563b46 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -124,7 +124,6 @@ static void switch_core_standard_on_ring(switch_core_session_t *session) static void switch_core_standard_on_execute(switch_core_session_t *session) { switch_caller_extension_t *extension; - const switch_application_interface_t *application_interface; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Standard EXECUTE\n"); @@ -137,56 +136,15 @@ static void switch_core_standard_on_execute(switch_core_session_t *session) } while (switch_channel_get_state(session->channel) == CS_EXECUTE && extension->current_application) { - char *expanded = NULL; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Execute %s(%s)\n", switch_channel_get_name(session->channel), extension->current_application->application_name, switch_str_nil(extension->current_application->application_data)); - if ((application_interface = switch_loadable_module_get_application_interface(extension->current_application->application_name)) == 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Application %s\n", extension->current_application->application_name); - switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + + if (switch_core_session_execute_application(session, + extension->current_application->application_name, + extension->current_application->application_data) != SWITCH_STATUS_SUCCESS) { return; } - if (!application_interface->application_function) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Function for %s\n", extension->current_application->application_name); - switch_channel_hangup(session->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); - return; - } - - if (switch_channel_test_flag(session->channel, CF_PROXY_MODE) && !switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA)) { - switch_ivr_media(session->uuid_str, SMF_NONE); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Application %s Requires media on channel %s!\n", - extension->current_application->application_name, switch_channel_get_name(session->channel)); - } else if (!switch_test_flag(application_interface, SAF_SUPPORT_NOMEDIA) && !switch_channel_media_ready(session->channel)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Application %s Requires media! pre_answering channel %s\n", - extension->current_application->application_name, switch_channel_get_name(session->channel)); - if (switch_channel_pre_answer(session->channel) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Well, that didn't work very well did it? ...\n"); - return; - } - } - - if ((expanded = - switch_channel_expand_variables(session->channel, - extension->current_application->application_data)) != extension->current_application->application_data) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s Expanded String %s(%s)\n", switch_channel_get_name(session->channel), - extension->current_application->application_name, expanded); - } - - if (switch_channel_get_variable(session->channel, "presence_id")) { - char *arg = switch_mprintf("%s(%s)", extension->current_application->application_name, expanded); - if (arg) { - switch_channel_presence(session->channel, "unknown", arg); - switch_safe_free(arg); - } - } - switch_core_session_exec(session, application_interface, expanded); - //application_interface->application_function(session, expanded); - - if (expanded != extension->current_application->application_data) { - switch_safe_free(expanded); - } - if (switch_channel_test_flag(session->channel, CF_RESET)) { goto top; }