Browse code

Message core select functions implemented:

(from|f)
(from|f).(uri|name|tag)
(from|f).params.<name>

(to|t)
(to|t).(uri|name|tag)
(to|t).params.<name>

(contact|m)
(contact|m).(uri|name|q|expires|method|received|instance)
(contact|m).params.<name>
- temporarily only the first contact is used

(from|f|to|t|contact|m).uri.(type|user|pwd|host|port|params)

(via|v|via[index]|v[index])
(via|v|via[index]|v[index]).(name|version|transport|host|port|comment|branch|received|rport|i|alias)
(via|v|via[index]|v[index]).params.<name>

msg.(<header_name>|<header_name>[index])
- index value -1 denotes the last header with such name
- header aliases are not supported, e.g. msg.t and msg.to will return
different results

Michal Matyska authored on 20/12/2005 01:00:27
Showing 2 changed files
... ...
@@ -1,3 +1,594 @@
1 1
 #include "select.h"
2 2
 #include "select_core.h"
3
+#include "dprint.h"
4
+#include "trim.h"
5
+#include "parser/hf.h"
6
+#include "parser/parse_from.h"
7
+#include "parser/parse_to.h"
8
+#include "parser/contact/parse_contact.h"
9
+#include "parser/contact/contact.h"
10
+#include "parser/parse_via.h"
11
+#include "parser/parse_uri.h"
12
+
13
+#define RETURN0_res(x) {*res=x;return 0;}
14
+#define TRIM_RET0_res(x) {*res=x;trim(res);return 0;} 
15
+#define TEST_RET_res_body(x) if (x){*res=x->body;return 0;}else return 1;
16
+#define TEST_RET_res_value(x) if (x){*res=x->value;return 0;}else return 1;
17
+
18
+int select_from(str* res, select_t* s, struct sip_msg* msg)
19
+{
20
+	if (parse_from_header(msg)<0)
21
+		return -1;
22
+	RETURN0_res(msg->from->body);
23
+}
24
+
25
+int select_from_uri(str* res, select_t* s, struct sip_msg* msg)
26
+{
27
+	if (parse_from_header(msg)<0)
28
+		return -1;
29
+	RETURN0_res(get_from(msg)->uri);
30
+}
31
+
32
+int select_from_tag(str* res, select_t* s, struct sip_msg* msg)
33
+{
34
+	if (parse_from_header(msg)<0)
35
+		return -1;
36
+	RETURN0_res(get_from(msg)->tag_value);
37
+}
38
+
39
+int select_from_name(str* res, select_t* s, struct sip_msg* msg)
40
+{
41
+	if (parse_from_header(msg)<0)
42
+		return -1;
43
+	RETURN0_res(get_from(msg)->display);
44
+}
45
+
46
+int select_from_params(str* res, select_t* s, struct sip_msg* msg)
47
+{
48
+	struct to_param* p;
49
+	if (parse_from_header(msg)<0)
50
+		return -1;
51
+	
52
+	p = get_from(msg)->param_lst;
53
+	while (p) {
54
+		if ((p->name.len==s->params[s->n-1].v.s.len)
55
+		    && !strncasecmp(p->name.s, s->params[s->n-1].v.s.s,p->name.len)) {
56
+			RETURN0_res(p->value);
57
+		}
58
+		p = p->next;
59
+	}
60
+	return 1;
61
+}
62
+
63
+int parse_to_header(struct sip_msg *msg)
64
+{
65
+        if ( !msg->to && ( parse_headers(msg,HDR_TO_F,0)==-1 || !msg->to)) {
66
+                ERR("bad msg or missing TO header\n");
67
+                return -1;
68
+        }
69
+
70
+        // HDR_TO_T is automatically parsed (get_hdr_field in parser/msg_parser.c)
71
+        // so check only ptr validity
72
+        if (msg->to->parsed)
73
+                return 0;
74
+	else
75
+		return -1;
76
+}
77
+
78
+int select_to(str* res, select_t* s, struct sip_msg* msg)
79
+{
80
+	if (parse_to_header(msg)<0)
81
+		return -1; 
82
+	RETURN0_res(msg->to->body);
83
+}
84
+
85
+int select_to_uri(str* res, select_t* s, struct sip_msg* msg)
86
+{
87
+	if (parse_to_header(msg)<0)
88
+		return -1;
89
+	RETURN0_res(get_to(msg)->uri);
90
+}
91
+
92
+int select_to_tag(str* res, select_t* s, struct sip_msg* msg)
93
+{
94
+	if (parse_to_header(msg)<0)
95
+		return -1;
96
+	RETURN0_res(get_to(msg)->tag_value);
97
+}
98
+
99
+int select_to_name(str* res, select_t* s, struct sip_msg* msg)
100
+{
101
+	if (parse_to_header(msg)<0)
102
+		return -1;
103
+	RETURN0_res(get_to(msg)->display);
104
+}
105
+
106
+int select_to_params(str* res, select_t* s, struct sip_msg* msg)
107
+{
108
+	struct to_param* p;
109
+
110
+	if (parse_to_header(msg)<0)
111
+		return -1;
112
+	
113
+	p = get_to(msg)->param_lst;
114
+	while (p) {
115
+		if ((p->name.len==s->params[s->n-1].v.s.len)
116
+		    && !strncasecmp(p->name.s, s->params[s->n-1].v.s.s,p->name.len)) {
117
+			RETURN0_res(p->value);
118
+		}
119
+		p = p->next;
120
+	}
121
+	return 1;
122
+}
123
+
124
+int parse_contact_header( struct sip_msg *msg)
125
+{
126
+        if ( !msg->contact && ( parse_headers(msg,HDR_CONTACT_F,0)==-1 || !msg->contact)) {
127
+                ERR("bad msg or missing CONTACT header\n");
128
+                return -1;
129
+        }
130
+
131
+        if (msg->contact->parsed)
132
+                return 0;
133
+
134
+	return parse_contact(msg->contact);
135
+}
136
+
137
+#define get_contact(msg) ((contact_body_t*)(msg->contact->parsed))
138
+
139
+int select_contact(str* res, select_t* s, struct sip_msg* msg)
140
+{
141
+	if (parse_contact_header(msg)<0)
142
+		return -1;
143
+	RETURN0_res(msg->contact->body);
144
+}
145
+
146
+int select_contact_uri(str* res, select_t* s, struct sip_msg* msg)
147
+{
148
+	contact_t* c;
149
+	if (parse_contact_header(msg)<0)
150
+		return -1;
151
+	
152
+	c = get_contact(msg)->contacts;
153
+	if (!c)
154
+		return 1;
155
+	RETURN0_res(c->uri);
156
+}
157
+
158
+int select_contact_name(str* res, select_t* s, struct sip_msg* msg)
159
+{
160
+	contact_t* c;
161
+	if (parse_contact_header(msg)<0)
162
+		return -1;
163
+	
164
+	c = get_contact(msg)->contacts;
165
+	if (!c)
166
+		return 1;
167
+	RETURN0_res(c->name);
168
+}
169
+
170
+int select_contact_params_spec(str* res, select_t* s, struct sip_msg* msg)
171
+{
172
+	contact_t* c;
173
+	
174
+	if (s->params[s->n-1].type != PARAM_DIV) {
175
+		BUG("Last parameter should have type DIV (converted)\n");
176
+		return -1;
177
+	}
178
+	
179
+	if (parse_contact_header(msg)<0)
180
+		return -1;
181
+	
182
+	c = get_contact(msg)->contacts;
183
+	if (!c)
184
+		return 1;
185
+	
186
+	switch (s->params[s->n-1].v.i) {
187
+	case SEL_PARAM_Q:
188
+		TEST_RET_res_body(c->q);
189
+	case SEL_PARAM_EXPIRES:
190
+		TEST_RET_res_body(c->expires);
191
+	case SEL_PARAM_METHOD:
192
+		TEST_RET_res_body(c->method);
193
+	case SEL_PARAM_RECEIVED:
194
+		TEST_RET_res_body(c->received);
195
+	case SEL_PARAM_INSTANCE:
196
+		TEST_RET_res_body(c->instance);
197
+	default:
198
+		BUG("Unexpected parameter value \"%d\"\n", s->params[s->n-1].v.i);
199
+		return -1;
200
+	}
201
+	return -1;
202
+}
203
+
204
+int select_contact_params(str* res, select_t* s, struct sip_msg* msg)
205
+{
206
+	contact_t* c;
207
+	param_t* p;
208
+	if (parse_contact_header(msg)<0)
209
+		return -1;
210
+	
211
+	c = get_contact(msg)->contacts;
212
+	if (!c)
213
+		return 1;
214
+	p = c->params;
215
+	while (p) {
216
+		if ((p->name.len==s->params[s->n-1].v.s.len)
217
+		    && !strncasecmp(p->name.s, s->params[s->n-1].v.s.s,p->name.len)) {
218
+			RETURN0_res(p->body)
219
+		}
220
+		p = p->next;
221
+	}
222
+	return 1;
223
+}
224
+
225
+int parse_via_header( struct sip_msg *msg, int n, struct via_body** q)
226
+{
227
+	struct hdr_field *p;
228
+	struct via_body *pp = NULL;
229
+	int i;
230
+	
231
+	switch (n) {
232
+	case 1:
233
+	case 2:
234
+		if (!msg->h_via1 && (parse_headers(msg,HDR_VIA_F,0)==-1 || !msg->h_via1)) {
235
+                        DBG("bad msg or missing VIA1 header \n");
236
+                        return -1;
237
+                }
238
+		pp = msg->h_via1->parsed;
239
+		if (n==1) break;
240
+		pp = pp->next;
241
+		if (pp) break;
242
+		
243
+                if (!msg->h_via2 && (parse_headers(msg,HDR_VIA2_F,0)==-1 || !msg->h_via2)) {
244
+                        DBG("bad msg or missing VIA2 header \n");
245
+                        return -1;
246
+                }
247
+                pp = msg->h_via2->parsed;
248
+                break;
249
+	default:	
250
+	        if (!msg->eoh && (parse_headers(msg,HDR_EOH_F,0)==-1 || !msg->eoh)) {
251
+        	        ERR("bad msg while parsing to EOH \n");
252
+	                return -1;
253
+		}
254
+		p = msg->h_via1;
255
+		i = n;
256
+		while (i && p) {
257
+		        if (p->type == HDR_VIA_T) {
258
+		        	i--;
259
+		        	pp = p->parsed;
260
+		        	while (i && (pp->next)) {
261
+		        		i--;
262
+		        		pp = pp->next;
263
+		        	}
264
+		        }
265
+			p = p->next;
266
+		}
267
+		if (i > 0) {
268
+			DBG("missing VIA[%d] header\n", n);
269
+			return -1;
270
+		}
271
+	}
272
+	if (pp) {
273
+		*q = pp;
274
+		return 0;
275
+	} else
276
+		return -1;
277
+}
278
+
279
+int select_via(str* res, select_t* s, struct sip_msg* msg)
280
+{
281
+	struct via_body *p = NULL;
282
+	
283
+	if (((s->n == 1) || (s->params[1].type == PARAM_STR)) && (parse_via_header(msg, 1, &p)<0)) return -1;
284
+	else if (parse_via_header(msg, s->params[1].v.i, &p)<0) return -1;
285
+	if (!p) return -1;
286
+	res->s=p->name.s;
287
+	res->len=p->bsize;
288
+	trim(res);
289
+	return 0;
290
+}
291
+
292
+int select_via_name(str* res, select_t* s, struct sip_msg* msg)
293
+{
294
+	struct via_body *p = NULL;
295
+	
296
+	// it's not neccessary to test if (s->n > 1)
297
+	if ((s->params[1].type == PARAM_STR) && (parse_via_header(msg, 1, &p)<0)) return -1;
298
+	else if (parse_via_header(msg, s->params[1].v.i, &p)<0) return -1;
299
+	if (!p) return -1;
300
+	RETURN0_res(p->name);
301
+}
302
+
303
+int select_via_version(str* res, select_t* s, struct sip_msg* msg)
304
+{
305
+	struct via_body *p = NULL;
306
+	
307
+	// it's not neccessary to test if (s->n > 1)
308
+	if ((s->params[1].type == PARAM_STR) && (parse_via_header(msg, 1, &p)<0)) return -1;
309
+	else if (parse_via_header(msg, s->params[1].v.i, &p)<0) return -1;
310
+	if (!p) return -1;
311
+	RETURN0_res(p->version);
312
+}
313
+
314
+int select_via_transport(str* res, select_t* s, struct sip_msg* msg)
315
+{
316
+	struct via_body *p = NULL;
317
+	
318
+	// it's not neccessary to test if (s->n > 1)
319
+	if ((s->params[1].type == PARAM_STR) && (parse_via_header(msg, 1, &p)<0)) return -1;
320
+	else if (parse_via_header(msg, s->params[1].v.i, &p)<0) return -1;
321
+	if (!p) return -1;
322
+	RETURN0_res(p->transport);
323
+}
324
+
325
+int select_via_host(str* res, select_t* s, struct sip_msg* msg)
326
+{
327
+	struct via_body *p = NULL;
328
+	
329
+	// it's not neccessary to test if (s->n > 1)
330
+	if ((s->params[1].type == PARAM_STR) && (parse_via_header(msg, 1, &p)<0)) return -1;
331
+	else if (parse_via_header(msg, s->params[1].v.i, &p)<0) return -1;
332
+	if (!p) return -1;
333
+	RETURN0_res(p->host);
334
+}
335
+
336
+int select_via_port(str* res, select_t* s, struct sip_msg* msg)
337
+{
338
+	struct via_body *p = NULL;
339
+	
340
+	// it's not neccessary to test if (s->n > 1)
341
+	if ((s->params[1].type == PARAM_STR) && (parse_via_header(msg, 1, &p)<0)) return -1;
342
+	else if (parse_via_header(msg, s->params[1].v.i, &p)<0) return -1;
343
+	if (!p) return -1;
344
+	RETURN0_res(p->port_str);
345
+}
346
+
347
+int select_via_comment(str* res, select_t* s, struct sip_msg* msg)
348
+{
349
+	struct via_body *p = NULL;
350
+	
351
+	// it's not neccessary to test if (s->n > 1)
352
+	if ((s->params[1].type == PARAM_STR) && (parse_via_header(msg, 1, &p)<0)) return -1;
353
+	else if (parse_via_header(msg, s->params[1].v.i, &p)<0) return -1;
354
+	if (!p) return -1;
355
+	RETURN0_res(p->comment);
356
+}
357
+
358
+int select_via_params(str* res, select_t* s, struct sip_msg* msg)
359
+{
360
+	struct via_body *p = NULL;
361
+	struct via_param *q;
362
+
363
+	// it's not neccessary to test if (s->n > 1)
364
+	if ((s->params[1].type == PARAM_STR) && (parse_via_header(msg, 1, &p)<0)) return -1;
365
+	else if (parse_via_header(msg, s->params[1].v.i, &p)<0) return -1;
366
+	if (!p) return -1;
367
+	
368
+	for (q = p->param_lst;q;q=q->next) {
369
+		if ((q->name.len==s->params[s->n-1].v.s.len)
370
+		    && !strncasecmp(q->name.s, s->params[s->n-1].v.s.s,q->name.len)) {
371
+			RETURN0_res(q->value);
372
+		}
373
+	}
374
+	return 1;
375
+}
376
+
377
+int select_via_params_spec(str* res, select_t* s, struct sip_msg* msg)
378
+{
379
+	struct via_body *p = NULL;
380
+
381
+	if (s->params[s->n-1].type != PARAM_DIV) {
382
+		BUG("Last parameter should have type DIV (converted)\n");
383
+		return -1;
384
+	}
385
+	
386
+	// it's not neccessary to test if (s->n > 1)
387
+	if ((s->params[1].type == PARAM_STR) && (parse_via_header(msg, 1, &p)<0)) return -1;
388
+	else if (parse_via_header(msg, s->params[1].v.i, &p)<0) return -1;
389
+	if (!p) return -1;
390
+	
391
+	switch (s->params[s->n-1].v.i) {
392
+	case SEL_PARAM_BRANCH:
393
+		TEST_RET_res_value(p->branch);
394
+	case SEL_PARAM_RECEIVED:
395
+		TEST_RET_res_value(p->received);
396
+	case SEL_PARAM_RPORT:
397
+		TEST_RET_res_value(p->rport);
398
+	case SEL_PARAM_I:
399
+		TEST_RET_res_value(p->i);
400
+	case SEL_PARAM_ALIAS:
401
+		TEST_RET_res_value(p->alias);
402
+	default:
403
+		BUG("Unexpected parameter value \"%d\"\n", s->params[s->n-1].v.i);
404
+		return -1;
405
+	}
406
+	return -1;
407
+}
408
+
409
+//ABSTRACT_F(select_msgheader)
410
+// Instead of ABSTRACT_F(select_msgheader)
411
+// use function which uses select_core_table
412
+// to avoid gcc warning about not used 
413
+int select_msgheader(str* res, select_t* s, struct sip_msg* msg)
414
+{
415
+	if (select_core_table.next)
416
+		return -1;
417
+	else
418
+		return -1;
419
+}
420
+
421
+int select_anyheader(str* res, select_t* s, struct sip_msg* msg)
422
+{
423
+	struct hdr_field *hf, *hf0;
424
+	int hi;
425
+	
426
+	if(msg==NULL)
427
+		return -1;
428
+
429
+	hf0 = NULL;
430
+
431
+	/* extract header index if present */
432
+	if (s->n == 3) {
433
+		if (s->params[2].type == PARAM_INT) {
434
+			hi = s->params[2].v.i;
435
+		} else {
436
+			hi = -1;
437
+		}
438
+	} else {
439
+		hi = 1;
440
+	}
441
+
442
+	/* we need to be sure we have parsed all headers */
443
+	if (!msg->eoh && (parse_headers(msg,HDR_EOH_F,0)==-1 || !msg->eoh)) {
444
+		ERR("bad msg while parsing to EOH \n");
445
+		return -1;
446
+	}
447
+	for (hf=msg->headers; hf; hf=hf->next) {
448
+		if(s->params[1].type==PARAM_DIV) {
449
+			if (s->params[1].v.i!=hf->type)	continue;
450
+		} else if(s->params[1].type==PARAM_STR) {
451
+			if (s->params[1].v.s.len!=hf->name.len)	continue;
452
+			if (strncasecmp(s->params[1].v.s.s, hf->name.s, hf->name.len)!=0) continue;
453
+		}
454
+		hf0 = hf;
455
+		hi--;
456
+		if (!hi) break;
457
+	}
458
+	if(hf0==NULL || hi>0)
459
+		return 1;
460
+	res->s = hf0->body.s;
461
+	res->len = hf0->body.len;
462
+	trim(res);
463
+	return 0;
464
+}
465
+
466
+ABSTRACT_F(select_any_uri)
467
+
468
+int select_uri_type(str* res, select_t* s, struct sip_msg* msg)
469
+{
470
+	if (!s->parent_f) {
471
+		ERR("BUG: no parent fuction defined\n");
472
+		return -1;
473
+	}
474
+
475
+	int ret;
476
+	ret = s->parent_f(res, s, msg);
477
+	if (ret != 0)
478
+		return ret;
479
+
480
+	struct sip_uri uri;
481
+	trim(res);
482
+	if (parse_uri(res->s, res->len, &uri)<0)
483
+		return -1;
484
+
485
+	switch (uri.type) {
486
+	case SIPS_URI_T:
487
+	case TELS_URI_T:
488
+		res->len=4;
489
+		break;
490
+	case SIP_URI_T:
491
+	case TEL_URI_T:
492
+		res->len=3;
493
+		break;
494
+	case ERROR_URI_T:
495
+		return -1;
496
+	}
497
+	return 0;
498
+}
499
+
500
+int select_uri_user(str* res, select_t* s, struct sip_msg* msg)
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
+	struct sip_uri uri;
513
+	if (parse_uri(res->s, res->len, &uri)<0)
514
+		return -1;
515
+
516
+	RETURN0_res(uri.user);
517
+}
518
+
519
+int select_uri_pwd(str* res, select_t* s, struct sip_msg* msg)
520
+{
521
+	if (!s->parent_f) {
522
+		ERR("BUG: no parent fuction defined\n");
523
+		return -1;
524
+	}
525
+
526
+	int ret;
527
+	ret = s->parent_f(res, s, msg);
528
+	if (ret != 0)
529
+		return ret;
530
+
531
+	struct sip_uri uri;
532
+	if (parse_uri(res->s, res->len, &uri)<0)
533
+		return -1;
534
+
535
+	RETURN0_res(uri.passwd);
536
+}
537
+
538
+int select_uri_host(str* res, select_t* s, struct sip_msg* msg)
539
+{
540
+	if (!s->parent_f) {
541
+		ERR("BUG: no parent fuction defined\n");
542
+		return -1;
543
+	}
544
+
545
+	int ret;
546
+	ret = s->parent_f(res, s, msg);
547
+	if (ret != 0)
548
+		return ret;
549
+
550
+	struct sip_uri uri;
551
+	if (parse_uri(res->s, res->len, &uri)<0)
552
+		return -1;
553
+
554
+	RETURN0_res(uri.host);
555
+}
556
+
557
+int select_uri_port(str* res, select_t* s, struct sip_msg* msg)
558
+{
559
+	if (!s->parent_f) {
560
+		ERR("BUG: no parent fuction defined\n");
561
+		return -1;
562
+	}
563
+
564
+	int ret;
565
+	ret = s->parent_f(res, s, msg);
566
+	if (ret != 0)
567
+		return ret;
568
+
569
+	struct sip_uri uri;
570
+	if (parse_uri(res->s, res->len, &uri)<0)
571
+		return -1;
572
+
573
+	RETURN0_res(uri.port);
574
+}
575
+
576
+int select_uri_params(str* res, select_t* s, struct sip_msg* msg)
577
+{
578
+	if (!s->parent_f) {
579
+		ERR("BUG: no parent fuction defined\n");
580
+		return -1;
581
+	}
582
+
583
+	int ret;
584
+	ret = s->parent_f(res, s, msg);
585
+	if (ret != 0)
586
+		return ret;
587
+
588
+	struct sip_uri uri;
589
+	if (parse_uri(res->s, res->len, &uri)<0)
590
+		return -1;
591
+		
592
+	RETURN0_res(uri.params);
593
+}
3 594
 
