Skip to content

Commit

Permalink
avpops: add avp_shuffle function which randomly reorders AVPs
Browse files Browse the repository at this point in the history
  • Loading branch information
john08burke committed Oct 25, 2022
1 parent 37c46db commit ace2b90
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 0 deletions.
50 changes: 50 additions & 0 deletions modules/avpops/avpops.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ static int fixup_free_avp_subst_p1(void** param);
static int fixup_free_avp_subst_p2(void** param);
static int fixup_free_pvname_list(void** param);
static int fixup_free_avp_dbparam(void** param);
static int fixup_avp_shuffle_name(void** param);

static int w_print_avps(struct sip_msg* msg, char* foo, char *bar);
static int w_dbload_avps(struct sip_msg* msg, void* source,
Expand All @@ -121,6 +122,7 @@ static int w_async_dbquery_avps(struct sip_msg* msg, async_ctx *ctx,
str* query, void* dest, void* url);
static int w_delete_avps(struct sip_msg* msg, void* param);
static int w_copy_avps(struct sip_msg* msg, void* name1, void *name2);
static int w_shuffle_avps(struct sip_msg* msg, void* param);
static int w_pushto_avps(struct sip_msg* msg, void* destination, void *param);
static int w_check_avps(struct sip_msg* msg, void* param, void *check);
static int w_op_avps(struct sip_msg* msg, char* param, char *op);
Expand Down Expand Up @@ -183,6 +185,11 @@ static cmd_export_t cmds[] = {
REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE|
STARTUP_ROUTE|TIMER_ROUTE|EVENT_ROUTE},

{"avp_shuffle", (cmd_function)w_shuffle_avps, {
{CMD_PARAM_STR|CMD_PARAM_NO_EXPAND, fixup_avp_shuffle_name, fixup_free_pkg}, {0, 0, 0}},
REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE|ONREPLY_ROUTE|LOCAL_ROUTE|
STARTUP_ROUTE|TIMER_ROUTE|EVENT_ROUTE},

{"avp_pushto", (cmd_function)w_pushto_avps, {
{CMD_PARAM_STR|CMD_PARAM_NO_EXPAND, fixup_pushto_avp_p1, fixup_free_pkg},
{CMD_PARAM_STR|CMD_PARAM_NO_EXPAND, fixup_pushto_avp_p2, fixup_free_pkg}, {0, 0, 0}},
Expand Down Expand Up @@ -843,6 +850,44 @@ static int fixup_copy_avp(void** param, int param_no)
return E_UNSPEC;
}

static int fixup_avp_shuffle_name(void** param)
{
struct fis_param *ap=NULL;
char *s;
str cpy;

if (pkg_nt_str_dup(&cpy, (str *)*param) < 0) {
LM_ERR("oom\n");
return -1;
}
s = cpy.s;

ap = avpops_parse_pvar(s);
if (ap==0)
{
LM_ERR("unable to get"
" pseudo-variable in param \n");
goto err_free;
}
if (ap->u.sval.type!=PVT_AVP)
{
LM_ERR("bad param; expected : $avp(name)\n");
goto err_free;
}
ap->opd|=AVPOPS_VAL_PVAR;
ap->type = AVPOPS_VAL_PVAR;

*param=(void*)ap;
pkg_free(cpy.s);

return 0;

err_free:
pkg_free(cpy.s);
pkg_free(ap);
return E_UNSPEC;
}

static int fixup_pushto_avp(void** param, int param_no)
{
struct fis_param *ap = NULL;
Expand Down Expand Up @@ -1485,6 +1530,11 @@ static int w_copy_avps(struct sip_msg* msg, void* name1, void *name2)
(struct fis_param*)name2);
}

static int w_shuffle_avps(struct sip_msg* msg, void* param)
{
return ops_shuffle_avp ( msg, (struct fis_param*)param);
}

