Browse code

- 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 authored on 19/01/2006 19:44:40
Showing 5 changed files
... ...
@@ -1263,7 +1263,7 @@ select_params:
1263 1263
 	| select_param
1264 1264
 	;
1265 1265
 select_id:
1266
-	SELECT_MARK { sel.n = 0; sel.f = 0; } select_params {
1266
+	SELECT_MARK { sel.n = 0; sel.f[0] = 0; } select_params {
1267 1267
 		sel_ptr = (select_t*)pkg_malloc(sizeof(select_t));
1268 1268
 		if (!sel_ptr) {
1269 1269
 			yyerror("No memory left to allocate select structure\n");
... ...
@@ -27,6 +27,8 @@
27 27
  * History:
28 28
  * --------
29 29
  *  2005-12-19  select framework (mma)
30
+ *  2006-01-19  multiple nested calls, IS_ALIAS -> NESTED flag renamed (mma)
31
+ *              DIVERSION flag checked
30 32
  */
31 33
 
32 34
 
... ...
@@ -44,13 +46,16 @@ static select_table_t *select_list = &select_core_table;
44 44
 
45 45
 int resolve_select(select_t* s)
46 46
 {
47
-	select_f f, pf;
47
+	select_f f;
48
+	int nested;
48 49
 	int param_idx = 0;
49 50
 	int table_idx = 0;
50 51
 	select_table_t* t = NULL;;
51 52
 	int accept = 0;
52 53
 	
53
-	f = pf = NULL;
54
+	f = NULL;
55
+	nested = 0;
56
+	s->f[0] = NULL;
54 57
 	while (param_idx<s->n) {
55 58
 		accept = 0;
56 59
 		for (t=select_list; t; t=t->next) {
... ...
@@ -58,12 +63,14 @@ int resolve_select(select_t* s)
58 58
 			if (!t->table) continue;
59 59
 			while (t->table[table_idx].curr_f || t->table[table_idx].new_f) {
60 60
 				if (t->table[table_idx].curr_f == f) {
61
-					if (t->table[table_idx].type == s->params[param_idx].type) {
61
+					if (t->table[table_idx].flags & NESTED) {
62
+						accept = 1;
63
+					} else if (t->table[table_idx].type == s->params[param_idx].type) {
62 64
 						switch (t->table[table_idx].type) {
63 65
 						case SEL_PARAM_INT:
64 66
 							accept = 1;
65 67
 							break;
66
-							case SEL_PARAM_STR:
68
+						case SEL_PARAM_STR:
67 69
 							accept = (((t->table[table_idx].name.len == s->params[param_idx].v.s.len) || !t->table[table_idx].name.len)
68 70
 								   && (!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)));
69 71
 							break;
... ...
@@ -71,21 +78,26 @@ int resolve_select(select_t* s)
71 71
 							break;
72 72
 						}
73 73
 					};
74
-					if ((t->table[table_idx].flags & IS_ALIAS)&&(!pf)) {
75
-						accept = 1;
76
-					}
77 74
 				}
78 75
 				if (accept) goto accepted;
79 76
 				table_idx++;
80 77
 			}
81 78
 		}
79
+		BUG ("Unable to resolve select at level %d\n", param_idx);
82 80
 		goto not_found;
83 81
 
84 82
 		accepted:
83
+		if (t->table[table_idx].flags & DIVERSION) {
84
+			if (s->params[param_idx].type == SEL_PARAM_STR) pkg_free(s->params[param_idx].v.s.s);
85
+			s->params[param_idx].type = SEL_PARAM_DIV;
86
+			s->params[param_idx].v.i = t->table[table_idx].flags & DIVERSION_MASK;
87
+			
88
+		}
85 89
 		if (t->table[table_idx].flags & CONSUME_NEXT_STR) {
86 90
 			if ((param_idx<s->n-1) && (s->params[param_idx+1].type == SEL_PARAM_STR)) {
87 91
 				param_idx++;
88 92
 			} else if (!(t->table[table_idx].flags & OPTIONAL)) {
93
+				BUG ("Mandatory STR parameter not found\n");
89 94
 				goto not_found;
90 95
 			}
91 96
 		}
... ...
@@ -93,20 +105,37 @@ int resolve_select(select_t* s)
93 93
 			if ((param_idx<s->n-1) && (s->params[param_idx+1].type == SEL_PARAM_INT)) {
94 94
 				param_idx++;
95 95
 			} else if (!(t->table[table_idx].flags & OPTIONAL)) {
96
+				BUG ("Mandatory INT parameter not found\n");
96 97
 				goto not_found;
97 98
 			}
98 99
 		}
99
-		if (t->table[table_idx].flags & IS_ALIAS) {
100
-			pf = f;
100
+		if (t->table[table_idx].flags & NESTED) {
101
+			if (nested < MAX_NESTED_CALLS-1) { /* need space for final function */
102
+				s->f[nested++] = f;
103
+				s->f[nested] = NULL;
104
+			} else {
105
+				BUG("MAX_NESTED_CALLS too small to resolve select\n");
106
+				goto not_found;
107
+			}
101 108
 		} else {
102 109
 			param_idx++;
103 110
 		}
104 111
 		f = t->table[table_idx].new_f;
105 112
 	}
106 113
 
107
-	if (t->table[table_idx].flags & SEL_PARAM_EXPECTED) goto not_found;
108
-	s->f = f;
109
-	s->parent_f = pf;
114
+	if (t->table[table_idx].flags & SEL_PARAM_EXPECTED) {
115
+		BUG ("final node has SEL_PARAM_EXPECTED set (no more parameters available)\n");
116
+		goto not_found;
117
+	}
118
+	if (nested >= MAX_NESTED_CALLS) {
119
+		BUG("MAX_NESTED_CALLS too small, no space for finally resolved function\n");
120
+		goto not_found;
121
+	}
122
+	if ((nested>0) && (s->f[nested-1] == f)) {
123
+		BUG("Topmost nested function equals to final function, won't call it twice\n");
124
+	} else {
125
+		s->f[nested] = f;
126
+	}
110 127
 	return 0;
111 128
 	
112 129
 not_found:
... ...
@@ -115,6 +144,8 @@ not_found:
115 115
 
116 116
 int run_select(str* res, select_t* s, struct sip_msg* msg)
117 117
 {
118
+	int ret, i;
119
+	
118 120
 	if (res == NULL) {
119 121
 		BUG("Select unprepared result space\n");
120 122
 		return -1;
... ...
@@ -123,12 +154,17 @@ int run_select(str* res, select_t* s, struct sip_msg* msg)
123 123
 		BUG("Select structure is NULL\n");
124 124
 		return -1;
125 125
 	}
126
-	if (s->f == 0) {
126
+	if (s->f[0] == 0) {
127 127
 		BUG("Select structure has not been resolved\n");
128 128
 		return -1;
129 129
 	}
130
-DBG("Calling SELECT %p \n", s->f);
131
-	return s->f(res, s, msg);
130
+	DBG("Calling SELECT %p \n", s->f);
131
+
132
+	ret = 0;
133
+	for (i=0; (ret == 0) && (s->f[i] !=0 ) && (i<MAX_NESTED_CALLS); i++)	{
134
+		ret = s->f[i](res, s, msg);
135
+	}
136
+	return ret;
132 137
 }
133 138
 
134 139
 void print_select(select_t* s)
... ...
@@ -27,6 +27,7 @@
27 27
  * History:
28 28
  * --------
29 29
  *  2005-12-19  select framework (mma)
30
+ *  2006-01-19  multiple nested calls, IS_ALIAS -> NESTED flag renamed (mma)
30 31
  */
31 32
 
32 33
  
... ...
@@ -37,25 +38,52 @@
37 37
 #include "parser/msg_parser.h"
38 38
 
39 39
 #define MAX_SELECT_PARAMS 32
40
+#define MAX_NESTED_CALLS  4
40 41
 
41
-// Flags for parser table FLAG bitfiels
42
+/* Flags for parser table FLAG bitfiels 
43
+ */
42 44
 #define DIVERSION_MASK   0x00FF
43
-// if DIVERSION is set and the function is accepted and has STR param
44
-// the param is changed into SEL_PARAM_DIV and the value is set to (flags & DIVERSION_MASK)
45
+
46
+/* if DIVERSION is set and the function is accepted
47
+ * the param is changed into SEL_PARAM_DIV and the value is set to (flags & DIVERSION_MASK)
48
+ *  - it is valuable for STR params (saves parsing time)
49
+ *  - does not release the memory occupied by the parameter
50
+ */
45 51
 #define DIVERSION        1<<8
46
-// if any parameter is expected at this stage
52
+
53
+/* set if any parameter is expected at this stage
54
+ * (the function must be resolved further)
55
+ */
47 56
 #define SEL_PARAM_EXPECTED   1<<9
48
-// accept if following parameter is STR (any)
57
+
58
+/* accept if following parameter is STR (any)
59
+ * consume that extra parameter in one step
60
+ */
49 61
 #define CONSUME_NEXT_STR 1<<10
50
-// accept if following parameter is INT
62
+
63
+/* accept if following parameter is INT
64
+ * consume that extra parameter in one ste
65
+ */
51 66
 #define CONSUME_NEXT_INT 1<<11
52
-// next parameter is optional (use with CONSUME_NEXT_STR or CONSUME_NEXT_INT
67
+
68
+/* next parameter is optional (use with CONSUME_NEXT_STR or CONSUME_NEXT_INT
69
+ * resolution is accepted even if there is no other parameter
70
+ * or the parameter is of wrong type
71
+ */
53 72
 #define OPTIONAL         1<<12
54
-// if conversion to common alias is needed
55
-// up-to now parsed function would be stored in parent_f
56
-// NOTE: the parameter is not consumed for ALIAS, 
57
-// so you can leave it as ..,SEL_PARAM_INT, STR_NULL,..
58
-#define IS_ALIAS         1<<13
73
+
74
+/* left function is noted to be called
75
+ * rigth function continues in resolution
76
+ * NOTE: the parameter is not consumed for PARENT, 
77
+ * so you can leave it as ..,SEL_PARAM_INT, 0,..
78
+ *
79
+ * run_select then calls all functions with PARENT flag
80
+ * in the order of resolution until the final call or 
81
+ * the result is != 0 (<0 error, 1 null str) 
82
+ * the only one parameter passed between nested calls
83
+ * is the result str*
84
+ */
85
+#define NESTED		1<<13
59 86
 
60 87
 /*
61 88
  * Selector call parameter
... ...
@@ -81,8 +109,7 @@ struct select;
81 81
 typedef int (*select_f)(str* res, struct select* s, struct sip_msg* msg);
82 82
 
83 83
 typedef struct select {
84
-	select_f f;
85
-	select_f parent_f;
84
+	select_f f[MAX_NESTED_CALLS];
86 85
 	select_param_t params[MAX_SELECT_PARAMS];
87 86
 	int n;
88 87
 } select_t;
... ...
@@ -27,6 +27,7 @@
27 27
  * History:
28 28
  * --------
29 29
  *  2005-12-19  select framework, basic core functions (mma)
30
+ *  2006-01-19  multiple nested calls, IS_ALIAS -> NESTED flag renamed (mma)
30 31
  */
31 32
 
32 33
  
... ...
@@ -499,17 +500,8 @@ ABSTRACT_F(select_any_uri)
499 499
 
500 500
 int select_uri_type(str* res, select_t* s, struct sip_msg* msg)
501 501
 {
502
-	if (!s->parent_f) {
503
-		ERR("BUG: no parent fuction defined\n");
504
-		return -1;
505
-	}
506
-
507
-	int ret;
508
-	ret = s->parent_f(res, s, msg);
509
-	if (ret != 0)
510
-		return ret;
511
-
512 502
 	struct sip_uri uri;
503
+	
513 504
 	trim(res);
514 505
 	if (parse_uri(res->s, res->len, &uri)<0)
515 506
 		return -1;
... ...
@@ -531,17 +523,8 @@ int select_uri_type(str* res, select_t* s, struct sip_msg* msg)
531 531
 
532 532
 int select_uri_user(str* res, select_t* s, struct sip_msg* msg)
533 533
 {
534
-	if (!s->parent_f) {
535
-		ERR("BUG: no parent fuction defined\n");
536
-		return -1;
537
-	}
538
-
539
-	int ret;
540
-	ret = s->parent_f(res, s, msg);
541
-	if (ret != 0)
542
-		return ret;
543
-
544 534
 	struct sip_uri uri;
535
+
545 536
 	if (parse_uri(res->s, res->len, &uri)<0)
546 537
 		return -1;
547 538
 
... ...
@@ -550,17 +533,8 @@ int select_uri_user(str* res, select_t* s, struct sip_msg* msg)
550 550
 
551 551
 int select_uri_pwd(str* res, select_t* s, struct sip_msg* msg)
552 552
 {
553
-	if (!s->parent_f) {
554
-		ERR("BUG: no parent fuction defined\n");
555
-		return -1;
556
-	}
557
-
558
-	int ret;
559
-	ret = s->parent_f(res, s, msg);
560
-	if (ret != 0)
561
-		return ret;
562
-
563 553
 	struct sip_uri uri;
554
+
564 555
 	if (parse_uri(res->s, res->len, &uri)<0)
565 556
 		return -1;
566 557
 
... ...
@@ -569,17 +543,8 @@ int select_uri_pwd(str* res, select_t* s, struct sip_msg* msg)
569 569
 
570 570
 int select_uri_host(str* res, select_t* s, struct sip_msg* msg)
571 571
 {
572
-	if (!s->parent_f) {
573
-		ERR("BUG: no parent fuction defined\n");
574
-		return -1;
575
-	}
576
-
577
-	int ret;
578
-	ret = s->parent_f(res, s, msg);
579
-	if (ret != 0)
580
-		return ret;
581
-
582 572
 	struct sip_uri uri;
573
+
583 574
 	if (parse_uri(res->s, res->len, &uri)<0)
584 575
 		return -1;
585 576
 
... ...
@@ -588,17 +553,8 @@ int select_uri_host(str* res, select_t* s, struct sip_msg* msg)
588 588
 
589 589
 int select_uri_port(str* res, select_t* s, struct sip_msg* msg)
590 590
 {
591
-	if (!s->parent_f) {
592
-		ERR("BUG: no parent fuction defined\n");
593
-		return -1;
594
-	}
595
-
596
-	int ret;
597
-	ret = s->parent_f(res, s, msg);
598
-	if (ret != 0)
599
-		return ret;
600
-
601 591
 	struct sip_uri uri;
592
+	
602 593
 	if (parse_uri(res->s, res->len, &uri)<0)
603 594
 		return -1;
604 595
 
... ...
@@ -607,17 +563,8 @@ int select_uri_port(str* res, select_t* s, struct sip_msg* msg)
607 607
 
608 608
 int select_uri_params(str* res, select_t* s, struct sip_msg* msg)
609 609
 {
610
-	if (!s->parent_f) {
611
-		ERR("BUG: no parent fuction defined\n");
612
-		return -1;
613
-	}
614
-
615
-	int ret;
616
-	ret = s->parent_f(res, s, msg);
617
-	if (ret != 0)
618
-		return ret;
619
-
620 610
 	struct sip_uri uri;
611
+
621 612
 	if (parse_uri(res->s, res->len, &uri)<0)
622 613
 		return -1;
623 614
 		
... ...
@@ -27,6 +27,7 @@
27 27
  * History:
28 28
  * --------
29 29
  *  2005-12-19  select framework, basic core functions (mma)
30
+ *  2006-01-19  multiple nested calls, IS_ALIAS -> NESTED flag renamed (mma)
30 31
  */
31 32
 
32 33
  
... ...
@@ -117,9 +118,9 @@ static select_row_t select_core[] = {
117 117
 	{ select_via, SEL_PARAM_STR, STR_STATIC_INIT("alias"), select_via_params_spec, DIVERSION | SEL_PARAM_ALIAS},
118 118
 	{ select_via, SEL_PARAM_STR, STR_STATIC_INIT("params"), select_via_params, CONSUME_NEXT_STR},
119 119
 	
120
-	{ select_from_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, IS_ALIAS},
121
-	{ select_to_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, IS_ALIAS},
122
-	{ select_contact_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, IS_ALIAS},
120
+	{ select_from_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, NESTED},
121
+	{ select_to_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, NESTED},
122
+	{ select_contact_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, NESTED},
123 123
 	{ select_any_uri, SEL_PARAM_STR, STR_STATIC_INIT("type"), select_uri_type, 0},
124 124
 	{ select_any_uri, SEL_PARAM_STR, STR_STATIC_INIT("user"), select_uri_user, 0},
125 125
 	{ select_any_uri, SEL_PARAM_STR, STR_STATIC_INIT("pwd"), select_uri_pwd, 0},