Module: sip-router Branch: master Commit: c5081ad634742d88e56e4fcc097b756098119e4e URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=c5081ad6...
Author: Daniel-Constantin Mierla miconda@gmail.com Committer: Daniel-Constantin Mierla miconda@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) {