Browse code

- added (uint|int|str)_to_static_buffer functions to select_buffer - fixed minor bug in struct msg_start where is not known start of first line when empty lines preceed (sip_msg.buff points before them), so added line field holding correct position of first_line, fixed usage in textops and xmlrpc modules - added new select_core selects to resolve SER-158 - added new tm module select to resolve SER-158

Tomas Mandys authored on 18/02/2007 14:05:44
Showing 9 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,195 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * Copyright (C) 2001-2003 FhG Fokus
4
+ *
5
+ * This file is part of ser, a free SIP server.
6
+ *
7
+ * ser is free software; you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation; either version 2 of the License, or
10
+ * (at your option) any later version
11
+ *
12
+ * For a license to use the ser software under conditions
13
+ * other than those described here, or to purchase support for this
14
+ * software, please contact iptel.org by e-mail at the following addresses:
15
+ *    info@iptel.org
16
+ *
17
+ * ser is distributed in the hope that it will be useful,
18
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
+ * GNU General Public License for more details.
21
+ *
22
+ * You should have received a copy of the GNU General Public License
23
+ * along with this program; if not, write to the Free Software
24
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
+ *
26
+ */
27
+
28
+
29
+#include <stdio.h>
30
+#include "select.h"
31
+#include "h_table.h"
32
+#include "t_lookup.h"
33
+#include "../../dprint.h"
34
+#include "../../mem/mem.h"
35
+#include "../../ut.h"
36
+#include "../../select.h"
37
+#include "../../select_buf.h"
38
+
39
+#define RETURN0_res(x) {*res=(x);return 0;}
40
+
41
+inline static int select_tm_get_cell(struct sip_msg* msg, int *branch, struct cell **t) {
42
+
43
+	/* make sure we know the associated transaction ... */
44
+	if (t_check( msg  , branch )==-1)  /* it's not necessary whan calling from script because already done */ 
45
+		return -1;
46
+
47
+	/*... if there is none, tell the core router to fwd statelessly */
48
+	*t = get_t();
49
+	if ( (*t==0)||(*t==T_UNDEFINED)) return -1;
50
+
51
+	return 0;
52
+}	
53
+
54
+static int select_tm(str* res, select_t* s, struct sip_msg* msg) {
55
+	int branch;
56
+	struct cell *t;
57
+	if (select_tm_get_cell(msg, &branch, &t) < 0) {
58
+		res->s = "0";
59
+	}
60
+	else {
61
+		res->s = "1";
62
+	}
63
+	res->len = 1;
64
+	return 0;
65
+}
66
+
67
+#define SEL_BRANCH_POS 2
68
+#define BRANCH_NO(_s_) (_s_->params[SEL_BRANCH_POS].v.i)
69
+
70
+#define SELECT_check(msg) \
71
+	int branch; \
72
+	struct cell *t; \
73
+	if (select_tm_get_cell(msg, &branch, &t) < 0) return -1;
74
+
75
+#define SELECT_check_branch(_s_, _msg_) \
76
+	SELECT_check(_msg_); \
77
+	if (BRANCH_NO(_s_) >=t->nr_of_outgoings) return -1;
78
+ 
79
+
80
+/* string resides in shared memory but I think it's not worth copying to
81
+ * static buffer (str_to_static_buffer) as minimal probability that string 
82
+ * is changed by other process (or cell is already locked ?)
83
+ */
84
+ 
85
+static int select_tm_method(str* res, select_t* s, struct sip_msg* msg) {
86
+	SELECT_check(msg);
87
+	RETURN0_res(t->method);
88
+}
89
+
90
+static ABSTRACT_F(select_tm_uas);
91
+
92
+static int select_tm_uas_status(str* res, select_t* s, struct sip_msg* msg) {
93
+	SELECT_check(msg);
94
+	return int_to_static_buffer(res, t->uas.status);
95
+}
96
+
97
+/* transaction cell has request in sip_msg structure which brings idea to
98
+ * use selects from select_core.c (e.g. to avoid copy&paste automatically 
99
+ * generate select definitions in tm_init_selects()). But it's not so easy
100
+ * as select may perform any parsing which is stored in sip_msg structure.
101
+ * But transaction cell resides in shared memory while parsing is done in
102
+ * private memory. Therefore we support currently only complete request */
103
+ 
104
+static int select_tm_uas_request(str* res, select_t* s, struct sip_msg* msg) {
105
+	SELECT_check(msg);
106
+	res->s = t->uas.request->buf;
107
+	res->len = t->uas.request->len;
108
+	return 0; 
109
+}
110
+
111
+static int select_tm_uas_local_to_tag(str* res, select_t* s, struct sip_msg* msg) {
112
+	SELECT_check(msg);
113
+	RETURN0_res(t->uas.local_totag);
114
+}
115
+
116
+static int select_tm_uas_response(str* res, select_t* s, struct sip_msg* msg) {
117
+	SELECT_check(msg);
118
+	res->s = t->uas.response.buffer;	
119
+	res->len = t->uas.response.buffer_len;
120
+	return 0;	
121
+}
122
+
123
+static ABSTRACT_F(select_tm_uac);
124
+
125
+static int select_tm_uac_count(str* res, select_t* s, struct sip_msg* msg) {
126
+	SELECT_check(msg);
127
+	return int_to_static_buffer(res, t->nr_of_outgoings);
128
+}
129
+
130
+static int select_tm_uac_relayed(str* res, select_t* s, struct sip_msg* msg) {
131
+	SELECT_check(msg);
132
+	return int_to_static_buffer(res, t->relayed_reply_branch);
133
+}
134
+
135
+static ABSTRACT_F(select_tm_uac_branch);
136
+
137
+static int select_tm_uac_status(str* res, select_t* s, struct sip_msg* msg) {
138
+	SELECT_check_branch(s, msg);
139
+	return int_to_static_buffer(res, t->uac[BRANCH_NO(s)].last_received);
140
+}
141
+
142
+static int select_tm_uac_uri(str* res, select_t* s, struct sip_msg* msg) {
143
+	SELECT_check_branch(s, msg);
144
+	RETURN0_res(t->uac[BRANCH_NO(s)].uri);
145
+}
146
+
147
+/* see select_tm_uas_request comments */
148
+static int select_tm_uac_response(str* res, select_t* s, struct sip_msg* msg) {  // struct
149
+	SELECT_check_branch(s, msg);
150
+	if (t->uac[BRANCH_NO(s)].reply) {
151
+		res->s = t->uac[BRANCH_NO(s)].reply->buf;
152
+		res->len = t->uac[BRANCH_NO(s)].reply->len;
153
+		return 0;
154
+	}
155
+	else
156
+		return -1;
157
+}
158
+
159
+static int select_tm_uac_branch_request(str* res, select_t* s, struct sip_msg* msg) {
160
+	SELECT_check_branch(s, msg);
161
+	res->s = t->uac[BRANCH_NO(s)].request.buffer;	
162
+	res->len = t->uac[BRANCH_NO(s)].request.buffer_len;
163
+	return 0;	
164
+}
165
+
166
+static select_row_t select_declaration[] = {
167
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("tm"), select_tm, 0},
168
+	{ select_tm, SEL_PARAM_STR, STR_STATIC_INIT("method"), select_tm_method, 0},
169
+	{ select_tm, SEL_PARAM_STR, STR_STATIC_INIT("uas"), select_tm_uas, SEL_PARAM_EXPECTED},
170
+	{ select_tm_uas, SEL_PARAM_STR, STR_STATIC_INIT("status"), select_tm_uas_status, 0},
171
+	{ select_tm_uas, SEL_PARAM_STR, STR_STATIC_INIT("request"), select_tm_uas_request, 0},
172
+	{ select_tm_uas, SEL_PARAM_STR, STR_STATIC_INIT("req"), select_tm_uas_request, 0},
173
+	{ select_tm_uas, SEL_PARAM_STR, STR_STATIC_INIT("local_to_tag"), select_tm_uas_local_to_tag, 0},
174
+	{ select_tm_uas, SEL_PARAM_STR, STR_STATIC_INIT("response"), select_tm_uas_response, 0},
175
+	{ select_tm_uas, SEL_PARAM_STR, STR_STATIC_INIT("resp"), select_tm_uas_response, 0},
176
+
177
+	{ select_tm, SEL_PARAM_STR, STR_STATIC_INIT("uac"), select_tm_uac, SEL_PARAM_EXPECTED},
178
+	{ select_tm_uac, SEL_PARAM_STR, STR_STATIC_INIT("count"), select_tm_uac_count, 0},
179
+	{ select_tm_uac, SEL_PARAM_STR, STR_STATIC_INIT("relayed"), select_tm_uac_relayed, 0},
180
+	{ select_tm_uac, SEL_PARAM_INT, STR_NULL, select_tm_uac_branch, SEL_PARAM_EXPECTED},
181
+	{ select_tm_uac_branch, SEL_PARAM_STR, STR_STATIC_INIT("status"), select_tm_uac_status, 0},
182
+	{ select_tm_uac_branch, SEL_PARAM_STR, STR_STATIC_INIT("uri"), select_tm_uac_uri, 0},
183
+	{ select_tm_uac_branch, SEL_PARAM_STR, STR_STATIC_INIT("response"), select_tm_uac_response, 0},
184
+	{ select_tm_uac_branch, SEL_PARAM_STR, STR_STATIC_INIT("resp"), select_tm_uac_response, 0},
185
+	{ select_tm_uac_branch, SEL_PARAM_STR, STR_STATIC_INIT("request"), select_tm_uac_branch_request, 0},
186
+	{ select_tm_uac_branch, SEL_PARAM_STR, STR_STATIC_INIT("req"), select_tm_uac_branch_request, 0},
187
+
188
+	{ NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
189
+};
190
+
191
+int tm_init_selects() {
192
+	register_select_table(select_declaration);
193
+	return 0;
194
+}
0 195
new file mode 100644
... ...
@@ -0,0 +1,37 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ *
4
+ * Copyright (C) 2001-2003 FhG Fokus
5
+ *
6
+ * This file is part of ser, a free SIP server.
7
+ *
8
+ * ser is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation; either version 2 of the License, or
11
+ * (at your option) any later version
12
+ *
13
+ * For a license to use the ser software under conditions
14
+ * other than those described here, or to purchase support for this
15
+ * software, please contact iptel.org by e-mail at the following addresses:
16
+ *    info@iptel.org
17
+ *
18
+ * ser is distributed in the hope that it will be useful,
19
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
+ * GNU General Public License for more details.
22
+ *
23
+ * You should have received a copy of the GNU General Public License 
24
+ * along with this program; if not, write to the Free Software 
25
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
+ *
27
+ */
28
+
29
+#ifndef _T_SELECT_H
30
+#define _T_SELECT_H
31
+
32
+
33
+int tm_init_selects();
34
+
35
+
36
+#endif
... ...
@@ -115,6 +115,7 @@
115 115
 #include "t_fifo.h"
