Browse Source

- support for AVP classes (user, domain, global attributes)

Jan Janak 20 năm trước cách đây
mục cha
commit
35f927fb10
3 tập tin đã thay đổi với 236 bổ sung137 xóa
  1. 3 3
      receive.c
  2. 181 119
      usr_avp.c
  3. 52 15
      usr_avp.h

+ 3 - 3
receive.c

@@ -228,7 +228,7 @@ end:
 	skipped = 0;
 	skipped = 0;
 #endif
 #endif
 	/* free possible loaded avps -bogdan */
 	/* free possible loaded avps -bogdan */
-	reset_avps();
+	reset_user_avps();
 	DBG("receive_msg: cleaning up\n");
 	DBG("receive_msg: cleaning up\n");
 	free_sip_msg(msg);
 	free_sip_msg(msg);
 	pkg_free(msg);
 	pkg_free(msg);
@@ -239,14 +239,14 @@ end:
 error_rpl:
 error_rpl:
 	/* execute post reply-script callbacks */
 	/* execute post reply-script callbacks */
 	exec_post_rpl_cb(msg);
 	exec_post_rpl_cb(msg);
-	reset_avps();
+	reset_user_avps();
 	goto error02;
 	goto error02;
 error_req:
 error_req:
 	DBG("receive_msg: error:...\n");
 	DBG("receive_msg: error:...\n");
 	/* execute post request-script callbacks */
 	/* execute post request-script callbacks */
 	exec_post_req_cb(msg);
 	exec_post_req_cb(msg);
 	/* free possible loaded avps -bogdan */
 	/* free possible loaded avps -bogdan */
-	reset_avps();
+	reset_user_avps();
 error02:
 error02:
 	free_sip_msg(msg);
 	free_sip_msg(msg);
 	pkg_free(msg);
 	pkg_free(msg);

+ 181 - 119
usr_avp.c

@@ -60,10 +60,15 @@ struct avp_galias {
 };
 };
 
 
 static struct avp_galias *galiases = 0;
 static struct avp_galias *galiases = 0;
