Explorar el Código

htable: new functions sht_has_name(...) and sht_has_str_value(...)

- sht_has_name(htable, op, mval) - return >0 if there is an item
matching its name with mval based on operator op
- sht_has_str_valye(htable, op, mval) - return >0 if there is an item
matching its string value with mval based on operator op
Daniel-Constantin Mierla hace 7 años
padre
commit
37eb8b00c2
Se han modificado 3 ficheros con 189 adiciones y 1 borrados
  1. 88 0
      src/modules/htable/ht_api.c
  2. 5 1
      src/modules/htable/ht_api.h
  3. 96 0
      src/modules/htable/htable.c

+ 88 - 0
src/modules/htable/ht_api.c

@@ -1304,6 +1304,94 @@ int ht_rm_cell_op(str *sre, ht_t *ht, int mode, int op)
 	return 0;
 }
 
+int ht_has_cell_op_str(str *sre, ht_t *ht, int mode, int op)
+{
+	ht_cell_t *it;
+	str sm;
+	int i;
+	int nomatch;
+	regex_t re;
+	regmatch_t pmatch;
+
+	if(sre==NULL || sre->len<=0 || ht==NULL)
+		return -1;
+
+	if(op == HT_RM_OP_RE) {
+		if (regcomp(&re, sre->s, REG_EXTENDED|REG_ICASE|REG_NEWLINE)) {
+			LM_ERR("bad re %s\n", sre->s);
+			return -1;
+		}
+	}
+
+	for(i=0; i<ht->htsize; i++) {
+		/* free entries */
+		ht_slot_lock(ht, i);
+		it = ht->entries[i].first;
+		while(it) {
+			nomatch = 0;
+			if(mode==0) {
+				sm = it->name;
+			} else {
+				if(it->flags&AVP_VAL_STR) {
+					sm = it->value.s;
+				} else {
+					/* no str value - skip matching */
+					nomatch = 1;
+				}
+			}
+			if(nomatch==0) {
+				switch(op) {
+					case HT_RM_OP_EQ:
+						if(sre->len==sm.len
+									&& strncmp(sm.s, sre->s, sre->len)==0) {
+							goto matched;
+						}
+					break;
+					case HT_RM_OP_NE:
+						if(sre->len!=sm.len
+									|| strncmp(sm.s, sre->s, sre->len)!=0) {
+							goto matched;
+						}
+					break;
+					case HT_RM_OP_SW:
+						if(sre->len<=sm.len
+									&& strncmp(sm.s, sre->s, sre->len)==0) {
+							goto matched;
+						}
+					break;
+					case HT_RM_OP_RE:
+						if (regexec(&re, sm.s, 1, &pmatch, 0)==0) {
+							goto matched;
+						}
+					break;
+					default:
+						goto notmatched;
+				}
+			}
+			it = it->next;
+		}
+		ht_slot_unlock(ht, i);
+	}
+	if(op==HT_RM_OP_RE) {
+		regfree(&re);
+	}
+	return -1;
+
+matched:
+	ht_slot_unlock(ht, i);
+	if(op==HT_RM_OP_RE) {
+		regfree(&re);
+	}
+	return 1;
+
+notmatched:
+	ht_slot_unlock(ht, i);
+	if(op==HT_RM_OP_RE) {
+		regfree(&re);
+	}
+	return -1;
+}
+
 int ht_reset_content(ht_t *ht)
 {
 	ht_cell_t *it;

+ 5 - 1
src/modules/htable/ht_api.h

@@ -114,8 +114,12 @@ int ht_count_cells_re(str *sre, ht_t *ht, int mode);
 ht_t *ht_get_root(void);
 int ht_reset_content(ht_t *ht);
 
-#define HT_RM_OP_SW	1
+#define HT_RM_OP_EQ	1
+#define HT_RM_OP_NE	2
+#define HT_RM_OP_SW	3
+#define HT_RM_OP_RE	4
 int ht_rm_cell_op(str *sre, ht_t *ht, int mode, int op);
+int ht_has_cell_op_str(str *sre, ht_t *ht, int mode, int op);
 
 void ht_iterator_init(void);
 int ht_iterator_start(str *iname, str *hname);

+ 96 - 0
src/modules/htable/htable.c

@@ -70,6 +70,8 @@ static int ht_rm_name_re(struct sip_msg* msg, char* key, char* foo);
 static int ht_rm_value_re(struct sip_msg* msg, char* key, char* foo);
 static int w_ht_rm_name(struct sip_msg* msg, char* hname, char* op, char *val);
 static int w_ht_rm_value(struct sip_msg* msg, char* hname, char* op, char *val);
+static int w_ht_has_name(struct sip_msg* msg, char* hname, char* op, char *val);
+static int w_ht_has_str_value(struct sip_msg* msg, char* hname, char* op, char *val);
 static int w_ht_slot_lock(struct sip_msg* msg, char* key, char* foo);
 static int w_ht_slot_unlock(struct sip_msg* msg, char* key, char* foo);
 static int ht_reset(struct sip_msg* msg, char* htname, char* foo);
@@ -114,6 +116,10 @@ static cmd_export_t cmds[]={
 		ANY_ROUTE},
 	{"sht_rm_value", (cmd_function)w_ht_rm_value,  3, fixup_spve_all, 0,
 		ANY_ROUTE},
+	{"sht_has_name",  (cmd_function)w_ht_has_name,   3, fixup_spve_all, 0,
+		ANY_ROUTE},
+	{"sht_has_str_value", (cmd_function)w_ht_has_str_value,  3, fixup_spve_all, 0,
+		ANY_ROUTE},
 	{"sht_lock",        (cmd_function)w_ht_slot_lock,    1, fixup_ht_key, 0,
 		ANY_ROUTE},
 	{"sht_unlock",      (cmd_function)w_ht_slot_unlock,  1, fixup_ht_key, 0,
@@ -536,6 +542,86 @@ static int ki_ht_rm_value(sip_msg_t* msg, str* sname, str* sop, str *sval)
 	return ht_rm_items(msg, sname, sop, sval, 1);
 }
 
+static int ht_has_str_items(sip_msg_t* msg, str* hname, str* op, str *val,
+		int mkey)
+{
+	ht_t *ht;
+	int vop;
+
+	ht = ht_get_table(hname);
+	if(ht==NULL) {
+		LM_ERR("cannot get hash table [%.*s]\n", hname->len, hname->s);
+		return -1;
+	}
+
+	switch(op->len) {
+		case 2:
+			if(strncmp(op->s, "eq", 2)==0) {
+				vop = HT_RM_OP_EQ;
+			} else if(strncmp(op->s, "ne", 2)==0) {
+				vop = HT_RM_OP_NE;
+			} else if(strncmp(op->s, "re", 2)==0) {
+				vop = HT_RM_OP_RE;
+			} else if(strncmp(op->s, "sw", 2)==0) {
+				vop = HT_RM_OP_SW;
+			} else {
+				LM_WARN("unsupported match operator: %.*s\n", op->len, op->s);
+				return -1;
+			}
+			if(ht_has_cell_op_str(val, ht, mkey, vop)<0) {
+				return -1;
+			}
+			return 1;
+		default:
+			LM_WARN("unsupported match operator: %.*s\n", op->len, op->s);
+			return -1;
+	}
+}
+
+static int w_ht_has_str_items(sip_msg_t* msg, char* hname, char* op, char *val,
+		int mkey)
+{
+	str sname;
+	str sop;
+	str sval;
+
+	if(fixup_get_svalue(msg, (gparam_t*)hname, &sname)<0 || sname.len<=0) {
+		LM_ERR("cannot get the hash table name\n");
+		return -1;
+	}
+	if(fixup_get_svalue(msg, (gparam_t*)op, &sop)<0 || sop.len<=0) {
+		LM_ERR("cannot get the match operation\n");
+		return -1;
+	}
+	if(fixup_get_svalue(msg, (gparam_t*)val, &sval)<0 || sval.len<=0) {
+		LM_ERR("cannot the get match value\n");
+		return -1;
+	}
+
+	return ht_has_str_items(msg, &sname, &sop, &sval, mkey);
+}
+
+static int w_ht_has_name(sip_msg_t* msg, char* hname, char* op, char *val)
+{
+	return w_ht_has_str_items(msg, hname, op, val, 0);
+}
+
+static int w_ht_has_str_value(sip_msg_t* msg, char* hname, char* op, char *val)
+{
+	return w_ht_has_str_items(msg, hname, op, val, 1);
+}
+
+static int ki_ht_has_name(sip_msg_t* msg, str* sname, str* sop, str *sval)
+{
+	return ht_has_str_items(msg, sname, sop, sval, 0);
+
+}
+
+static int ki_ht_has_str_value(sip_msg_t* msg, str* sname, str* sop, str *sval)
+{
+	return ht_has_str_items(msg, sname, sop, sval, 1);
+}
+
 static int ht_reset_by_name(str *hname)
 {
 	ht_t *ht;
@@ -1342,6 +1428,16 @@ static sr_kemi_t sr_kemi_htable_exports[] = {
 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
 	},
+	{ str_init("htable"), str_init("sht_has_name"),
+		SR_KEMIP_INT, ki_ht_has_name,
+		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
+	},
+	{ str_init("htable"), str_init("sht_has_str_value"),
+		SR_KEMIP_INT, ki_ht_has_str_value,
+		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
+	},
 
 	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
 };