diff --git a/src/modules/dispatcher/dispatch.c b/src/modules/dispatcher/dispatch.c index 5631a92e7a5..3d1098c462e 100644 --- a/src/modules/dispatcher/dispatch.c +++ b/src/modules/dispatcher/dispatch.c @@ -176,7 +176,7 @@ int ds_hash_load_destroy(void) /** * Recursivly iterate over ds_set and execute callback */ -void ds_iter_set(ds_set_t *node, void (*ds_action_cb)(ds_set_t *node, int i)) +void ds_iter_set(ds_set_t *node, void (*ds_action_cb)(ds_set_t *node, int i, void *arg), void *ds_action_arg) { if(!node) return; @@ -184,16 +184,16 @@ void ds_iter_set(ds_set_t *node, void (*ds_action_cb)(ds_set_t *node, int i)) int i; for(i = 0; i < 2; ++i) - ds_iter_set(node->next[i], ds_action_cb); + ds_iter_set(node->next[i], ds_action_cb, ds_action_arg); for(i = 0; i < node->nr; i++) { - ds_action_cb(node, i); + ds_action_cb(node, i, ds_action_arg); } return; } -void ds_log_dst_cb(ds_set_t *node, int i) +void ds_log_dst_cb(ds_set_t *node, int i, void *arg) { LM_DBG("dst>> %d %.*s %d %d (%.*s,%d,%d,%d)\n", node->id, node->dlist[i].uri.len, node->dlist[i].uri.s, @@ -208,7 +208,7 @@ void ds_log_dst_cb(ds_set_t *node, int i) */ void ds_log_set(ds_set_t *node) { - ds_iter_set(node, &ds_log_dst_cb); + ds_iter_set(node, &ds_log_dst_cb, NULL); return; } @@ -2350,7 +2350,7 @@ int ds_update_dst(struct sip_msg *msg, int upos, int mode) } /* callback for adding nodes based on index */ -void ds_add_dest_cb(ds_set_t *node, int i) +void ds_add_dest_cb(ds_set_t *node, int i, void *arg) { int setn; @@ -2378,7 +2378,7 @@ int ds_add_dst(int group, str *address, int flags) ds_avl_destroy(&ds_lists[*next_idx]); // add all existing destinations - ds_iter_set(_ds_list, &ds_add_dest_cb); + ds_iter_set(_ds_list, &ds_add_dest_cb, NULL); // add new destination if(add_dest2list(group, *address, flags, priority, &attrs, @@ -2406,6 +2406,61 @@ int ds_add_dst(int group, str *address, int flags) return -1; } +/* callback for removing nodes based on setid & address */ +void ds_filter_dest_cb(ds_set_t *node, int i, void *arg) +{ + struct ds_filter_dest_cb_arg *filter_arg = (typeof(filter_arg)) arg; + + if(node->id == filter_arg->setid && node->dlist[i].uri.len == filter_arg->dest->uri.len && + strncmp(node->dlist[i].uri.s, filter_arg->dest->uri.s, filter_arg->dest->uri.len) == 0) + return; + + if(add_dest2list(node->id, node->dlist[i].uri, node->dlist[i].flags, + node->dlist[i].priority, &node->dlist[i].attrs.body, *next_idx, + filter_arg->setn) != 0) { + LM_WARN("failed to add destination in group %d - %.*s\n", + node->id, node->dlist[i].uri.len, node->dlist[i].uri.s); + } + return; +} + +/* remove dispatcher entry from in-memory dispatcher list */ +int ds_remove_dst(int group, str *address) +{ + int setn; + struct ds_filter_dest_cb_arg filter_arg; + ds_dest_t *dp = NULL; + + setn = 0; + + dp = pack_dest(*address, 0, 0, NULL); + filter_arg.setid = group; + filter_arg.dest = dp; + filter_arg.setn = &setn; + + *next_idx = (*crt_idx + 1) % 2; + ds_avl_destroy(&ds_lists[*next_idx]); + + // add existing destinations except destination that matches group & address + ds_iter_set(_ds_list, &ds_filter_dest_cb, &filter_arg); + + if(reindex_dests(ds_lists[*next_idx]) != 0) { + LM_ERR("error on reindex\n"); + goto error; + } + + _ds_list_nr = setn; + *crt_idx = *next_idx; + ds_ht_clear_slots(_dsht_load); + ds_log_sets(); + return 0; + +error: + ds_avl_destroy(&ds_lists[*next_idx]); + *next_idx = *crt_idx; + return -1; +} + int ds_mark_dst(struct sip_msg *msg, int state) { sr_xavp_t *rxavp = NULL; diff --git a/src/modules/dispatcher/dispatch.h b/src/modules/dispatcher/dispatch.h index 2d52ef54cb8..3a6a5aedc6a 100644 --- a/src/modules/dispatcher/dispatch.h +++ b/src/modules/dispatcher/dispatch.h @@ -130,6 +130,7 @@ int ds_select_dst_limit(sip_msg_t *msg, int set, int alg, uint32_t limit, int ds_select_dst(struct sip_msg *msg, int set, int alg, int mode); int ds_update_dst(struct sip_msg *msg, int upos, int mode); int ds_add_dst(int group, str *address, int flags); +int ds_remove_dst(int group, str *address); int ds_update_state(sip_msg_t *msg, int group, str *address, int state); int ds_reinit_state(int group, str *address, int state); int ds_reinit_state_all(int group, int state); @@ -228,6 +229,12 @@ typedef struct _ds_select_state { sr_xavp_t *lxavp; } ds_select_state_t; +struct ds_filter_dest_cb_arg { + int setid; + ds_dest_t *dest; + int *setn; +}; + /* clang-format on */ #define AVL_LEFT 0 diff --git a/src/modules/dispatcher/dispatcher.c b/src/modules/dispatcher/dispatcher.c index 15224024956..df117222156 100644 --- a/src/modules/dispatcher/dispatcher.c +++ b/src/modules/dispatcher/dispatcher.c @@ -1668,6 +1668,31 @@ static void dispatcher_rpc_add(rpc_t *rpc, void *ctx) return; } +static const char *dispatcher_rpc_remove_doc[2] = { + "Remove a destination address from memory", 0}; + + +/* + * RPC command to remove a destination address from memory + */ +static void dispatcher_rpc_remove(rpc_t *rpc, void *ctx) +{ + int group; + str dest; + + if(rpc->scan(ctx, "dS", &group, &dest) < 2) { + rpc->fault(ctx, 500, "Invalid Parameters"); + return; + } + + if(ds_remove_dst(group, &dest) != 0) { + rpc->fault(ctx, 500, "Removing dispatcher dst failed"); + return; + } + + return; +} + /* clang-format off */ rpc_export_t dispatcher_rpc_cmds[] = { {"dispatcher.reload", dispatcher_rpc_reload, @@ -1680,6 +1705,8 @@ rpc_export_t dispatcher_rpc_cmds[] = { dispatcher_rpc_ping_active_doc, 0}, {"dispatcher.add", dispatcher_rpc_add, dispatcher_rpc_add_doc, 0}, + {"dispatcher.remove", dispatcher_rpc_remove, + dispatcher_rpc_remove_doc, 0}, {0, 0, 0, 0} }; /* clang-format on */ diff --git a/src/modules/dispatcher/doc/dispatcher_admin.xml b/src/modules/dispatcher/doc/dispatcher_admin.xml index 580959f0464..50fa5e4b70a 100644 --- a/src/modules/dispatcher/doc/dispatcher_admin.xml +++ b/src/modules/dispatcher/doc/dispatcher_admin.xml @@ -1831,6 +1831,39 @@ DEST: { &sercmd; dispatcher.add 2 sip:127.0.0.1:5080 &sercmd; dispatcher.add 3 sip:127.0.0.1:5075 8 ... + + +
+ + <function moreinfo="none">dispatcher.remove</function> + + + Remove a destination address from the in-memory dispatcher list. Reloading + the dispatcher from file or database will re-add destinations that are + removed using this command. + + + This command will remove all entries that match the group and address. + + + Name: dispatcher.remove + + Parameters: + + _group_: destination group id + + _address_: address of the destination in the _group_ + + + + Example: + + +... +# prototype: &sercmd; dispatcher.remove _group_ _address_ +&sercmd; dispatcher.remove 2 sip:127.0.0.1:5080 +&sercmd; dispatcher.remove 3 sip:127.0.0.1:5075;transport=udp +...