Browse Source

- avp core replaced with .14 version
- avp DB support removed from core (later to be added as separate module)
- tm support for avps (avp list saved into transactions and made available into
tm callbacks, in failure and reply routes).

Bogdan-Andrei Iancu 21 years ago
parent
commit
2be21e31d9
13 changed files with 351 additions and 486 deletions
  1. 0 55
      action.c
  2. 0 8
      cfg.lex
  3. 0 41
      cfg.y
  4. 0 10
      main.c
  5. 14 0
      modules/tm/h_table.c
  6. 6 1
      modules/tm/h_table.h
  7. 5 10
      modules/tm/t_fifo.c
  8. 15 0
      modules/tm/t_hooks.c
  9. 38 66
      modules/tm/t_reply.c
  10. 5 0
      modules/tm/uac.c
  11. 6 4
      receive.c
  12. 235 266
      usr_avp.c
  13. 27 25
      usr_avp.h

+ 0 - 55
action.c

@@ -36,7 +36,6 @@
  *  2003-04-22  strip_tail added (jiri)
  *  2003-10-02  added SET_ADV_ADDR_T & SET_ADV_PORT_T (andrei)
  *  2003-10-29  added FORCE_TCP_ALIAS_T (andrei)
- *  2004-02-24  added LOAD_AVP_T and AVP_TO_URI_T (bogdan)
  */
 
 
@@ -57,7 +56,6 @@
 #include "mem/mem.h"
 #include "globals.h"
 #include "dset.h"
-#include "usr_avp.h"
 #ifdef USE_TCP
 #include "tcp_server.h"
 #endif
@@ -90,7 +88,6 @@ int do_action(struct action* a, struct sip_msg* msg)
 	int len;
 	int user;
 	struct sip_uri uri, next_hop;
-	struct usr_avp *avp;
 	struct sip_uri *u;
 	unsigned short port;
 	int proto;
@@ -661,58 +658,6 @@ int do_action(struct action* a, struct sip_msg* msg)
 #endif
 			ret=1; /* continue processing */
 			break;
-		case LOAD_AVP_T:
-			if (a->p1_type!=NUMBER_ST || a->p2_type!=STRING_ST ||
-			a->p3_type!=NUMBER_ST) {
-				LOG(L_CRIT,"BUG: do_action: bad load_avp(%d,%d,%d) params "
-						"types\n",a->p1_type,a->p2_type,a->p3_type);
-				ret=E_BUG;
-				break;
-			}
-			/* load the attribute(s)*/
-			if ( (ret=load_avp( msg, (int)a->p1.number, a->p2.string,
-			(int)a->p3.number))==-1 ) {
-				LOG(L_ERR,"ERROR:do_action: load avp failed\n");
-				ret=E_UNSPEC;
-				break;
-			}
-			ret = (ret==0)?1/*success*/:E_UNSPEC/*notfound*/;
-			break;
-		case AVP_TO_URI_T:
-			if (a->p1_type!=STR_ST ) {
-				LOG(L_CRIT,"BUG: do_action: bad avp_to_uri(%d) params "
-						"types\n",a->p1_type);
-				ret=E_BUG;
-				break;
-			}
-			/* look for the attribute */
-			if ( (avp=search_avp( (str*)a->p1.string ))==0) {
-				ret=E_UNSPEC;
-				break;
-			}
-			if (avp->val_type!=AVP_TYPE_STR) {
-				LOG(L_ERR,"ERROR:do_action: in avp_to_uri attribute <%s> "
-					"doesn't has a STR value\n",((str*)a->p1.string)->s);
-				ret=E_UNSPEC;
-				break;
-			}
-			/* replace the ruri */
-			new_uri = (char*)pkg_malloc( avp->val.str_val.len+1 );
-			if (new_uri==0) {
-				LOG(L_ERR,"ERROR:tm:t_attr_to_uri: no more pkg memory\n");
-				ret = E_OUT_OF_MEM;
-				break;
-			}
-			memcpy( new_uri, avp->val.str_val.s, avp->val.str_val.len);
-			new_uri[avp->val.str_val.len] = 0;
-			if (msg->new_uri.s)
-				pkg_free( msg->new_uri.s );
-			msg->new_uri.s = new_uri;
-			msg->new_uri.len = avp->val.str_val.len;
-			msg->parsed_uri_ok=0;
-
-			ret = 1;
-			break;
 		default:
 			LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
 	}

+ 0 - 8
cfg.lex

@@ -44,7 +44,6 @@
  *  2003-10-13  added fifo_dir (andrei)
  *  2003-10-28  added tcp_accept_aliases (andrei)
  *  2003-11-29  added {tcp_send, tcp_connect, tls_*}_timeout (andrei)
- *  2004-02-24  added LOAD_AVP_T and AVP_TO_URI_T (bogdan)
  *  2004-03-30  added DISABLE_CORE and OPEN_FD_LIMIT (andrei)
  *  2004-04-28  added sock_mode (replaces fifo_mode), sock_user &
  *               sock_group  (andrei)
@@ -120,8 +119,6 @@ IF				"if"
 ELSE			"else"
 SET_ADV_ADDRESS	"set_advertised_address"
 SET_ADV_PORT	"set_advertised_port"
-LOAD_AVP		"load_avp"
-AVP_TO_URI		"avp_to_uri"
 
 /*ACTION LVALUES*/
 URIHOST			"uri:host"
@@ -184,7 +181,6 @@ FIFO_DB_URL fifo_db_url
 UNIX_SOCK unix_sock
 UNIX_SOCK_CHILDREN unix_sock_children
 UNIX_TX_TIMEOUT unix_tx_timeout
-AVP_DB_URL  avp_db_url
 SERVER_SIGNATURE server_signature
 REPLY_TO_VIA reply_to_via
 USER		"user"|"uid"
@@ -304,9 +300,6 @@ EAT_ABLE	[\ \t\b\r]
 <INITIAL>{FORCE_RPORT}	{ count(); yylval.strval=yytext; return FORCE_RPORT; }
 <INITIAL>{FORCE_TCP_ALIAS}	{ count(); yylval.strval=yytext;
 								return FORCE_TCP_ALIAS; }
-<INITIAL>{LOAD_AVP}	{ count(); yylval.strval=yytext; return LOAD_AVP; }
-<INITIAL>{AVP_TO_URI}	{ count(); yylval.strval=yytext; return AVP_TO_URI; }
-	
 <INITIAL>{IF}	{ count(); yylval.strval=yytext; return IF; }
 <INITIAL>{ELSE}	{ count(); yylval.strval=yytext; return ELSE; }
 
