Module: sip-router
Branch: master
Commit: 15d1022b575ae06f92f5a966bc12e144f3def5c5
URL:    
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=15d1022b575ae06f92f5a966bc12e144f3def5c5

Author: Alekzander Spiridonov <[email protected]>
Committer: Daniel-Constantin Mierla <[email protected]>
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.


_______________________________________________
sr-dev mailing list
[email protected]
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev

Reply via email to