Bläddra i källkod

- Support for regex based search

Jan Janak 20 år sedan
förälder
incheckning
9d7f35155e
2 ändrade filer med 93 tillägg och 35 borttagningar
  1. 74 34
      usr_avp.c
  2. 19 1
      usr_avp.h

+ 74 - 34
usr_avp.c

@@ -47,17 +47,6 @@
 #include "usr_avp.h"
 #include "usr_avp.h"
 
 
 
 
-/* usr_avp data bodies */
-struct str_int_data {
-	str  name;
-	int  val;
-};
-
-struct str_str_data {
-	str  name;
-	str  val;
-};
-
 /* avp aliases structs*/
 /* avp aliases structs*/
 struct avp_spec {
 struct avp_spec {
 	int type;
 	int type;
@@ -74,7 +63,7 @@ static struct avp_galias *galiases = 0;
 static struct usr_avp *global_avps = 0;
 static struct usr_avp *global_avps = 0;
 static struct usr_avp **crt_avps  = &global_avps;
 static struct usr_avp **crt_avps  = &global_avps;
 
 
-
+static regex_t* search_re;  /* Regex for use in subsequent searches */
 
 
 inline static unsigned short compute_ID( str *name )
 inline static unsigned short compute_ID( str *name )
 {
 {
@@ -110,13 +99,17 @@ int add_avp(unsigned short flags, int_str name, int_str val)
 			LOG(L_ERR,"ERROR:avp:add_avp: EMPTY NAME AVP!");
 			LOG(L_ERR,"ERROR:avp:add_avp: EMPTY NAME AVP!");
 			goto error;
 			goto error;
 		}
 		}
-		if (flags&AVP_VAL_STR)
-			len += sizeof(struct str_str_data)-sizeof(void*) + name.s->len
-				+ (val.s->len+1);
-		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+1);
+		if (flags&AVP_VAL_STR) {
+			len += sizeof(struct str_str_data)-sizeof(void*) 
+				+ name.s->len + 1 /* Terminating zero for regex search */
+				+ val.s->len + 1; /* Value is zero terminated */
+		} else {
+			len += sizeof(struct str_int_data)-sizeof(void*) 
+				+ name.s->len + 1; /* Terminating zero for regex search */
+		}
+	} else if (flags&AVP_VAL_STR) {
+		len += sizeof(str)-sizeof(void*) + val.s->len + 1;
+	}
 
 
 	avp = (struct usr_avp*)shm_malloc( len );
 	avp = (struct usr_avp*)shm_malloc( len );
 	if (avp==0) {
 	if (avp==0) {
@@ -143,6 +136,7 @@ int add_avp(unsigned short flags, int_str name, int_str val)
 			sid->name.len =name.s->len;
 			sid->name.len =name.s->len;
 			sid->name.s = (char*)sid + sizeof(struct str_int_data);
 			sid->name.s = (char*)sid + sizeof(struct str_int_data);
 			memcpy( sid->name.s , name.s->s, name.s->len);
 			memcpy( sid->name.s , name.s->s, name.s->len);
+			sid->name.s[name.s->len] = '\0'; /* Zero terminator */
 			break;
 			break;
 		case AVP_VAL_STR:
 		case AVP_VAL_STR:
 			/* avp type ID, str value */
 			/* avp type ID, str value */
@@ -158,8 +152,9 @@ int add_avp(unsigned short flags, int_str name, int_str val)
 			ssd->name.len = name.s->len;
 			ssd->name.len = name.s->len;
 			ssd->name.s = (char*)ssd + sizeof(struct str_str_data);
 			ssd->name.s = (char*)ssd + sizeof(struct str_str_data);
 			memcpy( ssd->name.s , name.s->s, name.s->len);
 			memcpy( ssd->name.s , name.s->s, name.s->len);
+			ssd->name.s[name.s->len]='\0'; /* Zero terminator */
 			ssd->val.len = val.s->len;
 			ssd->val.len = val.s->len;
-			ssd->val.s = ssd->name.s + ssd->name.len;
+			ssd->val.s = ssd->name.s + ssd->name.len + 1;
 			memcpy( ssd->val.s , val.s->s, val.s->len);
 			memcpy( ssd->val.s , val.s->s, val.s->len);
 			ssd->val.s[ssd->val.len] = 0;
 			ssd->val.s[ssd->val.len] = 0;
 			break;
 			break;
@@ -261,9 +256,36 @@ inline static struct usr_avp *internal_search_name_avp( struct usr_avp *avp,
 }
 }
 
 
 
 
+/* 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)
+{
+	str * avp_name;
+	regmatch_t pmatch;
+	
+	     /* validation */
+	if (re==0) {
+		LOG(L_ERR, "ERROR: internal_search_avp_by_re: No regular expression\n");
+		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;
+		}
+	}
+	return 0;
+}
+
 
 
 struct usr_avp *search_first_avp( unsigned short name_type,
 struct usr_avp *search_first_avp( unsigned short name_type,
-										int_str name, int_str *val)
+				  int_str name, int_str *val)
 {
 {
 	struct usr_avp *avp;
 	struct usr_avp *avp;
 
 
@@ -284,14 +306,20 @@ struct usr_avp *search_first_avp( unsigned short name_type,
 			return 0;
 			return 0;
 		}
 		}
 		avp = internal_search_name_avp(*crt_avps,compute_ID(name.s),name.s);
 		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);
 	} else {
 	} else {
 		avp = internal_search_ID_avp( *crt_avps, name.n );
 		avp = internal_search_ID_avp( *crt_avps, name.n );
 	}
 	}
