diff --git a/modules/ratelimit/doc/ratelimit_admin.xml b/modules/ratelimit/doc/ratelimit_admin.xml index 806fded2d3c..59b0d1ce79e 100644 --- a/modules/ratelimit/doc/ratelimit_admin.xml +++ b/modules/ratelimit/doc/ratelimit_admin.xml @@ -650,6 +650,42 @@ modparam("ratelimit", "slot_period", 100) rl_reset_count("gw_$ru"); }; ... + + + +
+ + <function moreinfo="none">rl_values(ret_avp, regexp)</function> + + + Returns all the available pipes' names in the ret_avp + output variable. + + Meaning of the parameters is as follows: + + + ret_avp (string) - an AVP where the pipes' + names will be stored. + + + + regexp (regex, optional) - a regular expression + used to filter the names of the pipes. If missing, all the pipes + are returned. + + + + + This function can be used from any route. + + + <function>rl_values</function> usage + +... + rl_values($avp(values)); + for ($var(pipe) in $(avp(values)[*])) + xlog("RATELIMIT: $var(pipe): $rl_count($var(pipe))\n"); +...
diff --git a/modules/ratelimit/ratelimit.c b/modules/ratelimit/ratelimit.c index eaa41f2660d..c4a415feebc 100644 --- a/modules/ratelimit/ratelimit.c +++ b/modules/ratelimit/ratelimit.c @@ -122,6 +122,8 @@ static int pv_get_rl_count(struct sip_msg *msg, pv_param_t *param, pv_value_t *res); static int pv_parse_rl_count(pv_spec_p sp, const str *in); +static int fixup_avp(void** param); + static const cmd_export_t cmds[] = { {"rl_check", (cmd_function)w_rl_check, { {CMD_PARAM_STR,0,0}, @@ -137,6 +139,10 @@ static const cmd_export_t cmds[] = { {CMD_PARAM_STR,0,0}, {0,0,0}}, REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE| BRANCH_ROUTE|ERROR_ROUTE|LOCAL_ROUTE|TIMER_ROUTE|EVENT_ROUTE}, + {"rl_values", (cmd_function)w_rl_values, { + {CMD_PARAM_VAR,fixup_avp,0}, + {CMD_PARAM_REGEX|CMD_PARAM_OPT,0, 0}, {0,0,0}}, + ALL_ROUTES}, {0,0,{{0,0,0}},0} }; @@ -1127,3 +1133,13 @@ static int pv_parse_rl_count(pv_spec_p sp, const str *in) return 0; } + +static int fixup_avp(void** param) +{ + if (((pv_spec_t*)*param)->type != PVT_AVP) { + LM_ERR("invalid pvar type - only AVPs are allowed!\n"); + return E_SCRIPT; + } + + return 0; +} diff --git a/modules/ratelimit/ratelimit.h b/modules/ratelimit/ratelimit.h index e36a3e45bdd..38461fc5284 100644 --- a/modules/ratelimit/ratelimit.h +++ b/modules/ratelimit/ratelimit.h @@ -140,6 +140,7 @@ int w_rl_check(struct sip_msg*, str *, int *, str *); int w_rl_dec(struct sip_msg*, str *); int w_rl_reset(struct sip_msg*, str *); int w_rl_set_count(str, int); +int w_rl_values(struct sip_msg*, pv_spec_t *out, regex_t *regexp); int rl_stats(mi_item_t *, str *, str *, int); int rl_pipe_check(rl_pipe_t *); int rl_get_counter_value(str *); diff --git a/modules/ratelimit/ratelimit_helper.c b/modules/ratelimit/ratelimit_helper.c index 07109cc5fb9..dac831b8f67 100644 --- a/modules/ratelimit/ratelimit_helper.c +++ b/modules/ratelimit/ratelimit_helper.c @@ -1169,3 +1169,50 @@ int rl_get_counter_value(str *key) RL_RELEASE_LOCK(hash_idx); return ret; } + +int w_rl_values(struct sip_msg* msg, pv_spec_t *out, regex_t *regexp) +{ + int i; + map_iterator_t it; + str *key, nkey; + regmatch_t pmatch; + pv_value_t val; + + val.flags = PV_VAL_STR; + + /* iterate through each map */ + for (i = 0; i < rl_htable.size; i++) { + RL_GET_LOCK(i); + /* iterate through all the entries */ + if (map_first(rl_htable.maps[i], &it) < 0) { + LM_ERR("map doesn't exist\n"); + continue; + } + for (; iterator_is_valid(&it);) { + key = iterator_key(&it); + if (!key) { + LM_ERR("cannot retrieve pipe key\n"); + goto next_it; + } + if (regexp) { + if (pkg_nt_str_dup(&nkey, key) != 0) { + LM_ERR("oom for duplicating %.*s\n", key->len, key->s); + goto next_it; + } + if (regexec(regexp, nkey.s, 1, &pmatch, 0) != 0) { + pkg_free(nkey.s); + goto next_it; + } + pkg_free(nkey.s); + } + val.rs = *key; + if (pv_set_value(msg, out, 0, &val) != 0) + LM_ERR("could not set key %.*s\n", key->len, key->s); +next_it: + if (iterator_next(&it) < 0) + break; + } + RL_RELEASE_LOCK(i); + } + return 1; +}