[sr-dev] git:master: uac_redirect: fetch all contact headers in redirect replies

Daniel-Constantin Mierla miconda at gmail.com
Wed Jul 3 23:26:17 CEST 2013


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

Author: Daniel-Constantin Mierla <miconda at gmail.com>
Committer: Daniel-Constantin Mierla <miconda at gmail.com>
Date:   Wed Jul  3 23:23:40 2013 +0200

uac_redirect: fetch all contact headers in redirect replies

- only first header was considered for redirect handling
- based on a report by Geoffrey Mina
- generate fake ruid (used as instance and user-agent) to satisfy the
  requirements of t_load_contacts()/t_next_contacts()

---

 modules/uac_redirect/Makefile   |    2 +
 modules/uac_redirect/rd_funcs.c |  137 ++++++++++++++++++++++-----------------
 modules/uac_redirect/redirect.c |   15 ++++-
 3 files changed, 94 insertions(+), 60 deletions(-)

diff --git a/modules/uac_redirect/Makefile b/modules/uac_redirect/Makefile
index d8c2ae1..0b7e22d 100644
--- a/modules/uac_redirect/Makefile
+++ b/modules/uac_redirect/Makefile
@@ -10,4 +10,6 @@ LIBS=
 
 DEFS+=-DKAMAILIO_MOD_INTERFACE
 
+SERLIBPATH=../../lib
+SER_LIBS+=$(SERLIBPATH)/srutils/srutils
 include ../../Makefile.modules
diff --git a/modules/uac_redirect/rd_funcs.c b/modules/uac_redirect/rd_funcs.c
index 2f85ed1..89917f7 100644
--- a/modules/uac_redirect/rd_funcs.c
+++ b/modules/uac_redirect/rd_funcs.c
@@ -32,11 +32,14 @@
 #include "../../dprint.h"
 #include "../../qvalue.h"
 #include "../../parser/contact/parse_contact.h"
+#include "../../lib/srutils/sruid.h"
 #include "../../qvalue.h"
 #include "rd_filter.h"
 #include "rd_funcs.h"
 
 
+extern sruid_t _redirect_sruid;
+
 #define MAX_CONTACTS_PER_REPLY   16
 #define DEFAULT_Q_VALUE          10
 
@@ -115,7 +118,7 @@ error:
 
 
 /* returns the number of contacts put in the sorted array */
