Skip to content

Commit

Permalink
Added "filter" and "filter_out" options for "rl_list"
Browse files Browse the repository at this point in the history
Using the filter or filter_out optional parameter, you can use patterns (with wildcards) to filter the pipes to be listed (instead of listing all or only one)
  • Loading branch information
bogdan-iancu committed Aug 12, 2021
1 parent 40355a3 commit 35f55f1
Show file tree
Hide file tree
Showing 4 changed files with 158 additions and 13 deletions.
28 changes: 23 additions & 5 deletions modules/ratelimit/doc/ratelimit_admin.xml
Expand Up @@ -671,16 +671,34 @@ modparam("ratelimit", "slot_period", 100)
<para>Parameters:</para>
<itemizedlist>
<listitem><para>
<emphasis>pipe</emphasis> (optional) - indicates the name of the pipe.
If the parameter doesn't exist, all the active pipes
are listed. Otherwise only the one specified.
<emphasis>pipe</emphasis> (optional) - indicates the name of the
single pipe to be listed.
</para></listitem>
<listitem><para>
<emphasis>filter</emphasis> (optional) - a pattern used to filter
the active pipes to be listed. The filter is a shell wildcard
pattern (see glob(7)).
</para></listitem>
<listitem><para>
<emphasis>filter_out</emphasis> (optional) - a pattern used to
filter out the active pipes NOT to be listed.
The filter is a shell wildcard pattern (see glob(7)).
</para></listitem>
</itemizedlist>
<para>
<para>
Note that you cannot combine multiple paramters when calling this
function. If using parameters, only one is accepted.
</para>
<para>
If no parameter are passed to the function, all the active pipes
are listed.
</para>
<para>
MI FIFO Command Format:
</para>
<programlisting format="linespecific">
opensips-cli -x mi rl_list gw_10.0.0.1
opensips-cli -x mi rl_list pipe=gw_10.0.0.1
opensips-cli -x mi rl_list filter=gw_*
</programlisting>
</section>
<section id="mi_rl_dump_pipe" xreflabel="rl_dump_pipe">
Expand Down
84 changes: 82 additions & 2 deletions modules/ratelimit/ratelimit.c
Expand Up @@ -105,6 +105,10 @@ mi_response_t *mi_stats(const mi_params_t *params,
struct mi_handler *async_hdl);
mi_response_t *mi_stats_1(const mi_params_t *params,
struct mi_handler *async_hdl);
mi_response_t *mi_stats_2(const mi_params_t *params,
struct mi_handler *async_hdl);
mi_response_t *mi_stats_3(const mi_params_t *params,
struct mi_handler *async_hdl);
mi_response_t *mi_reset_pipe(const mi_params_t *params,
struct mi_handler *async_hdl);
mi_response_t *mi_set_pid(const mi_params_t *params,
Expand Down Expand Up @@ -166,6 +170,8 @@ static mi_export_t mi_cmds [] = {
{"rl_list", RLH1, 0, 0, {
{mi_stats, {0}},
{mi_stats_1, {"pipe", 0}},
{mi_stats_2, {"filter", 0}},
{mi_stats_3, {"filter_out", 0}},
{EMPTY_MI_RECIPE}}
},
{"rl_reset_pipe", RLH2, 0, 0, {
Expand Down Expand Up @@ -658,7 +664,7 @@ mi_response_t *mi_stats(const mi_params_t *params,
if (!resp)
return 0;

if (rl_stats(resp_obj, NULL) < 0) {
if (rl_stats(resp_obj, NULL, NULL, 0) < 0) {
LM_ERR("cannot mi print values\n");
goto free;
}
Expand Down Expand Up @@ -692,7 +698,81 @@ mi_response_t *mi_stats_1(const mi_params_t *params,
if (get_mi_string_param(params, "pipe", &pipe_name.s, &pipe_name.len) < 0)
return init_mi_param_error();

rc = rl_stats(resp_obj, &pipe_name);
rc = rl_stats(resp_obj, &pipe_name, NULL, 0);
if (rc < 0) {
LM_ERR("cannot mi print values\n");
goto free;
} else if (rc == 1) {
return init_mi_error(404, MI_SSTR("Pipe Not Found"));
}

LOCK_GET(rl_lock);
if (add_mi_number(resp_obj, MI_SSTR("drop_rate"), *drop_rate) < 0) {
LOCK_RELEASE(rl_lock);
goto free;
}
LOCK_RELEASE(rl_lock);

return resp;

free:
free_mi_response(resp);
return 0;
}

mi_response_t *mi_stats_2(const mi_params_t *params,
struct mi_handler *async_hdl)
{
mi_response_t *resp;
mi_item_t *resp_obj;
str filter;
int rc;

resp = init_mi_result_object(&resp_obj);
if (!resp)
return 0;

if (get_mi_string_param(params, "filter", &filter.s, &filter.len) < 0)
return init_mi_param_error();

rc = rl_stats(resp_obj, NULL, &filter, 0);
if (rc < 0) {
LM_ERR("cannot mi print values\n");
goto free;
} else if (rc == 1) {
return init_mi_error(404, MI_SSTR("Pipe Not Found"));
}

LOCK_GET(rl_lock);
if (add_mi_number(resp_obj, MI_SSTR("drop_rate"), *drop_rate) < 0) {
LOCK_RELEASE(rl_lock);
goto free;
}
LOCK_RELEASE(rl_lock);

return resp;

free:
free_mi_response(resp);
return 0;
}

mi_response_t *mi_stats_3(const mi_params_t *params,
struct mi_handler *async_hdl)
{
mi_response_t *resp;
mi_item_t *resp_obj;
str filter;
int rc;

resp = init_mi_result_object(&resp_obj);
if (!resp)
return 0;

if (get_mi_string_param(params, "filter_out", &filter.s, &filter.len) < 0)
return init_mi_param_error();

rc = rl_stats(resp_obj, NULL, &filter, 1);
if (rc < 0) {
LM_ERR("cannot mi print values\n");
goto free;
Expand Down
2 changes: 1 addition & 1 deletion modules/ratelimit/ratelimit.h
Expand Up @@ -137,7 +137,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 rl_stats(mi_item_t *, str *);
int rl_stats(mi_item_t *, str *, str *, int);
int rl_pipe_check(rl_pipe_t *);
int rl_get_counter_value(str *);
/* update load */
Expand Down
57 changes: 52 additions & 5 deletions modules/ratelimit/ratelimit_helper.c
Expand Up @@ -39,6 +39,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fnmatch.h>

#include "ratelimit.h"

Expand Down Expand Up @@ -651,18 +652,50 @@ static int rl_map_print(void *param, str key, void *value)
return 0;
}

static int rl_map_print_array(void *param, str key, void *value)
static int rl_map_print_array(void *extras, str key, void *value)
{
mi_item_t *pipe_item = add_mi_object((mi_item_t *)param, NULL, 0);
mi_item_t *pipe_item = add_mi_object((mi_item_t *)(((void**)extras)[0]),
NULL, 0);
if (!pipe_item)
return -1;
return rl_map_print(pipe_item, key, value);
return rl_map_print(pipe_item, key, value );
}

int rl_stats(mi_item_t *resp_obj, str * value)
static int rl_map_print_array_filter(void *extras, str key, void *value)
{
static str nt_key = {NULL,0};
mi_item_t *pipe_item;
char *filter_s = (char*)(((void**)extras)[1]);
int filter_out = (int)(long)(((void**)extras)[2]);

/* make the key null terminated */
if (pkg_str_extend( &nt_key, key.len+1))
return -1;
memcpy( nt_key.s, key.s, key.len);
nt_key.s[key.len] = 0;

if ( fnmatch( filter_s, nt_key.s, 0)!=0 ) {
if (filter_out==0)
return 0;
} else {
if (filter_out==1)
return 0;
}

pipe_item = add_mi_object((mi_item_t *)(((void**)extras)[0]), NULL, 0);
if (!pipe_item)
return -1;

return rl_map_print(pipe_item, key, value );
}

int rl_stats(mi_item_t *resp_obj, str * value, str *filter, int filter_out)
{
mi_item_t *pipe_item, *pipe_arr;
rl_pipe_t **pipe;
void *extras[3];
char *filter_s;
process_each_func func;
int i;

if (value && value->s && value->len) {
Expand All @@ -688,11 +721,25 @@ int rl_stats(mi_item_t *resp_obj, str * value)
pipe_arr = add_mi_array(resp_obj, MI_SSTR("Pipes"));
if (!pipe_arr)
return -1;
extras[0] = pipe_arr;
if (filter && filter->s && filter->len) {
// make filter NULL terminated
filter_s = (char*)pkg_malloc( filter->len+1 );
if (!filter_s)
return -1;
memcpy( filter_s, filter->s, filter->len);
filter_s[filter->len] = 0;
extras[1] = filter_s;
extras[2] = (void*)(long)filter_out;
func = rl_map_print_array_filter;
} else {
func = rl_map_print_array;
}
for (i = 0; i < rl_htable.size; i++) {
if (map_size(rl_htable.maps[i]) == 0)
continue;
RL_GET_LOCK(i);
if (map_for_each(rl_htable.maps[i], rl_map_print_array, pipe_arr)) {
if (map_for_each(rl_htable.maps[i], func, (void*)extras)) {
LM_ERR("cannot print values\n");
goto error;
}
Expand Down

0 comments on commit 35f55f1

Please sign in to comment.