[sr-dev] git:master: dispatcher: option to limit the number of items in dst_avp list

Daniel-Constantin Mierla miconda at gmail.com
Fri Aug 22 15:59:53 CEST 2014


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 <sipidronov at gmail.com>
Committer: Daniel-Constantin Mierla <miconda at 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 at localhost", 24};
+str ds_ping_method = str_init("OPTIONS");
+str ds_ping_from   = str_init("sip:dispatcher at 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.




More information about the sr-dev mailing list