... ...
@@ -5,7 +5,97 @@
5 5
 #include "parser/msg_parser.h"
6 6
 #include "select.h"
7 7
 
8
+enum {
9
+	SEL_PARAM_TAG, 
10
+	SEL_PARAM_Q, SEL_PARAM_EXPIRES, SEL_PARAM_METHOD, SEL_PARAM_RECEIVED, SEL_PARAM_INSTANCE, 
11
+	SEL_PARAM_BRANCH, SEL_PARAM_RPORT, SEL_PARAM_I, SEL_PARAM_ALIAS
12
+       };
13
+
14
+SELECT_F(select_from)
15
+SELECT_F(select_from_uri)
16
+SELECT_F(select_from_tag)
17
+SELECT_F(select_from_name)
18
+SELECT_F(select_from_params)
19
+SELECT_F(select_to)
20
+SELECT_F(select_to_uri)
21
+SELECT_F(select_to_tag)
22
+SELECT_F(select_to_name)
23
+SELECT_F(select_to_params)
24
+SELECT_F(select_contact)
25
+SELECT_F(select_contact_uri)
26
+SELECT_F(select_contact_name)
27
+SELECT_F(select_contact_params)
28
+SELECT_F(select_contact_params_spec)
29
+SELECT_F(select_via)
30
+SELECT_F(select_via_name)
31
+SELECT_F(select_via_version)
32
+SELECT_F(select_via_transport)
33
+SELECT_F(select_via_host)
34
+SELECT_F(select_via_port)
35
+SELECT_F(select_via_comment)
36
+SELECT_F(select_via_params)
37
+SELECT_F(select_via_params_spec)
38
+
39
+SELECT_F(select_msgheader)
40
+SELECT_F(select_anyheader)
41
+
42
+SELECT_F(select_any_uri)
43
+SELECT_F(select_uri_type)
44
+SELECT_F(select_uri_user)
45
+SELECT_F(select_uri_pwd)
46
+SELECT_F(select_uri_host)
47
+SELECT_F(select_uri_port)
48
+SELECT_F(select_uri_params)
49
+
8 50
 static select_row_t select_core[] = {
51
+	{ NULL, PARAM_STR, STR_STATIC_INIT("from"), select_from, 0},
52
+	{ NULL, PARAM_STR, STR_STATIC_INIT("f"), select_from, 0},
53
+	{ select_from, PARAM_STR, STR_STATIC_INIT("uri"), select_from_uri, 0},
54
+	{ select_from, PARAM_STR, STR_STATIC_INIT("tag"), select_from_tag, 0},
55
+	{ select_from, PARAM_STR, STR_STATIC_INIT("name"), select_from_name, 0},
56
+	{ select_from, PARAM_STR, STR_STATIC_INIT("params"), select_from_params, CONSUME_NEXT_STR},
57
+	{ NULL, PARAM_STR, STR_STATIC_INIT("to"), select_to, 0},
58
+	{ NULL, PARAM_STR, STR_STATIC_INIT("t"), select_to, 0},
59
+	{ select_to, PARAM_STR, STR_STATIC_INIT("uri"), select_to_uri, 0},
60
+	{ select_to, PARAM_STR, STR_STATIC_INIT("tag"), select_to_tag, 0},
61
+	{ select_to, PARAM_STR, STR_STATIC_INIT("name"), select_to_name, 0},
62
+	{ select_to, PARAM_STR, STR_STATIC_INIT("params"), select_to_params, CONSUME_NEXT_STR},
63
+	{ NULL, PARAM_STR, STR_STATIC_INIT("contact"), select_contact, 0},
64
+	{ NULL, PARAM_STR, STR_STATIC_INIT("m"), select_contact, 0},
65
+	{ select_contact, PARAM_STR, STR_STATIC_INIT("uri"), select_contact_uri, 0},
66
+	{ select_contact, PARAM_STR, STR_STATIC_INIT("name"), select_contact_name, 0}, 
67
+	{ select_contact, PARAM_STR, STR_STATIC_INIT("q"), select_contact_params_spec, DIVERSION | SEL_PARAM_Q}, 
68
+	{ select_contact, PARAM_STR, STR_STATIC_INIT("expires"), select_contact_params_spec, DIVERSION | SEL_PARAM_EXPIRES}, 
69
+	{ select_contact, PARAM_STR, STR_STATIC_INIT("method"), select_contact_params_spec, DIVERSION | SEL_PARAM_METHOD}, 
70
+	{ select_contact, PARAM_STR, STR_STATIC_INIT("received"), select_contact_params_spec, DIVERSION | SEL_PARAM_RECEIVED}, 
71
+	{ select_contact, PARAM_STR, STR_STATIC_INIT("instance"), select_contact_params_spec, DIVERSION | SEL_PARAM_INSTANCE}, 	
72
+	{ select_contact, PARAM_STR, STR_STATIC_INIT("params"), select_contact_params, CONSUME_NEXT_STR},
73
+	{ NULL, PARAM_STR, STR_STATIC_INIT("via"), select_via, OPTIONAL | CONSUME_NEXT_INT},
74
+	{ NULL, PARAM_STR, STR_STATIC_INIT("v"), select_via, OPTIONAL | CONSUME_NEXT_INT},
75
+	{ select_via, PARAM_STR, STR_STATIC_INIT("name"), select_via_name, 0},
76
+	{ select_via, PARAM_STR, STR_STATIC_INIT("version"), select_via_version, 0},
77
+	{ select_via, PARAM_STR, STR_STATIC_INIT("transport"), select_via_transport, 0},
78
+	{ select_via, PARAM_STR, STR_STATIC_INIT("host"), select_via_host, 0},
79
+	{ select_via, PARAM_STR, STR_STATIC_INIT("port"), select_via_port, 0},
80
+	{ select_via, PARAM_STR, STR_STATIC_INIT("comment"), select_via_comment, 0},
81
+	{ select_via, PARAM_STR, STR_STATIC_INIT("branch"), select_via_params_spec, DIVERSION | SEL_PARAM_BRANCH},
82
+	{ select_via, PARAM_STR, STR_STATIC_INIT("received"), select_via_params_spec, DIVERSION | SEL_PARAM_RECEIVED},
83
+	{ select_via, PARAM_STR, STR_STATIC_INIT("rport"), select_via_params_spec, DIVERSION | SEL_PARAM_RPORT},
84
+	{ select_via, PARAM_STR, STR_STATIC_INIT("i"), select_via_params_spec, DIVERSION | SEL_PARAM_I},
85
+	{ select_via, PARAM_STR, STR_STATIC_INIT("alias"), select_via_params_spec, DIVERSION | SEL_PARAM_ALIAS},
86
+	{ select_via, PARAM_STR, STR_STATIC_INIT("params"), select_via_params, CONSUME_NEXT_STR},
87
+	
88
+	{ select_from_uri, PARAM_INT, STR_NULL, select_any_uri, IS_ALIAS},
89
+	{ select_to_uri, PARAM_INT, STR_NULL, select_any_uri, IS_ALIAS},
90
+	{ select_contact_uri, PARAM_INT, STR_NULL, select_any_uri, IS_ALIAS},
91
+	{ select_any_uri, PARAM_STR, STR_STATIC_INIT("type"), select_uri_type, 0},
92
+	{ select_any_uri, PARAM_STR, STR_STATIC_INIT("user"), select_uri_user, 0},
93
+	{ select_any_uri, PARAM_STR, STR_STATIC_INIT("pwd"), select_uri_pwd, 0},
94
+	{ select_any_uri, PARAM_STR, STR_STATIC_INIT("host"), select_uri_host, 0},
95
+	{ select_any_uri, PARAM_STR, STR_STATIC_INIT("port"), select_uri_port, 0},
96
+	{ select_any_uri, PARAM_STR, STR_STATIC_INIT("params"), select_uri_params, 0},
97
+	{ NULL, PARAM_STR, STR_STATIC_INIT("msg"), select_msgheader, PARAM_EXPECTED},
98
+	{ select_msgheader, PARAM_STR, STR_NULL, select_anyheader, OPTIONAL | CONSUME_NEXT_INT},
9 99
 	{ NULL, PARAM_INT, STR_NULL, NULL, 0}
10 100
 };
11 101