Browse Source

- multiple nested calls allowed
- default MAX_NESTED_CALLS set to 4 (select was supposed to be fast :-)
- IS_ALIAS renamed to NESTED flag
- DIVERSION flag is processed at resolve_select

Michal Matyska 19 years ago
parent
commit
43f88e4ff4
5 changed files with 104 additions and 93 deletions
  1. 1 1
      cfg.y
  2. 51 15
      select.c
  3. 41 14
      select.h
  4. 7 60
      select_core.c
  5. 4 3
      select_core.h

+ 1 - 1
cfg.y

@@ -1263,7 +1263,7 @@ select_params:
 	| select_param
 	| select_param
 	;
 	;
 select_id:
 select_id:
-	SELECT_MARK { sel.n = 0; sel.f = 0; } select_params {
+	SELECT_MARK { sel.n = 0; sel.f[0] = 0; } select_params {
 		sel_ptr = (select_t*)pkg_malloc(sizeof(select_t));
 		sel_ptr = (select_t*)pkg_malloc(sizeof(select_t));
 		if (!sel_ptr) {
 		if (!sel_ptr) {
 			yyerror("No memory left to allocate select structure\n");
 			yyerror("No memory left to allocate select structure\n");

+ 51 - 15
select.c

@@ -27,6 +27,8 @@
  * History:
  * History:
  * --------
  * --------
  *  2005-12-19  select framework (mma)
  *  2005-12-19  select framework (mma)
+ *  2006-01-19  multiple nested calls, IS_ALIAS -> NESTED flag renamed (mma)
+ *              DIVERSION flag checked
  */
  */
 
 
 
 
@@ -44,13 +46,16 @@ static select_table_t *select_list = &select_core_table;
 
 
 int resolve_select(select_t* s)
 int resolve_select(select_t* s)
 {
 {
-	select_f f, pf;
+	select_f f;
+	int nested;
 	int param_idx = 0;
 	int param_idx = 0;
 	int table_idx = 0;
 	int table_idx = 0;
 	select_table_t* t = NULL;;
 	select_table_t* t = NULL;;
 	int accept = 0;
 	int accept = 0;
 	
 	
-	f = pf = NULL;
+	f = NULL;
+	nested = 0;
+	s->f[0] = NULL;
 	while (param_idx<s->n) {
 	while (param_idx<s->n) {
 		accept = 0;
 		accept = 0;
 		for (t=select_list; t; t=t->next) {
 		for (t=select_list; t; t=t->next) {
@@ -58,12 +63,14 @@ int resolve_select(select_t* s)
 			if (!t->table) continue;
 			if (!t->table) continue;
 			while (t->table[table_idx].curr_f || t->table[table_idx].new_f) {
 			while (t->table[table_idx].curr_f || t->table[table_idx].new_f) {
 				if (t->table[table_idx].curr_f == f) {
 				if (t->table[table_idx].curr_f == f) {
-					if (t->table[table_idx].type == s->params[param_idx].type) {
+					if (t->table[table_idx].flags & NESTED) {
+						accept = 1;
+					} else if (t->table[table_idx].type == s->params[param_idx].type) {
 						switch (t->table[table_idx].type) {
 						switch (t->table[table_idx].type) {
 						case SEL_PARAM_INT:
 						case SEL_PARAM_INT:
 							accept = 1;
 							accept = 1;
 							break;
 							break;
-							case SEL_PARAM_STR:
+						case SEL_PARAM_STR:
 							accept = (((t->table[table_idx].name.len == s->params[param_idx].v.s.len) || !t->table[table_idx].name.len)
 							accept = (((t->table[table_idx].name.len == s->params[param_idx].v.s.len) || !t->table[table_idx].name.len)
 								   && (!t->table[table_idx].name.s || !strncasecmp(t->table[table_idx].name.s, s->params[param_idx].v.s.s, s->params[param_idx].v.s.len)));
 								   && (!t->table[table_idx].name.s || !strncasecmp(t->table[table_idx].name.s, s->params[param_idx].v.s.s, s->params[param_idx].v.s.len)));
 							break;
 							break;
@@ -71,21 +78,26 @@ int resolve_select(select_t* s)
 							break;
 							break;
 						}
 						}
 					};
 					};
-					if ((t->table[table_idx].flags & IS_ALIAS)&&(!pf)) {
-						accept = 1;
-					}
 				}
 				}
 				if (accept) goto accepted;
 				if (accept) goto accepted;
 				table_idx++;
 				table_idx++;
 			}
 			}
 		}
 		}
+		BUG ("Unable to resolve select at level %d\n", param_idx);
 		goto not_found;
 		goto not_found;
 
 
 		accepted:
 		accepted:
+		if (t->table[table_idx].flags & DIVERSION) {
+			if (s->params[param_idx].type == SEL_PARAM_STR) pkg_free(s->params[param_idx].v.s.s);
+			s->params[param_idx].type = SEL_PARAM_DIV;
+			s->params[param_idx].v.i = t->table[table_idx].flags & DIVERSION_MASK;
+			
+		}
 		if (t->table[table_idx].flags & CONSUME_NEXT_STR) {
 		if (t->table[table_idx].flags & CONSUME_NEXT_STR) {
 			if ((param_idx<s->n-1) && (s->params[param_idx+1].type == SEL_PARAM_STR)) {
 			if ((param_idx<s->n-1) && (s->params[param_idx+1].type == SEL_PARAM_STR)) {
 				param_idx++;
 				param_idx++;
 			} else if (!(t->table[table_idx].flags & OPTIONAL)) {
 			} else if (!(t->table[table_idx].flags & OPTIONAL)) {
+				BUG ("Mandatory STR parameter not found\n");
 				goto not_found;
 				goto not_found;
 			}
 			}
 		}
 		}
@@ -93,20 +105,37 @@ int resolve_select(select_t* s)
 			if ((param_idx<s->n-1) && (s->params[param_idx+1].type == SEL_PARAM_INT)) {
 			if ((param_idx<s->n-1) && (s->params[param_idx+1].type == SEL_PARAM_INT)) {
 				param_idx++;
 				param_idx++;
 			} else if (!(t->table[table_idx].flags & OPTIONAL)) {
 			} else if (!(t->table[table_idx].flags & OPTIONAL)) {
+				BUG ("Mandatory INT parameter not found\n");
 				goto not_found;
 				goto not_found;
 			}
 			}
 		}
 		}
-		if (t->table[table_idx].flags & IS_ALIAS) {
-			pf = f;
+		if (t->table[table_idx].flags & NESTED) {
+			if (nested < MAX_NESTED_CALLS-1) { /* need space for final function */
+				s->f[nested++] = f;
+				s->f[nested] = NULL;
+			} else {
+				BUG("MAX_NESTED_CALLS too small to resolve select\n");
+				goto not_found;
+			}
 		} else {
 		} else {
 			param_idx++;
 			param_idx++;
 		}
 		}
 		f = t->table[table_idx].new_f;
 		f = t->table[table_idx].new_f;
 	}
 	}
 
 
-	if (t->table[table_idx].flags & SEL_PARAM_EXPECTED) goto not_found;
-	s->f = f;
-	s->parent_f = pf;
+	if (t->table[table_idx].flags & SEL_PARAM_EXPECTED) {
+		BUG ("final node has SEL_PARAM_EXPECTED set (no more parameters available)\n");
+		goto not_found;
+	}
+	if (nested >= MAX_NESTED_CALLS) {
+		BUG("MAX_NESTED_CALLS too small, no space for finally resolved function\n");
+		goto not_found;
+	}
+	if ((nested>0) && (s->f[nested-1] == f)) {
+		BUG("Topmost nested function equals to final function, won't call it twice\n");
+	} else {
+		s->f[nested] = f;
+	}
 	return 0;
 	return 0;
 	
 	
 not_found:
 not_found:
@@ -115,6 +144,8 @@ not_found:
 
 
 int run_select(str* res, select_t* s, struct sip_msg* msg)
 int run_select(str* res, select_t* s, struct sip_msg* msg)
 {
 {
+	int ret, i;
+	
 	if (res == NULL) {
 	if (res == NULL) {
 		BUG("Select unprepared result space\n");
 		BUG("Select unprepared result space\n");
 		return -1;
 		return -1;
@@ -123,12 +154,17 @@ int run_select(str* res, select_t* s, struct sip_msg* msg)
 		BUG("Select structure is NULL\n");
 		BUG("Select structure is NULL\n");
 		return -1;
 		return -1;
 	}
 	}
-	if (s->f == 0) {
+	if (s->f[0] == 0) {
 		BUG("Select structure has not been resolved\n");
 		BUG("Select structure has not been resolved\n");
 		return -1;
 		return -1;
 	}
 	}
-DBG("Calling SELECT %p \n", s->f);
-	return s->f(res, s, msg);
+	DBG("Calling SELECT %p \n", s->f);
+
+	ret = 0;
+	for (i=0; (ret == 0) && (s->f[i] !=0 ) && (i<MAX_NESTED_CALLS); i++)	{
+		ret = s->f[i](res, s, msg);
+	}
+	return ret;
 }
 }
 
 
 void print_select(select_t* s)
 void print_select(select_t* s)

+ 41 - 14
select.h

@@ -27,6 +27,7 @@
  * History:
  * History:
  * --------
  * --------
  *  2005-12-19  select framework (mma)
  *  2005-12-19  select framework (mma)
+ *  2006-01-19  multiple nested calls, IS_ALIAS -> NESTED flag renamed (mma)
  */
  */
 
 
  
  
@@ -37,25 +38,52 @@
 #include "parser/msg_parser.h"
 #include "parser/msg_parser.h"
 
 
 #define MAX_SELECT_PARAMS 32
 #define MAX_SELECT_PARAMS 32
+#define MAX_NESTED_CALLS  4
 
 
-// Flags for parser table FLAG bitfiels
+/* Flags for parser table FLAG bitfiels 
+ */
 #define DIVERSION_MASK   0x00FF
 #define DIVERSION_MASK   0x00FF
-// if DIVERSION is set and the function is accepted and has STR param
-// the param is changed into SEL_PARAM_DIV and the value is set to (flags & DIVERSION_MASK)
+
+/* if DIVERSION is set and the function is accepted
+ * the param is changed into SEL_PARAM_DIV and the value is set to (flags & DIVERSION_MASK)
+ *  - it is valuable for STR params (saves parsing time)
+ *  - does not release the memory occupied by the parameter
+ */
 #define DIVERSION        1<<8
 #define DIVERSION        1<<8
-// if any parameter is expected at this stage
+
+/* set if any parameter is expected at this stage
+ * (the function must be resolved further)
+ */
 #define SEL_PARAM_EXPECTED   1<<9
 #define SEL_PARAM_EXPECTED   1<<9
-// accept if following parameter is STR (any)
+
+/* accept if following parameter is STR (any)
+ * consume that extra parameter in one step
+ */
 #define CONSUME_NEXT_STR 1<<10
 #define CONSUME_NEXT_STR 1<<10
-// accept if following parameter is INT
+
+/* accept if following parameter is INT
+ * consume that extra parameter in one ste
+ */
 #define CONSUME_NEXT_INT 1<<11
 #define CONSUME_NEXT_INT 1<<11
-// next parameter is optional (use with CONSUME_NEXT_STR or CONSUME_NEXT_INT
+
+/* next parameter is optional (use with CONSUME_NEXT_STR or CONSUME_NEXT_INT
+ * resolution is accepted even if there is no other parameter
+ * or the parameter is of wrong type
+ */
 #define OPTIONAL         1<<12
 #define OPTIONAL         1<<12
-// if conversion to common alias is needed
-// up-to now parsed function would be stored in parent_f
-// NOTE: the parameter is not consumed for ALIAS, 
-// so you can leave it as ..,SEL_PARAM_INT, STR_NULL,..
-#define IS_ALIAS         1<<13
+
+/* left function is noted to be called
+ * rigth function continues in resolution
+ * NOTE: the parameter is not consumed for PARENT, 
+ * so you can leave it as ..,SEL_PARAM_INT, 0,..
+ *
+ * run_select then calls all functions with PARENT flag
+ * in the order of resolution until the final call or 
+ * the result is != 0 (<0 error, 1 null str) 
+ * the only one parameter passed between nested calls
+ * is the result str*
+ */
+#define NESTED		1<<13
 
 
 /*
 /*
  * Selector call parameter
  * Selector call parameter
@@ -81,8 +109,7 @@ struct select;
 typedef int (*select_f)(str* res, struct select* s, struct sip_msg* msg);
 typedef int (*select_f)(str* res, struct select* s, struct sip_msg* msg);
 
 
 typedef struct select {
 typedef struct select {
-	select_f f;
-	select_f parent_f;
+	select_f f[MAX_NESTED_CALLS];
 	select_param_t params[MAX_SELECT_PARAMS];
 	select_param_t params[MAX_SELECT_PARAMS];
 	int n;
 	int n;
 } select_t;
 } select_t;

+ 7 - 60
select_core.c

@@ -27,6 +27,7 @@
  * History:
  * History:
  * --------
  * --------
  *  2005-12-19  select framework, basic core functions (mma)
  *  2005-12-19  select framework, basic core functions (mma)
+ *  2006-01-19  multiple nested calls, IS_ALIAS -> NESTED flag renamed (mma)
  */
  */
 
 
  
  
@@ -499,17 +500,8 @@ ABSTRACT_F(select_any_uri)
 
 
 int select_uri_type(str* res, select_t* s, struct sip_msg* msg)
 int select_uri_type(str* res, select_t* s, struct sip_msg* msg)
 {
 {
-	if (!s->parent_f) {
-		ERR("BUG: no parent fuction defined\n");
-		return -1;
-	}
-
-	int ret;
-	ret = s->parent_f(res, s, msg);
-	if (ret != 0)
-		return ret;
-
 	struct sip_uri uri;
 	struct sip_uri uri;
+	
 	trim(res);
 	trim(res);
 	if (parse_uri(res->s, res->len, &uri)<0)
 	if (parse_uri(res->s, res->len, &uri)<0)
 		return -1;
 		return -1;
@@ -531,17 +523,8 @@ int select_uri_type(str* res, select_t* s, struct sip_msg* msg)
 
 
 int select_uri_user(str* res, select_t* s, struct sip_msg* msg)
 int select_uri_user(str* res, select_t* s, struct sip_msg* msg)
 {
 {
-	if (!s->parent_f) {
-		ERR("BUG: no parent fuction defined\n");
-		return -1;
-	}
-
-	int ret;
-	ret = s->parent_f(res, s, msg);
-	if (ret != 0)
-		return ret;
-
 	struct sip_uri uri;
 	struct sip_uri uri;
+
 	if (parse_uri(res->s, res->len, &uri)<0)
 	if (parse_uri(res->s, res->len, &uri)<0)
 		return -1;
 		return -1;
 
 
@@ -550,17 +533,8 @@ int select_uri_user(str* res, select_t* s, struct sip_msg* msg)
 
 
 int select_uri_pwd(str* res, select_t* s, struct sip_msg* msg)
 int select_uri_pwd(str* res, select_t* s, struct sip_msg* msg)
 {
 {
-	if (!s->parent_f) {
-		ERR("BUG: no parent fuction defined\n");
-		return -1;
-	}
-
-	int ret;
-	ret = s->parent_f(res, s, msg);
-	if (ret != 0)
-		return ret;
-
 	struct sip_uri uri;
 	struct sip_uri uri;
+
 	if (parse_uri(res->s, res->len, &uri)<0)
 	if (parse_uri(res->s, res->len, &uri)<0)
 		return -1;
 		return -1;
 
 
@@ -569,17 +543,8 @@ int select_uri_pwd(str* res, select_t* s, struct sip_msg* msg)
 
 
 int select_uri_host(str* res, select_t* s, struct sip_msg* msg)
 int select_uri_host(str* res, select_t* s, struct sip_msg* msg)
 {
 {
-	if (!s->parent_f) {
-		ERR("BUG: no parent fuction defined\n");
-		return -1;
-	}
-
-	int ret;
-	ret = s->parent_f(res, s, msg);
-	if (ret != 0)
-		return ret;
-
 	struct sip_uri uri;
 	struct sip_uri uri;
+
 	if (parse_uri(res->s, res->len, &uri)<0)
 	if (parse_uri(res->s, res->len, &uri)<0)
 		return -1;
 		return -1;
 
 
@@ -588,17 +553,8 @@ int select_uri_host(str* res, select_t* s, struct sip_msg* msg)
 
 
 int select_uri_port(str* res, select_t* s, struct sip_msg* msg)
 int select_uri_port(str* res, select_t* s, struct sip_msg* msg)
 {
 {
-	if (!s->parent_f) {
-		ERR("BUG: no parent fuction defined\n");
-		return -1;
-	}
-
-	int ret;
-	ret = s->parent_f(res, s, msg);
-	if (ret != 0)
-		return ret;
-
 	struct sip_uri uri;
 	struct sip_uri uri;
+	
 	if (parse_uri(res->s, res->len, &uri)<0)
 	if (parse_uri(res->s, res->len, &uri)<0)
 		return -1;
 		return -1;
 
 
@@ -607,17 +563,8 @@ int select_uri_port(str* res, select_t* s, struct sip_msg* msg)
 
 
 int select_uri_params(str* res, select_t* s, struct sip_msg* msg)
 int select_uri_params(str* res, select_t* s, struct sip_msg* msg)
 {
 {
-	if (!s->parent_f) {
-		ERR("BUG: no parent fuction defined\n");
-		return -1;
-	}
-
-	int ret;
-	ret = s->parent_f(res, s, msg);
-	if (ret != 0)
-		return ret;
-
 	struct sip_uri uri;
 	struct sip_uri uri;
+
 	if (parse_uri(res->s, res->len, &uri)<0)
 	if (parse_uri(res->s, res->len, &uri)<0)
 		return -1;
 		return -1;
 		
 		

+ 4 - 3
select_core.h

@@ -27,6 +27,7 @@
  * History:
  * History:
  * --------
  * --------
  *  2005-12-19  select framework, basic core functions (mma)
  *  2005-12-19  select framework, basic core functions (mma)
+ *  2006-01-19  multiple nested calls, IS_ALIAS -> NESTED flag renamed (mma)
  */
  */
 
 
  
  
@@ -117,9 +118,9 @@ static select_row_t select_core[] = {
 	{ select_via, SEL_PARAM_STR, STR_STATIC_INIT("alias"), select_via_params_spec, DIVERSION | SEL_PARAM_ALIAS},
 	{ select_via, SEL_PARAM_STR, STR_STATIC_INIT("alias"), select_via_params_spec, DIVERSION | SEL_PARAM_ALIAS},
 	{ select_via, SEL_PARAM_STR, STR_STATIC_INIT("params"), select_via_params, CONSUME_NEXT_STR},
 	{ select_via, SEL_PARAM_STR, STR_STATIC_INIT("params"), select_via_params, CONSUME_NEXT_STR},
 	
 	
-	{ select_from_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, IS_ALIAS},
-	{ select_to_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, IS_ALIAS},
-	{ select_contact_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, IS_ALIAS},
+	{ select_from_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, NESTED},
+	{ select_to_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, NESTED},
+	{ select_contact_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, NESTED},
 	{ select_any_uri, SEL_PARAM_STR, STR_STATIC_INIT("type"), select_uri_type, 0},
 	{ select_any_uri, SEL_PARAM_STR, STR_STATIC_INIT("type"), select_uri_type, 0},
 	{ select_any_uri, SEL_PARAM_STR, STR_STATIC_INIT("user"), select_uri_user, 0},
 	{ select_any_uri, SEL_PARAM_STR, STR_STATIC_INIT("user"), select_uri_user, 0},
 	{ select_any_uri, SEL_PARAM_STR, STR_STATIC_INIT("pwd"), select_uri_pwd, 0},
 	{ select_any_uri, SEL_PARAM_STR, STR_STATIC_INIT("pwd"), select_uri_pwd, 0},