Module: sip-router
Branch: master
Commit: 15d1022b575ae06f92f5a966bc12e144f3def5c5
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=15d1022…
Author: Alekzander Spiridonov <sipidronov(a)gmail.com>
Committer: Daniel-Constantin Mierla <miconda(a)gmail.com>
Date: Thu Aug 21 08:20:09 2014 -0700
dispatcher: option to limit the number of items in dst_avp list
---
modules/dispatcher/dispatch.c | 18 +++++++-
modules/dispatcher/dispatch.h | 1 +
modules/dispatcher/dispatcher.c | 56 ++++++++++++++++++++++-----
modules/dispatcher/doc/dispatcher_admin.xml | 26 +++++++++----
4 files changed, 80 insertions(+), 21 deletions(-)
diff --git a/modules/dispatcher/dispatch.c b/modules/dispatcher/dispatch.c
index bc945f8..8fc6b79 100644
--- a/modules/dispatcher/dispatch.c
+++ b/modules/dispatcher/dispatch.c
@@ -1583,6 +1583,11 @@ static inline int ds_update_dst(struct sip_msg *msg, str *uri, int
mode)
*/
int ds_select_dst(struct sip_msg *msg, int set, int alg, int mode)
{
+ return ds_select_dst_limit(msg, set, alg, 0, mode);
+}
+
+int ds_select_dst_limit(struct sip_msg *msg, int set, int alg, unsigned int limit, int
mode)
+{
int i, cnt;
unsigned int hash;
int_str avp_val;
@@ -1600,6 +1605,13 @@ int ds_select_dst(struct sip_msg *msg, int set, int alg, int mode)
return -1;
}
+ if (limit==0)
+ {
+ LM_DBG("Limit set to 0 - forcing to unlimited\n");
+ limit = 0xffffffff;
+ }
+ --limit; /* reserving 1 slot for selected dst */
+
if((mode==0) && (ds_force_dst==0)
&& (msg->dst_uri.s!=NULL || msg->dst_uri.len>0))
{
@@ -1767,7 +1779,7 @@ int ds_select_dst(struct sip_msg *msg, int set, int alg, int mode)
if(dst_avp_name.n!=0)
{
/* add default dst to last position in AVP list */
- if(ds_use_default!=0 && hash!=idx->nr-1)
+ if(ds_use_default!=0 && hash!=idx->nr-1 && cnt<limit)
{
avp_val.s = idx->dlist[idx->nr-1].uri;
if(add_avp(AVP_VAL_STR|dst_avp_type, dst_avp_name, avp_val)!=0)
@@ -1799,7 +1811,7 @@ int ds_select_dst(struct sip_msg *msg, int set, int alg, int mode)
/* add to avp */
- for(i=hash-1; i>=0; i--)
+ for(i=hash-1; i>=0 && cnt<limit; i--)
{
if(ds_skip_dst(idx->dlist[i].flags)
|| (ds_use_default!=0 && i==(idx->nr-1)))
@@ -1833,7 +1845,7 @@ int ds_select_dst(struct sip_msg *msg, int set, int alg, int mode)
cnt++;
}
- for(i=idx->nr-1; i>hash; i--)
+ for(i=idx->nr-1; i>hash && cnt<limit; i--)
{
if(ds_skip_dst(idx->dlist[i].flags)
|| (ds_use_default!=0 && i==(idx->nr-1)))
diff --git a/modules/dispatcher/dispatch.h b/modules/dispatcher/dispatch.h
index 31262b5..c02cf50 100644
--- a/modules/dispatcher/dispatch.h
+++ b/modules/dispatcher/dispatch.h
@@ -107,6 +107,7 @@ void ds_disconnect_db(void);
int ds_load_db(void);
int ds_reload_db(void);
int ds_destroy_list(void);
+int ds_select_dst_limit(struct sip_msg *msg, int set, int alg, unsigned int limit, int
mode);
int ds_select_dst(struct sip_msg *msg, int set, int alg, int mode);
int ds_next_dst(struct sip_msg *msg, int mode);
int ds_update_state(sip_msg_t *msg, int group, str *address, int state);
diff --git a/modules/dispatcher/dispatcher.c b/modules/dispatcher/dispatcher.c
index 7df0c6d..0ec3338 100644
--- a/modules/dispatcher/dispatcher.c
+++ b/modules/dispatcher/dispatcher.c
@@ -106,8 +106,8 @@ pv_elem_t * hash_param_model = NULL;
int probing_threshhold = 1; /* number of failed requests, before a destination
is taken into probing */
-str ds_ping_method = {"OPTIONS",7};
-str ds_ping_from = {"sip:dispatcher@localhost", 24};
+str ds_ping_method = str_init("OPTIONS");
+str ds_ping_from = str_init("sip:dispatcher@localhost");
static int ds_ping_interval = 0;
int ds_probing_mode = DS_PROBE_NONE;
@@ -147,7 +147,9 @@ static int ds_parse_reply_codes();
static int ds_init_rpc(void);
static int w_ds_select_dst(struct sip_msg*, char*, char*);
+static int w_ds_select_dst_limit(struct sip_msg*, char*, char*, char*);
static int w_ds_select_domain(struct sip_msg*, char*, char*);
+static int w_ds_select_domain_limit(struct sip_msg*, char*, char*, char*);
static int w_ds_next_dst(struct sip_msg*, char*, char*);
static int w_ds_next_domain(struct sip_msg*, char*, char*);
static int w_ds_mark_dst0(struct sip_msg*, char*, char*);
@@ -170,8 +172,12 @@ static int mi_child_init(void);
static cmd_export_t cmds[]={
{"ds_select_dst", (cmd_function)w_ds_select_dst, 2,
fixup_igp_igp, 0, REQUEST_ROUTE|FAILURE_ROUTE},
+ {"ds_select_dst", (cmd_function)w_ds_select_dst_limit, 3,
+ fixup_igp_null, 0, REQUEST_ROUTE|FAILURE_ROUTE},
{"ds_select_domain", (cmd_function)w_ds_select_domain, 2,
fixup_igp_igp, 0, REQUEST_ROUTE|FAILURE_ROUTE},
+ {"ds_select_domain", (cmd_function)w_ds_select_domain_limit, 3,
+ fixup_igp_null, 0, REQUEST_ROUTE|FAILURE_ROUTE},
{"ds_next_dst", (cmd_function)w_ds_next_dst, 0,
ds_warn_fixup, 0, REQUEST_ROUTE|FAILURE_ROUTE},
{"ds_next_domain", (cmd_function)w_ds_next_domain, 0,
@@ -526,12 +532,13 @@ static void destroy(void)
/**
*
*/
-static int w_ds_select(struct sip_msg* msg, char* set, char* alg, int mode)
+static int w_ds_select(struct sip_msg* msg, char* set, char* alg, char* limit, int mode)
{
- unsigned int algo_flags, set_flags;
- str s_algo = {NULL, 0};
- str s_set = {NULL, 0};
- int a, s;
+ unsigned int algo_flags, set_flags, limit_flags;
+ str s_algo = STR_NULL;
+ str s_set = STR_NULL;
+ str s_limit = STR_NULL;
+ int a, s, l;
if(msg==NULL)
return -1;
@@ -552,14 +559,35 @@ static int w_ds_select(struct sip_msg* msg, char* set, char* alg,
int mode)
return -1;
}
- return ds_select_dst(msg, s, a, mode);
+ if (limit) {
+ GET_VALUE("limit", limit, l, s_limit, limit_flags);
+ if (!(limit_flags&PARAM_INT)) {
+ if (limit_flags&PARAM_STR)
+ LM_ERR("unable to get dst number limit from [%.*s]\n", s_limit.len,
s_limit.s);
+ else
+ LM_ERR("unable to get dst number limit\n");
+ return -1;
+ }
+ } else {
+ l = -1; /* will be casted to a rather big unsigned value */
+ }
+
+ return ds_select_dst_limit(msg, s, a, (unsigned int)l, mode);
}
/**
*
*/
static int w_ds_select_dst(struct sip_msg* msg, char* set, char* alg)
{
- return w_ds_select(msg, set, alg, 0 /*set dst uri*/);
+ return w_ds_select(msg, set, alg, 0 /* limit number of dst*/, 0 /*set dst uri*/);
+}
+
+/**
+ *
+ */
+static int w_ds_select_dst_limit(struct sip_msg* msg, char* set, char* alg, char* limit)
+{
+ return w_ds_select(msg, set, alg, limit /* limit number of dst*/, 0 /*set dst uri*/);
}
/**
@@ -567,7 +595,15 @@ static int w_ds_select_dst(struct sip_msg* msg, char* set, char*
alg)
*/
static int w_ds_select_domain(struct sip_msg* msg, char* set, char* alg)
{
- return w_ds_select(msg, set, alg, 1 /*set host port*/);
+ return w_ds_select(msg, set, alg, 0 /* limit number of dst*/, 1 /*set host port*/);
+}
+
+/**
+ *
+ */
+static int w_ds_select_domain_limit(struct sip_msg* msg, char* set, char* alg, char*
limit)
+{
+ return w_ds_select(msg, set, alg, limit /* limit number of dst*/, 1 /*set host
port*/);
}
/**
diff --git a/modules/dispatcher/doc/dispatcher_admin.xml
b/modules/dispatcher/doc/dispatcher_admin.xml
index 75debec..75031f9 100644
--- a/modules/dispatcher/doc/dispatcher_admin.xml
+++ b/modules/dispatcher/doc/dispatcher_admin.xml
@@ -737,7 +737,7 @@ modparam("dispatcher", "force_dst", 1)
<title>Functions</title>
<section id="dispatcher.f.ds_select_dst">
<title>
- <function moreinfo="none">ds_select_dst(set, alg)</function>
+ <function moreinfo="none">ds_select_dst(set, alg[,
limit])</function>
</title>
<para>
The method selects a destination from addresses set. It returns true if
@@ -747,9 +747,9 @@ modparam("dispatcher", "force_dst", 1)
</para>
<para>
If the bit 2 in 'flags' parameter is set, the rest of the addresses from
- the destination set is stored in AVP list. You can use 'ds_next_dst()'
- to use next address in order to achieve serial forking to all possible
- destinations.
+ the destination set is stored in AVP list (limited with an optional 'limit'
+ parameter). You can use 'ds_next_dst()' to use next address in order to
+ achieve serial forking to all possible destinations.
</para>
<para>Meaning of the parameters is as follows:</para>
<itemizedlist>
@@ -856,6 +856,14 @@ modparam("dispatcher", "force_dst", 1)
</listitem>
</itemizedlist>
</listitem>
+ <listitem>
+ <para>
+ <emphasis>limit</emphasis> - the maximum number of items to be
+ stored in AVP list for further failovers (the first selected
+ destination and default destination are the first to be put in
+ the list)
+ </para>
+ </listitem>
</itemizedlist>
<para>
If the bit 2 in 'flags' is set, the rest of the addresses from the
@@ -875,12 +883,14 @@ ds_select_dst("1", "0");
$var(a) = 4;
ds_select_dst("1", "$var(a)");
...
+ds_select_dst("1", "4", "3");
+...
</programlisting>
</example>
</section>
<section id="dispatcher.f.ds_select_domain">
<title>
- <function moreinfo="none">ds_select_domain(set, alg)</function>
+ <function moreinfo="none">ds_select_domain(set, alg[,
limit])</function>
</title>
<para>
The method selects a destination from addresses set and rewrites the
@@ -889,9 +899,9 @@ ds_select_dst("1", "$var(a)");
</para>
<para>
If the bit 2 in 'flags' is set, the rest of the addresses from the
- destination set is stored in AVP list. You can use 'ds_next_domain()'
- to use next address to achieve serial forking to all possible
- destinations.
+ destination set is stored in AVP list (limited with an optional 'limit'
+ parameter). You can use 'ds_next_domain()' to use next address
to
+ achieve serial forking to all possible destinations.
</para>
<para>
This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.