static int w_pushto_avps(struct sip_msg* msg, void* destination, void *param)
{
return ops_pushto_avp ( msg, (struct fis_param*)destination,
Expand Down
43 changes: 43 additions & 0 deletions modules/avpops/avpops_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,49 @@ int ops_copy_avp( struct sip_msg* msg, struct fis_param* src,
return -1;
}

int ops_shuffle_avp( struct sip_msg* msg, struct fis_param* src)
{
struct usr_avp *src_avp, *rnd_avp;
struct usr_avp *temp_avp = NULL;
int_str src_val, rnd_val;
unsigned short avp_type;
int avp_name;
int n, rnd_idx;

/* get avp src name */
if(avpops_get_aname(msg, src, &avp_name, &avp_type)!=0)
{
LM_ERR("failed to get src AVP name\n");
goto error;
}

/* count AVPs */
n = 0;
while ((temp_avp=search_first_avp(avp_type, avp_name, NULL, temp_avp)) != 0)
n++;

/* randomize AVPs */
for ( ; n>1; n-- ) {
rnd_idx = random() % n;
if (rnd_idx == (n-1))
continue;

LM_DBG("swapping [%d] <--> [%d]\n", (n-1), rnd_idx);

src_avp = search_index_avp(avp_type, avp_name, &src_val, (n-1));
rnd_avp = search_index_avp(avp_type, avp_name, &rnd_val, rnd_idx);

if ( replace_avp(avp_type|(rnd_avp->flags&AVP_VAL_STR), avp_name, rnd_val, (n-1))==-1 ||
replace_avp(avp_type|(src_avp->flags&AVP_VAL_STR), avp_name, src_val, rnd_idx)==-1 ) {
LM_ERR("failed to swap avp\n");
goto error;
}
}

return 1;
error:
return -1;
}

#define STR_BUF_SIZE 1024
static char str_buf[STR_BUF_SIZE];
Expand Down
3 changes: 3 additions & 0 deletions modules/avpops/avpops_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ int ops_delete_avp(struct sip_msg* msg,
int ops_copy_avp(struct sip_msg* msg, struct fis_param* name1,
struct fis_param* name2);

int ops_shuffle_avp(struct sip_msg* msg,
struct fis_param *param);

int ops_pushto_avp(struct sip_msg* msg, struct fis_param* dst,
struct fis_param* ap);

Expand Down
39 changes: 39 additions & 0 deletions modules/avpops/doc/avpops_admin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,45 @@ avp_op("$avp(number)", "sub/$avp(number2)/d");
...
if(is_avp_set("$avp(foo)"))
xlog("AVP with name 'foo' is set!\n");
...
</programlisting>
</example>
</section>
<section id="func_avp_shuffle" xreflabel="avp_shuffle()">
<title>
<function moreinfo="none">avp_shuffle(name)
</function>
</title>
<para>
Randomly shuffles AVPs with <emphasis>name</emphasis>.
</para>
<para>Meaning of the parameters is as follows:</para>
<itemizedlist>
<listitem>
<para><emphasis>name (string, no expand)</emphasis> - name of AVP to shuffle.
Parameter syntax is:
<itemizedlist>
<listitem><para><emphasis>
name = avp_name
</emphasis></para></listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
<para>
This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
BRANCH_ROUTE, LOCAL_ROUTE and ONREPLY_ROUTE.
</para>
<example>
<title><function>avp_shuffle</function> usage</title>
<programlisting format="linespecific">
...
$avp(foo) := "str1";
$avp(foo) = "str2";
$avp(foo) = "str3";
xlog("Initial AVP list is: $(avp(foo)[*])\n"); # str3 str2 str1
if(avp_shuffle("$avp(foo)"))
xlog("Shuffled AVP list is: $(avp(foo)[*])\n"); # str1, str3, str2 (for example)
...
</programlisting>
</example>
Expand Down

0 comments on commit ace2b90

Please sign in to comment.