@@ -385,7 +378,6 @@ EAT_ABLE	[\ \t\b\r]
 <INITIAL>{UNIX_SOCK} { count(); yylval.strval=yytext; return UNIX_SOCK; }
 <INITIAL>{UNIX_SOCK_CHILDREN} { count(); yylval.strval=yytext; return UNIX_SOCK_CHILDREN; }
 <INITIAL>{UNIX_TX_TIMEOUT} { count(); yylval.strval=yytext; return UNIX_TX_TIMEOUT; }
-<INITIAL>{AVP_DB_URL}	{ count(); yylval.strval=yytext; return AVP_DB_URL; }
 <INITIAL>{SERVER_SIGNATURE}	{ count(); yylval.strval=yytext; return SERVER_SIGNATURE; }
 <INITIAL>{REPLY_TO_VIA}	{ count(); yylval.strval=yytext; return REPLY_TO_VIA; }
 <INITIAL>{ADVERTISED_ADDRESS}	{	count(); yylval.strval=yytext;

+ 0 - 41
cfg.y

@@ -50,7 +50,6 @@
  * 2003-10-24  converted to the new socket_info lists (andrei)
  * 2003-10-28  added tcp_accept_aliases (andrei)
  * 2003-11-20  added {tcp_connect, tcp_send, tls_*}_timeout (andrei)
- * 2004-02-24  added LOAD_AVP_T and AVP_TO_URI_T (bogdan)
  * 2004-03-30  added DISABLE_CORE and OPEN_FD_LIMIT (andrei)
  * 2004-04-29  added SOCK_MODE, SOCK_USER & SOCK_GROUP (andrei)
  * 2004-05-03  applied multicast support patch (MCAST_LOOPBACK) from janakj
@@ -80,7 +79,6 @@
 #include "resolve.h"
 #include "socket_info.h"
 #include "name_alias.h"
-#include "usr_avp.h"
 #include "ut.h"
 #include "dset.h"
 
@@ -186,8 +184,6 @@ static struct id_list* mk_listen_id(char*, int, int);
 %token UDP
 %token TCP
 %token TLS
-%token LOAD_AVP
-%token AVP_TO_URI
 
 /* config vars. */
 %token DEBUG
@@ -214,7 +210,6 @@ static struct id_list* mk_listen_id(char*, int, int);
 %token UNIX_SOCK
 %token UNIX_SOCK_CHILDREN
 %token UNIX_TX_TIMEOUT
-%token AVP_DB_URL
 %token SERVER_SIGNATURE
 %token REPLY_TO_VIA
 %token LOADMODULE
@@ -438,8 +433,6 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
 		| UNIX_SOCK_CHILDREN EQUAL error { yyerror("int value expected\n"); }
 		| UNIX_TX_TIMEOUT EQUAL NUMBER { unixsock_tx_timeout=$3; }
 		| UNIX_TX_TIMEOUT EQUAL error { yyerror("int value expected\n"); }
-		| AVP_DB_URL EQUAL STRING { avp_db_url=$3; }
-		| AVP_DB_URL EQUAL error  { yyerror("string value expected"); }
 		| USER EQUAL STRING     { user=$3; }
 		| USER EQUAL ID         { user=$3; }
 		| USER EQUAL error      { yyerror("string value expected"); }
@@ -1561,40 +1554,6 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
 		| FORCE_TCP_ALIAS LPAREN error RPAREN	{$$=0; 
 					yyerror("bad argument, number expected");
 					}
-		| LOAD_AVP LPAREN STRING COMMA NUMBER RPAREN {
-					$$=(void*)get_user_type( $3 );
-					if ($$==(void*)-1) {
-						yyerror("unknown user type in arg 1 for "
-							"load_avp(x,x)");
-					} else {
-						$$=mk_action3( LOAD_AVP_T, NUMBER_ST, STRING_ST,
-							NUMBER_ST, $$, 0,(void*)$5);
-					}
-					}
-		| LOAD_AVP LPAREN STRING COMMA STRING COMMA NUMBER RPAREN {
-					$$=(void*)get_user_type( $3 );
-					if ($$==(void*)-1) {
-						yyerror("unknown user type in arg 1 for "
-							"load_avp(x,x,x)");
-					} else {
-						$$=mk_action3( LOAD_AVP_T, NUMBER_ST, STRING_ST,
-							NUMBER_ST, $$, $5, (void*)$7);
-					}
-					}
-		| LOAD_AVP error { $$=0; yyerror("missing '(' or ')' ?"); }
-		| AVP_TO_URI LPAREN STRING RPAREN {
-								$$=0;
-								if ((str_tmp=pkg_malloc(sizeof(str)))==0){
-										LOG(L_CRIT, "ERROR: cfg. parser:"
-													" out of memory.\n");
-								}else{
-										str_tmp->s=$3;
-										str_tmp->len=strlen($3);
-										$$=mk_action(AVP_TO_URI_T, STR_ST,
-											0, str_tmp, 0);
-								}
-										}
-		| AVP_TO_URI error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| SET_ADV_ADDRESS LPAREN listen_id RPAREN {
 								$$=0;
 								if ((str_tmp=pkg_malloc(sizeof(str)))==0){

+ 0 - 10
main.c

@@ -45,7 +45,6 @@
  *  2003-06-29  replaced port_no_str snprintf w/ int2str (andrei)
  *  2003-10-10  added switch for config check (-c) (andrei)
  *  2003-10-24  converted to the new socket_info lists (andrei)
- *  2004-02-06  added support for user pref. - init_avp_child() (bogdan)
  *  2004-03-30  core dump is enabled by default
  *              added support for increasing the open files limit    (andrei)
  *  2004-04-28  sock_{user,group,uid,gid,mode} added
@@ -100,7 +99,6 @@
 #include "parser/digest/digest_parser.h"
 #include "fifo_server.h"
 #include "unixsock_server.h"
-#include "usr_avp.h"
 #include "name_alias.h"
 #include "hash_func.h"
 #include "pt.h"
@@ -826,10 +824,6 @@ int main_loop()
 			LOG(L_ERR, "main_dontfork: init_child failed\n");
 			goto error;
 		}
-		if (init_avp_child(1)<0) {
-			LOG(L_ERR, "init_avp_child failed\n");
-			goto error;
-		}
 
 		is_main=1; /* hack 42: call init_child with is_main=0 in case
 					 some modules wants to fork a child */
@@ -944,10 +938,6 @@ int main_loop()
 					}
 #endif
 					bind_address=si; /* shortcut */
-					if (init_avp_child(i + 1)<0) {
-						LOG(L_ERR, "init_avp_child failed\n");
-						goto error;
-					}
 					if (init_child(i + 1) < 0) {
 						LOG(L_ERR, "init_child failed\n");
 						goto error;

+ 14 - 0
modules/tm/h_table.c

@@ -39,6 +39,8 @@
  * 2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
  * 2004-02-13  t->is_invite and t->local replaced with flags;
  *             timer_link.payload removed (bogdan)
+ * 2004-08-23  avp support added - move and remove avp list to/from
+ *             transactions (bogdan)
  */
 
 #include <stdlib.h>
@@ -157,6 +159,10 @@ void free_cell( struct cell* dead_cell )
 		tt=foo;
 	}
 
+	/* free the avp list */
+	if (dead_cell->user_avps)
+		destroy_avp_list_unsafe( &dead_cell->user_avps );
+
 	/* the cell's body */
 	shm_free_unsafe( dead_cell );
 
@@ -219,6 +225,7 @@ struct cell*  build_cell( struct sip_msg* p_msg )
 {
 	struct cell* new_cell;
 	int          sip_msg_len;
+	struct usr_avp **old;
 
 	/* allocs a new cell */
 	new_cell = (struct cell*)shm_malloc( sizeof( struct cell ) );
@@ -237,6 +244,11 @@ struct cell*  build_cell( struct sip_msg* p_msg )
 #endif
 	new_cell->uas.response.my_T=new_cell;
 
+	/* move the current avp list to transaction -bogdan */
+	old = set_avp_list( &new_cell->user_avps );
+	new_cell->user_avps = *old;
+	*old = 0;
+
 	/* enter callback, which may potentially want to parse some stuff,
 	 * before the request is shmem-ized */
 	if ( p_msg && has_reqin_tmcbs() )
@@ -265,6 +277,8 @@ struct cell*  build_cell( struct sip_msg* p_msg )
 
 error:
 	shm_free(new_cell);
+	/* unlink transaction AVP list and link back the global AVP list (bogdan)*/
+	reset_avps();
 	return NULL;
 }
 

+ 6 - 1
modules/tm/h_table.h

@@ -32,8 +32,9 @@
  * 2003-12-04  callbacks per transaction added; completion callback
  *             merge into them as LOCAL_COMPETED (bogdan)
  * 2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
- * 2004-02-13: t->is_invite, t->local, t->noisy_ctimer replaced
+ * 2004-02-13  t->is_invite, t->local, t->noisy_ctimer replaced
  *             with flags (bogdan)
+ * 2004-08-23  avp support added - avp list linked in transaction (bogdan)
  */
 
 #include "defs.h"
@@ -48,6 +49,7 @@
 #include "../../parser/msg_parser.h"
 #include "../../types.h"
 #include "../../md5utils.h"
+#include "../../usr_avp.h"
 #include "config.h"
 
 struct s_table;
@@ -249,6 +251,9 @@ typedef struct cell
 	 * forwarded or passed to UAC; note that there can be arbitrarily 
 	 * many due to downstream forking; */
 	struct totag_elem *fwded_totags;
+
+	/* list with user avp */
+	struct usr_avp *user_avps;
 }cell_type;
 
 