116 116
 #include "timer.h"
117 117
 #include "t_msgbuilder.h"
118
+#include "select.h"
118 119
 
119 120
 MODULE_VERSION
120 121
 
... ...
@@ -339,7 +340,6 @@ static param_export_t params[]={
339 339
 	{0,0,0}
340 340
 };
341 341
 
342
-
343 342
 #ifdef STATIC_TM
344 343
 struct module_exports tm_exports = {
345 344
 #else
... ...
@@ -531,6 +531,11 @@ static int mod_init(void)
531 531
 	/* init static hidden values */
532 532
 	init_t();
533 533
 
534
+	if (tm_init_selects()==-1) {
535
+		LOG(L_ERR, "ERROR: mod_init: select init failed\n");
536
+		return -1;
537
+	}
538
+	
534 539
 	if (tm_init_timers()==-1) {
535 540
 		LOG(L_ERR, "ERROR: mod_init: timer init failed\n");
536 541
 		return -1;
... ...
@@ -92,7 +92,7 @@ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl)
92 92
 		LOG(L_INFO, "ERROR: parse_first_line: message too short: %d\n", len);
93 93
 		goto error1;
94 94
 	}
95
-
95
+	fl->line.s = buffer;
96 96
 	tmp=buffer;
97 97
   	/* is it perhaps a reply, ie does it start with "SIP...." ? */
98 98
 	if ( 	(*tmp=='S' || *tmp=='s') && 
... ...
@@ -212,6 +212,7 @@ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl)
212 212
 		}
213 213
 		offset+=tmp-third;
214 214
 	}
215
+	fl->line.len = tmp-fl->line.s;
215 216
 	nl=eat_line(tmp,len-offset);
