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