diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 3d8b2e8988..0d21a9fe2e 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -980,11 +980,21 @@ typedef enum { \param var_val The value to look for \param cause the hangup cause to apply to the hungup channels */ -SWITCH_DECLARE(uint32_t) switch_core_session_hupall_matching_var_ans(_In_ const char *var_name, _In_ const char *var_val, _In_ +SWITCH_DECLARE(uint32_t) switch_core_session_hupall_matching_var_ans(_In_ const char *var_name, _In_ const char *var_val, _In_ switch_call_cause_t cause, switch_hup_type_t type); SWITCH_DECLARE(switch_console_callback_match_t *) switch_core_session_findall_matching_var(const char *var_name, const char *var_val); #define switch_core_session_hupall_matching_var(_vn, _vv, _c) switch_core_session_hupall_matching_var_ans(_vn, _vv, _c, SHT_UNANSWERED | SHT_ANSWERED) SWITCH_DECLARE(switch_console_callback_match_t *) switch_core_session_findall(void); +/*! + \brief Hangup all sessions which match specific channel variable(s) + \param var_name The variable name to look for + \param var_val The value to look for + \param cause the hangup cause to apply to the hungup channels +*/ +SWITCH_DECLARE(uint32_t) switch_core_session_hupall_matching_vars_ans(_In_ switch_event_t *vars, _In_ + switch_call_cause_t cause, switch_hup_type_t type); +#define switch_core_session_hupall_matching_vars(_vs, _c) switch_core_session_hupall_matching_vars_ans(_vs, _c, SHT_UNANSWERED | SHT_ANSWERED) + /*! \brief Hangup all sessions that belong to an endpoint \param endpoint_interface The endpoint interface diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index e1cb3f0063..93593b4629 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -6283,37 +6283,48 @@ SWITCH_STANDARD_API(strftime_tz_api_function) SWITCH_STANDARD_API(hupall_api_function) { - char *mycmd = NULL, *argv[3] = { 0 }; - char *var = NULL; - char *val = NULL; + char *mycmd = NULL, *argv[11] = { 0 }; switch_call_cause_t cause = SWITCH_CAUSE_MANAGER_REQUEST; + switch_event_t *vars = NULL; + int vars_count = 0; if (!zstr(cmd) && (mycmd = strdup(cmd))) { - switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + int argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + int i; switch_assert(argv[0]); if ((cause = switch_channel_str2cause(argv[0])) == SWITCH_CAUSE_NONE) { cause = SWITCH_CAUSE_MANAGER_REQUEST; } - var = argv[1]; - val = argv[2]; + for (i = 1; i < argc - 1; i += 2) { + char *var = argv[i]; + char *val = argv[i + 1]; + if (!zstr(var) && !zstr(val)) { + if (!vars) { + switch_event_create(&vars, SWITCH_EVENT_CLONE); + } + switch_event_add_header_string(vars, SWITCH_STACK_BOTTOM, var, val); + vars_count++; + } + } } - if (!val) { - var = NULL; - } - - if (zstr(var)) { + if (!vars_count) { switch_core_session_hupall(cause); } else { - switch_core_session_hupall_matching_var(var, val, cause); + switch_core_session_hupall_matching_vars(vars, cause); } - if (zstr(var)) { + if (!vars_count) { stream->write_function(stream, "+OK hangup all channels with cause %s\n", switch_channel_cause2str(cause)); + } else if (vars_count == 1) { + stream->write_function(stream, "+OK hangup all channels matching [%s]=[%s] with cause: %s\n", argv[1], argv[2], switch_channel_cause2str(cause)); } else { - stream->write_function(stream, "+OK hangup all channels matching [%s]=[%s] with cause: %s\n", var, val, switch_channel_cause2str(cause)); + stream->write_function(stream, "+OK hangup all channels matching [%s]=[%s]... with cause: %s\n", argv[1], argv[2], switch_channel_cause2str(cause)); } + if (vars) { + switch_event_destroy(&vars); + } switch_safe_free(mycmd); return SWITCH_STATUS_SUCCESS; } @@ -7199,7 +7210,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) SWITCH_ADD_API(commands_api_interface, "switchname", "Return the switch name", switchname_api_function, ""); SWITCH_ADD_API(commands_api_interface, "gethost", "gethostbyname", gethost_api_function, ""); SWITCH_ADD_API(commands_api_interface, "getenv", "getenv", getenv_function, GETENV_SYNTAX); - SWITCH_ADD_API(commands_api_interface, "hupall", "hupall", hupall_api_function, " [ ]"); + SWITCH_ADD_API(commands_api_interface, "hupall", "hupall", hupall_api_function, " [ ] [ ]"); SWITCH_ADD_API(commands_api_interface, "in_group", "Determine if a user is in a group", in_group_function, "[@] "); SWITCH_ADD_API(commands_api_interface, "is_lan_addr", "See if an ip is a lan addr", lan_addr_function, ""); SWITCH_ADD_API(commands_api_interface, "limit_usage", "Get the usage count of a limited resource", limit_usage_function, " "); diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 8433308609..240da23886 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -207,8 +207,7 @@ struct str_node { struct str_node *next; }; -SWITCH_DECLARE(uint32_t) switch_core_session_hupall_matching_var_ans(const char *var_name, const char *var_val, switch_call_cause_t cause, - switch_hup_type_t type) +SWITCH_DECLARE(uint32_t) switch_core_session_hupall_matching_vars_ans(switch_event_t *vars, switch_call_cause_t cause, switch_hup_type_t type) { switch_hash_index_t *hi; void *val; @@ -219,7 +218,7 @@ SWITCH_DECLARE(uint32_t) switch_core_session_hupall_matching_var_ans(const char switch_core_new_memory_pool(&pool); - if (!var_val) + if (!vars || !vars->headers) return r; switch_mutex_lock(runtime.session_hash_mutex); @@ -243,11 +242,23 @@ SWITCH_DECLARE(uint32_t) switch_core_session_hupall_matching_var_ans(const char for(np = head; np; np = np->next) { if ((session = switch_core_session_locate(np->str))) { - const char *this_val; - if (switch_channel_up_nosig(session->channel) && - (this_val = switch_channel_get_variable(session->channel, var_name)) && (!strcmp(this_val, var_val))) { - switch_channel_hangup(session->channel, cause); - r++; + const char *this_value; + if (switch_channel_up_nosig(session->channel)) { + /* check if all conditions are satisfied */ + int do_hangup = 1; + switch_event_header_t *hp; + for (hp = vars->headers; hp; hp = hp->next) { + const char *var_name = hp->name; + const char *var_value = hp->value; + if (!(this_value = switch_channel_get_variable(session->channel, var_name)) || (strcmp(this_value, var_value))) { + do_hangup = 0; + break; + } + } + if (do_hangup) { + switch_channel_hangup(session->channel, cause); + r++; + } } switch_core_session_rwunlock(session); } @@ -258,6 +269,21 @@ SWITCH_DECLARE(uint32_t) switch_core_session_hupall_matching_var_ans(const char return r; } +SWITCH_DECLARE(uint32_t) switch_core_session_hupall_matching_var_ans(const char *var_name, const char *var_val, switch_call_cause_t cause, + switch_hup_type_t type) +{ + switch_event_t *vars; + int r = 0; + + if (!var_val || !var_name) + return r; + + switch_event_create(&vars, SWITCH_EVENT_CLONE); + switch_event_add_header_string(vars, SWITCH_STACK_BOTTOM, var_name, var_val); + r = switch_core_session_hupall_matching_vars_ans(vars, cause, type); + switch_event_destroy(&vars); + return r; +} SWITCH_DECLARE(switch_console_callback_match_t *) switch_core_session_findall_matching_var(const char *var_name, const char *var_val) {