216 217
 	if (nl>=end){ /* no crlf in packet or only 1 line > invalid */
217 218
 		goto error;
... ...
@@ -61,6 +61,7 @@
61 61
 
62 62
 struct msg_start {
63 63
 	int type;                         /* Type of the Message - Request/Response */
64
+	str line;                         /* len does not include CRLF, correct way how to point at second line is line.s+len */
64 65
 	int len; 						/* length including delimiter */
65 66
 	union {
66 67
 		struct {
... ...
@@ -40,6 +40,8 @@
40 40
 
41 41
 #include "dprint.h"
42 42
 #include "mem/mem.h"
43
+#include "str.h"
44
+#include "ut.h"
43 45
 
44 46
 /*
45 47
  * Placeholder for the buffer
... ...
@@ -130,3 +132,50 @@ int reset_static_buffer() {
130 130
 	active_buffer=0;
131 131
 	return 0;
132 132
 }
133
+
134
+int str_to_static_buffer(str* res, str* s)
135
+{
136
+	res->s = get_static_buffer(s->len);
137
+	if (!res->s) return -1;
138
+	memcpy(res->s, s->s, s->len);
139
+	res->len = s->len;
140
+	return 0;
141
+}
142
+
143
+int int_to_static_buffer(str* res, int val)
144
+{
145
+	char *c;
146
+	c = int2str(abs(val), &res->len);
147
+	res->s = get_static_buffer(res->len+(val<0)?1:0);
148
+	if (!res->s) return -1;
149
+	if (val < 0) {
150
+		res->s[0] = '-';	
151
+		memcpy(res->s+1, c, res->len);
152
+		res->len++;
153
+	}
154
+	else {
155
+		memcpy(res->s, c, res->len);
156
+	}
157
+	return 0;
158
+}
159
+
160
+int uint_to_static_buffer(str* res, unsigned int val)
161
+{
162
+	char *c;
163
+	c = int2str(val, &res->len);
164
+	res->s = get_static_buffer(res->len);
165
+	if (!res->s) return -1;
166
+	memcpy(res->s, c, res->len);
167
+	return 0;
168
+}
169
+
170
+int uint_to_static_buffer_ex(str* res, unsigned int val, int base, int pad)
171
+{
172
+	char *c;
173
+	c = int2str_base_0pad(val, &res->len, base, pad); 
174
+	res->s = get_static_buffer(res->len);
175
+	if (!res->s) return -1;
176
+	memcpy(res->s, c, res->len);
177
+	return 0;
178
+}
179
+
... ...
@@ -51,4 +51,9 @@ char* get_static_buffer(int req_size);
51 51
 
52 52
 int reset_static_buffer();
53 53
 
54
+int str_to_static_buffer(str* res, str* s);
55
+int int_to_static_buffer(str* res, int val);
56
+int uint_to_static_buffer(str* res, unsigned int val);
57
+int uint_ex_to_static_buffer(str* res, unsigned int val, int base, int pad);
58
+
54 59
 #endif /* SELECT_BUFFER_H */
... ...
@@ -31,7 +31,7 @@
31 31
  *  2006-02-17  fixup call for select_anyhdr (mma)
32 32
  */
33 33
 
34
- 
34
+#include <stdlib.h> 
35 35
 #include "select.h"
36 36
 #include "select_core.h"
37 37
 #include "select_buf.h"
... ...
@@ -52,18 +52,15 @@
52 52
 #include "mem/mem.h"
53 53
 #include "parser/parse_hname2.h"
54 54
 #include "ip_addr.h"
55
+#include "parser/parse_expires.h"
56
+#include "parser/parse_refer_to.h"
57
+#include "parser/parse_rpid.h"
58
+#include "dset.h"
55 59
 
56
-#define RETURN0_res(x) {*res=x;return 0;}
57
-#define TRIM_RET0_res(x) {*res=x;trim(res);return 0;} 
58
-#define TEST_RET_res_body(x) if (x){*res=x->body;return 0;}else return 1;
59
-#define TEST_RET_res_value(x) if (x){*res=x->value;return 0;}else return 1;
60
-
61
-int select_method(str* res, select_t* s, struct sip_msg* msg)
62
-{
63
-	if (msg->first_line.type==SIP_REQUEST) {
64
-		RETURN0_res(msg->first_line.u.request.method);
65
-	} else return -1;
66
-}
60
+#define RETURN0_res(x) {*res=(x);return 0;}
61
+#define TRIM_RET0_res(x) {*res=(x);trim(res);return 0;} 
62
+#define TEST_RET_res_body(x) if (x){*res=(x)->body;return 0;}else return 1;
63
+#define TEST_RET_res_value(x) if (x){*res=(x)->value;return 0;}else return 1;
67 64
 
68 65
 int select_ruri(str* res, select_t* s, struct sip_msg* msg)
69 66
 {
... ...
@@ -101,50 +98,51 @@ int select_next_hop(str* res, select_t* s, struct sip_msg* msg)
101 101
 	return -1;
102 102
 }
103 103
 
104
-int select_from(str* res, select_t* s, struct sip_msg* msg)
105
-{
106
-	if (parse_from_header(msg)<0)
107
-		return -1;
108
-	RETURN0_res(msg->from->body);
109
-}
110
-
111
-int select_from_uri(str* res, select_t* s, struct sip_msg* msg)
112
-{
113
-	if (parse_from_header(msg)<0)
114
-		return -1;
115
-	RETURN0_res(get_from(msg)->uri);
116
-}
117
-
118
-int select_from_tag(str* res, select_t* s, struct sip_msg* msg)
119
-{
120
-	if (parse_from_header(msg)<0)
121
-		return -1;
122
-	RETURN0_res(get_from(msg)->tag_value);
123
-}
124
-
125
-int select_from_name(str* res, select_t* s, struct sip_msg* msg)
126
-{
127
-	if (parse_from_header(msg)<0)
128
-		return -1;
129
-	RETURN0_res(get_from(msg)->display);
130
-}
131
-
132
-int select_from_params(str* res, select_t* s, struct sip_msg* msg)
133
-{
134
-	struct to_param* p;
135
-	if (parse_from_header(msg)<0)
136
-		return -1;
137
-	
138
-	p = get_from(msg)->param_lst;
139
-	while (p) {
140
-		if ((p->name.len==s->params[s->n-1].v.s.len)
141
-		    && !strncasecmp(p->name.s, s->params[s->n-1].v.s.s,p->name.len)) {
142
-			RETURN0_res(p->value);
143
-		}
144
-		p = p->next;
145
-	}
146
-	return 1;
147
-}
104
+#define SELECT_uri_header(_name_) \
105
+int select_##_name_(str* res, select_t* s, struct sip_msg* msg) \
106
+{ \
107
+	if (parse_##_name_##_header(msg)<0) \
108
+		return -1; \
109
+	RETURN0_res(msg->_name_->body); \
110
+} \
111
+\
112
+int select_##_name_##_uri(str* res, select_t* s, struct sip_msg* msg) \
113
+{ \
114
+	if (parse_##_name_##_header(msg)<0) \
115
+		return -1; \
116
+	RETURN0_res(get_##_name_(msg)->uri); \
117
+} \
118
+\
119
+int select_##_name_##_tag(str* res, select_t* s, struct sip_msg* msg) \
120
+{ \
121
+	if (parse_##_name_##_header(msg)<0) \
122
+		return -1; \
123
+	RETURN0_res(get_##_name_(msg)->tag_value); \
124
+} \
125
+\
126
+int select_##_name_##_name(str* res, select_t* s, struct sip_msg* msg) \
127
+{ \
128
+	if (parse_##_name_##_header(msg)<0) \
129
+		return -1; \
130
+	RETURN0_res(get_##_name_(msg)->display); \
131
+} \
132
+\
133
+int select_##_name_##_params(str* res, select_t* s, struct sip_msg* msg) \
134
+{ \
135
+	struct to_param* p; \
136
+	if (parse_##_name_##_header(msg)<0) \
137
+		return -1; \
138
+	\
139
+	p = get_##_name_(msg)->param_lst; \
140
+	while (p) { \
141
+		if ((p->name.len==s->params[s->n-1].v.s.len) \
142
+		    && !strncasecmp(p->name.s, s->params[s->n-1].v.s.s,p->name.len)) { \
143
+			RETURN0_res(p->value); \
144
+		} \
145
+		p = p->next; \
146
+	} \
147
+	return 1; \
148
+} 
148 149
 
149 150
 int parse_to_header(struct sip_msg *msg)
150 151
 {
... ...
@@ -161,51 +159,10 @@ int parse_to_header(struct sip_msg *msg)
161 161
 		return -1;
162 162
 }
163 163
 
164
-int select_to(str* res, select_t* s, struct sip_msg* msg)
165
-{
166
-	if (parse_to_header(msg)<0)
167
-		return -1; 
168
-	RETURN0_res(msg->to->body);
169
-}
170
-
171
-int select_to_uri(str* res, select_t* s, struct sip_msg* msg)
172
-{
173
-	if (parse_to_header(msg)<0)
174
-		return -1;
175
-	RETURN0_res(get_to(msg)->uri);
176
-}
177
-
178
-int select_to_tag(str* res, select_t* s, struct sip_msg* msg)
179
-{
180
-	if (parse_to_header(msg)<0)
181
-		return -1;
182
-	RETURN0_res(get_to(msg)->tag_value);
183
-}
184
-
185
-int select_to_name(str* res, select_t* s, struct sip_msg* msg)
186
-{
187
-	if (parse_to_header(msg)<0)
188
-		return -1;
189
-	RETURN0_res(get_to(msg)->display);
190
-}
191
-
192
-int select_to_params(str* res, select_t* s, struct sip_msg* msg)
193
-{
194
-	struct to_param* p;
195
-
196
-	if (parse_to_header(msg)<0)
197
-		return -1;
198
-	
199
-	p = get_to(msg)->param_lst;
200
-	while (p) {
201
-		if ((p->name.len==s->params[s->n-1].v.s.len)
202
-		    && !strncasecmp(p->name.s, s->params[s->n-1].v.s.s,p->name.len)) {
203
-			RETURN0_res(p->value);
204
-		}
205
-		p = p->next;
206
-	}
207
-	return 1;
208
-}
164
+SELECT_uri_header(to)
165
+SELECT_uri_header(from)
166
+SELECT_uri_header(refer_to)
167
+SELECT_uri_header(rpid)
209 168
 
210 169
 int parse_contact_header( struct sip_msg *msg)
211 170
 {
... ...
@@ -492,16 +449,53 @@ int select_via_params_spec(str* res, select_t* s, struct sip_msg* msg)
492 492
 	return -1;
493 493
 }
494 494
 
495
-//ABSTRACT_F(select_msgheader)
496
-// Instead of ABSTRACT_F(select_msgheader)
497
-// use function which uses select_core_table
498
-// to avoid gcc warning about not used 
499
-int select_msgheader(str* res, select_t* s, struct sip_msg* msg)
495
+int select_msg(str* res, select_t* s, struct sip_msg* msg)
500 496
 {
501
-	if (select_core_table.next)
502
-		return -1;
503
-	else
504
-		return -1;
497
+	res->s = msg->buf;
498
+	res->len = msg->len;
499
+	return 0;
500
+}
501
+
502
+int select_msg_first_line(str* res, select_t* s, struct sip_msg* msg) 
503
+{
504
+	RETURN0_res(msg->first_line.line);
505
+}
506
+
507
+int select_msg_type(str* res, select_t* s, struct sip_msg* msg) {
508
+	return uint_to_static_buffer(res, msg->first_line.type);
509
+} 
510
+
511
+int select_msg_len(str* res, select_t* s, struct sip_msg* msg) {
512
+	return uint_to_static_buffer(res, msg->len);
513
+}
514
+
515
+int select_msg_id(str* res, select_t* s, struct sip_msg* msg) {
516
+	return uint_to_static_buffer(res, msg->id);
517
+}
518
+
519
+int select_msg_id_hex(str* res, select_t* s, struct sip_msg* msg) {
520
+	return uint_to_static_buffer_ex(res, msg->id, 16, 8);
521
+}
522
+
523
+int select_msg_flags(str* res, select_t* s, struct sip_msg* msg) { 
524
+	return uint_to_static_buffer(res, msg->flags);
525
+} 
526
+
527
+int select_msg_body(str* res, select_t* s, struct sip_msg* msg)
528
+{
529
+	res->s = get_body(msg);
530
+	res->len = msg->buf+msg->len - res->s;
531
+	return 0;	
532
+}
533
+
534
+int select_msg_header(str* res, select_t* s, struct sip_msg* msg)
535
+{
536
+	/* get all headers */
537
+	char *c;
538
+	res->s = msg->first_line.line.s + msg->first_line.len; 
539
+	c = get_body(msg);
540
+	res->len = c - res->s;
541
+	return 0;
505 542
 }
506 543
 
507 544
 int select_anyheader(str* res, select_t* s, struct sip_msg* msg)
... ...
@@ -515,22 +509,22 @@ int select_anyheader(str* res, select_t* s, struct sip_msg* msg)
515 515
 		if (res!=NULL) return -1;
516 516
 
517 517
 		/* "fixup" call, res & msg are NULL */
518
-		if (s->n <2) return -1;
518
+		if (s->n <3) return -1;
519 519
 
520
-		if (s->params[1].type==SEL_PARAM_STR) {
520
+		if (s->params[2].type==SEL_PARAM_STR) {
521 521
 				/* replace _ with - (for P-xxx headers) */
522
-			for (hi=s->params[1].v.s.len-1; hi>0; hi--)
523
-				if (s->params[1].v.s.s[hi]=='_')
524
-					s->params[1].v.s.s[hi]='-';
522
+			for (hi=s->params[2].v.s.len-1; hi>0; hi--)
523
+				if (s->params[2].v.s.s[hi]=='_')
524
+					s->params[2].v.s.s[hi]='-';
525 525
 				/* if header name is parseable, parse it and set SEL_PARAM_DIV */
526
-			c=s->params[1].v.s.s[s->params[1].v.s.len];
527
-			s->params[1].v.s.s[s->params[1].v.s.len]=':';
528
-			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),
526
+			c=s->params[2].v.s.s[s->params[2].v.s.len];
527
+			s->params[2].v.s.s[s->params[2].v.s.len]=':';
528
+			if (parse_hname2(s->params[2].v.s.s,s->params[2].v.s.s+(s->params[2].v.s.len<3?4:s->params[2].v.s.len+1),
529 529
 						&hdr)==0) {
530 530
 				ERR("select_anyhdr:fixup_call:parse error\n");
531 531
 				return -1;
532 532
 			}
533
-			s->params[1].v.s.s[s->params[1].v.s.len]=c;
533
+			s->params[2].v.s.s[s->params[2].v.s.len]=c;
534 534
 			
535 535
 			if (hdr.type!=HDR_OTHER_T && hdr.type!=HDR_ERROR_T) {
536 536
 				/* pkg_free(s->params[1].v.s.s); */
... ...
@@ -538,8 +532,8 @@ int select_anyheader(str* res, select_t* s, struct sip_msg* msg)
538 538
 				 * the parsed string can live inside larger string block
539 539
 				 * e.g. when xlog's select is parsed
540 540
 				 */
541
-				s->params[1].type = SEL_PARAM_DIV;
542
-				s->params[1].v.i = hdr.type;
541
+				s->params[2].type = SEL_PARAM_DIV;
542
+				s->params[2].v.i = hdr.type;
543 543
 			}
544 544
 		}
545 545
 		return 1;
... ...
@@ -548,9 +542,9 @@ int select_anyheader(str* res, select_t* s, struct sip_msg* msg)
548 548
 	hf0 = NULL;
549 549
 
550 550
 	/* extract header index if present */
551
-	if (s->param_offset[s->lvl+1] == 3) {
552
-		if (s->params[2].type == SEL_PARAM_INT) {
553
-			hi = s->params[2].v.i;
551
+	if (s->param_offset[s->lvl+1] == 4) {
552
+		if (s->params[3].type == SEL_PARAM_INT) {
553
+			hi = s->params[3].v.i;
554 554
 		} else {
555 555
 			hi = -1;
556 556
 		}
... ...
@@ -564,11 +558,11 @@ int select_anyheader(str* res, select_t* s, struct sip_msg* msg)
564 564
 		return -1;
565 565
 	}
566 566
 	for (hf=msg->headers; hf; hf=hf->next) {
567
-		if(s->params[1].type==SEL_PARAM_DIV) {
568
-			if (s->params[1].v.i!=hf->type)	continue;
569
-		} else if(s->params[1].type==SEL_PARAM_STR) {
570
-			if (s->params[1].v.s.len!=hf->name.len)	continue;
571
-			if (strncasecmp(s->params[1].v.s.s, hf->name.s, hf->name.len)!=0) continue;
567
+		if(s->params[2].type==SEL_PARAM_DIV) {
568
+			if (s->params[2].v.i!=hf->type)	continue;
569
+		} else if(s->params[2].type==SEL_PARAM_STR) {
570
+			if (s->params[2].v.s.len!=hf->name.len)	continue;
571
+			if (strncasecmp(s->params[2].v.s.s, hf->name.s, hf->name.len)!=0) continue;
572 572
 		}
573 573
 		hf0 = hf;
574 574
 		hi--;
... ...
@@ -582,7 +576,19 @@ int select_anyheader(str* res, select_t* s, struct sip_msg* msg)
582 582
 	return 0;
583 583
 }
584 584
 
585
-ABSTRACT_F(select_anyheader_params)
585
+//ABSTRACT_F(select_anyheader_params)
586
+// Instead of ABSTRACT_F(select_anyheader_params)
587
+// use function which uses select_core_table
588
+// to avoid gcc warning about not used
589
+ 
590
+int select_anyheader_params(str* res, select_t* s, struct sip_msg* msg)
591
+{
592
+	if (select_core_table.next)
593
+		return -1;
594
+	else
595
+		return -1;
596
+}
597
+
586 598
 ABSTRACT_F(select_any_uri)
587 599
 
588 600
 static struct sip_uri uri;
... ...
@@ -1138,3 +1144,340 @@ int select_ip_port(str* res, select_t* s, struct sip_msg* msg)
1138 1138
 
1139 1139
 }
1140 1140
 
1141
+
1142
+int select_expires(str* res, select_t* s, struct sip_msg* msg)
1143
+{
1144
+	if (!msg->expires && (parse_headers(msg, HDR_EXPIRES_F, 0) == -1)) {
1145
+		return -1; /* error */
1146
+	}
1147
+
1148
+	if (!msg->expires) {
1149
+		return 1;  /* null */
1150
+	}
1151
+
1152
+	if (msg->expires->parsed == NULL && parse_expires(msg->expires) < 0) {
1153
+		return -1;
1154
+	}
1155
+
1156
+	RETURN0_res(((struct exp_body*)msg->expires->parsed)->text);
1157
+}
1158
+
1159
+#define SELECT_plain_header(_sel_name_,_fld_name_,_hdr_f_) \
1160
+int select_##_sel_name_(str* res, select_t* s, struct sip_msg* msg) \
1161
+{ \
1162
+	if (!msg->_fld_name_ && (parse_headers(msg, _hdr_f_, 0) == -1)) { \
1163
+		return -1; \
1164
+	} \
1165
+	if (!msg->_fld_name_) { \
1166
+		return 1; \
1167
+	} \
1168
+	RETURN0_res(msg->_fld_name_->body); \
1169
+}
1170
+
1171
+SELECT_plain_header(call_id, callid, HDR_CALLID_F)
1172
+SELECT_plain_header(max_forwards, maxforwards, HDR_MAXFORWARDS_F)
1173
+SELECT_plain_header(content_type, content_type, HDR_CONTENTTYPE_F)
1174
+SELECT_plain_header(content_length, content_length, HDR_CONTENTLENGTH_F)
1175
+SELECT_plain_header(user_agent, user_agent, HDR_USERAGENT_F)
1176
+SELECT_plain_header(subject, subject, HDR_SUBJECT_F)
1177
+SELECT_plain_header(organization, organization, HDR_ORGANIZATION_F)
1178
+SELECT_plain_header(priority, priority, HDR_PRIORITY_F)
1179
+SELECT_plain_header(session_expires, session_expires, HDR_SESSIONEXPIRES_F)
1180
+SELECT_plain_header(min_se, min_se, HDR_MIN_SE_F)
1181
+SELECT_plain_header(sip_if_match, sipifmatch, HDR_SIPIFMATCH_F)
1182
+
1183
+int select_msg_request(str* res, select_t* s, struct sip_msg* msg)
1184
+{
1185
+	if (msg->first_line.type==SIP_REQUEST) { 
1186
+		return select_msg(res, s, msg); 
1187
+	}
1188
+	else
1189
+		return -1;	
1190
+}
1191
+
1192
+int select_msg_response(str* res, select_t* s, struct sip_msg* msg)
1193
+{
1194
+	if (msg->first_line.type==SIP_REPLY) {
1195
+		return select_msg(res, s, msg); 
1196
+	}
1197
+	else
1198
+		return -1;	
1199
+}
1200
+
1201
+#define SELECT_first_line(_sel_name_,_type_,_fld_) \
1202
+int select_msg_##_sel_name_(str* res, select_t* s, struct sip_msg* msg) {\
1203
+	if (msg->first_line.type==_type_) { \
1204
+		RETURN0_res(msg->first_line._fld_); \
1205
+	} else return -1; \
1206
+}
1207
+
1208
+SELECT_first_line(request_method,SIP_REQUEST,u.request.method)
1209
+SELECT_first_line(request_uri,SIP_REQUEST,u.request.uri)
1210
+SELECT_first_line(request_version,SIP_REQUEST,u.request.version)
1211
+SELECT_first_line(response_version,SIP_REPLY,u.reply.version)
1212
+SELECT_first_line(response_status,SIP_REPLY,u.reply.status)
1213
+SELECT_first_line(response_reason,SIP_REPLY,u.reply.reason)
1214
+
1215
+
1216
+int select_version(str* res, select_t* s, struct sip_msg* msg)
1217
+{
1218
+	switch (msg->first_line.type) { 
1219
+		case SIP_REQUEST:
1220
+			RETURN0_res(msg->first_line.u.request.version)
1221
+			break;
1222
+		case SIP_REPLY:
1223
+			RETURN0_res(msg->first_line.u.reply.version)
1224
+			break;
1225
+		default:
1226
+			return -1;
1227
+	}
1228
+}
1229
+
1230
+ABSTRACT_F(select_sys)
1231
+
1232
+int select_sys_pid(str* res, select_t* s, struct sip_msg* msg) {
1233
+	return uint_to_static_buffer(res, getpid());
1234
+}
1235
+
1236
+int select_sys_unique(str* res, select_t* s, struct sip_msg* msg) {
1237
+	#define UNIQUE_ID_PID_LEN 4
1238
+	#define UNIQUE_ID_TIME_LEN 8
1239
+	#define UNIQUE_ID_FIX_LEN (UNIQUE_ID_PID_LEN+1+UNIQUE_ID_TIME_LEN+1)
1240
+	#define UNIQUE_ID_RAND_LEN 8
1241
+	static char uniq_id[UNIQUE_ID_FIX_LEN+UNIQUE_ID_RAND_LEN];
1242
+	static int uniq_for_pid = -1;
1243
+	int i;
1244
+
1245
+	if (uniq_for_pid != getpid()) {
1246
+		/* first call for this process */
1247
+		int cb, rb, x, l;
1248
+		char *c;
1249
+		/* init gloabally uniq part */
1250
+		c = int2str_base_0pad(getpid(), &l, 16, UNIQUE_ID_PID_LEN);
1251
+		memcpy(uniq_id, c, UNIQUE_ID_PID_LEN);
1252
+		uniq_id[UNIQUE_ID_PID_LEN] = '-';
1253
+		c = int2str_base_0pad(time(NULL), &l, 16, UNIQUE_ID_TIME_LEN);
1254
+		memcpy(uniq_id+UNIQUE_ID_PID_LEN+1, c, UNIQUE_ID_TIME_LEN);
1255
+		uniq_id[UNIQUE_ID_PID_LEN+1+UNIQUE_ID_TIME_LEN] = '-';
1256
+
1257
+		/* init random part */
1258
+		for (i = RAND_MAX, rb=0; i; rb++, i>>=1);
1259
+		for (i = UNIQUE_ID_FIX_LEN, cb = 0, x = 0; i < UNIQUE_ID_FIX_LEN+UNIQUE_ID_RAND_LEN; i++) {
1260
+			if (!cb) {
1261
+				cb = rb;
1262
+				x = rand();
1263
+			}
1264
+			uniq_id[i] = fourbits2char[x & 0x0F];
1265
+			x >>= rb;
1266
+			cb -= rb;
1267
+		}
1268
+		uniq_for_pid = getpid();
1269
+	}
1270
+        for (i = UNIQUE_ID_FIX_LEN + UNIQUE_ID_RAND_LEN - 1; i >= UNIQUE_ID_FIX_LEN; i--) {
1271
+		switch (uniq_id[i]) {
1272
+			case '9':
1273
+				uniq_id[i]='a';
1274
+				i = 0;
1275
+				break;
1276
+			case 'f':
1277
+				uniq_id[i]='0';
1278
+				/* go on */
1279
+				break;
1280
+			default:
1281
+				uniq_id[i]++;
1282
+				i = 0;
1283
+				break;
1284
+		}
1285
+	}
1286
+	res->s = uniq_id;   /* I think it's not worth copying at static buffer, I hope there is no real meaning of @sys.unique==@sys.unique */
1287
+	res->len = UNIQUE_ID_FIX_LEN+UNIQUE_ID_RAND_LEN;
1288
+	return 0;
1289
+}
1290
+
1291
+
1292
+int select_sys_now(str* res, select_t* s, struct sip_msg* msg) {
1293
+	return uint_to_static_buffer(res, time(NULL));
1294
+}
1295
+
1296
+int select_sys_now_fmt(str* res, select_t* s, struct sip_msg* msg)
1297
+{
1298
+#define SEL_POS 2
1299
+	time_t t;
1300
+	struct tm *tm;
1301
+	
1302
+	t = time(NULL);
1303
+	switch (s->params[SEL_POS].v.i) {
1304
+		case SEL_NOW_GMT:
1305
+			tm = gmtime(&t);
1306
+			break;
1307
+	
1308
+		case SEL_NOW_LOCAL:
1309
+			tm = localtime(&t);
1310
+			break;
1311
+		default:
1312
+			BUG("Unexpected parameter value 'now' \"%d\"\n", s->params[SEL_POS].v.i);
1313
+			return -1;
1314
+	}
1315
+	if (s->n <= SEL_POS+1) {
1316
+		char *c;
1317
+		c = asctime(tm);
1318
+		res->len = strlen(c);
1319
+		while (res->len && c[res->len-1] < ' ') res->len--; /* rtrim */
1320
+		res->s = get_static_buffer(res->len);
1321
+		if (!res->s) return -1;
1322
+		memcpy(res->s, c, res->len);
1323
+	}
1324
+	else {
1325
+		char c, buff[80];
1326
+		c = s->params[SEL_POS+1].v.s.s[s->params[SEL_POS+1].v.s.len];
1327
+		s->params[SEL_POS+1].v.s.s[s->params[SEL_POS+1].v.s.len] = '\0';
1328
+		res->len = strftime(buff, sizeof(buff)-1, s->params[SEL_POS+1].v.s.s, tm);
1329
+		s->params[SEL_POS+1].v.s.s[s->params[SEL_POS+1].v.s.len] = c;
1330
+		res->s = get_static_buffer(res->len);
1331
+		if (!res->s) return -1;
1332
+		memcpy(res->s, buff, res->len);
1333
+	}
1334
+	return 0;
1335
+#undef SEL_POS
1336
+}
1337
+
1338
+ABSTRACT_F(select_branch)
1339
+
1340
+int select_branch_count(str* res, select_t* s, struct sip_msg* msg) {
1341
+	return uint_to_static_buffer(res, nr_branches);
1342
+}
1343
+
1344
+int select_branch_uri(str* res, select_t* s, struct sip_msg* msg) {
1345
+#define SEL_POS 1 
1346
+#define Q_PARAM ">;q="
1347
+#define Q_PARAM_LEN (sizeof(Q_PARAM) - 1)
1348
+
1349
+	qvalue_t q;
1350
+	int l, n;
1351
+	str dst_uri;
1352
+	if (s->n <= SEL_POS+1 && nr_branches > 1) { /* get all branches, if nr_branches==1 then use faster algorithm */
1353
+		int len;
1354
+		unsigned l2;
1355
+		char *c;
1356
+		init_branch_iterator();
1357
+		len = 0;
1358
+		while ((c = next_branch(&l, &q, &dst_uri.s, &dst_uri.len, 0))) {
1359
+
1360
+			if (s->params[SEL_POS].v.i & SEL_BRANCH_DST_URI) {
1361
+				l = dst_uri.len;
1362
+				c = dst_uri.s;
1363
+			}
1364
+			if (s->params[SEL_POS].v.i & (SEL_BRANCH_URI|SEL_BRANCH_DST_URI) ) {
1365
+				len += l;
1366
+			}
1367
+	                if (q != Q_UNSPECIFIED && (s->params[SEL_POS].v.i & SEL_BRANCH_Q)) {
1368
+				len += len_q(q);
1369
+				if (s->params[SEL_POS].v.i & SEL_BRANCH_URI) {
1370
+					len += 1 + Q_PARAM_LEN;
1371
+				}
1372
+			}
1373
+ 			len += 1;
1374
+		}
1375
+		if (!len) return 1;
1376
+		res->s = get_static_buffer(len);
1377
+		if (!res->s) return -1;
1378
+		
1379
+		init_branch_iterator();
1380
+		res->len = 0;
1381
+		n = 0;
1382
+		while ((c = next_branch(&l, &q, &dst_uri.s, &dst_uri.len, 0))) {
1383
+			if (s->params[SEL_POS].v.i & SEL_BRANCH_DST_URI) {
1384
+				l = dst_uri.len;
1385
+				c = dst_uri.s;
1386
+			}
1387
+			if (n) {
1388
+				res->s[res->len] = ',';
1389
+				res->len++;
1390
+			}
1391
+			if ((s->params[SEL_POS].v.i & SEL_BRANCH_Q) == 0) {
1392
+				q = Q_UNSPECIFIED;
1393
+			}
1394
+			if ((s->params[SEL_POS].v.i & (SEL_BRANCH_URI|SEL_BRANCH_DST_URI)) && q != Q_UNSPECIFIED) {
1395
+				res->s[res->len] = '<';
1396
+				res->len++;
1397
+				memcpy(res->s+res->len, c, l);
1398
+				res->len += l; 
1399
+				memcpy(res->s+res->len, Q_PARAM, Q_PARAM_LEN);
1400
+				res->len += Q_PARAM_LEN;
1401
+				c = q2str(q, &l2); l = l2;
1402
+				memcpy(res->s+res->len, c, l);
1403
+				res->len += l; 
1404
+			}
1405
+			else if (s->params[SEL_POS].v.i & (SEL_BRANCH_URI|SEL_BRANCH_DST_URI)) {
1406
+				memcpy(res->s+res->len, c, l);
1407
+				res->len += l; 
1408
+			}
1409
+			else if (q != Q_UNSPECIFIED) {
1410
+				c = q2str(q, &l2); l = l2;
1411
+				memcpy(res->s+res->len, c, l);
1412
+				res->len += l; 
1413
+			}
1414
+			n++;
1415
+		}
1416
+	}
1417
+	else {
1418
+		unsigned l2;
1419
+		char *c;
1420
+		n = s->params[SEL_POS+1].v.i;
1421
+		if (n < 0 || n >= nr_branches) 
1422
+			return -1;
1423
+		init_branch_iterator();
1424
+		for (; (c = next_branch(&l, &q, &dst_uri.s, &dst_uri.len, 0)) && n; n--);
1425
+		if (!c) return 1;
1426
+		
1427
+		if (s->params[SEL_POS].v.i & SEL_BRANCH_DST_URI) {
1428
+			l = dst_uri.len;
1429
+			c = dst_uri.s;
1430
+		}
1431
+		if ((s->params[SEL_POS].v.i & SEL_BRANCH_Q) == 0) {
1432
+			q = Q_UNSPECIFIED;
1433
+		}
1434
+		if ((s->params[SEL_POS].v.i & (SEL_BRANCH_URI|SEL_BRANCH_DST_URI)) && q != Q_UNSPECIFIED) {
1435
+
1436
+			res->s = get_static_buffer(l + 1 + Q_PARAM_LEN + len_q(q));
1437
+			if (!res->s) return -1;
1438
+			res->len = 1;
1439
+			res->s[0] = '<';
1440
+			memcpy(res->s+res->len, c, l);
1441
+			res->len += l; 
1442
+			memcpy(res->s+res->len, Q_PARAM, Q_PARAM_LEN);
1443
+			res->len += Q_PARAM_LEN;
1444
+			c = q2str(q, &l2); l = l2;
1445
+			memcpy(res->s+res->len, c, l);
1446
+			res->len += l; 
1447
+		}
1448
+		else if (s->params[SEL_POS].v.i & (SEL_BRANCH_URI|SEL_BRANCH_DST_URI)) {
1449
+			res->s = c;  /* not necessary to copy to static buffer */
1450
+			res->len = l;
1451
+		} 
1452
+		else if (q != Q_UNSPECIFIED) {
1453
+			c = q2str(q, &l2);
1454
+			res->len = l2;
1455
+			res->s = get_static_buffer(res->len);
1456
+			if (!res->s) return -1;
1457
+			memcpy(res->s, c, res->len);
1458
+		}
1459
+		else {
1460
+			res->len = 0;
1461
+		}
1462
+	}
1463
+	return 0;
1464
+#undef SEL_POS
1465
+}
1466
+
1467
+int select_branch_uriq(str* res, select_t* s, struct sip_msg* msg) {
1468
+	return select_branch_uri(res, s, msg);
1469
+}
1470
+
1471
+int select_branch_q(str* res, select_t* s, struct sip_msg* msg) {
1472
+	return select_branch_uri(res, s, msg);
1473
+}
1474
+
1475
+int select_branch_dst_uri(str* res, select_t* s, struct sip_msg* msg) {
1476
+	return select_branch_uri(res, s, msg);
1477
+}
... ...
@@ -71,7 +71,17 @@ enum {
71 71
 	SEL_IP_PORT = SEL_IP | SEL_PORT,
72 72
 };
73 73
 
74
-SELECT_F(select_method)
74
+enum {
75
+	SEL_NOW_GMT = 1,
76
+	SEL_NOW_LOCAL = 2
77
+};
78
+
79
+enum {
80
+	SEL_BRANCH_URI = 1<<0,
81
+	SEL_BRANCH_Q = 1<<1,
82
+	SEL_BRANCH_DST_URI = 1<<2
83
+};
84
+
75 85
 SELECT_F(select_ruri)
76 86
 SELECT_F(select_dst_uri)
77 87
 SELECT_F(select_next_hop)
... ...
@@ -85,6 +95,16 @@ SELECT_F(select_to_uri)
85 85
 SELECT_F(select_to_tag)
86 86
 SELECT_F(select_to_name)
87 87
 SELECT_F(select_to_params)
88
+SELECT_F(select_refer_to)
89
+SELECT_F(select_refer_to_uri)
90
+SELECT_F(select_refer_to_tag)
91
+SELECT_F(select_refer_to_name)
92
+SELECT_F(select_refer_to_params)
93
+SELECT_F(select_rpid)
94
+SELECT_F(select_rpid_uri)
95
+SELECT_F(select_rpid_tag)
96
+SELECT_F(select_rpid_name)
97
+SELECT_F(select_rpid_params)
88 98
 SELECT_F(select_contact)
89 99
 SELECT_F(select_contact_uri)
90 100
 SELECT_F(select_contact_name)
... ...
@@ -100,9 +120,26 @@ SELECT_F(select_via_comment)
100 100
 SELECT_F(select_via_params)
101 101
 SELECT_F(select_via_params_spec)
102 102
 
103
-SELECT_F(select_msgheader)
103
+SELECT_F(select_msg)
104
+SELECT_F(select_msg_first_line)
105
+SELECT_F(select_msg_flags)
106
+SELECT_F(select_msg_type)
107
+SELECT_F(select_msg_len)
108
+SELECT_F(select_msg_id)
109
+SELECT_F(select_msg_id_hex)
110
+SELECT_F(select_msg_body)
111
+SELECT_F(select_msg_header)
104 112
 SELECT_F(select_anyheader)
105 113
 SELECT_F(select_anyheader_params)
114
+SELECT_F(select_msg_request)
115
+SELECT_F(select_msg_request_method)
116
+SELECT_F(select_msg_request_uri)
117
+SELECT_F(select_msg_request_version)
118
+SELECT_F(select_msg_response)
119
+SELECT_F(select_msg_response_version)
120
+SELECT_F(select_msg_response_status)
121
+SELECT_F(select_msg_response_reason)
122
+SELECT_F(select_version)
106 123
 
107 124
 SELECT_F(select_any_nameaddr)
108 125
 SELECT_F(select_nameaddr_name)
... ...
@@ -140,9 +177,35 @@ SELECT_F(select_dst)
140 140
 SELECT_F(select_rcv)
141 141
 SELECT_F(select_ip_port)
142 142
 
143
+SELECT_F(select_call_id)
144
+SELECT_F(select_expires)
145
+SELECT_F(select_max_forwards)
146
+SELECT_F(select_content_type)
147
+SELECT_F(select_content_length)
148
+SELECT_F(select_subject)
149
+SELECT_F(select_organization)
150
+SELECT_F(select_priority)
151
+SELECT_F(select_session_expires)
152
+SELECT_F(select_min_se)
153
+SELECT_F(select_user_agent)
154
+SELECT_F(select_sip_if_match)
155
+
156
+SELECT_F(select_sys)
157
+SELECT_F(select_sys_pid)
158
+SELECT_F(select_sys_unique)
159
+SELECT_F(select_sys_now)
160
+SELECT_F(select_sys_now_fmt)
161
+
162
+SELECT_F(select_branch)
163
+SELECT_F(select_branch_count)
164
+SELECT_F(select_branch_uri)
165
+SELECT_F(select_branch_dst_uri)
166
+SELECT_F(select_branch_uriq)
167
+SELECT_F(select_branch_q)
168
+
143 169
 static select_row_t select_core[] = {
144
-	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("method"), select_method, 0},
145
-	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("ruri"), select_ruri, 0},
170
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("ruri"), select_ruri, 0}, /* not the same as request.uri because it is involved by new_uri */
171
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("request_uri"), select_ruri, 0},
146 172
 	{ select_ruri, SEL_PARAM_STR, STR_NULL, select_any_uri, NESTED},
147 173
 	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("dst_uri"), select_dst_uri, 0},
148 174
 	{ select_dst_uri, SEL_PARAM_STR, STR_NULL, select_any_uri, NESTED},
... ...
@@ -160,6 +223,17 @@ static select_row_t select_core[] = {
160 160
 	{ select_to, SEL_PARAM_STR, STR_STATIC_INIT("tag"), select_to_tag, 0},
161 161
 	{ select_to, SEL_PARAM_STR, STR_STATIC_INIT("name"), select_to_name, 0},
162 162
 	{ select_to, SEL_PARAM_STR, STR_STATIC_INIT("params"), select_to_params, CONSUME_NEXT_STR},
163
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("refer_to"), select_refer_to, 0},
164
+	{ select_refer_to, SEL_PARAM_STR, STR_STATIC_INIT("uri"), select_refer_to_uri, 0},
165
+	{ select_refer_to, SEL_PARAM_STR, STR_STATIC_INIT("tag"), select_refer_to_tag, 0},
166
+	{ select_refer_to, SEL_PARAM_STR, STR_STATIC_INIT("name"), select_refer_to_name, 0},
167
+	{ select_refer_to, SEL_PARAM_STR, STR_STATIC_INIT("params"), select_refer_to_params, CONSUME_NEXT_STR},
168
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("remote_party_id"), select_rpid, 0},
169
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("rpid"), select_rpid, 0},
170
+	{ select_rpid, SEL_PARAM_STR, STR_STATIC_INIT("uri"), select_rpid_uri, 0},
171
+	{ select_rpid, SEL_PARAM_STR, STR_STATIC_INIT("tag"), select_rpid_tag, 0},
172
+	{ select_rpid, SEL_PARAM_STR, STR_STATIC_INIT("name"), select_rpid_name, 0},
173
+	{ select_rpid, SEL_PARAM_STR, STR_STATIC_INIT("params"), select_rpid_params, CONSUME_NEXT_STR},
163 174
 	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("contact"), select_contact, 0},
164 175
 	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("m"), select_contact, 0},
165 176
 	{ select_contact, SEL_PARAM_STR, STR_STATIC_INIT("uri"), select_contact_uri, 0},
... ...
@@ -187,6 +261,8 @@ static select_row_t select_core[] = {
187 187
 	
188 188
 	{ select_from_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, NESTED},
189 189
 	{ select_to_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, NESTED},
190
+	{ select_refer_to_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, NESTED},
191
+	{ select_rpid_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, NESTED},
190 192
 	{ select_contact_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, NESTED},
191 193
 	{ select_rr_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, NESTED},
192 194
 	{ select_any_uri, SEL_PARAM_STR, STR_STATIC_INIT("type"), select_uri_type, 0},
... ...
@@ -214,11 +290,40 @@ static select_row_t select_core[] = {
214 214
 	{ select_any_nameaddr, SEL_PARAM_STR, STR_STATIC_INIT("params"), select_nameaddr_params, OPTIONAL | CONSUME_NEXT_STR},
215 215
 	{ select_nameaddr_uri, SEL_PARAM_INT, STR_NULL, select_any_uri, NESTED},
216 216
 
217
-	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("msg"), select_msgheader, SEL_PARAM_EXPECTED},
218
-	{ select_msgheader, SEL_PARAM_STR, STR_NULL, select_anyheader, OPTIONAL | CONSUME_NEXT_INT | FIXUP_CALL},
217
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("msg"), select_msg, 0},
218
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("message"), select_msg, 0},
219
+	{ select_msg, SEL_PARAM_STR, STR_STATIC_INIT("first_line"), select_msg_first_line, 0},
220
+	{ select_msg, SEL_PARAM_STR, STR_STATIC_INIT("flags"), select_msg_flags, 0},
221
+	{ select_msg, SEL_PARAM_STR, STR_STATIC_INIT("len"), select_msg_len, 0},
222
+	{ select_msg, SEL_PARAM_STR, STR_STATIC_INIT("id"), select_msg_id, 0},
223
+	{ select_msg_id, SEL_PARAM_STR, STR_STATIC_INIT("hex"), select_msg_id_hex, 0},
224
+	{ select_msg, SEL_PARAM_STR, STR_STATIC_INIT("type"), select_msg_type, 0},
225
+	{ select_msg, SEL_PARAM_STR, STR_STATIC_INIT("header"), select_msg_header, 0},
226
+	{ select_msg, SEL_PARAM_STR, STR_STATIC_INIT("h"), select_msg_header, 0},
227
+	{ select_msg_header, SEL_PARAM_STR, STR_NULL, select_anyheader, OPTIONAL | CONSUME_NEXT_INT | FIXUP_CALL},
219 228
 	{ select_anyheader, SEL_PARAM_STR, STR_STATIC_INIT("nameaddr"), select_any_nameaddr, NESTED | CONSUME_NEXT_STR},
220 229
 	{ select_anyheader, SEL_PARAM_STR, STR_STATIC_INIT("params"), select_anyheader_params, NESTED},
221 230
 	{ select_anyheader_params, SEL_PARAM_STR, STR_STATIC_INIT("params"), select_any_params, CONSUME_NEXT_STR},
231
+	{ select_msg, SEL_PARAM_STR, STR_STATIC_INIT("body"), select_msg_body, 0},
232
+	{ select_msg, SEL_PARAM_STR, STR_STATIC_INIT("content"), select_msg_body, 0},
233
+	{ select_msg, SEL_PARAM_STR, STR_STATIC_INIT("request"), select_msg_request, 0},
234
+	{ select_msg, SEL_PARAM_STR, STR_STATIC_INIT("req"), select_msg_request, 0},
235
+	{ select_msg_request, SEL_PARAM_STR, STR_STATIC_INIT("method"), select_msg_request_method, 0},
236
+	{ select_msg_request, SEL_PARAM_STR, STR_STATIC_INIT("uri"), select_msg_request_uri, 0},
237
+	{ select_msg_request_uri, SEL_PARAM_STR, STR_NULL, select_any_uri, NESTED},
238
+	{ select_msg_request, SEL_PARAM_STR, STR_STATIC_INIT("version"), select_msg_request_version, 0},
239
+	{ select_msg, SEL_PARAM_STR, STR_STATIC_INIT("response"), select_msg_response, 0},
240
+	{ select_msg, SEL_PARAM_STR, STR_STATIC_INIT("res"), select_msg_response, 0},
241
+	{ select_msg_response, SEL_PARAM_STR, STR_STATIC_INIT("version"), select_msg_response_version, 0},
242
+	{ select_msg_response, SEL_PARAM_STR, STR_STATIC_INIT("status"), select_msg_response_status, 0},
243
+	{ select_msg_response, SEL_PARAM_STR, STR_STATIC_INIT("code"), select_msg_response_status, 0},
244
+	{ select_msg_response, SEL_PARAM_STR, STR_STATIC_INIT("reason"), select_msg_response_reason, 0},
245
+	/*short aliases*/
246
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("method"), select_msg_request_method, 0},
247
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("version"), select_version, 0},
248
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("status"), select_msg_response_status, 0},
249
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("code"), select_msg_response_status, 0},
250
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("reason"), select_msg_response_reason, 0},
222 251
 
