From 5c043828fad5d666d1a484e0c5c25d8601381c17 Mon Sep 17 00:00:00 2001 From: Vladut Paiu Date: Fri, 15 Oct 2010 12:04:44 +0000 Subject: [PATCH] added a new core function, construct_uri which builds a sip uri based on the protocol, username, domain, port and extra params that it receives git-svn-id: svn+ssh://svn.code.sf.net/p/opensips/svn/trunk@7292 689a6050-402a-0410-94f2-e92a70836424 --- action.c | 47 ++++++++++++++++++++++++++++++++++++++- cfg.lex | 4 +++- cfg.y | 15 +++++++++++++ msg_translator.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ msg_translator.h | 2 ++ pvar.c | 2 +- route.c | 28 ++++++++++++++++++++++++ route_struct.h | 3 ++- 8 files changed, 154 insertions(+), 4 deletions(-) diff --git a/action.c b/action.c index 0a32f9fa951..db39e636d35 100644 --- a/action.c +++ b/action.c @@ -67,6 +67,7 @@ #include "blacklists.h" #include "memcache.h" #include "script_cb.h" +#include "msg_translator.h" #ifdef USE_TCP #include "tcp_server.h" #endif @@ -269,8 +270,10 @@ int do_action(struct action* a, struct sip_msg* msg) struct proxy_l* p; char* tmp; char *new_uri, *end, *crt; - int len; + int len,i; int user; + str vals[5]; + str result; struct sip_uri uri, next_hop; struct sip_uri *u; unsigned short port; @@ -1081,7 +1084,49 @@ int do_action(struct action* a, struct sip_msg* msg) } break; + case CONSTRUCT_URI_T: + for (i=0;i<5;i++) + { + pve = (pv_elem_t *)a->elem[i].u.data; + if (pve->spec.getf) + { + if ( pv_printf_s(msg, pve, &vals[i])!=0 || + vals[i].len == 0 || vals[i].s == NULL) + { + LM_WARN("cannot get string for value\n"); + ret=E_BUG; + return -1; + } + } + else + vals[i] = pve->text; + } + + result.s = construct_uri(&vals[0],&vals[1],&vals[2],&vals[3],&vals[4], + &result.len); + + if (result.s) + { + int_str res; + int_str avp_name; + unsigned short avp_type; + + spec = (pv_spec_t*)a->elem[5].u.data; + if (pv_get_avp_name( msg, &(spec->pvp), &avp_name, + &avp_type)!=0){ + LM_CRIT("BUG in getting AVP name\n"); + return -1; + } + res.s = result; + if (add_avp(AVP_VAL_STR|avp_type, avp_name, res)<0){ + LM_ERR("cannot add AVP\n"); + return -1; + } + } + + + break; case SWITCH_T: if (a->elem[0].type!=SCRIPTVAR_ST){ LM_ALERT("BUG in switch() type %d\n", diff --git a/cfg.lex b/cfg.lex index 7648ad399f1..cc2f5bf77f5 100644 --- a/cfg.lex +++ b/cfg.lex @@ -169,6 +169,7 @@ XDBG "xdbg" XLOG_BUF_SIZE "xlog_buf_size" XLOG_FORCE_COLOR "xlog_force_color" XLOG "xlog" +CONSTRUCT_URI "construct_uri" /*ACTION LVALUES*/ URIHOST "uri:host" @@ -459,7 +460,8 @@ WHITESPACE [ \t\r\n] return XLOG_BUF_SIZE; } {XLOG_FORCE_COLOR} { count(); yylval.strval=yytext; return XLOG_FORCE_COLOR;} - +{CONSTRUCT_URI} { count(); yylval.strval=yytext; + return CONSTRUCT_URI;} {MAX_LEN} { count(); yylval.strval=yytext; return MAX_LEN; } {METHOD} { count(); yylval.strval=yytext; return METHOD; } diff --git a/cfg.y b/cfg.y index 361d6b7c16b..c8e336acf53 100644 --- a/cfg.y +++ b/cfg.y @@ -279,6 +279,7 @@ extern int line; %token XLOG %token XLOG_BUF_SIZE %token XLOG_FORCE_COLOR +%token CONSTRUCT_URI /* config vars. */ %token DEBUG @@ -2445,6 +2446,20 @@ cmd: FORWARD LPAREN STRING RPAREN { mk_action2( $$, FORWARD_T, mk_action1($$, XLOG_T, STR_ST, $3); } | XLOG LPAREN STRING COMMA STRING RPAREN { mk_action2($$, XLOG_T, STR_ST, STR_ST, $3, $5); } + | CONSTRUCT_URI LPAREN STRING COMMA STRING COMMA STRING COMMA STRING COMMA STRING COMMA script_var RPAREN { + elems[0].type = STR_ST; + elems[0].u.data = $3; + elems[1].type = STR_ST; + elems[1].u.data = $5; + elems[2].type = STR_ST; + elems[2].u.data = $7; + elems[3].type = STR_ST; + elems[3].u.data = $9; + elems[4].type = STR_ST; + elems[4].u.data = $11; + elems[5].type = SCRIPTVAR_ST; + elems[5].u.data = $13; + $$ = mk_action(CONSTRUCT_URI_T,6,elems,line); } diff --git a/msg_translator.c b/msg_translator.c index 05104267243..35c59dbd4ec 100644 --- a/msg_translator.c +++ b/msg_translator.c @@ -1956,3 +1956,60 @@ char* via_builder( unsigned int *len, *len = via_len; return line_buf; } + +static char uri_buff[1024]; +char *construct_uri(str *protocol,str *username,str *domain,str *port, + str *params,int *len) +{ + int pos = 0; + + if (!protocol || !username || !domain || !port || !params || !len) + { + LM_ERR("null pointer provided for construct_uri \n"); + return 0; + } + + if (!protocol->s || protocol->len == 0) + { + LM_ERR("no protocol specified\n"); + return 0; + } + + if (!domain->s || domain->len == 0) + { + LM_ERR("no domain specified\n"); + return 0; + } + + memcpy(uri_buff,protocol->s,protocol->len); + pos += protocol->len; + uri_buff[pos++] = ':'; + + if (username->s && username->len != 0) + { + memcpy(uri_buff+pos,username->s,username->len); + pos += username->len; + uri_buff[pos++] = '@'; + } + + memcpy(uri_buff+pos,domain->s,domain->len); + pos += domain->len; + + if (port->s && port->len !=0) + { + uri_buff[pos++] = ':'; + memcpy(uri_buff+pos,port->s,port->len); + pos += port->len; + } + + if (params->s && params->len !=0 ) + { + uri_buff[pos++] = ';'; + memcpy(uri_buff+pos,params->s,params->len); + pos += params->len; + } + + uri_buff[pos] = 0; + *len = pos; + return uri_buff; +} diff --git a/msg_translator.h b/msg_translator.h index 3784250475b..ca606dfc21a 100644 --- a/msg_translator.h +++ b/msg_translator.h @@ -108,4 +108,6 @@ int branch_builder( unsigned int hash_index, /* check if IP address in Via != source IP address of signaling */ int received_test( struct sip_msg *msg ); +char *construct_uri(str *protocol,str *username,str *domain,str *port, + str *params,int *len); #endif diff --git a/pvar.c b/pvar.c index 1dc040f84c1..a3cda2a7efe 100644 --- a/pvar.c +++ b/pvar.c @@ -4055,7 +4055,7 @@ void pv_value_destroy(pv_value_t *val) } #define PV_PRINT_BUF_SIZE 1024 -#define PV_PRINT_BUF_NO 3 +#define PV_PRINT_BUF_NO 5 /*IMPORTANT NOTE - even if the function prints and returns a static buffer, it * has built-in support for 3 levels of nesting (or concurrent usage). * If you think it's not enough for you, either use pv_printf() directly, diff --git a/route.c b/route.c index b8299f394df..675e9b08952 100644 --- a/route.c +++ b/route.c @@ -253,6 +253,7 @@ static int fix_actions(struct action* a) int i; str s; pv_elem_t *model=NULL; + pv_elem_t *models[5]; xl_level_p xlp; if (a==0){ @@ -656,6 +657,33 @@ static int fix_actions(struct action* a) t->elem[1].u.data = model; t->elem[1].type = SCRIPTVAR_ELEM_ST; } + break; + case CONSTRUCT_URI_T: + for (i=0;i<5;i++) + { + s.s = (char*)t->elem[i].u.data; + s.len = strlen(s.s); + if(s.len==0) + continue; + + if(pv_parse_format(&s ,&(models[i])) || models[i]==NULL) + { + LM_ERR("wrong format [%s] for value param!\n",s.s); + ret=E_BUG; + goto error; + } + + t->elem[i].u.data = (void*)models[i]; + } + + if (((pv_spec_p)t->elem[5].u.data)->type != PVT_AVP) + { + LM_ERR("Wrong type for the third argument - " + "must be an AVP\n"); + ret=E_BUG; + goto error; + } + break; } } diff --git a/route_struct.h b/route_struct.h index 25ff53a4a23..2b3060c3258 100644 --- a/route_struct.h +++ b/route_struct.h @@ -88,7 +88,8 @@ enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T, SET_TIME_STAMP_T,RESET_TIME_STAMP_T, DIFF_TIME_STAMP_T, PV_PRINTF_T, CACHE_STORE_T, CACHE_FETCH_T, CACHE_REMOVE_T, - XDBG_T, XLOG_T + XDBG_T, XLOG_T, + CONSTRUCT_URI_T }; enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST, EXPR_ST, ACTIONS_ST, CMD_ST, MODFIXUP_ST,