+ 5 - 10
modules/tm/t_fifo.c

@@ -184,6 +184,7 @@ error:
 }
 
 
+#define EMAIL_AVP_ID  0xcaca
 static int assemble_msg(struct sip_msg* msg, char* action)
 {
 	static char     id_buf[IDBUF_LEN];
@@ -191,7 +192,7 @@ static int assemble_msg(struct sip_msg* msg, char* action)
 	static char     hdrs_buf[HDRS_BUFFER_MAX];
 	static char     cmd_buf[CMD_BUFFER_MAX];
 	static str      empty_param = {".",1};
-	static str      email_attr = {"email",5};
+	int_str           email_val;
 	unsigned int      hash_index, label;
 	contact_body_t*   cb=0;
 	contact_t*        c=0;
@@ -199,7 +200,6 @@ static int assemble_msg(struct sip_msg* msg, char* action)
 	rr_t*             record_route;
 	struct hdr_field* p_hdr;
 	param_hooks_t     hooks;
-	struct usr_avp    *email_avp;
 	int               l;
 	char*             s, fproxy_lr;
 	str               route, next_hop, hdrs, tmp_s, body, str_uri;
@@ -210,7 +210,7 @@ static int assemble_msg(struct sip_msg* msg, char* action)
 		goto error;
 	}
 
-	email_avp = 0;
+	email_val.s = 0;
 	body = empty_param;
 
 	/* parse all -- we will need every header field for a UAS */
@@ -344,12 +344,7 @@ static int assemble_msg(struct sip_msg* msg, char* action)
 		body.len = msg->len - (body.s - msg->buf);
 
 		/* get email (if any) */
-		if ( (email_avp=search_avp( &email_attr ))!=0 &&
-		email_avp->val_type!=AVP_TYPE_STR ) {
-			LOG(L_WARN, "assemble_msg: 'email' avp found but "
-			    "not string -> ignoring it\n");
-			email_avp = 0;
-		}
+		search_first_avp( 0, (int_str)EMAIL_AVP_ID, &email_val);
 	}
 
 	/* additional headers */
@@ -400,7 +395,7 @@ static int assemble_msg(struct sip_msg* msg, char* action)
 
 	eol_line(2)=REQ_LINE(msg).method;     /* method type */
 	eol_line(3)=msg->parsed_uri.user;     /* user from r-uri */
-	eol_line(4)=email_avp?(email_avp->val.str_val):empty_param;  /* email */
+	eol_line(4)=(email_val.s)?(*email_val.s):(empty_param);  /* email */
 	eol_line(5)=msg->parsed_uri.host;     /* domain */
 
 	eol_line(6)=msg->rcv.bind_address->address_str; /* dst ip */

+ 15 - 0
modules/tm/t_hooks.c

@@ -31,6 +31,8 @@
  *  2003-12-04  global callbacks moved into transaction callbacks;
  *              multiple events per callback added; single list per
  *              transaction for all its callbacks (bogdan)
+ *  2004-08-23  user avp(attribute value pair) added -> making avp list
+ *              available in callbacks (bogdan)
  */
 
 #include "defs.h"
@@ -40,6 +42,7 @@
 #include "../../dprint.h"
 #include "../../error.h"
 #include "../../mem/mem.h"
+#include "../../usr_avp.h"
 #include "t_hooks.h"
 #include "t_lookup.h"
 #include "t_funcs.h"