-static struct usr_avp *global_avps = 0;
-static struct usr_avp **crt_avps  = &global_avps;
 
 
-static regex_t* search_re;  /* Regex for use in subsequent searches */
+static avp_t *global_avps = 0;  /* Global attribute list */
+static avp_t *domain_avps = 0;  /* Domain-specific attribute list */
+static avp_t *user_avps = 0;    /* User-specific attribute list */
+
+static avp_t **crt_global_avps = &global_avps; /* Pointer to the current list of global attributes */
+static avp_t **crt_domain_avps = &domain_avps; /* Pointer to the current list of domain attributes */
+static avp_t **crt_user_avps   = &user_avps;   /* Pointer to the current list of user attributes */
+
 
 
 inline static unsigned short compute_ID( str *name )
 inline static unsigned short compute_ID( str *name )
 {
 {
@@ -79,13 +84,33 @@ inline static unsigned short compute_ID( str *name )
 
 
 int add_avp(unsigned short flags, int_str name, int_str val)
 int add_avp(unsigned short flags, int_str name, int_str val)
 {
 {
-	struct usr_avp *avp;
+	avp_t **list;
+	avp_t *avp;
 	str *s;
 	str *s;
 	struct str_int_data *sid;
 	struct str_int_data *sid;
 	struct str_str_data *ssd;
 	struct str_str_data *ssd;
+	unsigned short avp_class;
 	int len;
 	int len;
 
 
-	assert( crt_avps!=0 );
+	if ((flags & ALL_AVP_CLASSES) == 0) {
+		     /* The caller did not specify any class to search in, so enable
+		      * all of them by default
+		      */
+		flags |= ALL_AVP_CLASSES;
+	}
+
+	if (IS_USER_AVP(flags)) {
+		list = crt_user_avps;
+		avp_class = AVP_USER;
+	} else if (IS_DOMAIN_AVP(flags)) {
+		list = crt_domain_avps;
+		avp_class = AVP_DOMAIN;
+	} else {
+		list = crt_global_avps;
+		avp_class = AVP_GLOBAL;
+	}
+
+	assert(list != 0);
 
 
 	if ( name.s==0 ) {
 	if ( name.s==0 ) {
 		LOG(L_ERR,"ERROR:avp:add_avp: 0 ID or NULL NAME AVP!");
 		LOG(L_ERR,"ERROR:avp:add_avp: 0 ID or NULL NAME AVP!");
@@ -117,11 +142,14 @@ int add_avp(unsigned short flags, int_str name, int_str val)
 		goto error;
 		goto error;
 	}
 	}
 
 
-	avp->flags = flags;
+		 /* Make that only the selected class is set
+		  * if the caller set more classes in flags
+		  */
+	avp->flags = flags & (~(ALL_AVP_CLASSES) | avp_class);
 	avp->id = (flags&AVP_NAME_STR)? compute_ID(name.s) : name.n ;
 	avp->id = (flags&AVP_NAME_STR)? compute_ID(name.s) : name.n ;
 
 
-	avp->next = *crt_avps;
-	*crt_avps = avp;
+	avp->next = *list;
+	*list = avp;
 
 
 	switch ( flags&(AVP_NAME_STR|AVP_VAL_STR) )
 	switch ( flags&(AVP_NAME_STR|AVP_VAL_STR) )
 	{
 	{
@@ -167,8 +195,7 @@ error:
 
 
 
 
 /* get value functions */
 /* get value functions */
-
-inline str* get_avp_name(struct usr_avp *avp)
+inline str* get_avp_name(avp_t *avp)
 {
 {
 	switch ( avp->flags&(AVP_NAME_STR|AVP_VAL_STR) )
 	switch ( avp->flags&(AVP_NAME_STR|AVP_VAL_STR) )
 	{
 	{
@@ -191,7 +218,7 @@ inline str* get_avp_name(struct usr_avp *avp)
 }
 }
 
 
 
 
-inline void get_avp_val(struct usr_avp *avp, int_str *val)
+inline void get_avp_val(avp_t *avp, int_str *val)
 {
 {
 	if (avp==0 || val==0)
 	if (avp==0 || val==0)
 		return;
 		return;
@@ -217,140 +244,157 @@ inline void get_avp_val(struct usr_avp *avp, int_str *val)
 }
 }
 
 
 
 
-struct usr_avp** get_avp_list( )
+/* Return the current list of user attributes */
+avp_t** get_user_avp_list(void)
 {
 {
-	assert( crt_avps!=0 );
-	return crt_avps;
+	assert(crt_user_avps != 0);
+	return crt_user_avps;
 }
 }
 
 
+/* Return the current list of domain attributes */
+avp_t** get_domain_avp_list(void)
+{
+	assert(crt_domain_avps != 0);
+	return crt_domain_avps;
+}
 
 
 
 
+/* Return the current list of domain attributes */
+avp_t** get_global_avp_list(void)
+{
+	assert(crt_global_avps != 0);
+	return crt_global_avps;
+}
 
 
-/* search functions */
 
 
-inline static struct usr_avp *internal_search_ID_avp( struct usr_avp *avp,
-												unsigned short id)
+/*
+ * Compare given id with id in avp, return true if they match
+ */
+static inline int match_by_id(avp_t* avp, unsigned short id)
 {
 {
-	for( ; avp ; avp=avp->next ) {
-		if ( id==avp->id && (avp->flags&AVP_NAME_STR)==0  ) {
-			return avp;
-		}
+	if (avp->id == id && (avp->flags&AVP_NAME_STR)==0) {
+		return 1;
 	}
 	}
 	return 0;
 	return 0;
 }
 }
 
 
 
 
-
-inline static struct usr_avp *internal_search_name_avp( struct usr_avp *avp,
-												unsigned short id, str *name)
+/*
+ * Compare given name with name in avp, return true if they are same
+ */
+static inline int match_by_name(avp_t* avp, unsigned short id, str* name)
 {
 {
-	str * avp_name;
-
-	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;
-		}
+	str* avp_name;
+	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 1;
+	}
 	return 0;
 	return 0;
 }
 }
 
 
 
 
-/* find an attribute by name match against regular expression */
-static struct usr_avp *internal_search_avp_by_re(struct usr_avp *avp, regex_t* re)
+/*
+ * Compare name with name in AVP using regular expressions, return
+ * true if they match
+ */
+static inline int match_by_re(avp_t* avp, regex_t* re)
 {
 {
-	str * avp_name;
 	regmatch_t pmatch;
 	regmatch_t pmatch;
-	
-	     /* validation */
-	if (re==0) {
-		LOG(L_ERR, "ERROR: internal_search_avp_by_re: No regular expression\n");
+	str * avp_name;
+	     /* AVP identifiable by name ? */
+	if (!(avp->flags&AVP_NAME_STR)) return 0;
+	if ((avp_name=get_avp_name(avp))==0) /* valid AVP name ? */
 		return 0;
 		return 0;
-	}
-	
-	for( ; avp ; avp=avp->next ) {
-		     /* AVP identifiable by name ? */
-		if (!(avp->flags&AVP_NAME_STR)) continue;
-		if ((avp_name=get_avp_name(avp))==0) /* valid AVP name ? */
-			continue;
-		if (!avp_name->s) /* AVP name validation */
-			continue;
-		if (regexec(re, avp_name->s, 1, &pmatch,0)==0) { /* re match ? */
-			avp->search_type|= AVP_NAME_RE;
-			return avp;
-		}
+	if (!avp_name->s) /* AVP name validation */
+		return 0;
+	if (regexec(re, avp_name->s, 1, &pmatch,0)==0) { /* re match ? */
+		return 1;
 	}
 	}
 	return 0;
 	return 0;
 }
 }
 
 
 
 
-struct usr_avp *search_first_avp( unsigned short name_type,
-				  int_str name, int_str *val)
+avp_t *search_first_avp(unsigned short flags, int_str name, int_str *val, struct search_state* s)
 {
 {
-	struct usr_avp *avp;
+	static struct search_state st;
 
 
-	assert( crt_avps!=0 );
-	
-	if (*crt_avps==0)
-		return 0;
+	assert( crt_user_avps != 0 );
+	assert( crt_domain_avps != 0);
+	assert( crt_global_avps != 0);
 
 
-	if ( name.s==0) {
+	if (name.s==0) {
 		LOG(L_ERR,"ERROR:avp:search_first_avp: 0 ID or NULL NAME AVP!");
 		LOG(L_ERR,"ERROR:avp:search_first_avp: 0 ID or NULL NAME AVP!");
 		return 0;
 		return 0;
 	}
 	}
 
 
-	/* search for the AVP by ID (&name) */
-	if (name_type&AVP_NAME_STR) {
-		if ( name.s->s==0 || name.s->len==0) {
-			LOG(L_ERR,"ERROR:avp:search_first_avp: EMPTY NAME AVP!");
-			return 0;
-		}
-		avp = internal_search_name_avp(*crt_avps,compute_ID(name.s),name.s);
-	} else if (name_type & AVP_NAME_RE) {
-		search_re = name.re;
-		avp = internal_search_avp_by_re(*crt_avps, search_re);
+	if (!s) s = &st;
+
+	if ((flags & ALL_AVP_CLASSES) == 0) {
+		     /* The caller did not specify any class to search in, so enable
+		      * all of them by default
+		      */
+		flags |= ALL_AVP_CLASSES;
+	}
+	s->flags = flags;
+	if (IS_USER_AVP(flags)) {
+		s->avp = *crt_user_avps;
+	} else if (IS_DOMAIN_AVP(flags)) {
+		s->avp = *crt_domain_avps;
 	} else {
 	} else {
-		avp = internal_search_ID_avp( *crt_avps, name.n );
+		s->avp = *crt_global_avps;
 	}
 	}
-	
-	if (avp) {
-		     /* remember type of search for next searches */
-		avp->search_type=name_type;
-		if (val) /* get the value - if required */
-			get_avp_val(avp, val);
+	s->name = name;
+
+	if (!(flags & AVP_NAME_STR) && !(flags & AVP_NAME_RE)) {
+		s->id = compute_ID(name.s);
 	}
 	}
-	
-	return avp;
+
+	return search_next_avp(s, val);
 }
 }
 
 
 
 
 
 
-struct usr_avp *search_next_avp( struct usr_avp *avp,  int_str *val )
+avp_t *search_next_avp(struct search_state* s, int_str *val )
 {
 {
-	struct usr_avp* next;
+	avp_t* avp;
+	int matched;
 
 
-	if (avp == 0) {
+	if (s == 0) {
+		LOG(L_ERR, "search_next:avp: Invalid parameter value\n");
 		return 0;
 		return 0;
 	}
 	}
 
 
-	next = avp->next;
-	if (next == 0) {
-		return 0;
-	}
+	while(1) {
+		for( ; s->avp; s->avp = s->avp->next) {
+			if (s->flags & AVP_NAME_RE) {
+				matched = match_by_re(s->avp, s->name.re);
+			} else if (s->flags & AVP_NAME_STR) {
+				matched = match_by_name(s->avp, s->id, s->name.s);
+			} else {
+				matched = match_by_id(s->avp, s->name.n);
+			}
+			if (matched) {
+				avp = s->avp;
+				s->avp = s->avp->next;
+				if (val) get_avp_val(avp, val);
+				return avp;
+			}
+		}
 
 
-	if (avp->search_type & AVP_NAME_RE) {
-		next = internal_search_avp_by_re(next, search_re);
-	} else if (avp->flags & AVP_NAME_STR) {
-		next = internal_search_name_avp(next, avp->id, get_avp_name(avp));
-	} else {
-		next = internal_search_ID_avp(next, avp->id);
+		if (IS_USER_AVP(s->flags)) {
+			s->flags &= ~AVP_USER;
+			s->avp = *crt_domain_avps;
+		} else if (IS_DOMAIN_AVP(s->flags)) {
+			s->flags &= ~AVP_DOMAIN;
+			s->avp = *crt_global_avps;
+		} else {
+			s->flags &= ~AVP_GLOBAL;
+			return 0;
+		}
 	}
 	}
 
 
-	if (next && val) {
-		get_avp_val(next, val);
-	}
-	
-	return next;
+	return 0;
 }
 }
 
 
 
 
@@ -358,17 +402,16 @@ struct usr_avp *search_next_avp( struct usr_avp *avp,  int_str *val )
 
 
 /********* free functions ********/
 /********* free functions ********/
 
 
-void destroy_avp( struct usr_avp *avp_del)
+void destroy_avp( avp_t *avp_del)
 {
 {
-	struct usr_avp *avp;
-	struct usr_avp *avp_prev;
+	avp_t *avp, *avp_prev;
 
 
-	for( avp_prev=0,avp=*crt_avps ; avp ; avp_prev=avp,avp=avp->next ) {
+	for( avp_prev=0,avp=*crt_user_avps ; avp ; avp_prev=avp,avp=avp->next ) {
 		if (avp==avp_del) {
 		if (avp==avp_del) {
 			if (avp_prev)
 			if (avp_prev)
 				avp_prev->next=avp->next;
 				avp_prev->next=avp->next;
 			else
 			else
-				*crt_avps = avp->next;
+				*crt_user_avps = avp->next;
 			shm_free(avp);
 			shm_free(avp);
 			return;
 			return;
 		}
 		}
@@ -376,9 +419,9 @@ void destroy_avp( struct usr_avp *avp_del)
 }
 }
 
 
 
 
-void destroy_avp_list_unsafe( struct usr_avp **list )
+void destroy_avp_list_unsafe( avp_t **list )
 {
 {
-	struct usr_avp *avp, *foo;
+	avp_t *avp, *foo;
 
 
 	avp = *list;
 	avp = *list;
 	while( avp ) {
 	while( avp ) {
@@ -390,9 +433,9 @@ void destroy_avp_list_unsafe( struct usr_avp **list )
 }
 }
 
 
 
 
-inline void destroy_avp_list( struct usr_avp **list )
+inline void destroy_avp_list( avp_t **list )
 {
 {
-	struct usr_avp *avp, *foo;
+	avp_t *avp, *foo;
 
 
 	DBG("DEBUG:destroy_avp_list: destroying list %p\n", *list);
 	DBG("DEBUG:destroy_avp_list: destroying list %p\n", *list);
 	avp = *list;
 	avp = *list;
@@ -405,29 +448,50 @@ inline void destroy_avp_list( struct usr_avp **list )
 }
 }
 
 
 
 
-void reset_avps( )
+void reset_user_avps(void)
 {
 {
-	assert( crt_avps!=0 );
+	assert( crt_user_avps!=0 );
 	
 	
-	if ( crt_avps!=&global_avps) {
-		crt_avps = &global_avps;
+	if ( crt_user_avps!=&user_avps) {
+		crt_user_avps = &user_avps;
 	}
 	}
-	destroy_avp_list( crt_avps );
+	destroy_avp_list( crt_user_avps );
 }
 }
 
 
 
 
-struct usr_avp** set_avp_list( struct usr_avp **list )
+avp_t** set_user_avp_list( avp_t **list )
 {
 {
-	struct usr_avp **foo;
-	
-	assert( crt_avps!=0 );
+	avp_t **foo;
 
 
-	foo = crt_avps;
-	crt_avps = list;
+	assert( crt_user_avps!=0 );
+
+	foo = crt_user_avps;
+	crt_user_avps = list;
 	return foo;
 	return foo;
 }
 }
 
 
 
 
+avp_t** set_domain_avp_list( avp_t **list )
+{
+	avp_t **foo;
+
+	assert( crt_domain_avps!=0 );
+
+	foo = crt_domain_avps;
+	crt_domain_avps = list;
+	return foo;
+}
+
+avp_t** set_global_avp_list( avp_t **list )
+{
+	avp_t **foo;
+
+	assert( crt_global_avps!=0 );
+
+	foo = crt_global_avps;
+	crt_global_avps = list;
+	return foo;
+}
 
 
 
 
 /********* global aliases functions ********/
 /********* global aliases functions ********/
@@ -673,5 +737,3 @@ parse_error:
 error:
 error:
 	return -1;
 	return -1;
 }
 }
-
-

+ 52 - 15
usr_avp.h

@@ -44,13 +44,18 @@
  *   -------------------------------------------------------
  *   -------------------------------------------------------
  *     0        avp_core          avp has a string name
  *     0        avp_core          avp has a string name
  *     1        avp_core          avp has a string value
  *     1        avp_core          avp has a string value
+ *     2        avp_core          regex search in progress
  *     3        avpops module     avp was loaded from DB
  *     3        avpops module     avp was loaded from DB
  *     4        lcr module        contact avp qvalue change
  *     4        lcr module        contact avp qvalue change
+ *     5        core              avp is in user list
+ *     6        core              avp is in domain list
+ *     7        core              avp is in global list
  *
  *
  */
  */
 
 
 #include "str.h"
 #include "str.h"
 
 
+
 struct str_int_data {
 struct str_int_data {
 	str name;
 	str name;
 	int val;
 	int val;
@@ -68,42 +73,74 @@ typedef union {
 } int_str;
 } int_str;
 
 
 
 
-struct usr_avp {
+typedef struct usr_avp {
 	unsigned short id;
 	unsigned short id;
 	     /* Flags that are kept for the AVP lifetime */
 	     /* Flags that are kept for the AVP lifetime */
 	unsigned short flags;
 	unsigned short flags;
-	     /* Type of search in progress */
-	unsigned short search_type;
 	struct usr_avp *next;
 	struct usr_avp *next;
 	void *data;
 	void *data;
+} avp_t;
+
+
+/*
+ * AVP search state
+ */
+struct search_state {
+	unsigned short flags;  /* Type of search and additional flags */
+	unsigned short id;
+	int_str name;
+	avp_t* avp;            /* Current AVP */
+	regex_t* search_re;    /* Compiled regular expression */
 };
 };
 
 
 
 
 #define AVP_NAME_STR     (1<<0)
 #define AVP_NAME_STR     (1<<0)
 #define AVP_VAL_STR      (1<<1)
 #define AVP_VAL_STR      (1<<1)
 #define AVP_NAME_RE      (1<<2)
 #define AVP_NAME_RE      (1<<2)
+#define AVP_USER         (1<<5)
+#define AVP_DOMAIN       (1<<6)
+#define AVP_GLOBAL       (1<<7)
+
+#define ALL_AVP_CLASSES (AVP_USER|AVP_DOMAIN|AVP_GLOBAL)
+
+/* True for user avps */
+#define IS_USER_AVP(flags) ((flags) & AVP_USER)
+
+/* True for domain avps */
+#define IS_DOMAIN_AVP(flags) ((flags) & AVP_DOMAIN)
+
+/* true for global avps */
+#define IS_GLOBAL_AVP(flags) ((flags) & AVP_GLOBAL)
 
 
 #define GALIAS_CHAR_MARKER  '$'
 #define GALIAS_CHAR_MARKER  '$'
 
 
 /* add functions */
 /* add functions */
-int add_avp( unsigned short flags, int_str name, int_str val);
+int add_avp(unsigned short flags, int_str name, int_str val);
 
 
 /* search functions */
 /* search 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  );
+avp_t *search_first_avp( unsigned short flags, int_str name,
+			 int_str *val, struct search_state* state);
+avp_t *search_next_avp(struct search_state* state, int_str *val);
 
 
 /* free functions */
 /* 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 );
+void reset_user_avps(void);
+
+void destroy_avp(avp_t *avp);
+void destroy_avp_list(avp_t **list );
+void destroy_avp_list_unsafe(avp_t **list );
 
 
 /* get func */
 /* get func */
-void get_avp_val(struct usr_avp *avp, int_str *val );
-str* get_avp_name(struct usr_avp *avp);
-struct usr_avp** set_avp_list( struct usr_avp **list );
-struct usr_avp** get_avp_list( );
+void get_avp_val(avp_t *avp, int_str *val );
+str* get_avp_name(avp_t *avp);
+
+avp_t** get_user_avp_list(void);   /* Return current list of user avps */
+avp_t** get_domain_avp_list(void); /* Return current list of domain avps */
+avp_t** get_global_avp_list(void); /* Return current list of global avps */
+
+avp_t** set_user_avp_list(avp_t **list);   /* Set current list of user avps to list */
+avp_t** set_domain_avp_list(avp_t **list); /* Set current list of domain avps to list */
+avp_t** set_global_avp_list(avp_t **list); /* Set current list of global avps to list */
+
 
 
 /* global alias functions (manipulation and parsing)*/
 /* global alias functions (manipulation and parsing)*/
 int add_avp_galias_str(char *alias_definition);
 int add_avp_galias_str(char *alias_definition);