Browse code

Select framework extended to "fixup call" if demanded using flag FIXUP_CALL.

When this flag is included in the flags column, then during the select
resolution, the "fixup" call to the resolved function is done.

During this call the res & msg parameters set to NULL.
The function can change the parsed select structure, e.g. param.type from
SEL_PARAM_STR into SEL_PARAM_DIV, etc.

Currently used for select_anyheader:
- changes _ into - to support headers including dashes (use e.g. @msg.max_forwards)
- calls parse_hname2 to speed-up headers lookup for known headers

Michal Matyska authored on 17/02/2006 12:50:41
Showing 4 changed files
... ...
@@ -58,6 +58,14 @@ int resolve_select(select_t* s)
58 58
 	s->f[0] = NULL;
59 59
 	while (param_idx<s->n) {
60 60
 		accept = 0;
61
+		switch (s->params[param_idx].type) {
62
+		case SEL_PARAM_STR:
63
+			DBG("resolve_select: '%.*s'\n", s->params[param_idx].v.s.len, s->params[param_idx].v.s.s);
64
+			break;
65
+		case SEL_PARAM_INT:
66
+			DBG("resolve_select: [%d]\n", s->params[param_idx].v.i);
67
+			break;
68
+		}
61 69
 		for (t=select_list; t; t=t->next) {
62 70
 			table_idx = 0;	
63 71
 			if (!t->table) continue;
... ...
@@ -109,6 +117,10 @@ int resolve_select(select_t* s)
109 117
 				goto not_found;
110 118
 			}
111 119
 		}