@@ -169,11 +172,16 @@ void run_trans_callbacks( int type , struct cell *trans,
 {
 	static struct tmcb_params params = {0,0,0,0};
 	struct tm_callback    *cbp;
+	struct usr_avp **backup;
 
 	params.req = req;
 	params.rpl = rpl;
 	params.code = code;
 
+	if (trans->tmcb_hl.first==0 || ((trans->tmcb_hl.reg_types)&type)==0 )
+		return;
+
+	backup = set_avp_list( &trans->user_avps );
 	for (cbp=trans->tmcb_hl.first; cbp; cbp=cbp->next)  {
 		if ( (cbp->types)&type ) {
 			DBG("DBG: trans=%p, callback type %d, id %d entered\n",
@@ -181,6 +189,7 @@ void run_trans_callbacks( int type , struct cell *trans,
 			params.param = &(cbp->param);
 			cbp->callback( trans, type, &params );
 		}
+	set_avp_list( backup );
 	}
 }
 
@@ -190,15 +199,21 @@ void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code )
 {
 	static struct tmcb_params params = {0,0,0,0};
 	struct tm_callback    *cbp;
+	struct usr_avp **backup;
 
 	params.req = req;
 	params.code = code;
 
+	if (req_in_tmcb_hl->first==0)
+		return;
+
+	backup = set_avp_list( &trans->user_avps );
 	for (cbp=req_in_tmcb_hl->first; cbp; cbp=cbp->next)  {
 		DBG("DBG: trans=%p, callback type %d, id %d entered\n",
 			trans, cbp->types, cbp->id );
 		params.param = &(cbp->param);
 		cbp->callback( trans, cbp->types, &params );
 	}
+	set_avp_list( backup );
 }
 

+ 38 - 66
modules/tm/t_reply.c

@@ -60,6 +60,7 @@
  *  2003-11-11: build_lump_rpl() removed, add_lump_rpl() has flags (bogdan)
  *  2004-02-13: t->is_invite and t->local replaced with flags (bogdan)
  *  2004-02-18  fifo_t_reply imported from vm module (bogdan)
+ *  2004-08-23  avp list is available from failure/on_reply routes (bogdan)
  */
 
 
@@ -473,31 +474,36 @@ static inline void faked_env( struct cell *t,struct sip_msg *msg)
 	static enum route_mode backup_mode;
 	static struct cell *backup_t;
 	static unsigned int backup_msgid;
+	static struct usr_avp **backup_list;
 
 	if (msg) {
-	/* remember we are back in request processing, but process
-	 * a shmem-ed replica of the request; advertise it in rmode;
-	 * for example t_reply needs to know that
-	 */
-	backup_mode=rmode;
-	rmode=MODE_ONFAILURE;
-	/* also, tm actions look in beginning whether tranaction is
-	 * set -- whether we are called from a reply-processing 
-	 * or a timer process, we need to set current transaction;
-	 * otherwise the actions would attempt to look the transaction
-	 * up (unnecessary overhead, refcounting)
-	 */
-	/* backup */
-	backup_t=get_t();
-	backup_msgid=global_msg_id;
-	/* fake transaction and message id */
+		/* remember we are back in request processing, but process
+		 * a shmem-ed replica of the request; advertise it in rmode;
+		 * for example t_reply needs to know that
+		 */
+		backup_mode=rmode;
+		rmode=MODE_ONFAILURE;
+		/* also, tm actions look in beginning whether tranaction is
+		 * set -- whether we are called from a reply-processing 
+		 * or a timer process, we need to set current transaction;
+		 * otherwise the actions would attempt to look the transaction
+		 * up (unnecessary overhead, refcounting)
+		 */
+		/* backup */
+		backup_t=get_t();
+		backup_msgid=global_msg_id;
+		/* fake transaction and message id */
 		global_msg_id=msg->id;
 		set_t(t);
+		/* make available the avp list from transaction */
+		backup_list = set_avp_list( &t->user_avps );
 	} else {
 		/* restore original environment */
 		set_t(backup_t);
 		global_msg_id=backup_msgid;
 		rmode=backup_mode;
+		/* restore original avp list */
+		set_avp_list( backup_list );
 	}
 }
 
@@ -532,33 +538,7 @@ static inline int fake_req(struct sip_msg *faked_req,
 		faked_req->new_uri.s[faked_req->new_uri.len]=0;
 	}
 
-#if 0
-	/* create a duplicated lump list to which actions can add
-	 * new pkg items  */
-	if (shmem_msg->add_rm) {
-		faked_req->add_rm=dup_lump_list(shmem_msg->add_rm);
-		if (!faked_req->add_rm) { /* non_emty->empty ... failure */
-			LOG(L_ERR, "ERROR: fake_req: lump dup failed\n");
-			goto error01;
-		}
-	}
-	/* same for the body lumps */
-	if (shmem_msg->body_lumps) {
-		faked_req->body_lumps=dup_lump_list(shmem_msg->body_lumps);
-		if (!faked_req->body_lumps) { /* non_empty->empty ... failure */
-			LOG(L_ERR, "ERROR: fake_req: lump dup failed\n");
-			goto error02;
-		}
-	}
-#endif
 	return 1;
-
-#if 0
-error02:
-	free_duped_lump_list(faked_req->add_rm);
-error01:
-	if (faked_req->new_uri.s) pkg_free(faked_req->new_uri.s);
-#endif
 error00:
 	return 0;
 }
