Module: sip-router Branch: master Commit: 15d1022b575ae06f92f5a966bc12e144f3def5c5 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=15d1022b...
Author: Alekzander Spiridonov sipidronov@gmail.com Committer: Daniel-Constantin Mierla miconda@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.