223 252
 	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("proxy_authorization"), select_auth, CONSUME_NEXT_STR | DIVERSION | SEL_AUTH_PROXY},
224 253
 	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("authorization"), select_auth, CONSUME_NEXT_STR | DIVERSION | SEL_AUTH_WWW}, 
... ...
@@ -250,6 +355,37 @@ static select_row_t select_core[] = {
250 250
 	{ select_rcv, SEL_PARAM_STR, STR_STATIC_INIT("ip_port"), select_ip_port, DIVERSION | SEL_RCV | SEL_IP_PORT},
251 251
 	{ select_rcv, SEL_PARAM_STR, STR_STATIC_INIT("proto_ip_port"), select_ip_port, DIVERSION | SEL_RCV | SEL_PROTO | SEL_IP_PORT},
252 252
 
253
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("call_id"), select_call_id, 0},
254
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("expires"), select_expires, 0},
255
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("max_forwards"), select_max_forwards, 0},
256
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("content_type"), select_content_type, 0},
257
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("content_length"), select_content_length, 0},
258
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("subject"), select_subject, 0},
259
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("organization"), select_organization, 0},
260
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("priority"), select_priority, 0},
261
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("session_expires"), select_session_expires, 0},
262
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("min_se"), select_min_se, 0},
263
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("user_agent"), select_user_agent, 0},
264
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("sip_if_match"), select_sip_if_match, 0},
265
+
266
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("sys"), select_sys, SEL_PARAM_EXPECTED},
267
+	{ select_sys, SEL_PARAM_STR, STR_STATIC_INIT("pid"), select_sys_pid, 0},
268
+	{ select_sys, SEL_PARAM_STR, STR_STATIC_INIT("unique"), select_sys_unique, 0},
269
+	{ select_sys, SEL_PARAM_STR, STR_STATIC_INIT("now"), select_sys_now, 0},
270
+	{ select_sys_now, SEL_PARAM_STR, STR_STATIC_INIT("local"), select_sys_now_fmt, OPTIONAL | CONSUME_NEXT_STR | DIVERSION | SEL_NOW_LOCAL},
271
+	{ select_sys_now, SEL_PARAM_STR, STR_STATIC_INIT("gmt"), select_sys_now_fmt, OPTIONAL | CONSUME_NEXT_STR | DIVERSION | SEL_NOW_GMT},
272
+	{ select_sys_now, SEL_PARAM_STR, STR_STATIC_INIT("utc"), select_sys_now_fmt, OPTIONAL | CONSUME_NEXT_STR | DIVERSION | SEL_NOW_GMT},
273
+
274
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("branch"), select_branch, SEL_PARAM_EXPECTED},
275
+	{ select_branch, SEL_PARAM_STR, STR_STATIC_INIT("count"), select_branch_count, 0},
276
+	{ select_branch, SEL_PARAM_STR, STR_STATIC_INIT("uri"), select_branch_uri, OPTIONAL | CONSUME_NEXT_INT | DIVERSION | SEL_BRANCH_URI },
277
+	{ select_branch, SEL_PARAM_STR, STR_STATIC_INIT("dst_uri"), select_branch_dst_uri, OPTIONAL | CONSUME_NEXT_INT | DIVERSION | SEL_BRANCH_DST_URI},
278
+	{ select_branch_uri, SEL_PARAM_STR, STR_NULL, select_any_uri, NESTED},
279
+	{ select_branch_dst_uri, SEL_PARAM_STR, STR_NULL, select_any_uri, NESTED},
280
+	{ select_branch, SEL_PARAM_STR, STR_STATIC_INIT("uriq"), select_branch_uriq, OPTIONAL | CONSUME_NEXT_INT | DIVERSION | SEL_BRANCH_URI | SEL_BRANCH_Q},
281
+	{ select_branch_uriq, SEL_PARAM_STR, STR_NULL, select_any_nameaddr, NESTED},
282
+	{ select_branch, SEL_PARAM_STR, STR_STATIC_INIT("q"), select_branch_q, OPTIONAL | CONSUME_NEXT_INT | DIVERSION | SEL_BRANCH_Q},
283
+
253 284
 	{ NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
254 285
 };
255 286