-
-	/* get the value - if required */
-	if (avp && val)
-		get_avp_val(avp, val);
-
+	
+	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);
+	}
+	
 	return avp;
 	return avp;
 }
 }
 
 
@@ -299,18 +327,30 @@ struct usr_avp *search_first_avp( unsigned short name_type,
 
 
 struct usr_avp *search_next_avp( struct usr_avp *avp,  int_str *val )
 struct usr_avp *search_next_avp( struct usr_avp *avp,  int_str *val )
 {
 {
-	if (avp==0 || avp->next==0)
+	struct usr_avp* next;
+
+	if (avp == 0) {
 		return 0;
 		return 0;
+	}
 
 
-	if (avp->flags&AVP_NAME_STR)
-		avp = internal_search_name_avp( avp->next, avp->id, get_avp_name(avp));
-	else
-		avp = internal_search_ID_avp( avp->next, avp->id );
+	next = avp->next;
+	if (next == 0) {
+		return 0;
+	}
 
 
-	if (avp && val)
-		get_avp_val(avp, val);
+	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);
+	}
 
 
-	return avp;
+	if (next && val) {
+		get_avp_val(next, val);
+	}
+	
+	return next;
 }
 }
 
 
 
 

+ 19 - 1
usr_avp.h

@@ -34,6 +34,10 @@
 #ifndef _SER_URS_AVP_H_
 #ifndef _SER_URS_AVP_H_
 #define _SER_URS_AVP_H_
 #define _SER_URS_AVP_H_
 
 
+#include <sys/types.h>
+#include <regex.h>
+
+
 /*
 /*
  *   LIST with the allocated flags, their meaning and owner
  *   LIST with the allocated flags, their meaning and owner
  *   flag no.    owner            description
  *   flag no.    owner            description
@@ -47,15 +51,29 @@
 
 
 #include "str.h"
 #include "str.h"
 
 
+struct str_int_data {
+	str name;
+	int val;
+};
+
+struct str_str_data {
+	str name;
+	str val;
+};
+
 typedef union {
 typedef union {
 	int  n;
 	int  n;
 	str *s;
 	str *s;
+	regex_t* re;
 } int_str;
 } int_str;
 
 
 
 
 struct usr_avp {
 struct usr_avp {
 	unsigned short id;
 	unsigned short id;
+	     /* 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;
 };
 };
@@ -63,6 +81,7 @@ struct usr_avp {
 
 
 #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 GALIAS_CHAR_MARKER  '$'
 #define GALIAS_CHAR_MARKER  '$'
 
 
@@ -94,4 +113,3 @@ int parse_avp_name( str *name, int *type, int_str *avp_name);
 int parse_avp_spec( str *name, int *type, int_str *avp_name);
 int parse_avp_spec( str *name, int *type, int_str *avp_name);
 
 
 #endif
 #endif
-