Browse code

- new parse_uri function added (better + parses transport, maddr, lr, method, user, ttl ) - sip_uri structure updated - PROTO_SCTP added :-)

Andrei Pelinescu-Onciul authored on 10/04/2003 23:51:10
Showing 7 changed files
... ...
@@ -21,7 +21,7 @@
21 21
 VERSION = 0
22 22
 PATCHLEVEL = 8
23 23
 SUBLEVEL =   11
24
-EXTRAVERSION = pre14
24
+EXTRAVERSION = pre15-new_parse_uri
25 25
 
26 26
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
27 27
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")
... ...
@@ -19,6 +19,9 @@ x (different way) add request header bitmap field for the modules
19 19
 - add conflict in debs/rpms/etc (conflict w/ older ser-mysql, ser-jabber)
20 20
 - new packages ser-radius etc
21 21
 - tcp_destroy (called on ser exit)
22
+- BUG:?? ipv6 only and try to send to ipv4 => getsendsocket=>0 (send_ipv6=0)
23
+  the reverse is also true
24
+- resolver should resolve [ipv6]
22 25
 
23 26
 
24 27
 High priority:
... ...
@@ -45,7 +45,7 @@
45 45
 
46 46
 #include "dprint.h"
47 47
 
48
-enum sip_protos { PROTO_NONE, PROTO_UDP, PROTO_TCP, PROTO_TLS };
48
+enum sip_protos { PROTO_NONE, PROTO_UDP, PROTO_TCP, PROTO_TLS, PROTO_SCTP };
49 49
 
50 50
 
