From b7b0f25871fd99667db5f426cb7373deba7561ae Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Fri, 22 May 2020 21:25:48 +0200 Subject: [PATCH] dispatcher: new rpc command dispatcher.set_duid_state - set the state of a destination by matching on duid attribute kamctl rpc dispatcher.set_duid_state - example: kamctl rpc dispatcher.set_duid_state i 1 xyz - GH #2085 --- src/modules/dispatcher/dispatch.c | 41 ++++++++++++++++++++++++++ src/modules/dispatcher/dispatch.h | 1 + src/modules/dispatcher/dispatcher.c | 45 +++++++++++++++++++++++------ 3 files changed, 78 insertions(+), 9 deletions(-) diff --git a/src/modules/dispatcher/dispatch.c b/src/modules/dispatcher/dispatch.c index b51b5b48d0e..b5d56d405a9 100644 --- a/src/modules/dispatcher/dispatch.c +++ b/src/modules/dispatcher/dispatch.c @@ -2978,6 +2978,47 @@ int ds_reinit_state(int group, str *address, int state) return -1; } +/** + * + */ +int ds_reinit_duid_state(int group, str *vduid, int state) +{ + int i = 0; + ds_set_t *idx = NULL; + + if(_ds_list == NULL || _ds_list_nr <= 0) { + LM_ERR("the list is null\n"); + return -1; + } + + /* get the index of the set */ + if(ds_get_index(group, *crt_idx, &idx) != 0) { + LM_ERR("destination set [%d] not found\n", group); + return -1; + } + + for(i = 0; i < idx->nr; i++) { + if(idx->dlist[i].attrs.duid.len == vduid->len + && strncasecmp(idx->dlist[i].attrs.duid.s, vduid->s, vduid->len) + == 0) { + int old_state = idx->dlist[i].flags; + /* reset the bits used for states */ + idx->dlist[i].flags &= ~(DS_STATES_ALL); + /* set the new states */ + idx->dlist[i].flags |= state; + if(idx->dlist[i].attrs.rweight > 0) { + ds_reinit_rweight_on_state_change( + old_state, idx->dlist[i].flags, idx); + } + + return 0; + } + } + LM_ERR("destination duid [%d : %.*s] not found\n", group, vduid->len, + vduid->s); + return -1; +} + /** * */ diff --git a/src/modules/dispatcher/dispatch.h b/src/modules/dispatcher/dispatch.h index 59937b99941..ee4ea0b7607 100644 --- a/src/modules/dispatcher/dispatch.h +++ b/src/modules/dispatcher/dispatch.h @@ -146,6 +146,7 @@ int ds_update_state(sip_msg_t *msg, int group, str *address, int state, ds_rctx_t *rctx); int ds_reinit_state(int group, str *address, int state); int ds_reinit_state_all(int group, int state); +int ds_reinit_duid_state(int group, str *vduid, int state); int ds_mark_dst(struct sip_msg *msg, int mode); int ds_print_list(FILE *fout); int ds_log_sets(void); diff --git a/src/modules/dispatcher/dispatcher.c b/src/modules/dispatcher/dispatcher.c index 9bd51a2544c..2a566ab730c 100644 --- a/src/modules/dispatcher/dispatcher.c +++ b/src/modules/dispatcher/dispatcher.c @@ -1661,14 +1661,10 @@ static void dispatcher_rpc_list(rpc_t *rpc, void *ctx) } -static const char *dispatcher_rpc_set_state_doc[2] = { - "Set the state of a destination address", 0}; - - /* - * RPC command to set the state of a destination address + * RPC command to set the state of a destination address or duid */ -static void dispatcher_rpc_set_state(rpc_t *rpc, void *ctx) +static void dispatcher_rpc_set_state_helper(rpc_t *rpc, void *ctx, int mattr) { int group; str dest; @@ -1712,9 +1708,16 @@ static void dispatcher_rpc_set_state(rpc_t *rpc, void *ctx) if(dest.len == 3 && strncmp(dest.s, "all", 3) == 0) { ds_reinit_state_all(group, stval); } else { - if(ds_reinit_state(group, &dest, stval) < 0) { - rpc->fault(ctx, 500, "State Update Failed"); - return; + if (mattr==1) { + if(ds_reinit_duid_state(group, &dest, stval) < 0) { + rpc->fault(ctx, 500, "State Update Failed"); + return; + } + } else { + if(ds_reinit_state(group, &dest, stval) < 0) { + rpc->fault(ctx, 500, "State Update Failed"); + return; + } } } @@ -1722,6 +1725,28 @@ static void dispatcher_rpc_set_state(rpc_t *rpc, void *ctx) } +static const char *dispatcher_rpc_set_state_doc[2] = { + "Set the state of a destination by address", 0}; + +/* + * RPC command to set the state of a destination address + */ +static void dispatcher_rpc_set_state(rpc_t *rpc, void *ctx) +{ + dispatcher_rpc_set_state_helper(rpc, ctx, 0); +} + +static const char *dispatcher_rpc_set_duid_state_doc[2] = { + "Set the state of a destination by duid", 0}; + +/* + * RPC command to set the state of a destination duid + */ +static void dispatcher_rpc_set_duid_state(rpc_t *rpc, void *ctx) +{ + dispatcher_rpc_set_state_helper(rpc, ctx, 1); +} + static const char *dispatcher_rpc_ping_active_doc[2] = { "Manage setting on/off the pinging (keepalive) of destinations", 0}; @@ -1867,6 +1892,8 @@ rpc_export_t dispatcher_rpc_cmds[] = { dispatcher_rpc_list_doc, 0}, {"dispatcher.set_state", dispatcher_rpc_set_state, dispatcher_rpc_set_state_doc, 0}, + {"dispatcher.set_duid_state", dispatcher_rpc_set_duid_state, + dispatcher_rpc_set_duid_state_doc, 0}, {"dispatcher.ping_active", dispatcher_rpc_ping_active, dispatcher_rpc_ping_active_doc, 0}, {"dispatcher.add", dispatcher_rpc_add,