-static int sort_contacts(contact_t *ct_list, contact_t **ct_array,
+static int sort_contacts(hdr_field_t *chdr, contact_t **ct_array,
 														qvalue_t *q_array)
 {
 	param_t *q_para;
@@ -123,48 +126,54 @@ static int sort_contacts(contact_t *ct_list, contact_t **ct_array,
 	int n;
 	int i,j;
 	char backup;
+	contact_t *ct_list;
+	hdr_field_t *hdr;
 
 	n = 0; /* number of sorted contacts */
 
-	for( ; ct_list ; ct_list = ct_list->next ) {
-		/* check the filters first */
-		backup = ct_list->uri.s[ct_list->uri.len];
-		ct_list->uri.s[ct_list->uri.len] = 0;
-		if ( run_filters( ct_list->uri.s )==-1 ){
-			ct_list->uri.s[ct_list->uri.len] = backup;
-			continue;
-		}
-		ct_list->uri.s[ct_list->uri.len] = backup;
-		/* does the contact has a q val? */
-		q_para = ct_list->q;
-		if (q_para==0 || q_para->body.len==0) {
-			q = DEFAULT_Q_VALUE;
-		} else {
-			if (str2q( &q, q_para->body.s, q_para->body.len)!=0) {
-				LM_ERR("invalid q param\n");
-				/* skip this contact */
+	for(hdr=chdr; hdr; hdr=hdr->next) {
+		if(hdr->type != HDR_CONTACT_T) continue;
+		ct_list = ((contact_body_t*)hdr->parsed)->contacts;
+		for( ; ct_list ; ct_list = ct_list->next ) {
+			/* check the filters first */
+			backup = ct_list->uri.s[ct_list->uri.len];
+			ct_list->uri.s[ct_list->uri.len] = 0;
+			if ( run_filters( ct_list->uri.s )==-1 ){
+				ct_list->uri.s[ct_list->uri.len] = backup;
 				continue;
 			}
-		}
-		LM_DBG("sort_contacts: <%.*s> q=%d\n",
-				ct_list->uri.len,ct_list->uri.s,q);
-		/*insert the contact into the sorted array */
-		for(i=0;i<n;i++) {
-			/* keep in mind that the contact list is reversts */
-			if (q_array[i]<=q)
-				continue;
-			break;
-		}
-		if (i!=MAX_CONTACTS_PER_REPLY) {
-			/* insert the contact at this position */
-			for( j=n-1-1*(n==MAX_CONTACTS_PER_REPLY) ; j>=i ; j-- ) {
-				ct_array[j+1] = ct_array[j];
-				q_array[j+1] = q_array[j];
+			ct_list->uri.s[ct_list->uri.len] = backup;
+			/* does the contact has a q val? */
+			q_para = ct_list->q;
+			if (q_para==0 || q_para->body.len==0) {
+				q = DEFAULT_Q_VALUE;
+			} else {
+				if (str2q( &q, q_para->body.s, q_para->body.len)!=0) {
+					LM_ERR("invalid q param\n");
+					/* skip this contact */
+					continue;
+				}
+			}
+			LM_DBG("sort_contacts: <%.*s> q=%d\n",
+					ct_list->uri.len,ct_list->uri.s,q);
+			/*insert the contact into the sorted array */
+			for(i=0;i<n;i++) {
+				/* keep in mind that the contact list is reversts */
+				if (q_array[i]<=q)
+					continue;
+				break;
+			}
+			if (i!=MAX_CONTACTS_PER_REPLY) {
+				/* insert the contact at this position */
+				for( j=n-1-1*(n==MAX_CONTACTS_PER_REPLY) ; j>=i ; j-- ) {
+					ct_array[j+1] = ct_array[j];
+					q_array[j+1] = q_array[j];
+				}
+				ct_array[j+1] = ct_list;
+				q_array[j+1] = q;
+				if (n!=MAX_CONTACTS_PER_REPLY)
+					n++;
 			}
-			ct_array[j+1] = ct_list;
-			q_array[j+1] = q;
-			if (n!=MAX_CONTACTS_PER_REPLY)
-				n++;
 		}
 	}
 	return n;
@@ -211,7 +220,7 @@ static int shmcontact2dset(struct sip_msg *req, struct sip_msg *sh_rpl,
 			memcpy( &dup_rpl, sh_rpl, sizeof(struct sip_msg) );
 			dup = 2;
 			/* ok -> force the parsing of contact header */
-			if ( parse_headers( &dup_rpl, HDR_CONTACT_F, 0)<0 ) {
+			if ( parse_headers( &dup_rpl, HDR_EOH_F, 0)<0 ) {
 				LM_ERR("dup_rpl parse failed\n");
 				ret = -1;
 				goto restore;
@@ -224,7 +233,7 @@ static int shmcontact2dset(struct sip_msg *req, struct sip_msg *sh_rpl,
 		} else {
 			dup = 3;
 			/* force the parsing of contact header */
-			if ( parse_headers( sh_rpl, HDR_CONTACT_F, 0)<0 ) {
+			if ( parse_headers( sh_rpl, HDR_EOH_F, 0)<0 ) {
 				LM_ERR("sh_rpl parse failed\n");
 				ret = -1;
 				goto restore;
@@ -239,18 +248,23 @@ static int shmcontact2dset(struct sip_msg *req, struct sip_msg *sh_rpl,
 		contact_hdr = sh_rpl->contact;
 	}
 
-	/* parse the body of contact header */
-	if (contact_hdr->parsed==0) {
-		if ( parse_contact(contact_hdr)<0 ) {
-			LM_ERR("contact hdr parse failed\n");
-			ret = -1;
-			goto restore;
+	/* parse the body of contact headers */
+	hdr = contact_hdr;
+	while(hdr) {
+		if (hdr->type == HDR_CONTACT_T) {
+			if (hdr->parsed==0) {
+				if(parse_contact(hdr) < 0) {
+					LM_ERR("failed to parse Contact body\n");
+					ret = -1;
+					goto restore;
+				}
+				if (dup==0)
+					dup = 1;
+				}
 		}
-		if (dup==0)
-			dup = 1;
+		hdr = hdr->next;
 	}
 
-
 	/* we have the contact header and its body parsed -> sort the contacts
 	 * based on the q value */
 	contacts = ((contact_body_t*)contact_hdr->parsed)->contacts;
@@ -258,7 +272,7 @@ static int shmcontact2dset(struct sip_msg *req, struct sip_msg *sh_rpl,
 		LM_DBG("contact hdr has no contacts\n");
 		goto restore;
 	}
-	n = sort_contacts( contacts, scontacts, sqvalues);
+	n = sort_contacts(contact_hdr, scontacts, sqvalues);
 	if (n==0) {
 		LM_DBG("no contacts left after filtering\n");
 		goto restore;
@@ -274,17 +288,22 @@ static int shmcontact2dset(struct sip_msg *req, struct sip_msg *sh_rpl,
 	for ( i=0 ; i<n ; i++ ) {
 		LM_DBG("adding contact <%.*s>\n", scontacts[i]->uri.len,
 				scontacts[i]->uri.s);
-		if (km_append_branch( 0, &scontacts[i]->uri, 0, 0, sqvalues[i],
-					bflags, 0)<0) {
-			LM_ERR("failed to add contact to dset\n");
-		} else {
-			added++;
-			if (rd_acc_fct!=0 && reason) {
-				/* log the redirect */
-				req->new_uri =  scontacts[i]->uri;
-				//FIXME
-				rd_acc_fct( req, (char*)reason, acc_db_table);
+		if(sruid_next(&_redirect_sruid)==0) {
+			if(append_branch( 0, &scontacts[i]->uri, 0, 0, sqvalues[i],
+						bflags, 0, &_redirect_sruid.uid, 0,
+						&_redirect_sruid.uid, &_redirect_sruid.uid)<0) {
+				LM_ERR("failed to add contact to dset\n");
+			} else {
+				added++;
+				if (rd_acc_fct!=0 && reason) {
+					/* log the redirect */
+					req->new_uri =  scontacts[i]->uri;
+					//FIXME
+					rd_acc_fct( req, (char*)reason, acc_db_table);
+				}
 			}
+		} else {
+			LM_ERR("failed to generate ruid for a new branch\n");
 		}
 	}
 
diff --git a/modules/uac_redirect/redirect.c b/modules/uac_redirect/redirect.c
index febd373..b4e55d1 100644
--- a/modules/uac_redirect/redirect.c
+++ b/modules/uac_redirect/redirect.c
@@ -32,6 +32,7 @@
 #include "../../str.h"
 #include "../../dprint.h"
 #include "../../mem/mem.h"
+#include "../../lib/srutils/sruid.h"
 #include "../../modules/tm/tm_load.h"
 #include "rd_funcs.h"
 #include "rd_filter.h"
@@ -56,9 +57,12 @@ unsigned int bflags = 0;
 #define ACCEPT_RULE_STR "accept"
 #define DENY_RULE_STR   "deny"
 
+/* sruid to get internal uid */
+sruid_t _redirect_sruid;
 
 
 static int redirect_init(void);
+static int child_init(int rank);
 static int w_set_deny(struct sip_msg* msg, char *dir, char *foo);
 static int w_set_accept(struct sip_msg* msg, char *dir, char *foo);
 static int w_get_redirect1(struct sip_msg* msg, char *dir, char *foo);
@@ -103,7 +107,7 @@ struct module_exports exports = {
 	redirect_init, /* Module initialization function */
 	0,
 	0,
-	(child_init_function) 0 /* per-child init function */
+	child_init /* per-child init function */
 };
 
 
@@ -295,11 +299,20 @@ static int redirect_init(void)
 	}
 	add_default_filter( DENY_FILTER, filter);
 
+	if(sruid_init(&_redirect_sruid, '-', "rdir", SRUID_INC)<0)
+		return -1;
+
 	return 0;
 error:
 	return -1;
 }
 
+static int child_init(int rank)
+{
+	if(sruid_init(&_redirect_sruid, '-', "rdir", SRUID_INC)<0)
+		return -1;
+	return 0;
+}
 
 static inline void msg_tracer(struct sip_msg* msg, int reset)
 {




More information about the sr-dev mailing list