Module: sip-router
Branch: 4.0
Commit: 0227f5b61e1ea03e92a7fec9b177f602481fac84
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=0227f5b…
Author: Daniel-Constantin Mierla <miconda(a)gmail.com>
Committer: Daniel-Constantin Mierla <miconda(a)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()
(cherry picked from commit c5081ad634742d88e56e4fcc097b756098119e4e)
---
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)
{