diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index e3519bc10e..b6d3a60d6d 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -87,13 +87,15 @@ typedef enum { SSF_NONE = 0, SSF_DESTROYED = (1 << 0), - SSF_WARN_TRANSCODE = (1 << 1) + SSF_WARN_TRANSCODE = (1 << 1), + SSF_HANGUP = (1 << 2) } switch_session_flag_t; struct switch_core_session { switch_memory_pool_t *pool; switch_thread_t *thread; + switch_thread_id_t thread_id; switch_endpoint_interface_t *endpoint_interface; switch_size_t id; switch_session_flag_t flags; diff --git a/src/include/switch_core.h b/src/include/switch_core.h index a08eb6676c..2fc783e742 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -591,6 +591,7 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(_Inout_ switch_core_ses SWITCH_DECLARE(void) switch_core_session_destroy_state(switch_core_session_t *session); SWITCH_DECLARE(void) switch_core_session_reporting_state(switch_core_session_t *session); +SWITCH_DECLARE(void) switch_core_session_hangup_state(switch_core_session_t *session); /*! \brief Provide the total number of sessions diff --git a/src/include/switch_cpp.h b/src/include/switch_cpp.h index b59c2165c8..a143b0616b 100644 --- a/src/include/switch_cpp.h +++ b/src/include/switch_cpp.h @@ -260,7 +260,7 @@ SWITCH_DECLARE(void) consoleCleanLog(char *msg); * \return an int status code indicating success or failure * */ - SWITCH_DECLARE(int) originate(CoreSession * a_leg_session, char *dest, int timeout = 60); + SWITCH_DECLARE(int) originate(CoreSession * a_leg_session, char *dest, int timeout = 60, switch_state_handler_table_t *handlers = NULL); SWITCH_DECLARE(virtual void) destroy(void); diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index 6f460be9ce..96ce47777d 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -6048,6 +6048,14 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_session_reporting_state(void * ja } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_session_hangup_state(void * jarg1) { + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + + arg1 = (switch_core_session_t *)jarg1; + switch_core_session_hangup_state(arg1); +} + + SWIGEXPORT unsigned long SWIGSTDCALL CSharp_switch_core_session_count() { unsigned long jresult ; uint32_t result; @@ -28592,19 +28600,21 @@ SWIGEXPORT void SWIGSTDCALL CSharp_CoreSession_SetCallerData(void * jarg1, char } -SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_Originate(void * jarg1, void * jarg2, char * jarg3, int jarg4) { +SWIGEXPORT int SWIGSTDCALL CSharp_CoreSession_Originate(void * jarg1, void * jarg2, char * jarg3, int jarg4, void * jarg5) { int jresult ; CoreSession *arg1 = (CoreSession *) 0 ; CoreSession *arg2 = (CoreSession *) 0 ; char *arg3 = (char *) 0 ; int arg4 = (int) 60 ; + switch_state_handler_table_t *arg5 = (switch_state_handler_table_t *) NULL ; int result; arg1 = (CoreSession *)jarg1; arg2 = (CoreSession *)jarg2; arg3 = (char *)jarg3; arg4 = (int)jarg4; - result = (int)(arg1)->originate(arg2,arg3,arg4); + arg5 = (switch_state_handler_table_t *)jarg5; + result = (int)(arg1)->originate(arg2,arg3,arg4,arg5); jresult = result; return jresult; } diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index 4a4cdcbbd4..c521a5f630 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -244,8 +244,8 @@ public class CoreSession : IDisposable { freeswitchPINVOKE.CoreSession_SetCallerData(swigCPtr, var, val); } - public int Originate(CoreSession a_leg_session, string dest, int timeout) { - int ret = freeswitchPINVOKE.CoreSession_Originate(swigCPtr, CoreSession.getCPtr(a_leg_session), dest, timeout); + public int Originate(CoreSession a_leg_session, string dest, int timeout, switch_state_handler_table handlers) { + int ret = freeswitchPINVOKE.CoreSession_Originate(swigCPtr, CoreSession.getCPtr(a_leg_session), dest, timeout, switch_state_handler_table.getCPtr(handlers)); return ret; } @@ -1142,6 +1142,10 @@ public class freeswitch { freeswitchPINVOKE.switch_core_session_reporting_state(SWIGTYPE_p_switch_core_session.getCPtr(session)); } + public static void switch_core_session_hangup_state(SWIGTYPE_p_switch_core_session session) { + freeswitchPINVOKE.switch_core_session_hangup_state(SWIGTYPE_p_switch_core_session.getCPtr(session)); + } + public static uint switch_core_session_count() { uint ret = freeswitchPINVOKE.switch_core_session_count(); return ret; @@ -6008,6 +6012,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_reporting_state")] public static extern void switch_core_session_reporting_state(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_hangup_state")] + public static extern void switch_core_session_hangup_state(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_count")] public static extern uint switch_core_session_count(); @@ -11289,7 +11296,7 @@ class freeswitchPINVOKE { public static extern void CoreSession_SetCallerData(HandleRef jarg1, string jarg2, string jarg3); [DllImport("mod_managed", EntryPoint="CSharp_CoreSession_Originate")] - public static extern int CoreSession_Originate(HandleRef jarg1, HandleRef jarg2, string jarg3, int jarg4); + public static extern int CoreSession_Originate(HandleRef jarg1, HandleRef jarg2, string jarg3, int jarg4, HandleRef jarg5); [DllImport("mod_managed", EntryPoint="CSharp_CoreSession_destroy")] public static extern void CoreSession_destroy(HandleRef jarg1); diff --git a/src/switch_channel.c b/src/switch_channel.c index 6b75ef6cea..1b0ee19aa3 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -1714,6 +1714,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_hangup(switch_chan switch_core_session_kill_channel(channel->session, SWITCH_SIG_KILL); switch_core_session_signal_state_change(channel->session); + switch_core_session_hangup_state(channel->session); } return channel->state; diff --git a/src/switch_core_session.c b/src/switch_core_session.c index c714581204..1544e884cf 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -1062,7 +1062,8 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t *thre const char *val; session->thread = thread; - + session->thread_id = switch_thread_self(); + switch_core_session_run(session); switch_core_media_bug_remove_all(session); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Session %" SWITCH_SIZE_T_FMT " (%s) Locked, Waiting on external entities\n", @@ -1207,6 +1208,7 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request_uuid(switch_ session = switch_core_alloc(usepool, sizeof(*session)); session->pool = usepool; + session->thread_id = switch_thread_self(); switch_core_memory_pool_set_data(session->pool, "__session", session); diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index 9fdf8a7f54..00ba89e308 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -413,69 +413,7 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session) goto done; case CS_HANGUP: /* Deactivate and end the thread */ { - const char *hook_var; - switch_core_session_t *use_session = NULL; - switch_call_cause_t cause = switch_channel_get_cause(session->channel); - switch_call_cause_t cause_q850 = switch_channel_get_cause_q850(session->channel); - switch_event_t *event; - - switch_channel_set_hangup_time(session->channel); - - switch_core_media_bug_remove_all(session); - - switch_channel_stop_broadcast(session->channel); - - switch_channel_set_variable(session->channel, "hangup_cause", switch_channel_cause2str(cause)); - switch_channel_set_variable_printf(session->channel, "hangup_cause_q850", "%d", cause_q850); - switch_channel_presence(session->channel, "unknown", switch_channel_cause2str(cause), NULL); - - switch_channel_set_timestamps(session->channel); - - STATE_MACRO(hangup, "HANGUP"); - - hook_var = switch_channel_get_variable(session->channel, SWITCH_API_HANGUP_HOOK_VARIABLE); - if (switch_true(switch_channel_get_variable(session->channel, SWITCH_SESSION_IN_HANGUP_HOOK_VARIABLE))) { - use_session = session; - } - - if (!switch_strlen_zero(hook_var)) { - switch_stream_handle_t stream = { 0 }; - char *cmd = switch_core_session_strdup(session, hook_var); - char *arg = NULL; - char *expanded = NULL; - - if ((arg = strchr(cmd, ':')) && *(arg+1) == ':') { - *arg++ = '\0'; - *arg++ = '\0'; - } else { - if ((arg = strchr(cmd, ' '))) { - *arg++ = '\0'; - } - } - - SWITCH_STANDARD_STREAM(stream); - - switch_channel_get_variables(session->channel, &stream.param_event); - switch_channel_event_set_data(session->channel, stream.param_event); - expanded = switch_channel_expand_variables(session->channel, arg); - - switch_api_execute(cmd, expanded, use_session, &stream); - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Hangup Command %s(%s):\n%s\n", cmd, switch_str_nil(expanded), - switch_str_nil((char *) stream.data)); - - if (expanded != arg) { - switch_safe_free(expanded); - } - switch_safe_free(stream.data); - } - - if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Hangup-Cause", switch_channel_cause2str(cause)); - switch_channel_event_set_data(session->channel, event); - switch_event_fire(&event); - } - + switch_core_session_hangup_state(session); switch_channel_set_state(session->channel, CS_REPORTING); } @@ -557,6 +495,8 @@ SWITCH_DECLARE(void) switch_core_session_destroy_state(switch_core_session_t *se switch_assert(session != NULL); switch_channel_set_running_state(session->channel, CS_DESTROY); + switch_channel_clear_flag(session->channel, CF_TRANSFER); + switch_channel_clear_flag(session->channel, CF_REDIRECT); session->thread_running = 1; endpoint_interface = session->endpoint_interface; @@ -571,6 +511,101 @@ SWITCH_DECLARE(void) switch_core_session_destroy_state(switch_core_session_t *se } +SWITCH_DECLARE(void) switch_core_session_hangup_state(switch_core_session_t *session) +{ + const char *hook_var; + switch_core_session_t *use_session = NULL; + switch_call_cause_t cause = switch_channel_get_cause(session->channel); + switch_call_cause_t cause_q850 = switch_channel_get_cause_q850(session->channel); + switch_event_t *event; + int proceed = 1; + int global_proceed = 1; + int do_extra_handlers = 1; + int silly = 0; + int index = 0; + switch_channel_state_t state = switch_channel_get_state(session->channel), midstate = state; + const switch_endpoint_interface_t *endpoint_interface; + const switch_state_handler_table_t *driver_state_handler = NULL; + const switch_state_handler_table_t *application_state_handler = NULL; + + + if (switch_thread_self() != session->thread_id) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "thread mismatch skipping state handler.\n"); + return; + } + + if (switch_test_flag(session, SSF_HANGUP)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "handler already called, skipping state handler.\n"); + return; + } + + endpoint_interface = session->endpoint_interface; + switch_assert(endpoint_interface != NULL); + + driver_state_handler = endpoint_interface->state_handler; + switch_assert(driver_state_handler != NULL); + + switch_channel_set_hangup_time(session->channel); + + switch_core_media_bug_remove_all(session); + + switch_channel_stop_broadcast(session->channel); + + switch_channel_set_variable(session->channel, "hangup_cause", switch_channel_cause2str(cause)); + switch_channel_set_variable_printf(session->channel, "hangup_cause_q850", "%d", cause_q850); + switch_channel_presence(session->channel, "unknown", switch_channel_cause2str(cause), NULL); + + switch_channel_set_timestamps(session->channel); + + STATE_MACRO(hangup, "HANGUP"); + + hook_var = switch_channel_get_variable(session->channel, SWITCH_API_HANGUP_HOOK_VARIABLE); + if (switch_true(switch_channel_get_variable(session->channel, SWITCH_SESSION_IN_HANGUP_HOOK_VARIABLE))) { + use_session = session; + } + + if (!switch_strlen_zero(hook_var)) { + switch_stream_handle_t stream = { 0 }; + char *cmd = switch_core_session_strdup(session, hook_var); + char *arg = NULL; + char *expanded = NULL; + + if ((arg = strchr(cmd, ':')) && *(arg+1) == ':') { + *arg++ = '\0'; + *arg++ = '\0'; + } else { + if ((arg = strchr(cmd, ' '))) { + *arg++ = '\0'; + } + } + + SWITCH_STANDARD_STREAM(stream); + + switch_channel_get_variables(session->channel, &stream.param_event); + switch_channel_event_set_data(session->channel, stream.param_event); + expanded = switch_channel_expand_variables(session->channel, arg); + + switch_api_execute(cmd, expanded, use_session, &stream); + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Hangup Command %s(%s):\n%s\n", cmd, switch_str_nil(expanded), + switch_str_nil((char *) stream.data)); + + if (expanded != arg) { + switch_safe_free(expanded); + } + switch_safe_free(stream.data); + } + + if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Hangup-Cause", switch_channel_cause2str(cause)); + switch_channel_event_set_data(session->channel, event); + switch_event_fire(&event); + } + + switch_set_flag(session, SSF_HANGUP); + +} + SWITCH_DECLARE(void) switch_core_session_reporting_state(switch_core_session_t *session) { switch_channel_state_t state = switch_channel_get_state(session->channel), midstate = state; diff --git a/src/switch_cpp.cpp b/src/switch_cpp.cpp index 3f4fc4d18a..b6c2f68128 100644 --- a/src/switch_cpp.cpp +++ b/src/switch_cpp.cpp @@ -932,7 +932,7 @@ SWITCH_DECLARE(void) CoreSession::destroy(void) } -SWITCH_DECLARE(int) CoreSession::originate(CoreSession *a_leg_session, char *dest, int timeout) +SWITCH_DECLARE(int) CoreSession::originate(CoreSession *a_leg_session, char *dest, int timeout, switch_state_handler_table_t *handlers) { switch_core_session_t *aleg_core_session = NULL; @@ -957,7 +957,7 @@ SWITCH_DECLARE(int) CoreSession::originate(CoreSession *a_leg_session, char *des &cause, dest, timeout, - NULL, + handlers, NULL, NULL, &caller_profile,