51 51
 struct ip_addr{
... ...
@@ -455,7 +455,20 @@ static inline int lumps_len(struct sip_msg* msg, struct socket_info* send_sock)
455 455
 				break; \
456 456
 			case SUBST_RCV_PROTO: \
457 457
 				if (msg->rcv.bind_address){ \
458
-					new_len+=3; \
458
+					switch(msg->rcv.bind_address->proto){ \
459
+						case PROTO_NONE: \
460
+						case PROTO_UDP: \
461
+						case PROTO_TCP: \
462
+						case PROTO_TLS: \
463
+								new_len+=3; \
464
+								break; \
465
+						case PROTO_SCTP: \
466
+								new_len+=4; \
467
+								break; \
468
+						default: \
469
+						LOG(L_CRIT, "BUG: lumps_len: unknown proto %d\n", \
470
+								msg->rcv.bind_address->proto); \
471
+					}\
459 472
 				}else{ \
460 473
 					/* FIXME */ \
461 474
 					LOG(L_CRIT, "FIXME: null bind_address\n"); \
... ...
@@ -470,9 +483,21 @@ static inline int lumps_len(struct sip_msg* msg, struct socket_info* send_sock)
470 470
 						/* add :port_no */ \
471 471
 						new_len+=1+msg->rcv.bind_address->port_no_str.len; \
472 472
 					}\
473
-					if(msg->rcv.bind_address->proto!=PROTO_UDP) {\
474 473
 						/*add;transport=xxx*/ \
475
-							new_len+=TRANSPORT_PARAM_LEN+3; \
474
+					switch(msg->rcv.bind_address->proto){ \
475
+						case PROTO_NONE: \
476
+						case PROTO_UDP: \
477
+								break; /* udp is the default */ \
478
+						case PROTO_TCP: \
479
+						case PROTO_TLS: \
480
+								new_len+=TRANSPORT_PARAM_LEN+3; \
481
+								break; \
482
+						case PROTO_SCTP: \
483
+								new_len+=TRANSPORT_PARAM_LEN+4; \
484
+								break; \
485
+						default: \
486
+						LOG(L_CRIT, "BUG: lumps_len: unknown proto %d\n", \
487
+								msg->rcv.bind_address->proto); \
476 488
 					}\
477 489
 				}else{ \
478 490
 					/* FIXME */ \
... ...
@@ -499,7 +524,20 @@ static inline int lumps_len(struct sip_msg* msg, struct socket_info* send_sock)
499 499
 				break; \
500 500
 			case SUBST_SND_PROTO: \
501 501
 				if (send_sock){ \
502
-					new_len+=3; /* tcp, udp or tls*/ \
502
+					switch(send_sock->proto){ \
503
+						case PROTO_NONE: \
504
+						case PROTO_UDP: \
505
+						case PROTO_TCP: \
506
+						case PROTO_TLS: \
507
+								new_len+=3; \
508
+								break; \
509
+						case PROTO_SCTP: \
510
+								new_len+=4; \
511
+								break; \
512
+						default: \
513
+						LOG(L_CRIT, "BUG: lumps_len: unknown proto %d\n", \
514
+								send_sock->proto); \
515
+					}\
503 516
 				}else{ \
504 517
 					LOG(L_CRIT, "FIXME: lumps_len called with" \
505 518
 							" null send_sock\n"); \
... ...
@@ -514,9 +552,21 @@ static inline int lumps_len(struct sip_msg* msg, struct socket_info* send_sock)
514 514
 						/* add :port_no */ \
515 515
 						new_len+=1+send_sock->port_no_str.len; \
516 516
 					}\
517
-					if(send_sock->proto!=PROTO_UDP) {\
518
-						/*add;transport=xxx*/ \
519
-							new_len+=TRANSPORT_PARAM_LEN+3; \
517
+					/*add;transport=xxx*/ \
518
+					switch(send_sock->proto){ \
519
+						case PROTO_NONE: \
520
+						case PROTO_UDP: \
521
+								break; /* udp is the default */ \
522
+						case PROTO_TCP: \
523
+						case PROTO_TLS: \
524
+								new_len+=TRANSPORT_PARAM_LEN+3; \
525
+								break; \
526
+						case PROTO_SCTP: \
527
+								new_len+=TRANSPORT_PARAM_LEN+4; \
528
+								break; \
529
+						default: \
530
+						LOG(L_CRIT, "BUG: lumps_len: unknown proto %d\n", \
531
+								send_sock->proto); \
520 532
 					}\
521 533
 				}else{ \
522 534
 					/* FIXME */ \
... ...
@@ -703,6 +753,13 @@ static inline void process_lumps(	struct sip_msg* msg,
703 703
 						memcpy(new_buf+offset, "tls", 3); \
704 704
 						offset+=3; \
705 705
 						break; \
706
+					case PROTO_SCTP: \
707
+						memcpy(new_buf+offset, TRANSPORT_PARAM, \
708
+								TRANSPORT_PARAM_LEN); \
709
+						offset+=TRANSPORT_PARAM_LEN; \
710
+						memcpy(new_buf+offset, "sctp", 4); \
711
+						offset+=4; \
712
+						break; \
706 713
 					default: \
707 714
 						LOG(L_CRIT, "BUG: process_lumps: unknown proto %d\n", \
708 715
 								msg->rcv.bind_address->proto); \
... ...
@@ -777,6 +834,13 @@ static inline void process_lumps(	struct sip_msg* msg,
777 777
 						memcpy(new_buf+offset, "tls", 3); \
778 778
 						offset+=3; \
779 779
 						break; \
780
+					case PROTO_SCTP: \
781
+						memcpy(new_buf+offset, TRANSPORT_PARAM, \
782
+								TRANSPORT_PARAM_LEN); \
783
+						offset+=TRANSPORT_PARAM_LEN; \
784
+						memcpy(new_buf+offset, "sctp", 4); \
785
+						offset+=4; \
786
+						break; \
780 787
 					default: \
781 788
 						LOG(L_CRIT, "BUG: process_lumps: unknown proto %d\n", \
782 789
 								send_sock->proto); \
... ...
@@ -802,6 +866,10 @@ static inline void process_lumps(	struct sip_msg* msg,
802 802
 						memcpy(new_buf+offset, "tls", 3); \
803 803
 						offset+=3; \
804 804
 						break; \
805
+					case PROTO_SCTP: \
806
+						memcpy(new_buf+offset, "sctp", 4); \
807
+						offset+=4; \
808
+						break; \
805 809
 					default: \
806 810
 						LOG(L_CRIT, "BUG: process_lumps: unknown proto %d\n", \
807 811
 								msg->rcv.bind_address->proto); \
... ...
@@ -828,6 +896,10 @@ static inline void process_lumps(	struct sip_msg* msg,
828 828
 						memcpy(new_buf+offset, "tls", 3); \
829 829
 						offset+=3; \
830 830
 						break; \
831
+					case PROTO_SCTP: \
832
+						memcpy(new_buf+offset, "sctp", 4); \
833
+						offset+=4; \
834
+						break; \
831 835
 					default: \
832 836
 						LOG(L_CRIT, "BUG: process_lumps: unknown proto %d\n", \
833 837
 								send_sock->proto); \
... ...
@@ -26,13 +26,14 @@
26 26
  *
27 27
  * History
28 28
  * -------
29
- *  2003-03-06  enum_request_method changed to begin with 1;
30
- *             0 reserved for invalid values; (jiri)
31
- *  2003-02-28  scratchpad compatibility abandoned (jiri)
32 29
  *  2003-01-28  removed scratchpad (jiri)
30
+ *  2003-02-28  scratchpad compatibility abandoned (jiri)
31
+ *  2003-03-06  enum_request_method changed to begin with 1;
32
+ *               0 reserved for invalid values; (jiri)
33 33
  *  2003-03-31  removed sip_msg->repl_add_rm (andrei)
34 34
  *  2003-04-01  2 macros added: GET_NEXT_HOP and GET_RURI (janakj)
35 35
  *  2003-04-04  structure for parsed inbound uri added (jiri)
36
+ *  2003-04-11  updated the  sip_uri structure (lots of fields added) (andrei)
36 37
  */
37 38
 
38 39
 
... ...
@@ -98,6 +99,8 @@ if (  (*tmp==(firstchar) || *tmp==((firstchar) | 32)) &&                  \
98 98
 (((m)->new_uri.s && (m)->new_uri.len) ? ((m)->new_uri) : ((m)->first_line.u.request.uri))
99 99
 
100 100
 
101
+#if 0
102
+	/* old version */
101 103
 struct sip_uri {
102 104
 	str user;     /* Username */
103 105
 	str passwd;   /* Password */
... ...
@@ -107,7 +110,31 @@ struct sip_uri {
107 107
 	str headers;  
108 108
 	unsigned short port_no;
109 109
 };
110
+#endif
110 111
 
112
+struct sip_uri {
113
+	str user;     /* Username */
114
+	str passwd;   /* Password */
115
+	str host;     /* Host name */
116
+	str port;     /* Port number */
117
+	str params;   /* Parameters */
118
+	str headers;  
119
+	unsigned short port_no;
120
+	unsigned short proto; /* from transport */
121
+	/* parameters */
122
+	str transport;
123
+	str ttl;
124
+	str user_param;
125
+	str maddr;
126
+	str method;
127
+	str lr;
128
+	/* values */
129
+	str transport_val;
130
+	str ttl_val;
131
+	str user_param_val;
132
+	str maddr_val;
133
+	str method_val;
134
+};
111 135
 
112 136
 
113 137
 struct sip_msg {
... ...
@@ -28,19 +28,916 @@
28 28
  * --------
29 29
  * 2003-04-04  convenience inbound-uri parser parse_orig_ruri
30 30
  *             introduced (jiri)
31
+ * 2003-04-11  new parse_uri introduced (better, parses also some parameters,
32
+ *              works in one pass) (andrei)
31 33
  */
32 34
 
33 35
 
34 36
 #include "parse_uri.h"
35 37
 #include <string.h>
36 38
 #include "../dprint.h"
37
-#include "../ut.h"    /* q_memchr */
39
+#ifdef PARSE_URI_OLD
40
+#include "../ut.h"   /* q_memchr */
41
+#endif
38 42
 #include "../error.h"
39 43
 
40 44
 /* buf= pointer to begining of uri (sip:x@foo.bar:5060;a=b?h=i)
41 45
  * len= len of uri
42 46
  * returns: fills uri & returns <0 on error or 0 if ok 
43 47
  */
48
+#ifndef PARSE_URI_OLD
49
+int parse_uri(char* buf, int len, struct sip_uri* uri)
50
+{
51
+	enum states  {	URI_INIT, URI_USER, URI_PASSWORD, URI_PASSWORD_ALPHA,
52
+					URI_HOST, URI_HOST_P,
53
+					URI_HOST6_P, URI_HOST6_END, URI_PORT, 
54
+					URI_PARAM, URI_PARAM_P, URI_VAL_P, URI_HEADERS,
55
+					/* param states */
56
+					/* transport */
57
+					PT_T, PT_R, PT_A, PT_N, PT_S, PT_P, PT_O, PT_R2, PT_T2,
58
+					PT_eq,
59
+					/* ttl */
60
+					      PTTL_T2, PTTL_L, PTTL_eq,
61
+					/* user */
62
+					PU_U, PU_S, PU_E, PU_R, PU_eq,
63
+					/* method */
64
+					PM_M, PM_E, PM_T, PM_H, PM_O, PM_D, PM_eq,
65
+					/* maddr */
66
+					      PMA_A, PMA_D, PMA_D2, PMA_R, PMA_eq,
67
+					/* lr */
68
+					PLR_L, PLR_R_FIN,
69
+					/* transport values */
70
+					/* udp */
71
+					VU_U, VU_D, VU_P_FIN,
72
+					/* tcp */
73
+					VT_T, VT_C, VT_P_FIN,
74
+					/* tls */
75
+					      VTLS_L, VTLS_S_FIN,
76
+					/* sctp */
77
+					VS_S, VS_C, VS_T, VS_P_FIN
78
+	};
79
+	enum states state;
80
+	char* s;
81
+	char* b; /* param start */
82
+	char *v; /* value start */
83
+	str* param; /* current param */
84
+	str* param_val; /* current param val */
85
+	str user;
86
+	str password;
87
+	int port_no;
88
+	char* p;
89
+	char* end;
90
+	char* pass;
91
+	int found_user;
92
+	int error_headers;
93
+	
94
+#define case_port( ch, var) \
95
+	case ch: \
96
+			 (var)=(var)*10+ch-'0'; \
97
+			 break
98
+			 
99
+#define still_at_user  \
100
+						if (found_user==0){ \
101
+							user.s=uri->host.s; \
102
+							if (pass){\
103
+								user.len=pass-user.s; \
104
+								password.s=pass+1; \
105
+								password.len=p-password.s; \
106
+							}else{ \
107
+								user.len=p-user.s; \
108
+							}\
109
+							/* everything else is 0 */ \
110
+							memset(uri, 0, sizeof(struct sip_uri)); \
111
+							/* copy user & pass */ \
112
+							uri->user=user; \
113
+							if (pass)	uri->passwd=password;  \
114
+							s=p+1; \
115
+							found_user=1;\
116
+							error_headers=0; \
117
+							state=URI_HOST; \
118
+						}else goto error_bad_char 
119
+
120
+#define check_host_end \
121
+					case ':': \
122
+						/* found the host */ \
123
+						uri->host.s=s; \
124
+						uri->host.len=p-s; \
125
+						state=URI_PORT; \
126
+						s=p+1; \
127
+						break; \
128
+					case ';': \
129
+						uri->host.s=s; \
130
+						uri->host.len=p-s; \
131
+						state=URI_PARAM; \
132
+						s=p+1; \
133
+						break; \
134
+					case '?': \
135
+						uri->host.s=s; \
136
+						uri->host.len=p-s; \
137
+						state=URI_HEADERS; \
138
+						s=p+1; \
139
+						break; \
140
+					case '&': \
141
+					case '@': \
142
+						goto error_bad_char 
143
+
144
+
145
+#define param_set(t_start, v_start) \
146
+					param->s=(t_start);\
147
+					param->len=(p-(t_start));\
148
+					param_val->s=(v_start); \
149
+					param_val->len=(p-(v_start)) 
150
+
151
+#define semicolon_case \
152
+					case';': \
153
+						if (pass){ \
154
+							found_user=1;/* no user, pass cannot contain ';'*/ \
155
+							pass=0; \
156
+						} \
157
+						state=URI_PARAM   /* new param */ 
158
+
159
+#define question_case \
160
+					case '?': \
161
+						uri->params.s=s; \
162
+						uri->params.len=p-s; \
163
+						state=URI_HEADERS; \
164
+						s=p+1; \
165
+						if (pass){ \
166
+							found_user=1;/* no user, pass cannot contain '?'*/ \
167
+							pass=0; \
168
+						}
169
+
170
+#define colon_case \
171
+					case ':': \
172
+						if (found_user==0){ \
173
+							/*might be pass but only if user not found yet*/ \
174
+							if (pass){ \
175
+								found_user=1; /* no user */ \
176
+								pass=0; \
177
+							}else{ \
178
+								pass=p; \
179
+							} \
180
+						} \
181
+						state=URI_PARAM_P /* generic param */
182
+
183
+#define param_common_cases \
184
+					case '@': \
185
+						/* ughhh, this is still the user */ \
186
+						still_at_user; \
187
+						break; \
188
+					semicolon_case; \
189
+						break; \
190
+					question_case; \
191
+						break; \
192
+					colon_case; \
193
+						break
194
+
195
+#define value_common_cases \
196
+					case '@': \
197
+						/* ughhh, this is still the user */ \
198
+						still_at_user; \
199
+						break; \
200
+					semicolon_case; \
201
+						param_set(b, v); \
202
+						break; \
203
+					question_case; \
204
+						param_set(b, v); \
205
+						break; \
206
+					colon_case; \
207
+						state=URI_VAL_P; \
208
+						break
209
+
210
+#define param_switch(old_state, c1, c2, new_state) \
211
+			case old_state: \
212
+				switch(*p){ \
213
+					case c1: \
214
+					case c2: \
215
+						state=(new_state); \
216
+						break; \
217
+					param_common_cases; \
218
+					default: \
219
+						state=URI_PARAM_P; \
220
+				} \
221
+				break
222
+#define param_switch1(old_state, c1, new_state) \
223
+			case old_state: \
224
+				switch(*p){ \
225
+					case c1: \
226
+						state=(new_state); \
227
+						break; \
228
+					param_common_cases; \
229
+					default: \
230
+						state=URI_PARAM_P; \
231
+				} \
232
+				break
233
+#define param_switch_big(old_state, c1, c2, d1, d2, new_state_c, new_state_d) \
234
+			case old_state : \
235
+				switch(*p){ \
236
+					case c1: \
237
+					case c2: \
238
+						state=(new_state_c); \
239
+						break; \
240
+					case d1: \
241
+					case d2: \
242
+						state=(new_state_d); \
243
+						break; \
244
+					param_common_cases; \
245
+					default: \
246
+						state=URI_PARAM_P; \
247
+				} \
248
+				break
249
+#define value_switch(old_state, c1, c2, new_state) \
250
+			case old_state: \
251
+				switch(*p){ \
252
+					case c1: \
253
+					case c2: \
254
+						state=(new_state); \
255
+						break; \
256
+					value_common_cases; \
257
+					default: \
258
+						state=URI_VAL_P; \
259
+				} \
260
+				break
261
+#define value_switch_big(old_state, c1, c2, d1, d2, new_state_c, new_state_d) \
262
+			case old_state: \
263
+				switch(*p){ \
264
+					case c1: \
265
+					case c2: \
266
+						state=(new_state_c); \
267
+						break; \
268
+					case d1: \
269
+					case d2: \
270
+						state=(new_state_d); \
271
+						break; \
272
+					value_common_cases; \
273
+					default: \
274
+						state=URI_VAL_P; \
275
+				} \
276
+				break
277
+
278
+#define transport_fin(c_state, proto_no) \
279
+			case c_state: \
280
+				switch(*p){ \
281
+					case '@': \
282
+						still_at_user; \
283
+						break; \
284
+					semicolon_case; \
285
+						param_set(b, v); \
286
+						uri->proto=(proto_no); \
287
+						break; \
288
+					question_case; \
289
+						param_set(b, v); \
290
+						uri->proto=(proto_no); \
291
+						break; \
292
+					colon_case;  \
293
+					default: \
294
+						state=URI_VAL_P; \
295
+						break; \
296
+				} \
297
+				break
298
+			
299
+	
300
+
301
+	/* init */
302
+	end=buf+len;
303
+	p=buf+4;
304
+	found_user=0;
305
+	error_headers=0;
306
+	b=v=0;
307
+	param=param_val=0;
308
+	pass=0;
309
+	port_no=0;
310
+	state=URI_INIT;
311
+	memset(uri, 0, sizeof(struct sip_uri)); /* zero it all, just to be sure*/
312
+	/*look for sip:*/
313
+	if (len<4) goto error_too_short;
314
+	if (! ( ((buf[0]|0x20)=='s')&&((buf[1]|0x20)=='i')&&((buf[2]|0x20)=='p')&&
315
+		     (buf[3]==':') ) ) goto error_bad_uri;
316
+	
317
+	s=p;
318
+	for(;p<end; p++){
319
+		switch(state){
320
+			case URI_INIT:
321
+				switch(*p){
322
+					case '[':
323
+						/* uri =  [ipv6address]... */
324
+						state=URI_HOST6_P;
325
+						s=p;
326
+						break;
327
+					case ']':
328
+						/* invalid, no uri can start with ']' */
329
+					case ':':
330
+						/* the same as above for ':' */
331
+						goto error_bad_char;
332
+					case '@': /* error no user part, or
333
+								 be forgiving and accept it ? */
334
+					default:
335
+						state=URI_USER;
336
+				}
337
+				break; 
338
+			case URI_USER:
339
+				switch(*p){
340
+					case '@':
341
+						/* found the user*/
342
+						uri->user.s=s;
343
+						uri->user.len=p-s;
344
+						state=URI_HOST;
345
+						found_user=1;
346
+						s=p+1; /* skip '@' */
347
+						break;
348
+					case ':':
349
+						/* found the user, or the host? */
350
+						uri->user.s=s;
351
+						uri->user.len=p-s;
352
+						state=URI_PASSWORD;
353
+						s=p+1; /* skip ':' */
354
+						break;
355
+					case ';':
356
+						/* this could be still the user or
357
+						 * params?*/
358
+						uri->host.s=s;
359
+						uri->host.len=p-s;
360
+						state=URI_PARAM;
361
+						s=p+1;
362
+						break;
363
+					case '?': /* still user or headers? */
364
+						uri->host.s=s;
365
+						uri->host.len=p-s;
366
+						state=URI_HEADERS;
367
+						s=p+1;
368
+						break;
369
+						/* almost anything permitted in the user part */
370
+					case '[':
371
+					case ']': /* the user part cannot contain "[]" */
372
+						goto error_bad_char;
373
+				}
374
+				break;
375
+			case URI_PASSWORD: /* this can also be the port (missing user)*/
376
+				switch(*p){
377
+					case '@':
378
+						/* found the password*/
379
+						uri->passwd.s=s;
380
+						uri->passwd.len=p-s;
381
+						port_no=0;
382
+						state=URI_HOST;
383
+						found_user=1;
384
+						s=p+1; /* skip '@' */
385
+						break;
386
+					case ';':
387
+						/* upps this is the port */
388
+						uri->port.s=s;
389
+						uri->port.len=p-s;
390
+						uri->port_no=port_no;
391
+						/* user contains in fact the host */
392
+						uri->host.s=uri->user.s;
393
+						uri->host.len=uri->user.len;
394
+						uri->user.s=0;
395
+						uri->user.len=0;
396
+						state=URI_PARAM;
397
+						found_user=1; /*  there is no user part */
398
+						s=p+1;
399
+						break;
400
+					case '?':
401
+						/* upps this is the port */
402
+						uri->port.s=s;
403
+						uri->port.len=p-s;
404
+						uri->port_no=port_no;
405
+						/* user contains in fact the host */
406
+						uri->host.s=uri->user.s;
407
+						uri->host.len=uri->user.len;
408
+						uri->user.s=0;
409
+						uri->user.len=0;
410
+						state=URI_HEADERS;
411
+						found_user=1; /*  there is no user part */
412
+						s=p+1;
413
+						break;
414
+					case_port('0', port_no);
415
+					case_port('1', port_no);
416
+					case_port('2', port_no);
417
+					case_port('3', port_no);
418
+					case_port('4', port_no);
419
+					case_port('5', port_no);
420
+					case_port('6', port_no);
421
+					case_port('7', port_no);
422
+					case_port('8', port_no);
423
+					case_port('9', port_no);
424
+					case '[':
425
+					case ']':
426
+					case ':':
427
+						goto error_bad_char;
428
+					default:
429
+						/* it can't be the port, non number found */
430
+						port_no=0;
431
+						state=URI_PASSWORD_ALPHA;
432
+				}
433
+				break;
434
+			case URI_PASSWORD_ALPHA:
435
+				switch(*p){
436
+					case '@':
437
+						/* found the password*/
438
+						uri->passwd.s=s;
439
+						uri->passwd.len=p-s;
440
+						state=URI_HOST;
441
+						found_user=1;
442
+						s=p+1; /* skip '@' */
443
+						break;
444
+					case ';': /* contains non-numbers => cannot be port no*/
445
+					case '?':
446
+						goto error_bad_port;
447
+					case '[':
448
+					case ']':
449
+					case ':':
450
+						goto error_bad_char;
451
+				}
452
+				break;
453
+			case URI_HOST:
454
+				switch(*p){
455
+					case '[':
456
+						state=URI_HOST6_P;
457
+						break;
458
+					case ':': 
459
+					case ';':
460
+					case '?': /* null host name ->invalid */
461
+					case '&':
462
+					case '@': /*chars not allowed in hosts names */
463
+						goto error_bad_host;
464
+					default:
465
+						state=URI_HOST_P;
466
+				}
467
+				break;
468
+			case URI_HOST_P:
469
+				switch(*p){
470
+					check_host_end;
471
+				}
472
+				break;
473
+			case URI_HOST6_END:
474
+				switch(*p){
475
+					check_host_end;
476
+					default: /*no chars allowed after [ipv6] */
477
+						goto error_bad_host;
478
+				}
479
+				break;
480
+			case URI_HOST6_P:
481
+				switch(*p){
482
+					case ']':
483
+						state=URI_HOST6_END;
484
+						break;
485
+					case '[':
486
+					case '&':
487
+					case '@':
488
+					case ';':
489
+					case '?':
490
+						goto error_bad_host;
491
+				}
492
+				break;
493
+			case URI_PORT:
494
+				switch(*p){
495
+					case ';':
496
+						uri->port.s=s;
497
+						uri->port.len=p-s;
498
+						uri->port_no=port_no;
499
+						state=URI_PARAM;
500
+						s=p+1;
501
+						break;
502
+					case '?':
503
+						uri->port.s=s;
504
+						uri->port.len=p-s;
505
+						uri->port_no=port_no;
506
+						state=URI_HEADERS;
507
+						s=p+1;
508
+						break;
509
+					case_port('0', port_no);
510
+					case_port('1', port_no);
511
+					case_port('2', port_no);
512
+					case_port('3', port_no);
513
+					case_port('4', port_no);
514
+					case_port('5', port_no);
515
+					case_port('6', port_no);
516
+					case_port('7', port_no);
517
+					case_port('8', port_no);
518
+					case_port('9', port_no);
519
+					case '&':
520
+					case '@':
521
+					case ':':
522
+					default:
523
+						goto error_bad_port;
524
+				}
525
+				break;
526
+			case URI_PARAM: /* beginning of a new param */
527
+				switch(*p){
528
+					param_common_cases;
529
+					/* recognized params */
530
+					case 't':
531
+					case 'T':
532
+						b=p;
533
+						state=PT_T;
534
+						break;
535
+					case 'u':
536
+					case 'U':
537
+						b=p;
538
+						state=PU_U;
539
+						break;
540
+					case 'm':
541
+					case 'M':
542
+						b=p;
543
+						state=PM_M;
544
+						break;
545
+					case 'l':
546
+					case 'L':
547
+						b=p;
548
+						state=PLR_L;
549
+						break;
550
+					default:
551
+						state=URI_PARAM_P;
552
+				}
553
+				break;
554
+			case URI_PARAM_P: /* ignore current param */
555
+				/* supported params:
556
+				 *  maddr, transport, ttl, lr, user, method  */
557
+				switch(*p){
558
+					param_common_cases;
559
+				};
560
+				break;
561
+			/* ugly but fast param names parsing */
562
+			/*transport */
563
+			param_switch_big(PT_T,  'r', 'R', 't', 'T', PT_R, PTTL_T2);
564
+			param_switch(PT_R,  'a', 'A', PT_A);
565
+			param_switch(PT_A,  'n', 'N', PT_N);
566
+			param_switch(PT_N,  's', 'S', PT_S);
567
+			param_switch(PT_S,  'p', 'P', PT_P);
568
+			param_switch(PT_P,  'o', 'O', PT_O);
569
+			param_switch(PT_O,  'r', 'R', PT_R2);
570
+			param_switch(PT_R2, 't', 'T', PT_T2);
571
+			param_switch1(PT_T2, '=',  PT_eq);
572
+			/* value parsing */
573
+			case PT_eq:
574
+				param=&uri->transport;
575
+				param_val=&uri->transport_val;
576
+				switch (*p){
577
+					param_common_cases;
578
+					case 'u':
579
+					case 'U':
580
+						v=p;
581
+						state=VU_U;
582
+						break;
583
+					case 't':
584
+					case 'T':
585
+						v=p;
586
+						state=VT_T;
587
+						break;
588
+					case 's':
589
+					case 'S':
590
+						v=p;
591
+						state=VS_S;
592
+						break;
593
+					default:
594
+						v=p;
595
+						state=URI_VAL_P;
596
+				}
597
+				break;
598
+				/* generic value */
599
+			case URI_VAL_P:
600
+				switch(*p){
601
+					value_common_cases;
602
+				}
603
+				break;
604
+			/* udp */
605
+			value_switch(VU_U,  'd', 'D', VU_D);
606
+			value_switch(VU_D,  'p', 'P', VU_P_FIN);
607
+			transport_fin(VU_P_FIN, PROTO_UDP);
608
+			/* tcp */
609
+			value_switch_big(VT_T,  'c', 'C', 'l', 'L', VT_C, VTLS_L);
610
+			value_switch(VT_C,  'p', 'P', VT_P_FIN);
611
+			transport_fin(VT_P_FIN, PROTO_TCP);
612
+			/* tls */
613
+			value_switch(VTLS_L, 's', 'S', VTLS_S_FIN);
614
+			transport_fin(VTLS_S_FIN, PROTO_TLS);
615
+			/* sctp */
616
+			value_switch(VS_S, 'c', 'C', VS_C);
617
+			value_switch(VS_C, 't', 'T', VS_T);
618
+			value_switch(VS_T, 'p', 'P', VS_P_FIN);
619
+			transport_fin(VS_P_FIN, PROTO_SCTP);
620
+			
621
+			/* ttl */
622
+			param_switch(PTTL_T2,  'l', 'L', PTTL_L);
623
+			param_switch1(PTTL_L,  '=', PTTL_eq);
624
+			case PTTL_eq:
625
+				param=&uri->ttl;
626
+				param_val=&uri->ttl_val;
627
+				switch(*p){
628
+					param_common_cases;
629
+					default:
630
+						v=p;
631
+						state=URI_VAL_P;
632
+				}
633
+				break;
634
+			
635
+			/* user param */
636
+			param_switch(PU_U, 's', 'S', PU_S);
637
+			param_switch(PU_S, 'e', 'E', PU_E);
638
+			param_switch(PU_E, 'r', 'R', PU_R);
639
+			param_switch1(PU_R, '=', PU_eq);
640
+			case PU_eq:
641
+				param=&uri->user_param;
642
+				param_val=&uri->user_param_val;
643
+				switch(*p){
644
+					param_common_cases;
645
+					default:
646
+						v=p;
647
+						state=URI_VAL_P;
648
+				}
649
+				break;
650
+			
651
+			/* method*/
652
+			param_switch_big(PM_M, 'e', 'E', 'a', 'A', PM_E, PMA_A);
653
+			param_switch(PM_E, 't', 'T', PM_T);
654
+			param_switch(PM_T, 'h', 'H', PM_H);
655
+			param_switch(PM_H, 'o', 'O', PM_O);
656
+			param_switch(PM_O, 'd', 'D', PM_D);
657
+			param_switch1(PM_D, '=', PM_eq);
658
+			case PM_eq:
659
+				param=&uri->method;
660
+				param_val=&uri->method_val;
661
+				switch(*p){
662
+					param_common_cases;
663
+					default:
664
+						v=p;
665
+						state=URI_VAL_P;
666
+				}
667
+				break;
668
+
669
+			/*maddr*/
670
+			param_switch(PMA_A,  'd', 'D', PMA_D);
671
+			param_switch(PMA_D,  'd', 'D', PMA_D2);
672
+			param_switch(PMA_D2, 'r', 'R', PMA_R);
673
+			param_switch1(PMA_R, '=', PMA_eq);
674
+			case PMA_eq:
675
+				param=&uri->maddr;
676
+				param_val=&uri->maddr_val;
677
+				switch(*p){
678
+					param_common_cases;
679
+					default:
680
+						v=p;
681
+						state=URI_VAL_P;
682
+				}
683
+				break;
684
+			
685
+			/* lr */
686
+			param_switch(PLR_L,  'r', 'R', PLR_R_FIN);
687
+			case PLR_R_FIN:
688
+				switch(*p){
689
+					case '@':
690
+						still_at_user; 
691
+						break;
692
+					semicolon_case; 
693
+						uri->lr.s=b;
694
+						uri->lr.len=(p-b);
695
+						break;
696
+					question_case; 
697
+						uri->lr.s=b;
698
+						uri->lr.len=(p-b);
699
+						break;
700
+					colon_case;
701
+						break;
702
+					default:
703
+						state=URI_PARAM_P;
704
+				}
705
+				break;
706
+						
707
+				
708
+				
709
+			case URI_HEADERS:
710
+				/* for now nobody needs them so we completely ignore the 
711
+				 * headers (they are not allowed in request uri) --andrei */
712
+				switch(*p){
713
+					case '@':
714
+						/* yak, we are still at user */
715
+						still_at_user;
716
+						break;
717
+					case ';':
718
+						/* we might be still parsing user, try it */
719
+						if (found_user) goto error_bad_char;
720
+						error_headers=1; /* if this is not the user
721
+											we have an error */
722
+						/* if pass is set => it cannot be user:pass
723
+						 * => error (';') is illegal in a header */
724
+						if (pass) goto error_headers;
725
+						break;
726
+					case ':':
727
+						if (found_user==0){
728
+							/*might be pass but only if user not found yet*/
729
+							if (pass){
730
+								found_user=1; /* no user */
731
+								pass=0;
732
+							}else{
733
+								pass=p;
734
+							}
735
+						}
736
+						break;
737
+					case '?':
738
+						if (pass){
739
+							found_user=1; /* no user, pass cannot conaint '?'*/
740
+							pass=0;
741
+						}
742
+						break;
743
+				}
744
+				break;
745
+			default:
746
+				goto error_bug;
747
+		}
748
+	}
749
+	/*end of uri */
750
+	switch (state){
751
+		case URI_INIT: /* error empy uri */
752
+			goto error_too_short;
753
+		case URI_USER:
754
+			/* this is the host, it can't be the user */
755
+			if (found_user) goto error_bad_uri;
756
+			uri->host.s=s;
757
+			uri->host.len=p-s;
758
+			state=URI_HOST;
759
+			break;
760
+		case URI_PASSWORD:
761
+			/* this is the port, it can't be the passwd */
762
+			if (found_user) goto error_bad_port;
763
+			uri->port.s=s;
764
+			uri->port.len=p-s;
765
+			uri->port_no=port_no;
766
+			uri->host=uri->user;
767
+			uri->user.s=0;
768
+			uri->user.len=0;
769
+			break;
770
+		case URI_PASSWORD_ALPHA:
771
+			/* this is the port, it can't be the passwd */
772
+			goto error_bad_port;
773
+		case URI_HOST_P:
774
+		case URI_HOST6_END:
775
+			uri->host.s=s;
776
+			uri->host.len=p-s;
777
+			break;
778
+		case URI_HOST: /* error: null host */
779
+		case URI_HOST6_P: /* error: unterminated ipv6 reference*/
780
+			goto error_bad_host;
781
+		case URI_PORT:
782
+			uri->port.s=s;
783
+			uri->port.len=p-s;
784
+			uri->port_no=port_no;
785
+			break;
786
+		case URI_PARAM:
787
+		case URI_PARAM_P:
788
+		/* intermediate param states */
789
+		case PT_T: /* transport */
790
+		case PT_R:
791
+		case PT_A:
792
+		case PT_N:
793
+		case PT_S:
794
+		case PT_P:
795
+		case PT_O:
796
+		case PT_R2:
797
+		case PT_T2:
798
+		case PT_eq: /* ignore empty transport params */
799
+		case PTTL_T2: /* ttl */
800
+		case PTTL_L:
801
+		case PTTL_eq:
802
+		case PU_U:  /* user */
803
+		case PU_S:
804
+		case PU_E:
805
+		case PU_R:
806
+		case PU_eq:
807
+		case PM_M: /* method */
808
+		case PM_E:
809
+		case PM_T:
810
+		case PM_H:
811
+		case PM_O:
812
+		case PM_D:
813
+		case PM_eq:
814
+		case PLR_L: /* lr */
815
+			uri->params.s=s;
816
+			uri->params.len=p-s;
817
+			break;
818
+		/* fin param states */
819
+		case PLR_R_FIN:
820
+			uri->params.s=s;
821
+			uri->params.len=p-s;
822
+			uri->lr.s=b;
823
+			uri->lr.len=p-b;
824
+			break;
825
+		case URI_VAL_P:
826
+		/* intermediate value states */
827
+		case VU_U:
828
+		case VU_D:
829
+		case VT_T:
830
+		case VT_C:
831
+		case VTLS_L:
832
+		case VS_S:
833
+		case VS_C:
834
+		case VS_T:
835
+			uri->params.s=s;
836
+			uri->params.len=p-s;
837
+			param_set(b, v);
838
+			break;
839
+		/* fin value states */
840
+		case VU_P_FIN:
841
+			uri->params.s=s;
842
+			uri->params.len=p-s;
843
+			param_set(b, v);
844
+			uri->proto=PROTO_UDP;
845
+			break;
846
+		case VT_P_FIN:
847
+			uri->params.s=s;
848
+			uri->params.len=p-s;
849
+			param_set(b, v);
850
+			uri->proto=PROTO_TCP;
851
+			break;
852
+		case VTLS_S_FIN:
853
+			uri->params.s=s;
854
+			uri->params.len=p-s;
855
+			param_set(b, v);
856
+			uri->proto=PROTO_TLS;
857
+			break;
858
+		case VS_P_FIN:
859
+			uri->params.s=s;
860
+			uri->params.len=p-s;
861
+			param_set(b, v);
862
+			uri->proto=PROTO_SCTP;
863
+			break;
864
+		/* headers */
865
+		case URI_HEADERS:
866
+			uri->headers.s=s;
867
+			uri->headers.len=p-s;
868
+			if (error_headers) goto error_headers;
869
+			break;
870
+		default:
871
+			goto error_bug;
872
+	}
873
+	
874
+	/* do stuff */
875
+	DBG("parsed uri:\n user=<%.*s>(%d)\n passwd=<%.*s>(%d)\n host=<%.*s>(%d)\n"
876
+			" port=<%.*s>(%d): %d\n params=<%.*s>(%d)\n headers=<%.*s>(%d)\n",
877
+			uri->user.len, uri->user.s, uri->user.len,
878
+			uri->passwd.len, uri->passwd.s, uri->passwd.len,
879
+			uri->host.len, uri->host.s, uri->host.len,
880
+			uri->port.len, uri->port.s, uri->port.len, uri->port_no,
881
+			uri->params.len, uri->params.s, uri->params.len,
882
+			uri->headers.len, uri->headers.s, uri->headers.len
883
+		);
884
+	DBG(" uri params:\n   transport=<%.*s>, val=<%.*s>, proto=%d\n",
885
+			uri->transport.len, uri->transport.s, uri->transport_val.len,
886
+			uri->transport_val.s, uri->proto);
887
+	DBG("   user-param=<%.*s>, val=<%.*s>\n",
888
+			uri->user_param.len, uri->user_param.s, uri->user_param_val.len,
889
+			uri->user_param_val.s);
890
+	DBG("   method=<%.*s>, val=<%.*s>\n",
891
+			uri->method.len, uri->method.s, uri->method_val.len,
892
+			uri->method_val.s);
893
+	DBG("   ttl=<%.*s>, val=<%.*s>\n",
894
+			uri->ttl.len, uri->ttl.s, uri->ttl_val.len,
895
+			uri->ttl_val.s);
896
+	DBG("   maddr=<%.*s>, val=<%.*s>\n",
897
+			uri->maddr.len, uri->maddr.s, uri->maddr_val.len,
898
+			uri->maddr_val.s);
899
+	DBG("   lr=<%.*s>\n", uri->lr.len, uri->lr.s); 
900
+	return 0;
901
+	
902
+error_too_short:
903
+	LOG(L_ERR, "ERROR: parse_uri: uri too short: <%.*s> (%d)\n",
904
+			len, buf, len);
905
+	return -1;
906
+error_bad_char:
907
+	LOG(L_ERR, "ERROR: parse_uri: bad char '%c' in state %d"
908
+			" parsed: <%.*s> (%d) / <%.*s> (%d)\n",
909
+			*p, state, (p-buf), buf, (p-buf), len, buf, len);
910
+	return -1;
911
+error_bad_host:
912
+	LOG(L_ERR, "ERROR: parse_uri: bad host in uri (error at char %c in"
913
+			" state %d) parsed: <%.*s>(%d) /<%.*s> (%d)\n",
914
+			*p, state, (p-buf), buf, (p-buf), len, buf, len);
915
+	return -1;
916
+error_bad_port:
917
+	LOG(L_ERR, "ERROR: parse_uri: bad port in uri (error at char %c in"
918
+			" state %d) parsed: <%.*s>(%d) /<%.*s> (%d)\n",
919
+			*p, state, (p-buf), buf, (p-buf), len, buf, len);
920
+	return -1;
921
+error_bad_uri:
922
+	LOG(L_ERR, "ERROR: parse_uri: bad uri,  state %d"
923
+			" parsed: <%.*s> (%d) / <%.*s> (%d)\n",
924
+			 state, (p-buf), buf, (p-buf), len, buf, len);
925
+	return -1;
926
+error_headers:
927
+	LOG(L_ERR, "ERROR: parse_uri: bad uri headers: <%.*s>(%d)"
928
+			" / <%.*s>(%d)\n",
929
+			uri->headers.len, uri->headers.s, uri->headers.len,
930
+			len, buf, len);
931
+	return -1;
932
+error_bug:
933
+	LOG(L_CRIT, "BUG: parse_uri: bad  state %d"
934
+			" parsed: <%.*s> (%d) / <%.*s> (%d)\n",
935
+			 state, (p-buf), buf, (p-buf), len, buf, len);
936
+	return -1;
937
+}
938
+
939
+#else /* PARSE_URI_OLD */
940
+
44 941
 int parse_uri(char *buf, int len, struct sip_uri* uri)
45 942
 {
46 943
 	char* next, *end;
... ...
@@ -176,6 +1073,9 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
176 176
 
177 177
 	return ret;
178 178
 }
179
+#endif
180
+
181
+
179 182
 
180 183
 
181 184
 static inline int _parse_ruri(str *uri,
... ...
@@ -6,6 +6,8 @@
6 6
 #define DBG printf
7 7
 #define LOG(lev, fmt, args...) printf(fmt, ## args)
8 8
 
9
+enum {PROTO_NONE, PROTO_UDP, PROTO_TCP, PROTO_TLS, PROTO_SCTP };
10
+
9 11
 struct sip_uri {
10 12
 	str user;     /* Username */
11 13
 	str passwd;   /* Password */
... ...
@@ -14,48 +16,95 @@ struct sip_uri {
14 14
 	str params;   /* Parameters */
15 15
 	str headers;  
16 16
 	unsigned short port_no;
17
+	unsigned short proto; /* from transport */
18
+	/* parameters */
19
+	str transport;
20
+	str ttl;
21
+	str user_param;
22
+	str maddr;
23
+	str method;
24
+	str lr;
25
+	/* values */
26
+	str transport_val;
27
+	str ttl_val;
28
+	str user_param_val;
29
+	str maddr_val;
30
+	str method_val;
17 31
 };
18 32
 
19 33
 
20 34
 
21 35
 int parse_uri(char* buf, int len, struct sip_uri* uri)
22 36
 {
23
-	enum states  {	URI_INIT, URI_USER, URI_PASSWORD, URI_HOST, URI_HOST_P,
24
-					URI_HOST6_P, URI_HOST6_END, URI_PORT,
25
-					URI_PARAM, URI_HEADERS };
37
+	enum states  {	URI_INIT, URI_USER, URI_PASSWORD, URI_PASSWORD_ALPHA,
38
+					URI_HOST, URI_HOST_P,
39
+					URI_HOST6_P, URI_HOST6_END, URI_PORT, 
40
+					URI_PARAM, URI_PARAM_P, URI_VAL_P, URI_HEADERS,
41
+					/* param states */
42
+					/* transport */
43
+					PT_T, PT_R, PT_A, PT_N, PT_S, PT_P, PT_O, PT_R2, PT_T2,
44
+					PT_eq,
45
+					/* ttl */
46
+					      PTTL_T2, PTTL_L, PTTL_eq,
47
+					/* user */
48
+					PU_U, PU_S, PU_E, PU_R, PU_eq,
49
+					/* method */
50
+					PM_M, PM_E, PM_T, PM_H, PM_O, PM_D, PM_eq,
51
+					/* maddr */
52
+					      PMA_A, PMA_D, PMA_D2, PMA_R, PMA_eq,
53
+					/* lr */
54
+					PLR_L, PLR_R_FIN,
55
+					/* transport values */
56
+					/* udp */
57
+					VU_U, VU_D, VU_P_FIN,
58
+					/* tcp */
59
+					VT_T, VT_C, VT_P_FIN,
60
+					/* tls */
61
+					      VTLS_L, VTLS_S_FIN,
62
+					/* sctp */
63
+					VS_S, VS_C, VS_T, VS_P_FIN
64
+	};
26 65
 	enum states state;
27 66
 	char* s;
67
+	char* b; /* param start */
68
+	char *v; /* value start */
69
+	str* param; /* current param */
70
+	str* param_val; /* current param val */
71
+	str user;
72
+	str password;
73
+	int port_no;
28 74
 	char* p;
29 75
 	char* end;
30 76
 	char* pass;
31 77
 	int found_user;
32 78
 	int error_headers;
33 79
 	
80
+#define case_port( ch, var) \
81
+	case ch: \
82
+			 (var)=(var)*10+ch-'0'; \
83
+			 break
84
+			 
34 85
 #define still_at_user  \
35 86
 						if (found_user==0){ \
36
-							uri->user.s=uri->host.s; \
87
+							user.s=uri->host.s; \
37 88
 							if (pass){\
38
-								uri->user.len=pass-uri->user.s; \
39
-								uri->passwd.s=pass+1; \
40
-								uri->passwd.len=p-uri->passwd.s; \
41
-								pass=0; \
89
+								user.len=pass-user.s; \
90
+								password.s=pass+1; \
91
+								password.len=p-password.s; \
42 92
 							}else{ \
43
-								uri->user.len=p-uri->user.s; \
93
+								user.len=p-user.s; \
44 94
 							}\
45 95
 							/* everything else is 0 */ \
46
-							uri->host.len=0; \
47
-							uri->port.s=0; \
48
-							uri->port.len=0; \
49
-							uri->params.s=0; \
50
-							uri->params.len=0; \
51
-							uri->headers.s=0; \
52
-							uri->headers.len=0; \
53
-							/* more zeroing */ \
96
+							memset(uri, 0, sizeof(struct sip_uri)); \
97
+							/* copy user & pass */ \
98
+							uri->user=user; \
99
+							if (pass)	uri->passwd=password;  \
54 100
 							s=p+1; \
55 101
 							found_user=1;\
56 102
 							error_headers=0; \
57 103
 							state=URI_HOST; \
58 104
 						}else goto error_bad_char 
105
+
59 106
 #define check_host_end \
60 107
 					case ':': \
61 108
 						/* found the host */ \
... ...
@@ -79,12 +128,173 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
79 79
 					case '&': \
80 80
 					case '@': \
81 81
 						goto error_bad_char 
82
+
83
+
84
+#define param_set(t_start, v_start) \
85
+					param->s=(t_start);\
86
+					param->len=(p-(t_start));\
87
+					param_val->s=(v_start); \
88
+					param_val->len=(p-(v_start)) 
89
+
90
+#define semicolon_case \
91
+					case';': \
92
+						if (pass){ \
93
+							found_user=1;/* no user, pass cannot contain ';'*/ \
94
+							pass=0; \
95
+						} \
96
+						state=URI_PARAM   /* new param */ 
97
+
98
+#define question_case \
99
+					case '?': \
100
+						uri->params.s=s; \
101
+						uri->params.len=p-s; \
102
+						state=URI_HEADERS; \
103
+						s=p+1; \
104
+						if (pass){ \
105
+							found_user=1;/* no user, pass cannot contain '?'*/ \
106
+							pass=0; \
107
+						}
108
+
109
+#define colon_case \
110
+					case ':': \
111
+						if (found_user==0){ \
112
+							/*might be pass but only if user not found yet*/ \
113
+							if (pass){ \
114
+								found_user=1; /* no user */ \
115
+								pass=0; \
116
+							}else{ \
117
+								pass=p; \
118
+							} \
119
+						} \
120
+						state=URI_PARAM_P /* generic param */
121
+
122
+#define param_common_cases \
123
+					case '@': \
124
+						/* ughhh, this is still the user */ \
125
+						still_at_user; \
126
+						break; \
127
+					semicolon_case; \
128
+						break; \
129
+					question_case; \
130
+						break; \
131
+					colon_case; \
132
+						break
133
+
134
+#define value_common_cases \
135
+					case '@': \
136
+						/* ughhh, this is still the user */ \
137
+						still_at_user; \
138
+						break; \
139
+					semicolon_case; \
140
+						param_set(b, v); \
141
+						break; \
142
+					question_case; \
143
+						param_set(b, v); \
144
+						break; \
145
+					colon_case; \
146
+						state=URI_VAL_P; \
147
+						break
148
+
149
+#define param_switch(old_state, c1, c2, new_state) \
150
+			case old_state: \
151
+				switch(*p){ \
152
+					case c1: \
153
+					case c2: \
154
+						state=(new_state); \
155
+						break; \
156
+					param_common_cases; \
157
+					default: \
158
+						state=URI_PARAM_P; \
159
+				} \
160
+				break
161
+#define param_switch1(old_state, c1, new_state) \
162
+			case old_state: \
163
+				switch(*p){ \
164
+					case c1: \
165
+						state=(new_state); \
166
+						break; \
167
+					param_common_cases; \
168
+					default: \
169
+						state=URI_PARAM_P; \
170
+				} \
171
+				break
172
+#define param_switch_big(old_state, c1, c2, d1, d2, new_state_c, new_state_d) \
173
+			case old_state : \
174
+				switch(*p){ \
175
+					case c1: \
176
+					case c2: \
177
+						state=(new_state_c); \
178
+						break; \
179
+					case d1: \
180
+					case d2: \
181
+						state=(new_state_d); \
182
+						break; \
183
+					param_common_cases; \
184
+					default: \
185
+						state=URI_PARAM_P; \
186
+				} \
187
+				break
188
+#define value_switch(old_state, c1, c2, new_state) \
189
+			case old_state: \
190
+				switch(*p){ \
191
+					case c1: \
192
+					case c2: \
193
+						state=(new_state); \
194
+						break; \
195
+					value_common_cases; \
196
+					default: \
197
+						state=URI_VAL_P; \
198
+				} \
199
+				break
200
+#define value_switch_big(old_state, c1, c2, d1, d2, new_state_c, new_state_d) \
201
+			case old_state: \
202
+				switch(*p){ \
203
+					case c1: \
204
+					case c2: \
205
+						state=(new_state_c); \
206
+						break; \
207
+					case d1: \
208
+					case d2: \
209
+						state=(new_state_d); \
210
+						break; \
211
+					value_common_cases; \
212
+					default: \
213
+						state=URI_VAL_P; \
214
+				} \
215
+				break
216
+
217
+#define transport_fin(c_state, proto_no) \
218
+			case c_state: \
219
+				switch(*p){ \
220
+					case '@': \
221
+						still_at_user; \
222
+						break; \