120
+		if (t->table[table_idx].flags & FIXUP_CALL) {
121
+			if (t->table[table_idx].new_f(NULL, s, NULL)<0) goto not_found;
122
+		}
123
+		
112 124
 		if (t->table[table_idx].flags & NESTED) {
113 125
 			if (nested < MAX_NESTED_CALLS-1) { /* need space for final function */
114 126
 				s->f[nested++] = f;
... ...
@@ -136,6 +148,7 @@ int resolve_select(select_t* s)
136 148
 	} else {
137 149
 		s->f[nested] = f;
138 150
 	}
151
+		
139 152
 	return 0;
140 153
 	
141 154
 not_found:
... ...
@@ -85,6 +85,13 @@
85 85
  */
86 86
 #define NESTED		1<<13
87 87
 
88
+/* "fixup call" would be done, when the structure is resolved to this node
89
+ * which means call with res and msg NULL
90
+ *
91
+ * if the fixup call return value <0, the select resolution will fail
92
+ */
93
+#define FIXUP_CALL	1<<14
94
+
88 95
 /*
89 96
  * Selector call parameter
90 97
  */
... ...
@@ -28,6 +28,7 @@
28 28
  * --------
29 29
  *  2005-12-19  select framework, basic core functions (mma)
30 30
  *  2006-01-19  multiple nested calls, IS_ALIAS -> NESTED flag renamed (mma)
31
+ *  2006-02-17  fixup call for select_anyhdr (mma)
31 32
  */
32 33
 
33 34
  
... ...
@@ -44,6 +45,8 @@
44 45
 #include "parser/parse_uri.h"
45 46
 #include "parser/parse_event.h"
46 47
 #include "parser/parse_rr.h"
48
+#include "mem/mem.h"
49
+#include "parser/parse_hname2.h"
47 50
 
48 51
 #define RETURN0_res(x) {*res=x;return 0;}
49 52
 #define TRIM_RET0_res(x) {*res=x;trim(res);return 0;} 
... ...
@@ -457,9 +460,38 @@ int select_anyheader(str* res, select_t* s, struct sip_msg* msg)
457 460
 {
458 461
 	struct hdr_field *hf, *hf0;
459 462
 	int hi;
463
+	char c;
464
+	struct hdr_field hdr;
460 465
 	
461
-	if(msg==NULL)
462
-		return -1;
466
+	if(msg==NULL) {
467
+		if (res!=NULL) return -1;
468
+
469
+		/* "fixup" call, res & msg are NULL */
470
+		if (s->n <2) return -1;
471
+
472
+		if (s->params[1].type==SEL_PARAM_STR) {
473
+				/* replace _ with - (for P-xxx headers) */
474
+			for (hi=s->params[1].v.s.len-1; hi>0; hi--)
475
+				if (s->params[1].v.s.s[hi]=='_')
476
+					s->params[1].v.s.s[hi]='-';
477
+				/* if header name is parseable, parse it and set SEL_PARAM_DIV */
478
+			c=s->params[1].v.s.s[s->params[1].v.s.len];
479
+			s->params[1].v.s.s[s->params[1].v.s.len]=':';
480
+			if (parse_hname2(s->params[1].v.s.s,s->params[1].v.s.s+(s->params[1].v.s.len<3?4:s->params[1].v.s.len+1),
481
+						&hdr)==0) {
482
+				ERR("select_anyhdr:fixup_call:parse error\n");
483
+				return -1;
484
+			}
485
+			s->params[1].v.s.s[s->params[1].v.s.len]=c;
486
+			
487
+			if (hdr.type!=HDR_OTHER_T && hdr.type!=HDR_ERROR_T) {
488
+				pkg_free(s->params[1].v.s.s);
489
+				s->params[1].type = SEL_PARAM_DIV;
490
+				s->params[1].v.i = hdr.type;
491
+			}
492
+		}
493
+		return 1;
494
+	}
463 495
 
464 496
 	hf0 = NULL;
465 497
 
... ...
@@ -139,8 +139,6 @@ static select_row_t select_core[] = {
139 139
 	{ select_any_uri, SEL_PARAM_STR, STR_STATIC_INIT("host"), select_uri_host, 0},
140 140
 	{ select_any_uri, SEL_PARAM_STR, STR_STATIC_INIT("port"), select_uri_port, 0},
141 141
 	{ select_any_uri, SEL_PARAM_STR, STR_STATIC_INIT("params"), select_uri_params, 0},
142
-	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("msg"), select_msgheader, SEL_PARAM_EXPECTED},
143
-	{ select_msgheader, SEL_PARAM_STR, STR_NULL, select_anyheader, OPTIONAL | CONSUME_NEXT_INT},
144 142
 	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("event"), select_event, 0},
145 143
 
146 144
 	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("record_route"), select_rr, 0},
... ...
@@ -149,10 +147,12 @@ static select_row_t select_core[] = {
149 147
 	{ select_rr, SEL_PARAM_STR, STR_STATIC_INIT("name"), select_rr_name, 0}, 
150 148
 	{ select_rr, SEL_PARAM_STR, STR_STATIC_INIT("params"), select_rr_params, CONSUME_NEXT_STR},
151 149
 
152
-        { NULL, SEL_PARAM_STR, STR_STATIC_INIT("cseq"), select_cseq, 0},
153
-        { select_cseq, SEL_PARAM_STR, STR_STATIC_INIT("num"), select_cseq_num, 0},
154
-        { select_cseq, SEL_PARAM_STR, STR_STATIC_INIT("method"), select_cseq_method, 0},
150
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("cseq"), select_cseq, 0},
151
+	{ select_cseq, SEL_PARAM_STR, STR_STATIC_INIT("num"), select_cseq_num, 0},
152
+	{ select_cseq, SEL_PARAM_STR, STR_STATIC_INIT("method"), select_cseq_method, 0},
155 153
 
154
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("msg"), select_msgheader, SEL_PARAM_EXPECTED},
155
+	{ select_msgheader, SEL_PARAM_STR, STR_NULL, select_anyheader, OPTIONAL | CONSUME_NEXT_INT | FIXUP_CALL},
156 156
 	{ NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
157 157
 };
158 158