@@ -567,11 +547,6 @@ void inline static free_faked_req(struct sip_msg *faked_req, struct cell *t)
 {
 	struct hdr_field *hdr;
 
-#if 0
-	free_duped_lump_list(faked_req->add_rm);
-	free_duped_lump_list(faked_req->body_lumps);
-	faked_req->add_rm = faked_req->body_lumps = 0;
-#endif
 	if (faked_req->new_uri.s) {
 		pkg_free(faked_req->new_uri.s);
 		faked_req->new_uri.s = 0;
@@ -608,12 +583,10 @@ static inline int run_failure_handlers(struct cell *t, struct sip_msg *rpl,
 
 	/* failure_route for a local UAC? */
 	if (!shmem_msg) {
-		LOG(L_WARN, 
-			"Warning: run_failure_handlers: no UAC support (%d, %d) \n",
-			t->on_negative, 
-			t->tmcb_hl.reg_types);
-                return 0;
-        }
+		LOG(L_WARN,"Warning: run_failure_handlers: no UAC support (%d, %d) \n",
+			t->on_negative, t->tmcb_hl.reg_types);
+		return 0;
+	}
 
 	/* don't start faking anything if we don't have to */
 	if ( !has_tran_tmcbs( t, TMCB_ON_FAILURE) && !t->on_negative ) {
@@ -644,9 +617,6 @@ static inline int run_failure_handlers(struct cell *t, struct sip_msg *rpl,
 		/* run a reply_route action if some was marked */
 		if (run_actions(failure_rlist[on_failure], &faked_req)<0)
 			LOG(L_ERR, "ERROR: run_failure_handlers: Error in do_action\n");
-		/* destroy any eventual avps */
-		if (users_avps)
-			destroy_avps();
 	}
 
 	/* restore original environment and free the fake msg */
@@ -1225,6 +1195,7 @@ int reply_received( struct sip_msg  *p_msg )
 	struct ua_client *uac;
 	struct cell *t;
 	str next_hop;
+	struct usr_avp **backup_list;
 
 	/* make sure we know the assosociated transaction ... */
 	if (t_check( p_msg  , &branch )==-1)
@@ -1265,9 +1236,9 @@ int reply_received( struct sip_msg  *p_msg )
 		/* acknowledge negative INVITE replies (do it before detailed
 		 * on_reply processing, which may take very long, like if it
 		 * is attempted to establish a TCP connection to a fail-over dst */
-
-        if (t->flags & T_IS_INVITE_FLAG) {
-                if (msg_status >= 300) {
+		
+	if (t->flags & T_IS_INVITE_FLAG) {
+		if (msg_status >= 300) {
 			ack = build_ack(p_msg, t, branch, &ack_len);
 			if (ack) {
 				SEND_PR_BUFFER(&uac->request, ack, ack_len);
@@ -1283,18 +1254,19 @@ int reply_received( struct sip_msg  *p_msg )
 			}
 		}
 	}
-	     /* processing of on_reply block */
+	/* processing of on_reply block */
 	if (t->on_reply) {
 		rmode=MODE_ONREPLY;
-		     /* transfer transaction flag to message context */
+		/* transfer transaction flag to message context */
 		if (t->uas.request) p_msg->flags=t->uas.request->flags;
-	 	if (run_actions(onreply_rlist[t->on_reply], p_msg)<0) 
+		/* set the as avp_list the one from transaction */
+		backup_list = set_avp_list( &t->user_avps );
+		if (run_actions(onreply_rlist[t->on_reply], p_msg)<0) 
 			LOG(L_ERR, "ERROR: on_reply processing failed\n");
-		     /* destroy any eventual avps */
-		if (users_avps)
-			destroy_avps();
-		     /* transfer current message context back to t */
+		/* transfer current message context back to t */
 		if (t->uas.request) t->uas.request->flags=p_msg->flags;
+		/* restore original avp list */
+		set_avp_list( backup_list );
 	}
 	LOCK_REPLIES( t );
 	if ( is_local(t) ) {

+ 5 - 0
modules/tm/uac.c

@@ -49,6 +49,7 @@
  *              merged in transaction callbacks as LOCAL_COMPLETED (bogdan)
  *  2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
  *  2004-02-13  t->is_invite, t->local, t->noisy_ctimer replaced (bogdan)
+ *  2004-08-23  avp support in t_uac (bogdan)
  */
 
 #include <string.h>
@@ -198,6 +199,10 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
 		goto error2;
 	}
 
+	/* better reset avp list now - anyhow, it's useless from
+	 * this point (bogdan) */
+	reset_avps();
+
 	/* add the callback the the transaction for LOCAL_COMPLETED event */
 	if(cb && insert_tmcb(&(new_cell->tmcb_hl),TMCB_LOCAL_COMPLETED,cb,cbp)!=1){
 		ret=E_OUT_OF_MEM;

+ 6 - 4
receive.c

@@ -36,6 +36,7 @@
  * 2004-02-06 added user preferences support - destroy_avps() (bogdan)
  * 2004-04-30 exec_pre_cb is called after basic sanity checks (at least one
  *            via present & parsed ok)  (andrei)
+ * 2004-08-23 avp core changed - destroy_avp-> reset_avps (bogdan)
  */
 
 
@@ -57,6 +58,7 @@
 #include "dset.h"
 #include "usr_avp.h"
 
+
 #include "tcp_server.h" /* for tcpconn_add_alias */
 
 
@@ -166,10 +168,6 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
 			goto error;
 		}
 
-		/* ... free posible loaded avps */
-		if (users_avps)
-			destroy_avps();
-
 #ifdef STATS
 		gettimeofday( & tve, &tz );
 		diff = (tve.tv_sec-tvb.tv_sec)*1000000+(tve.tv_usec-tvb.tv_usec);
@@ -229,6 +227,8 @@ end:
 #endif
 	/* execute post-script callbacks, if any; -jiri */
 	exec_post_cb(msg);
+	/* free possible loaded avps -bogdan */
+	reset_avps();
 	DBG("receive_msg: cleaning up\n");
 	free_sip_msg(msg);
 	pkg_free(msg);
@@ -240,6 +240,8 @@ error:
 	DBG("error:...\n");
 	/* execute post-script callbacks, if any; -jiri */
 	exec_post_cb(msg);
+	/* free possible loaded avps -bogdan */
+	reset_avps();
 error02:
 	free_sip_msg(msg);
 	pkg_free(msg);

+ 235 - 266
usr_avp.c

@@ -26,349 +26,318 @@
  *
  * History:
  * ---------
- *  2004-02-06  created (bogdan)
- *  2004-06-06  updated to the current DB api (andrei)
+ *  2004-07-21  created (bogdan)
  */
 
 
+#include <assert.h>
+
 #include "sr_module.h"
 #include "dprint.h"
 #include "str.h"
 #include "ut.h"
-#include "mem/mem.h"
-#include "db/db.h"
-#include "parser/parse_from.h"
-#include "parser/parse_uri.h"
+#include "mem/shm_mem.h"
 #include "usr_avp.h"
 
 
 
-static db_con_t  *avp_db_con = 0;
-static db_func_t avp_dbf; /* database call backs */
-struct usr_avp   *users_avps = 0;
-char             *avp_db_url = 0;
+struct str_int_data {
+	str  name;
+	int  val;
+};
+
+struct str_str_data {
+	str  name;
+	str  val;
+};
 
 
-static char* usr_type[] = {"ruri","from","to",0};
+static struct usr_avp *global_avps = 0;
+static struct usr_avp **crt_avps  = &global_avps;
 
 
-int init_avp_child( int rank )
+
+inline static unsigned short compute_ID( str *name )
 {
-	if ( rank>PROC_MAIN ) {
-		if (avp_db_url==0) {
-			LOG(L_NOTICE,"NOTICE:init_avp_child: no avp_db_url specified "
-				"-> feature disabled\n");
-			return 0;
-		}
-		/* init db connection */
-		if ( bind_dbmod(avp_db_url, &avp_dbf) < 0 ) {
-			LOG(L_ERR,"ERROR:init_avp_child: unable to find any db module\n");
-			return -1;
-		}
-		if ( (avp_db_con=avp_dbf.init( avp_db_url ))==0) {
-			/* connection failed */
-			LOG(L_ERR,"ERROR:init_avp_child: unable to connect to database\n");
-			return -1;
-		}
-		if (avp_dbf.use_table( avp_db_con, AVP_DB_TABLE ) < 0) {
-			/* table selection failed */
-			LOG(L_ERR,"ERROR:init_avp_child: unable to select db table\n");
-			return -1;
-		}
+	char *p;
+	unsigned short id;
+
+	id=0;
+	for( p=name->s+name->len-1 ; p>=name->s ; p-- )
+		id ^= *p;
+	return id;
+}
+
+
+int add_avp(unsigned short flags, int_str name, int_str val)
+{
+	struct usr_avp *avp;
+	str *s;
+	struct str_int_data *sid;
+	struct str_str_data *ssd;
+	int len;
+
+	assert( crt_avps!=0 );
+
+	/* compute the required mem size */
+	len = sizeof(struct usr_avp);
+	if (flags&AVP_NAME_STR) {
+		if (flags&AVP_VAL_STR)
+			len += sizeof(struct str_str_data)-sizeof(void*) + name.s->len
+				+ val.s->len;
+		else
+			len += sizeof(struct str_int_data)-sizeof(void*) + name.s->len;
+	} else if (flags&AVP_VAL_STR)
+			len += sizeof(str)-sizeof(void*) + val.s->len;
+
+	avp = (struct usr_avp*)shm_malloc( len );
+	if (avp==0) {
+		LOG(L_ERR,"ERROR:avp:add_avp: no more shm mem\n");
+		goto error;
+	}
+
+	avp->flags = flags;
+	avp->id = (flags&AVP_NAME_STR)? compute_ID(name.s) : name.n ;
+
+	avp->next = *crt_avps;
+	*crt_avps = avp;
+
+	switch ( flags&(AVP_NAME_STR|AVP_VAL_STR) )
+	{
+		case 0:
+			/* avp type ID, int value */
+			avp->data = (void*)(long)val.n;
+			break;
+		case AVP_NAME_STR:
+			/* avp type str, int value */
+			sid = (struct str_int_data*)&(avp->data);
+			sid->val = val.n;
+			sid->name.len =name.s->len;
+			sid->name.s = (char*)sid + sizeof(struct str_int_data);
+			memcpy( sid->name.s , name.s->s, name.s->len);
+			break;
+		case AVP_VAL_STR:
+			/* avp type ID, str value */
+			s = (str*)&(avp->data);
+			s->len = val.s->len;
+			s->s = (char*)s + sizeof(str);
+			memcpy( s->s, val.s->s , s->len);
+			break;
+		case AVP_NAME_STR|AVP_VAL_STR:
+			/* avp type str, str value */
+			ssd = (struct str_str_data*)&(avp->data);
+			ssd->name.len = name.s->len;
+			ssd->name.s = (char*)ssd + sizeof(struct str_str_data);
+			memcpy( ssd->name.s , name.s->s, name.s->len);
+			ssd->val.len = val.s->len;
+			ssd->val.s = ssd->name.s + ssd->name.len;
+			memcpy( ssd->val.s , val.s->s, val.s->len);
+			break;
 	}
 
 	return 0;
+error:
+	return -1;
 }
 
 
-void print_avps(struct usr_avp *avp)
+inline static str* get_avp_name(struct usr_avp *avp)
 {
-	if (!avp)
-		return;
-	if (avp->val_type==AVP_TYPE_STR)
-		DBG("DEBUG:print_avp: %.*s=%.*s\n",
-			avp->attr.len,avp->attr.s,
-			avp->val.str_val.len,avp->val.str_val.s);
-	else
-		DBG("DEBUG:print_avp: %.*s=%u\n",
-			avp->attr.len,avp->attr.s,
-			avp->val.uint_val);
-	print_avps(avp->next);
+	switch ( avp->flags&(AVP_NAME_STR|AVP_VAL_STR) )
+	{
+		case 0:
+			/* avp type ID, int value */
+		case AVP_VAL_STR:
+			/* avp type ID, str value */
+			return 0;
+		case AVP_NAME_STR:
+			/* avp type str, int value */
+			return &((struct str_int_data*)&avp->data)->name;
+		case AVP_NAME_STR|AVP_VAL_STR:
+			/* avp type str, str value */
+			return &((struct str_str_data*)&avp->data)->name;
+	}
+
+	LOG(L_ERR,"BUG:avp:get_avp_name: unknown avp type (name&val) %d\n",
+		avp->flags&(AVP_NAME_STR|AVP_VAL_STR));
+	return 0;
 }
 
 
-void destroy_avps( )
+/* get value functions */
+
+inline void get_avp_val(struct usr_avp *avp, int_str *val)
 {
-	struct usr_avp *avp;
+	if (avp==0 || val==0)
+		return;
 
-	/*print_avps(users_avps);*/
-	while (users_avps) {
-		avp = users_avps;
-		users_avps = users_avps->next;
-		pkg_free( avp );
+	switch ( avp->flags&(AVP_NAME_STR|AVP_VAL_STR) ) {
+		case 0:
+			/* avp type ID, int value */
+			val->n = (long)(avp->data);
+			break;
+		case AVP_NAME_STR:
+			/* avp type str, int value */
+			val->n = ((struct str_int_data*)(&avp->data))->val;
+			break;
+		case AVP_VAL_STR:
+			/* avp type ID, str value */
+			val->s = (str*)(&avp->data);
+			break;
+		case AVP_NAME_STR|AVP_VAL_STR:
+			/* avp type str, str value */
+			val->s = &(((struct str_str_data*)(&avp->data))->val);
+			break;
 	}
 }
 
 
 
-int get_user_type( char *id )
-{
-	int i;
 
-	for(i=0;usr_type[i];i++) {
-		if (!strcasecmp( id, usr_type[i]) )
-			return i;
-	}
+/* seach functions */
 
-	LOG(L_ERR,"ERROR:avp:get_user_type: unknown user type <%s>\n",id);
-	return -1;
+inline static struct usr_avp *internal_search_ID_avp( struct usr_avp *avp,
+												unsigned short id)
+{
+	for( ; avp ; avp=avp->next ) {
+		if ( id==avp->id && (avp->flags&AVP_NAME_STR)==0  ) {
+			return avp;
+		}
+	}
+	return 0;
 }
 
 
 
-inline static unsigned int compute_ID( str *attr )
+inline static struct usr_avp *internal_search_name_avp( struct usr_avp *avp,
+												unsigned short id, str *name)
 {
-	char *p;
-	unsigned int id;
+	str * avp_name;
 
-	id=0;
-	for( p=attr->s+attr->len-1 ; p>=attr->s ; p-- )
-		id ^= *p;
-	return id;
+	for( ; avp ; avp=avp->next )
+		if ( id==avp->id && avp->flags&AVP_NAME_STR &&
+		(avp_name=get_avp_name(avp))!=0 && avp_name->len==name->len
+		 && !strncasecmp( avp_name->s, name->s, name->len) ) {
+			return avp;
+		}
+	return 0;
 }
 
 
-inline static db_res_t *do_db_query(struct sip_uri *uri,char *attr,int use_dom)
+
+struct usr_avp *search_first_avp( unsigned short name_type,
+										int_str name, int_str *val)
 {
-	static db_key_t   keys_cmp[3] = {"username","domain","attribute"};
-	static db_key_t   keys_ret[] = {"attribute","value","type"};
-	static db_val_t   vals_cmp[3];
-	unsigned int      nr_keys_cmp;
-	db_res_t          *res;
-
-	/* prepare DB query */
-	nr_keys_cmp = 0;
-	keys_cmp[ nr_keys_cmp ] = "username";
-	vals_cmp[ nr_keys_cmp ].type = DB_STR;
-	vals_cmp[ nr_keys_cmp ].nul  = 0;
-	vals_cmp[ nr_keys_cmp ].val.str_val = uri->user;
-	nr_keys_cmp++;
-	if (use_dom) {
-		keys_cmp[ nr_keys_cmp ] = "domain";
-		vals_cmp[ nr_keys_cmp ].type = DB_STR;
-		vals_cmp[ nr_keys_cmp ].nul  = 0;
-		vals_cmp[ nr_keys_cmp ].val.str_val = uri->host;
-		nr_keys_cmp++;
-	}
-	if (attr) {
-		keys_cmp[ nr_keys_cmp ] = "attribute";
-		vals_cmp[ nr_keys_cmp ].type = DB_STRING;
-		vals_cmp[ nr_keys_cmp ].nul  = 0;
-		vals_cmp[ nr_keys_cmp ].val.string_val = attr;
-		nr_keys_cmp++;
-	}
+	struct usr_avp *avp;
 
-	/* do the DB query */
-	if ( avp_dbf.query( avp_db_con, keys_cmp, 0/*op*/, vals_cmp, keys_ret,
-	nr_keys_cmp, 3, 0/*order*/, &res) < 0)
+	assert( crt_avps!=0 );
+	
+	if (*crt_avps==0)
 		return 0;
 
-	return res;
+	/* search for the AVP by ID (&name) */
+	if (name_type&AVP_NAME_STR)
+		avp = internal_search_name_avp(*crt_avps,compute_ID(name.s),name.s);
+	else
+		avp = internal_search_ID_avp( *crt_avps, name.n );
+
+	/* get the value - if required */
+	if (avp && val)
+		get_avp_val(avp, val);
+
+	return avp;
 }
 
 
 
-inline static int validate_db_row(struct db_row *row, unsigned int *val_type,
-													unsigned int *uint_val)
+struct usr_avp *search_next_avp( struct usr_avp *avp,  int_str *val )
 {
-	/* we don't accept null values */
-	if (row->values[0].nul || row->values[1].nul || row->values[2].nul ) {
-		LOG(L_ERR,"ERROR:avp:validat_db_row: DBreply contains NULL entryes\n");
-		return -1;
-	}
-	/* check the value types */
-	if ( (row->values[0].type!=DB_STRING && row->values[0].type!=DB_STR)
-	||  (row->values[1].type!=DB_STRING && row->values[1].type!=DB_STR)
-	|| row->values[2].type!=DB_INT ) {
-		LOG(L_ERR,"ERROR:avp:validat_db_row: bad DB types in response\n");
-		return -1;
-	}
-	/* check the content of TYPE filed */
-	*val_type = (unsigned int)row->values[2].val.int_val;
-	if (*val_type!=AVP_TYPE_INT && *val_type!=AVP_TYPE_STR) {
-		LOG(L_ERR,"ERROR:avp:validat_db_row: bad val %d in type field\n",
-			*val_type);
-		return -1;
-	}
-	/* convert from DB_STRING to DB_STR if necesary */
-	if (row->values[0].type==DB_STRING) {
-		row->values[0].val.str_val.s =  (char*)row->values[0].val.string_val;
-		row->values[0].val.str_val.len = strlen(row->values[0].val.str_val.s);
-	}
-	if (row->values[1].type==DB_STRING) {
-		row->values[1].val.str_val.s =  (char*)row->values[1].val.string_val;
-		row->values[1].val.str_val.len = strlen(row->values[1].val.str_val.s);
-	}
-	/* if type is INT decode the value */
-	if ( *val_type==AVP_TYPE_INT &&
-	str2int( &row->values[1].val.str_val, uint_val)==-1 ) {
-		LOG(L_ERR,"ERROR:avp:validat_db_row: type is INT, but value not "
-			"<%s>\n",row->values[1].val.str_val.s);
-		return -1;
-	}
-	return 0;
-}
+	if (avp==0 || (avp=avp->next)==0)
+		return 0;
 
+	if (avp->flags&AVP_NAME_STR)
+		avp = internal_search_name_avp( avp, avp->id, get_avp_name(avp));
+	else
+		avp = internal_search_ID_avp( avp, avp->id );
 
+	if (avp && val)
+		get_avp_val(avp, val);
 
-#define copy_str(_p_,_sd_,_ss_) \
-	do {\
-		(_sd_).s = (_p_);\
-		(_sd_).len = (_ss_).len;\
-		memcpy( _p_, (_ss_).s, (_ss_).len);\
-		(_p_) += (_ss_).len;\
-	}while(0)
-/*
- * Returns:   -1 : error
- *             0 : sucess and avp(s) loaded
- *             1 : sucess but no avp loaded
- */
-int load_avp( struct sip_msg *msg, int uri_type, char *attr, int use_dom)
-{
-	db_res_t          *res;
-	struct sip_uri    uri;
-	struct usr_avp    *avp;
-	str               *uri_s;
-	int               n;
-	unsigned int      val_type;
-	unsigned int      uint_val;
-	int               len;
-	char              *p;
-
-	/* featch the user name [and domain] */
-	switch (uri_type) {
-		case 0: /* RURI */
-			uri_s = &(msg->first_line.u.request.uri);
-			break;
-		case 1: /* from */
-			if (parse_from_header( msg )<0 ) {
-				LOG(L_ERR,"ERROR:load_avp: failed to parse from\n");
-				goto error;
-			}
-			uri_s = &(get_from(msg)->uri);
-			break;
-		case 2: /* to */
-			if (parse_headers( msg, HDR_TO, 0)<0) {
-				LOG(L_ERR,"ERROR:load_avp: failed to parse to\n");
-				goto error;
-			}
-			uri_s = &(get_to(msg)->uri);
-			break;
-		default:
-			LOG(L_CRIT,"BUG:load_avp: unknow username type <%d>\n",uri_type);
-			goto error;
-	}
+	return avp;
+}
 
-	/* parse uri */
-	if (parse_uri( uri_s->s, uri_s->len , &uri )<0) {
-		LOG(L_ERR,"ERROR:load_avp: failed to parse uri\n");
-		goto error;
-	}
 
-	/* check uri */
-	if (!uri.user.s||!uri.user.len||(use_dom&&(!uri.host.len||!uri.host.s))) {
-		LOG(L_ERR,"ERROR:load_avp: uri has no user/host part <%.*s>\n",
-			uri_s->len,uri_s->s);
-		goto error;
-	}
 
-	/* do DB query */
-	if ( (res=do_db_query( &uri, attr,use_dom))==0 ) {
-		LOG(L_ERR,"ERROR:load_avp: db_query failed\n");
-		goto error;
-	}
 
-	/* process DB response */
-	if (res->n==0) {
-		DBG("DEBUG:load_avp: no avp found for %.*s@%.*s <%s>\n",
-			uri.user.len,uri.user.s,(use_dom!=0)*uri.host.len,uri.host.s,
-			attr?attr:"NULL");
-		avp_dbf.free_result( avp_db_con, res);
-		/*no avp found*/
-		return 1;
-	}
+/********* free functions ********/
 
-	for( n=0 ; n<res->n ; n++) {
-		/* validate row */
-		if (validate_db_row( &res->rows[n] ,&val_type, &uint_val) < 0 )
-			continue;
-		/* what do we have here?! */
-		DBG("DEBUG:load_avp: found avp: <%s,%s,%d>\n",
-			res->rows[n].values[0].val.string_val,
-			res->rows[n].values[1].val.string_val,
-		res->rows[n].values[2].val.int_val);
-		/* build a new avp struct */
-		len = sizeof(struct usr_avp);
-		len += res->rows[n].values[0].val.str_val.len ;
-		if (val_type==AVP_TYPE_STR)
-			len += res->rows[n].values[1].val.str_val.len ;
-		avp = (struct usr_avp*)pkg_malloc( len );
-		if (avp==0) {
-			LOG(L_ERR,"ERROR:load_avp: no more pkg mem\n");
-			continue;
-		}
-		/* fill the structure in */
-		p = ((char*)avp) + sizeof(struct usr_avp);
-		avp->id = compute_ID( &res->rows[n].values[0].val.str_val );
-		avp->val_type = val_type;
-		/* attribute name */
-		copy_str( p, avp->attr, res->rows[n].values[0].val.str_val);
-		if (val_type==AVP_TYPE_INT) {
-			/* INT */
-			avp->val.uint_val = uint_val;
-		} else {
-			/* STRING */
-			copy_str( p, avp->val.str_val,
-				res->rows[n].values[1].val.str_val);
+void destroy_avp( struct usr_avp *avp_del)
+{
+	struct usr_avp *avp;
+	struct usr_avp *avp_prev;
+
+	for( avp_prev=0,avp=*crt_avps ; avp ; avp_prev=avp,avp=avp->next ) {
+		if (avp==avp_del) {
+			if (avp_prev)
+				avp_prev->next=avp->next;
+			else
+				*crt_avps = avp->next;
+			shm_free(avp);
+			return;
 		}
-		/* add avp to internal list */
-		avp->next = users_avps;
-		users_avps = avp;
 	}
-
-	avp_dbf.free_result( avp_db_con, res);
-	return 0;
-error:
-	return -1;
 }
 
 
-
-inline static struct usr_avp *internal_search_avp( unsigned int id, str *attr)
+void destroy_avp_list_unsafe( struct usr_avp **list )
 {
-	struct usr_avp *avp;
+	struct usr_avp *avp, *foo;
 
-	for( avp=users_avps ; avp ; avp=avp->next )
-		if ( id==avp->id 
-		&& attr->len==avp->attr.len
-		&& !strncasecmp( attr->s, avp->attr.s, attr->len)
-		) {
-			return avp;
-		}
-	return 0;
+	avp = *list;
+	while( avp ) {
+		foo = avp;
+		avp = avp->next;
+		shm_free_unsafe( foo );
+	}
+	*list = 0;
 }
 
 
+inline void destroy_avp_list( struct usr_avp **list )
+{
+	struct usr_avp *avp, *foo;
+
+	DBG("DEBUG:destroy_avp_list: destroing list %p\n",*list);
+	avp = *list;
+	while( avp ) {
+		foo = avp;
+		avp = avp->next;
+		shm_free( foo );
+	}
+	*list = 0;
+}
 
-struct usr_avp *search_avp( str *attr)
+
+void reset_avps( )
 {
-	return internal_search_avp( compute_ID( attr ), attr);
+	assert( crt_avps!=0 );
+	
+	if ( crt_avps!=&global_avps) {
+		crt_avps = &global_avps;
+	}
+	destroy_avp_list( crt_avps );
 }
 
 
 
-struct usr_avp *search_next_avp( struct usr_avp *avp )
+struct usr_avp** set_avp_list( struct usr_avp **list )
 {
-	return internal_search_avp( avp->id, &avp->attr);
+	struct usr_avp **foo;
+	
+	assert( crt_avps!=0 );
+
+	foo = crt_avps;
+	crt_avps = list;
+	return foo;
 }
 

+ 27 - 25
usr_avp.h

@@ -26,50 +26,52 @@
  *
  * History:
  * ---------
- *  2004-02-06  created (bogdan)
+ *  2004-07-21  created (bogdan)
  */
 
 #ifndef _SER_URS_AVP_H_
 #define _SER_URS_AVP_H_
 
 
-#include "parser/msg_parser.h"
+#include "str.h"
+
+typedef union {
+	int  n;
+	str *s;
+} int_str;
+
 
 
 struct usr_avp {
-	unsigned int id;
-	str attr;
-	unsigned int val_type;
-	union {
-		str  str_val;
-		unsigned int uint_val;
-	}val;
+	unsigned short id;
+	unsigned short flags;
 	struct usr_avp *next;
+	void *data;
 };
 
-extern struct usr_avp   *users_avps;
+#define AVP_NAME_STR     (1<<0)
+#define AVP_VAL_STR      (1<<1)
 
+/* add functions */
+int add_avp( unsigned short flags, int_str name, int_str val);
 
-#define AVP_TYPE_INT     1
-#define AVP_TYPE_STR     2
 
-#define AVP_DB_TABLE     "usr_preferences"
+/* seach functions */
+struct usr_avp *search_first_avp( unsigned short name_type, int_str name,
+															int_str *val );
+struct usr_avp *search_next_avp( struct usr_avp *avp, int_str *val  );
 
-#define AVP_USER_RURI    1
-#define AVP_USER_FROM    2
-#define AVP_USER_TO      3
 
-#define AVP_ALL_ATTR     ((char*)0xffffffff)
+/* free functions */
+void reset_avps( );
+void destroy_avp( struct usr_avp *avp);
+void destroy_avp_list( struct usr_avp **list );
+void destroy_avp_list_unsafe( struct usr_avp **list );
 
-/* init function */
-int init_avp_child( int rank );
-int get_user_type( char *id );
+/* get val func */
+void get_avp_val(struct usr_avp *avp, int_str *val );
+struct usr_avp** set_avp_list( struct usr_avp **list );
 
-/* load/free/seach functions */
-void destroy_avps( );
-int load_avp( struct sip_msg *msg, int type, char *attr, int use_dom);
-struct usr_avp *search_avp( str *attr);
-struct usr_avp *search_next_avp( struct usr_avp *avp );
 
 #endif