diff --git a/src/include/switch_core.h b/src/include/switch_core.h index d96a9dbabb..6ce6db4c41 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -615,7 +615,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); +SWITCH_DECLARE(void) switch_core_session_hangup_state(switch_core_session_t *session, switch_bool_t force); /*! \brief Provide the total number of sessions diff --git a/src/include/switch_types.h b/src/include/switch_types.h index c94b1eddb7..64974c1fdd 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -241,7 +241,8 @@ typedef enum { SCF_VG = (1 << 3), SCF_RESTART = (1 << 4), SCF_SHUTDOWN_REQUESTED = (1 << 5), - SCF_USE_AUTO_NAT = (1 << 6) + SCF_USE_AUTO_NAT = (1 << 6), + SCF_EARLY_HANGUP = (1 << 7) } switch_core_flag_enum_t; typedef uint32_t switch_core_flag_t; @@ -946,6 +947,7 @@ typedef enum { CF_BYPASS_MEDIA_AFTER_BRIDGE, CF_LEG_HOLDING, CF_BROADCAST_DROP_MEDIA, + CF_EARLY_HANGUP, /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */ CF_FLAG_MAX } switch_channel_flag_t; diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index c8b71e3e14..a668f14376 100644 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -2787,6 +2787,11 @@ SWITCH_STANDARD_APP(verbose_events_function) switch_channel_set_flag(switch_core_session_get_channel(session), CF_VERBOSE_EVENTS); } +SWITCH_STANDARD_APP(early_hangup_function) +{ + switch_channel_set_flag(switch_core_session_get_channel(session), CF_EARLY_HANGUP); +} + #define WAIT_FOR_SILENCE_SYNTAX " []" SWITCH_STANDARD_APP(wait_for_silence_function) { @@ -2939,6 +2944,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) 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 | 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, "early_hangup", "Enable early hangup", "", early_hangup_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); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 9e5fc7d074..148d1636d7 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -3833,6 +3833,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, case nua_callstate_completed: case nua_callstate_received: case nua_callstate_proceeding: + case nua_callstate_completing: if (!(session && channel && tech_pvt)) goto done; break; default: @@ -3890,9 +3891,9 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, break; case nua_callstate_completing: nua_ack(nh, - TAG_IF(tech_pvt && !zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), + TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END()); - break; + goto done; case nua_callstate_received: if (!sofia_test_flag(tech_pvt, TFLAG_SDP)) { if (r_sdp && !sofia_test_flag(tech_pvt, TFLAG_SDP)) { diff --git a/src/switch_channel.c b/src/switch_channel.c index d6357973d1..5ddc455858 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -1911,7 +1911,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); + switch_core_session_hangup_state(channel->session, SWITCH_FALSE); } return channel->state; diff --git a/src/switch_core.c b/src/switch_core.c index 0dee04d28b..e10489bf8d 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1382,6 +1382,8 @@ static void switch_load_core_config(const char *file) if (tmp > -1 && tmp < 11) { switch_core_session_ctl(SCSC_DEBUG_LEVEL, &tmp); } + } else if (!strcasecmp(var, "enable-early-hangup") && switch_true(val)) { + switch_set_flag((&runtime), SCF_EARLY_HANGUP); } else if (!strcasecmp(var, "colorize-console") && switch_true(val)) { runtime.colorize_console = SWITCH_TRUE; } else if (!strcasecmp(var, "mailer-app") && !zstr(val)) { diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index 917d3855a5..a088452070 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -329,7 +329,7 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session) goto done; case CS_HANGUP: /* Deactivate and end the thread */ { - switch_core_session_hangup_state(session); + switch_core_session_hangup_state(session, SWITCH_TRUE); switch_channel_set_state(session->channel, CS_REPORTING); } @@ -437,7 +437,7 @@ 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) +SWITCH_DECLARE(void) switch_core_session_hangup_state(switch_core_session_t *session, switch_bool_t force) { const char *hook_var; switch_core_session_t *use_session = NULL; @@ -454,15 +454,21 @@ SWITCH_DECLARE(void) switch_core_session_hangup_state(switch_core_session_t *ses const switch_state_handler_table_t *driver_state_handler = NULL; const switch_state_handler_table_t *application_state_handler = NULL; + + if (!force) { + if (!switch_channel_test_flag(session->channel, CF_EARLY_HANGUP) && !switch_test_flag((&runtime), SCF_EARLY_HANGUP)) { + return; + } - if (switch_thread_self() != session->thread_id) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s thread mismatch skipping state handler.\n", - switch_channel_get_name(session->channel)); - return; + if (switch_thread_self() != session->thread_id) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "%s thread mismatch skipping state handler.\n", + switch_channel_get_name(session->channel)); + return; + } } if (switch_test_flag(session, SSF_HANGUP)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s handler already called, skipping state handler.\n", + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG10, "%s handler already called, skipping state handler.\n", switch_channel_get_name(session->channel)); return; } diff --git a/src/switch_cpp.cpp b/src/switch_cpp.cpp index 009e742404..df229cbc57 100644 --- a/src/switch_cpp.cpp +++ b/src/switch_cpp.cpp @@ -569,7 +569,7 @@ SWITCH_DECLARE(void) CoreSession::hangupState(void) sanity_check_noreturn; this->begin_allow_threads(); if (switch_channel_down(channel)) { - switch_core_session_hangup_state(session); + switch_core_session_hangup_state(session, SWITCH_FALSE); } this->end_allow_threads(); }