diff --git a/modules/dialog/README b/modules/dialog/README index 98f4e404179..1cabb5da123 100644 --- a/modules/dialog/README +++ b/modules/dialog/README @@ -124,10 +124,11 @@ Vladut-Stefan Paiu 1.9.4. profile_get_size 1.9.5. profile_list_dlgs 1.9.6. profile_get_values - 1.9.7. dlg_db_sync - 1.9.8. dlg_restore_db - 1.9.9. list_all_profiles - 1.9.10. profile_bin_status + 1.9.7. profile_end_dlgs + 1.9.8. dlg_db_sync + 1.9.9. dlg_restore_db + 1.9.10. list_all_profiles + 1.9.11. profile_bin_status 1.10. Exported pseudo-variables @@ -1609,7 +1610,26 @@ $var(account) = $dlg_val(account_type); inbound_calls _empty_line_ -1.9.7. dlg_db_sync +1.9.7. profile_end_dlgs + + Terminate all ongoing dialogs from a specified profile, on a + single dialog it performs the same operations as the command + dlg_end_dlg + + Name: profile_end_dlgs + + Parameters: + * profile - name of the profile that will have its dialogs + termianted + * value - (optional) if the profile supports values terminate + only the dialogs with the specified value + + MI FIFO Command Format: + :profile_end_dlgs:_reply_fifo_file_ + inbound_calls + _empty_line_ + +1.9.8. dlg_db_sync Will synchronize the information about the dialogs from the database with the OpenSIPS internal memory. To be used mainly @@ -1624,7 +1644,7 @@ $var(account) = $dlg_val(account_type); :dlg_db_sync:_reply_fifo_file_ _empty_line_ -1.9.8. dlg_restore_db +1.9.9. dlg_restore_db Restores the dialog table after a potential desynchronization event. The table is truncated, then populated with CONFIRMED @@ -1638,7 +1658,7 @@ $var(account) = $dlg_val(account_type); :dlg_restore_db:_reply_fifo_file_ _empty_line_ -1.9.9. list_all_profiles +1.9.10. list_all_profiles Lists all the dialog profiles, along with 1 or 0 if the given profile has/does not have an associated value. @@ -1651,7 +1671,7 @@ $var(account) = $dlg_val(account_type); :list_all_profiles:_reply_fifo_file_ _empty_line_ -1.9.10. profile_bin_status +1.9.11. profile_bin_status Dumps each destination used for profiles replication, as well as the timestamp of the last message received from them. diff --git a/modules/dialog/dialog.c b/modules/dialog/dialog.c index 163477b440f..4785196cfb2 100644 --- a/modules/dialog/dialog.c +++ b/modules/dialog/dialog.c @@ -308,6 +308,7 @@ static mi_export_t mi_cmds[] = { { "profile_list_dlgs", 0, mi_profile_list, 0, 0, 0}, { "profile_get_values", 0, mi_get_profile_values, 0, 0, 0}, { "list_all_profiles", 0, mi_list_all_profiles, 0, 0, 0}, + { "profile_end_dlgs", 0, mi_profile_terminate, 0, 0, 0}, { 0, 0, 0, 0, 0, 0} }; diff --git a/modules/dialog/dlg_profile.c b/modules/dialog/dlg_profile.c index 54b63b935c3..410cf009237 100644 --- a/modules/dialog/dlg_profile.c +++ b/modules/dialog/dlg_profile.c @@ -35,6 +35,7 @@ #include "dlg_hash.h" #include "dlg_profile.h" #include "dlg_repl_profile.h" +#include "dlg_req_within.h" #define PROFILE_HASH_SIZE 16 @@ -1280,3 +1281,98 @@ struct mi_root * mi_list_all_profiles(struct mi_root *cmd_tree, void *param ) return rpl_tree; } + +struct mi_root * mi_profile_terminate(struct mi_root *cmd_tree, void *param ) { + struct mi_node* node; + struct dlg_profile_table *profile; + str *profile_name; + str *value; + unsigned int i; + struct dlg_entry *d_entry; + struct dlg_cell *cur_dlg; + struct dlg_profile_link *cur_link; + struct dialog_list *deleted = NULL, *delete_entry ; + + node = cmd_tree->node.kids; + if (node==NULL || !node->value.s || !node->value.len) + return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM)); + profile_name = &node->value; + + if (node->next) { + node = node->next; + if (!node->value.s || !node->value.len) + return init_mi_tree( 400, MI_SSTR(MI_BAD_PARM)); + if (node->next) + return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM)); + value = &node->value; + } else { + value = NULL; + } + + profile = search_dlg_profile( profile_name ); + + if (profile==NULL) + return init_mi_tree( 404, MI_SSTR("Profile not found")); + + for (i = 0; i < d_table->size; i++) { + d_entry = &(d_table->entries[i]); + lock_set_get(d_table->locks,d_entry->lock_idx); + + cur_dlg = d_entry->first; + while( cur_dlg ) { + + cur_link = cur_dlg ->profile_links; + + while(cur_link) { + if( cur_link->profile == profile && + ( value == NULL || + ( value->len == cur_link->value.len + && !strncmp(value->s,cur_link->value.s, value->len)) + )) { + delete_entry = pkg_malloc(sizeof(struct dialog_list)); + if (!delete_entry) { + LM_CRIT("no more pkg memory\n"); + lock_set_release(d_table->locks,d_entry->lock_idx); + return init_mi_tree( 400, MI_SSTR(MI_INTERNAL_ERR)); + } + + delete_entry->dlg = cur_dlg; + delete_entry->next = deleted; + deleted = delete_entry; + + ref_dlg_unsafe(cur_dlg, 1); + + break; + } + cur_link = cur_link->next; + } + cur_dlg = cur_dlg->next; + } + + lock_set_release(d_table->locks,d_entry->lock_idx); + + delete_entry = deleted; + while(delete_entry){ + init_dlg_term_reason(delete_entry->dlg,"MI Termination",sizeof("MI Termination")-1); + + if ( dlg_end_dlg( delete_entry->dlg, NULL) ) { + while(delete_entry){ + deleted = delete_entry; + delete_entry = delete_entry->next; + pkg_free(deleted); + } + LM_CRIT("eror while terminating dlg\n"); + return init_mi_tree( 400, MI_SSTR("Dialog internal error")); + } + + unref_dlg(delete_entry->dlg, 1); + deleted = delete_entry; + delete_entry = delete_entry->next; + pkg_free(deleted); + } + + deleted = NULL; + } + + return init_mi_tree(400, MI_SSTR(MI_OK)); +} diff --git a/modules/dialog/dlg_profile.h b/modules/dialog/dlg_profile.h index 15a471627dd..59e7c434767 100644 --- a/modules/dialog/dlg_profile.h +++ b/modules/dialog/dlg_profile.h @@ -83,6 +83,11 @@ struct dlg_profile_table { struct dlg_profile_table *next; }; +struct dialog_list{ + struct dlg_cell *dlg; + struct dialog_list *next; +}; + typedef int (*set_dlg_profile_f)(struct dlg_cell *dlg, str *value, struct dlg_profile_table *profile, char is_replicated); @@ -131,6 +136,8 @@ struct mi_root * mi_profile_list(struct mi_root *cmd_tree, void *param ); struct mi_root * mi_list_all_profiles(struct mi_root *cmd_tree, void *param ); +struct mi_root * mi_profile_terminate(struct mi_root *cmd_tree, void *param ); + void get_value_names(struct dlg_profile_table *profile, struct dlg_profile_value_name *); /* cachedb interface */ diff --git a/modules/dialog/doc/dialog_admin.xml b/modules/dialog/doc/dialog_admin.xml index 7ab03e3d04f..1adb0cf5302 100644 --- a/modules/dialog/doc/dialog_admin.xml +++ b/modules/dialog/doc/dialog_admin.xml @@ -2129,7 +2129,7 @@ $var(account) = $dlg_val(account_type); -
+
<varname>dlg_end_dlg</varname> Terminates an ongoing dialog. @@ -2268,7 +2268,34 @@ $var(account) = $dlg_val(account_type); _empty_line_
- +
+ <varname>profile_end_dlgs</varname> + + Terminate all ongoing dialogs from a specified profile, on a single dialog it + performs the same operations as the command + + + Name: profile_end_dlgs + + Parameters: + + + profile - name of the profile that will have its dialogs termianted + + + value - (optional) if the profile supports values terminate only the dialogs + with the specified value + + + + MI FIFO Command Format: + + + :profile_end_dlgs:_reply_fifo_file_ + inbound_calls + _empty_line_ + +
<varname>dlg_db_sync</varname>