... | ... |
@@ -23,7 +23,13 @@ NAME=ser |
23 | 23 |
# recommanded: on (speed-up) |
24 | 24 |
# STATS allows to print out number of packets processed on CTRL-C; |
25 | 25 |
# implementation still nasty and reports per-process |
26 |
-DEFS=-DNOCR -DMACROEATER -DSTATS #-DNO_DEBUG #-DNO_LOG |
|
26 |
+# NO_DEBUG turns off some of the debug messages (DBG(...)). |
|
27 |
+# NO_LOG completely turns of all the logging (and DBG(...)) |
|
28 |
+# DEBUG compiles in some extra debugging code |
|
29 |
+# OLD_PARSER uses the old and stable parser (from ser 8.3.2) |
|
30 |
+DEFS=-DNOCR -DMACROEATER -DSTATS -DOLD_PARSER #-DNO_DEBUG #-DNO_LOG |
|
31 |
+ |
|
32 |
+PROFILE= # -pg #set this if you want profiling |
|
27 | 33 |
|
28 | 34 |
# platform dependent settings |
29 | 35 |
|
... | ... |
@@ -32,8 +38,8 @@ ARCH = $(shell uname -s) |
32 | 38 |
#common |
33 | 39 |
CC=gcc |
34 | 40 |
LD=gcc |
35 |
-CFLAGS=-O3 -Wcast-align #-Wmissing-prototypes |
|
36 |
-LDFLAGS=-Wl,-O2 -Wl,-E |
|
41 |
+CFLAGS=-O2 -Wcast-align $(PROFILE)#-Wmissing-prototypes |
|
42 |
+LDFLAGS=-Wl,-O2 -Wl,-E $(PROFILE) |
|
37 | 43 |
LEX=flex |
38 | 44 |
YACC=bison |
39 | 45 |
YACC_FLAGS=-d -b cfg |
... | ... |
@@ -49,7 +55,7 @@ ifeq ($(ARCH), SunOS) |
49 | 55 |
|
50 | 56 |
MAKE=gmake |
51 | 57 |
YACC=yacc |
52 |
-LDFLAGS=-O2 |
|
58 |
+LDFLAGS=-O2 $(PROFILE) |
|
53 | 59 |
LIBS+=-L/usr/local/lib -lxnet # or -lnsl -lsocket or -lglibc ? |
54 | 60 |
|
55 | 61 |
endif |
... | ... |
@@ -51,9 +51,14 @@ int do_action(struct action* a, struct sip_msg* msg) |
51 | 51 |
case FORWARD_T: |
52 | 52 |
if (a->p1_type==URIHOST_ST){ |
53 | 53 |
/*parse uri*/ |
54 |
- tmp=(msg->new_uri)?msg->new_uri: |
|
55 |
- msg->first_line.u.request.uri; |
|
56 |
- if (parse_uri(tmp, strlen(tmp), &uri)<0){ |
|
54 |
+ if (msg->new_uri.s){ |
|
55 |
+ tmp=msg->new_uri.s; |
|
56 |
+ len=msg->new_uri.len; |
|
57 |
+ }else{ |
|
58 |
+ tmp=msg->first_line.u.request.uri.s; |
|
59 |
+ len=msg->first_line.u.request.uri.len; |
|
60 |
+ } |
|
61 |
+ if (parse_uri(tmp, len, &uri)<0){ |
|
57 | 62 |
LOG(L_ERR, "ERROR: do_action: forward: bad_uri <%s>," |
58 | 63 |
" dropping packet\n",tmp); |
59 | 64 |
ret=E_UNSPEC; |
... | ... |
@@ -61,8 +66,8 @@ int do_action(struct action* a, struct sip_msg* msg) |
61 | 66 |
} |
62 | 67 |
switch (a->p2_type){ |
63 | 68 |
case URIPORT_ST: |
64 |
- if (uri.port){ |
|
65 |
- port=strtol(uri.port,&end,10); |
|
69 |
+ if (uri.port.s){ |
|
70 |
+ port=strtol(uri.port.s,&end,10); |
|
66 | 71 |
if ((end)&&(*end)){ |
67 | 72 |
LOG(L_ERR, "ERROR: do_action: " |
68 | 73 |
"forward: bad port in " |
... | ... |
@@ -83,7 +88,7 @@ int do_action(struct action* a, struct sip_msg* msg) |
83 | 88 |
goto skip; |
84 | 89 |
} |
85 | 90 |
/* create a temporary proxy*/ |
86 |
- p=mk_proxy(uri.host, port); |
|
91 |
+ p=mk_proxy(uri.host.s, port); |
|
87 | 92 |
ret=forward_request(msg, p); |
88 | 93 |
free_uri(&uri); |
89 | 94 |
free_proxy(p); /* frees only p content, not p itself */ |
... | ... |
@@ -201,23 +206,33 @@ int do_action(struct action* a, struct sip_msg* msg) |
201 | 206 |
break; |
202 | 207 |
} |
203 | 208 |
if (a->type==SET_URI_T){ |
204 |
- if (msg->new_uri) free(msg->new_uri); |
|
209 |
+ if (msg->new_uri.s) { |
|
210 |
+ free(msg->new_uri.s); |
|
211 |
+ msg->new_uri.len=0; |
|
212 |
+ } |
|
205 | 213 |
len=strlen(a->p1.string); |
206 |
- msg->new_uri=malloc(len+1); |
|
207 |
- if (msg->new_uri==0){ |
|
214 |
+ msg->new_uri.s=malloc(len+1); |
|
215 |
+ if (msg->new_uri.s==0){ |
|
208 | 216 |
LOG(L_ERR, "ERROR: do_action: memory allocation" |
209 | 217 |
" failure\n"); |
210 | 218 |
ret=E_OUT_OF_MEM; |
211 | 219 |
break; |
212 | 220 |
} |
213 |
- memcpy(msg->new_uri, a->p1.string, len); |
|
214 |
- msg->new_uri[len]=0; |
|
221 |
+ memcpy(msg->new_uri.s, a->p1.string, len); |
|
222 |
+ msg->new_uri.s[len]=0; |
|
223 |
+ msg->new_uri.len=len; |
|
224 |
+ |
|
215 | 225 |
ret=1; |
216 | 226 |
break; |
217 | 227 |
} |
218 |
- if (msg->new_uri) tmp=msg->new_uri; |
|
219 |
- else tmp=msg->first_line.u.request.uri; |
|
220 |
- if (parse_uri(tmp, strlen(tmp), &uri)<0){ |
|
228 |
+ if (msg->new_uri.s) { |
|
229 |
+ tmp=msg->new_uri.s; |
|
230 |
+ len=msg->new_uri.len; |
|
231 |
+ }else{ |
|
232 |
+ tmp=msg->first_line.u.request.uri.s; |
|
233 |
+ len=msg->first_line.u.request.uri.len; |
|
234 |
+ } |
|
235 |
+ if (parse_uri(tmp, len, &uri)<0){ |
|
221 | 236 |
LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping" |
222 | 237 |
" packet\n", tmp); |
223 | 238 |
ret=E_UNSPEC; |
... | ... |
@@ -241,14 +256,14 @@ int do_action(struct action* a, struct sip_msg* msg) |
241 | 256 |
if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) |
242 | 257 |
tmp=a->p1.string; |
243 | 258 |
else |
244 |
- tmp=uri.user; |
|
259 |
+ tmp=uri.user.s; |
|
245 | 260 |
if (tmp){ |
246 | 261 |
len=strlen(tmp); if(crt+len>end) goto error_uri; |
247 | 262 |
memcpy(crt,tmp,len);crt+=len; |
248 | 263 |
user=1; /* we have an user field so mark it */ |
249 | 264 |
} |
250 | 265 |
if (a->type==SET_USERPASS_T) tmp=0; |
251 |
- else tmp=uri.passwd; |
|
266 |
+ else tmp=uri.passwd.s; |
|
252 | 267 |
/* passwd */ |
253 | 268 |
if (tmp){ |
254 | 269 |
len=strlen(":"); if(crt+len>end) goto error_uri; |
... | ... |
@@ -264,7 +279,7 @@ int do_action(struct action* a, struct sip_msg* msg) |
264 | 279 |
if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T)) |
265 | 280 |
tmp=a->p1.string; |
266 | 281 |
else |
267 |
- tmp=uri.host; |
|
282 |
+ tmp=uri.host.s; |
|
268 | 283 |
if (tmp){ |
269 | 284 |
len=strlen(tmp); if(crt+len>end) goto error_uri; |
270 | 285 |
memcpy(crt,tmp,len);crt+=len; |
... | ... |
@@ -272,7 +287,7 @@ int do_action(struct action* a, struct sip_msg* msg) |
272 | 287 |
/* port */ |
273 | 288 |
if (a->type==SET_HOSTPORT_T) tmp=0; |
274 | 289 |
else if (a->type==SET_PORT_T) tmp=a->p1.string; |
275 |
- else tmp=uri.port; |
|
290 |
+ else tmp=uri.port.s; |
|
276 | 291 |
if (tmp){ |
277 | 292 |
len=strlen(":"); if(crt+len>end) goto error_uri; |
278 | 293 |
memcpy(crt,":",len);crt+=len; |
... | ... |
@@ -280,7 +295,7 @@ int do_action(struct action* a, struct sip_msg* msg) |
280 | 295 |
memcpy(crt,tmp,len);crt+=len; |
281 | 296 |
} |
282 | 297 |
/* params */ |
283 |
- tmp=uri.params; |
|
298 |
+ tmp=uri.params.s; |
|
284 | 299 |
if (tmp){ |
285 | 300 |
len=strlen(";"); if(crt+len>end) goto error_uri; |
286 | 301 |
memcpy(crt,";",len);crt+=len; |
... | ... |
@@ -288,7 +303,7 @@ int do_action(struct action* a, struct sip_msg* msg) |
288 | 303 |
memcpy(crt,tmp,len);crt+=len; |
289 | 304 |
} |
290 | 305 |
/* headers */ |
291 |
- tmp=uri.headers; |
|
306 |
+ tmp=uri.headers.s; |
|
292 | 307 |
if (tmp){ |
293 | 308 |
len=strlen("?"); if(crt+len>end) goto error_uri; |
294 | 309 |
memcpy(crt,"?",len);crt+=len; |
... | ... |
@@ -297,8 +312,9 @@ int do_action(struct action* a, struct sip_msg* msg) |
297 | 312 |
} |
298 | 313 |
*crt=0; /* null terminate the thing */ |
299 | 314 |
/* copy it to the msg */ |
300 |
- if (msg->new_uri) free(msg->new_uri); |
|
301 |
- msg->new_uri=new_uri; |
|
315 |
+ if (msg->new_uri.s) free(msg->new_uri.s); |
|
316 |
+ msg->new_uri.s=new_uri; |
|
317 |
+ msg->new_uri.len=crt-new_uri; |
|
302 | 318 |
free_uri(&uri); |
303 | 319 |
ret=1; |
304 | 320 |
break; |
... | ... |
@@ -191,7 +191,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p) |
191 | 191 |
|
192 | 192 |
|
193 | 193 |
/* check if received needs to be added */ |
194 |
- if (check_address(source_ip, msg->via1.host, received_dns)!=0){ |
|
194 |
+ if (check_address(source_ip, msg->via1.host.s, received_dns)!=0){ |
|
195 | 195 |
received_buf=malloc(sizeof(char)*MAX_RECEIVED_SIZE); |
196 | 196 |
if (received_buf==0){ |
197 | 197 |
LOG(L_ERR, "ERROR: forward_request: out of memory\n"); |
... | ... |
@@ -213,21 +213,22 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p) |
213 | 213 |
/* add via header to the list */ |
214 | 214 |
/* try to add it before msg. 1st via */ |
215 | 215 |
/*add first via, as an anchor for second via*/ |
216 |
- anchor=anchor_lump(&(msg->add_rm), msg->via1.hdr-buf, 0, HDR_VIA); |
|
216 |
+ anchor=anchor_lump(&(msg->add_rm), msg->via1.hdr.s-buf, 0, HDR_VIA); |
|
217 | 217 |
if (anchor==0) goto error; |
218 | 218 |
if (insert_new_lump_before(anchor, line_buf, via_len, HDR_VIA)==0) |
219 | 219 |
goto error; |
220 | 220 |
/* if received needs to be added, add anchor after host and add it */ |
221 | 221 |
if (received_len){ |
222 |
- if (msg->via1.params){ |
|
223 |
- size= msg->via1.params-msg->via1.hdr-1; /*compensate for ';' */ |
|
222 |
+ if (msg->via1.params.s){ |
|
223 |
+ size= msg->via1.params.s-msg->via1.hdr.s-1; /*compensate |
|
224 |
+ for ';' */ |
|
224 | 225 |
}else{ |
225 |
- size= msg->via1.host-msg->via1.hdr+strlen(msg->via1.host); |
|
226 |
+ size= msg->via1.host.s-msg->via1.hdr.s+msg->via1.host.len; |
|
226 | 227 |
if (msg->via1.port!=0){ |
227 |
- size+=strlen(msg->via1.hdr+size+1)+1; /* +1 for ':'*/ |
|
228 |
+ size+=strlen(msg->via1.hdr.s+size+1)+1; /* +1 for ':'*/ |
|
228 | 229 |
} |
229 | 230 |
} |
230 |
- anchor=anchor_lump(&(msg->add_rm), msg->via1.hdr-buf+size, 0, HDR_VIA); |
|
231 |
+ anchor=anchor_lump(&(msg->add_rm),msg->via1.hdr.s-buf+size,0, HDR_VIA); |
|
231 | 232 |
if (anchor==0) goto error; |
232 | 233 |
if (insert_new_lump_after(anchor, received_buf, received_len, HDR_VIA) |
233 | 234 |
==0 ) goto error; |
... | ... |
@@ -291,9 +292,9 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p) |
291 | 292 |
} |
292 | 293 |
|
293 | 294 |
|
294 |
- if (msg->new_uri){ |
|
295 |
- uri_len=strlen(msg->new_uri); |
|
296 |
- new_len=new_len-strlen(msg->first_line.u.request.uri)+uri_len; |
|
295 |
+ if (msg->new_uri.s){ |
|
296 |
+ uri_len=msg->new_uri.len; |
|
297 |
+ new_len=new_len-msg->first_line.u.request.uri.len+uri_len; |
|
297 | 298 |
} |
298 | 299 |
new_buf=(char*)malloc(new_len+1); |
299 | 300 |
if (new_buf==0){ |
... | ... |
@@ -302,16 +303,16 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p) |
302 | 303 |
} |
303 | 304 |
|
304 | 305 |
offset=s_offset=0; |
305 |
- if (msg->new_uri){ |
|
306 |
+ if (msg->new_uri.s){ |
|
306 | 307 |
/* copy message up to uri */ |
307 |
- size=msg->first_line.u.request.uri-buf; |
|
308 |
+ size=msg->first_line.u.request.uri.s-buf; |
|
308 | 309 |
memcpy(new_buf, orig, size); |
309 | 310 |
offset+=size; |
310 | 311 |
s_offset+=size; |
311 | 312 |
/* add our uri */ |
312 |
- memcpy(new_buf+offset, msg->new_uri, uri_len); |
|
313 |
+ memcpy(new_buf+offset, msg->new_uri.s, uri_len); |
|
313 | 314 |
offset+=uri_len; |
314 |
- s_offset+=strlen(msg->first_line.u.request.uri); /* skip original uri */ |
|
315 |
+ s_offset+=msg->first_line.u.request.uri.len; /* skip original uri */ |
|
315 | 316 |
} |
316 | 317 |
/* copy msg adding/removing lumps */ |
317 | 318 |
for (t=msg->add_rm;t;t=t->next){ |
... | ... |
@@ -487,23 +488,23 @@ int forward_reply(struct sip_msg* msg) |
487 | 488 |
/*check if first via host = us */ |
488 | 489 |
if (check_via){ |
489 | 490 |
for (r=0; r<addresses_no; r++) |
490 |
- if(strcmp(msg->via1.host, names[r])==0) break; |
|
491 |
+ if(strcmp(msg->via1.host.s, names[r])==0) break; |
|
491 | 492 |
if (r==addresses_no){ |
492 |
- LOG(L_NOTICE, "ERROR: forward_reply: host in first via!=me : %s\n", |
|
493 |
- msg->via1.host); |
|
493 |
+ LOG(L_NOTICE, "ERROR: forward_reply: host in first via!=me :" |
|
494 |
+ " %s\n", msg->via1.host); |
|
494 | 495 |
/* send error msg back? */ |
495 | 496 |
goto error; |
496 | 497 |
} |
497 | 498 |
} |
498 | 499 |
/* we must remove the first via */ |
499 | 500 |
via_len=msg->via1.size; |
500 |
- size=msg->via1.hdr-buf; |
|
501 |
+ size=msg->via1.hdr.s-buf; |
|
501 | 502 |
DBG("via len: %d, initial size: %d\n", via_len, size); |
502 | 503 |
if (msg->via1.next){ |
503 | 504 |
/* keep hdr =substract hdr size +1 (hdr':') and add |
504 | 505 |
*/ |
505 |
- via_len-=strlen(msg->via1.hdr)+1; |
|
506 |
- size+=strlen(msg->via1.hdr)+1; |
|
506 |
+ via_len-=msg->via1.hdr.len+1; |
|
507 |
+ size+=msg->via1.hdr.len+1; |
|
507 | 508 |
DBG(" adjusted via len: %d, initial size: %d\n", |
508 | 509 |
via_len, size); |
509 | 510 |
} |
... | ... |
@@ -525,27 +526,20 @@ int forward_reply(struct sip_msg* msg) |
525 | 526 |
s_offset, offset, |
526 | 527 |
len-s_offset ); |
527 | 528 |
DBG("Sending: to %s:%d, \n%s.\n", |
528 |
- msg->via2.host, |
|
529 |
+ msg->via2.host.s, |
|
529 | 530 |
(unsigned short)msg->via2.port, |
530 | 531 |
new_buf); |
531 | 532 |
/* fork? gethostbyname will probably block... */ |
532 |
- he=gethostbyname(msg->via2.host); |
|
533 |
+ he=gethostbyname(msg->via2.host.s); |
|
533 | 534 |
if (he==0){ |
534 | 535 |
LOG(L_NOTICE, "ERROR:forward_reply:gethostbyname(%s) failure\n", |
535 |
- msg->via2.host); |
|
536 |
+ msg->via2.host.s); |
|
536 | 537 |
goto error; |
537 | 538 |
} |
538 | 539 |
to->sin_family = AF_INET; |
539 | 540 |
to->sin_port = (msg->via2.port)?htons(msg->via2.port):htons(SIP_PORT); |
540 | 541 |
to->sin_addr.s_addr=*((long*)he->h_addr_list[0]); |
541 | 542 |
|
542 |
- |
|
543 |
- |
|
544 |
- |
|
545 |
- |
|
546 |
- |
|
547 |
- |
|
548 |
- |
|
549 | 543 |
#ifdef STATS |
550 | 544 |
stats.total_tx++; |
551 | 545 |
#endif |
... | ... |
@@ -34,7 +34,7 @@ |
34 | 34 |
|
35 | 35 |
|
36 | 36 |
static char id[]="@(#) $Id$"; |
37 |
-static char version[]="ser 0.8.3.2"; |
|
37 |
+static char version[]="ser 0.8.3.8"; |
|
38 | 38 |
static char flags[]="NOCR:" |
39 | 39 |
#ifdef NOCR |
40 | 40 |
"On" |
... | ... |
@@ -53,6 +53,18 @@ static char flags[]="NOCR:" |
53 | 53 |
#else |
54 | 54 |
"Off" |
55 | 55 |
#endif |
56 |
+#ifdef NO_DEBUG |
|
57 |
+", NO_DEBUG" |
|
58 |
+#endif |
|
59 |
+#ifdef NO_LOG |
|
60 |
+", NO_LOG" |
|
61 |
+#endif |
|
62 |
+#ifdef DEBUG |
|
63 |
+", DEBUG" |
|
64 |
+#endif |
|
65 |
+#ifdef OLD_PARSER |
|
66 |
+", OLD_PARSER" |
|
67 |
+#endif |
|
56 | 68 |
; |
57 | 69 |
|
58 | 70 |
static char help_msg[]= "\ |
... | ... |
@@ -33,6 +33,7 @@ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl) |
33 | 33 |
char* third; |
34 | 34 |
char* nl; |
35 | 35 |
int offset; |
36 |
+ int l; |
|
36 | 37 |
char* end; |
37 | 38 |
|
38 | 39 |
/* grammar: |
... | ... |
@@ -49,22 +50,24 @@ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl) |
49 | 50 |
LOG(L_INFO, "ERROR:parse_first_line: empty or bad first line\n"); |
50 | 51 |
goto error1; |
51 | 52 |
} |
52 |
- if ((strlen(SIP_VERSION)==(tmp-buffer)) && |
|
53 |
- (memcmp(buffer,SIP_VERSION,tmp-buffer)==0)){ |
|
53 |
+ l=tmp-buffer; |
|
54 |
+ if ((SIP_VERSION_LEN==l) && |
|
55 |
+ (memcmp(buffer,SIP_VERSION,l)==0)){ |
|
54 | 56 |
|
55 | 57 |
fl->type=SIP_REPLY; |
56 | 58 |
}else{ |
57 | 59 |
fl->type=SIP_REQUEST; |
58 | 60 |
} |
59 | 61 |
|
60 |
- offset=tmp-buffer; |
|
62 |
+ offset=l; |
|
61 | 63 |
second=eat_space(tmp, len-offset); |
62 | 64 |
offset+=second-tmp; |
63 | 65 |
if ((second==tmp)||(tmp>=end)){ |
64 | 66 |
goto error; |
65 | 67 |
} |
66 | 68 |
*tmp=0; /* mark the end of the token */ |
67 |
- fl->u.request.method=buffer; |
|
69 |
+ fl->u.request.method.s=buffer; |
|
70 |
+ fl->u.request.method.len=l; |
|
68 | 71 |
|
69 | 72 |
/* next element */ |
70 | 73 |
tmp=eat_token(second, len-offset); |
... | ... |
@@ -78,7 +81,9 @@ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl) |
78 | 81 |
goto error; |
79 | 82 |
} |
80 | 83 |
*tmp=0; /* mark the end of the token */ |
81 |
- fl->u.request.uri=second; |
|
84 |
+ fl->u.request.uri.s=second; |
|
85 |
+ fl->u.request.uri.len=tmp-second; |
|
86 |
+ |
|
82 | 87 |
/* last part: for a request it must be the version, for a reply |
83 | 88 |
* it can contain almost anything, including spaces, so we don't care |
84 | 89 |
* about it*/ |
... | ... |
@@ -104,7 +109,8 @@ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl) |
104 | 109 |
goto error; |
105 | 110 |
} |
106 | 111 |
*tmp=0; |
107 |
- fl->u.request.version=third; |
|
112 |
+ fl->u.request.version.s=third; |
|
113 |
+ fl->u.request.version.len=tmp-third; |
|
108 | 114 |
|
109 | 115 |
return nl; |
110 | 116 |
|
... | ... |
@@ -120,11 +126,10 @@ error1: |
120 | 126 |
} |
121 | 127 |
|
122 | 128 |
|
129 |
+#ifdef OLD_PARSER |
|
123 | 130 |
/* returns integer field name type */ |
124 |
-int field_name(char *s) |
|
131 |
+int field_name(char *s, int l) |
|
125 | 132 |
{ |
126 |
- int l; |
|
127 |
- l=strlen(s); |
|
128 | 133 |
if (l<1) return HDR_OTHER; |
129 | 134 |
else if ((l==1) && ((*s=='v')||(*s=='V'))) |
130 | 135 |
return HDR_VIA; |
... | ... |
@@ -134,10 +139,77 @@ int field_name(char *s) |
134 | 139 |
return HDR_TO;*/ |
135 | 140 |
return HDR_OTHER; |
136 | 141 |
} |
142 |
+#endif |
|
137 | 143 |
|
138 | 144 |
|
145 |
+#ifndef OLD_PARSER |
|
146 |
+/* returns pointer to next header line, and fill hdr_f ; |
|
147 |
+ * if at end of header returns pointer to the last crlf (always buf)*/ |
|
148 |
+char* get_hdr_field(char* buf, unsigned int len, struct hdr_field* hdr) |
|
149 |
+{ |
|
150 |
+ char* end; |
|
151 |
+ char* tmp; |
|
152 |
+ char *match; |
|
153 |
+ struct via_body *vb; |
|
154 |
+ |
|
155 |
+ end=buf+len; |
|
156 |
+ if ((*buf)=='\n' || (*buf)=='\r'){ |
|
157 |
+ /* double crlf or lflf or crcr */ |
|
158 |
+ DBG("found end of header\n"); |
|
159 |
+ hdr->type=HDR_EOH; |
|
160 |
+ return buf; |
|
161 |
+ } |
|
139 | 162 |
|
163 |
+ tmp=parse_hname(buf, end, hdr); |
|
164 |
+ if (hdr->type==HDR_ERROR){ |
|
165 |
+ LOG(L_ERR, "ERROR: get_hdr_field: bad header\n"); |
|
166 |
+ goto error; |
|
167 |
+ }else if (hdr->type==HDR_VIA){ |
|
168 |
+ vb=malloc(sizeof(struct via_body)); |
|
169 |
+ if (vb==0){ |
|
170 |
+ LOG(L_ERR, "get_hdr_field: out of memory\n"); |
|
171 |
+ goto error; |
|
172 |
+ } |
|
173 |
+ memset(vb,0,sizeof(struct via_body)); |
|
140 | 174 |
|
175 |
+ hdr->body.s=tmp; |
|
176 |
+ tmp=parse_via(tmp, end, vb); |
|
177 |
+ if (vb->error==VIA_PARSE_ERROR){ |
|
178 |
+ LOG(L_ERR, "ERROR: get_hdr_field: bad via\n"); |
|
179 |
+ free(vb); |
|
180 |
+ goto error; |
|
181 |
+ } |
|
182 |
+ hdr->parsed=vb; |
|
183 |
+ vb->hdr.s=hdr->name.s; |
|
184 |
+ vb->hdr.len=hdr->name.len; |
|
185 |
+ vb->size=tmp-hdr->name.s; |
|
186 |
+ hdr->body.len=tmp-hdr->body.s; |
|
187 |
+ }else{ |
|
188 |
+ /* just skip over it*/ |
|
189 |
+ hdr->body.s=tmp; |
|
190 |
+ /* find lf*/ |
|
191 |
+ match=memchr(tmp, '\n', end-tmp); |
|
192 |
+ if (match){ |
|
193 |
+ /* null terminate*/ |
|
194 |
+ *match=0; |
|
195 |
+ hdr->body.len=match-tmp; |
|
196 |
+ match++; /*skip*/ |
|
197 |
+ tmp=match; |
|
198 |
+ }else { |
|
199 |
+ tmp=end; |
|
200 |
+ LOG(L_ERR, "ERROR: get_hdr_field: bad body for <%s>(%d)\n", |
|
201 |
+ hdr->name.s, hdr->type); |
|
202 |
+ goto error; |
|
203 |
+ } |
|
204 |
+ } |
|
205 |
+ return tmp; |
|
206 |
+error: |
|
207 |
+ DBG("get_hdr_field: error exit\n"); |
|
208 |
+ hdr->type=HDR_ERROR; |
|
209 |
+ return tmp; |
|
210 |
+} |
|
211 |
+ |
|
212 |
+#else |
|
141 | 213 |
/* returns pointer to next header line, and fill hdr_f */ |
142 | 214 |
char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field* hdr_f) |
143 | 215 |
{ |
... | ... |
@@ -151,11 +223,14 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field* hdr_f) |
151 | 223 |
char* nl; |
152 | 224 |
char* body; |
153 | 225 |
int offset; |
226 |
+ int l; |
|
154 | 227 |
|
155 | 228 |
|
156 | 229 |
/* init content to the empty string */ |
157 |
- hdr_f->name=""; |
|
158 |
- hdr_f->body=""; |
|
230 |
+ hdr_f->name.s=""; |
|
231 |
+ hdr_f->name.len=0; |
|
232 |
+ hdr_f->body.s=""; |
|
233 |
+ hdr_f->body.len=0; |
|
159 | 234 |
|
160 | 235 |
if ((*buffer=='\n')||(*buffer=='\r')){ |
161 | 236 |
/* double crlf */ |
... | ... |
@@ -175,6 +250,7 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field* hdr_f) |
175 | 250 |
tmp2=eat_token(buffer, tmp-buffer); |
176 | 251 |
/* in the worst case tmp2=buffer+tmp-buffer=tmp */ |
177 | 252 |
*tmp2=0; |
253 |
+ l=tmp2-buffer; |
|
178 | 254 |
if (tmp2<tmp){ |
179 | 255 |
tmp2++; |
180 | 256 |
/* catch things like: "Via foo bar:" */ |
... | ... |
@@ -185,9 +261,10 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field* hdr_f) |
185 | 261 |
} |
186 | 262 |
} |
187 | 263 |
|
188 |
- hdr_f->type=field_name(buffer); |
|
264 |
+ hdr_f->type=field_name(buffer, l); |
|
189 | 265 |
body= ++tmp; |
190 |
- hdr_f->name=buffer; |
|
266 |
+ hdr_f->name.s=buffer; |
|
267 |
+ hdr_f->name.len=l; |
|
191 | 268 |
offset=tmp-buffer; |
192 | 269 |
/* get all the lines in this field body */ |
193 | 270 |
do{ |
... | ... |
@@ -202,20 +279,22 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field* hdr_f) |
202 | 279 |
goto error; |
203 | 280 |
} |
204 | 281 |
*(tmp-1)=0; /* should be an LF */ |
205 |
- hdr_f->body=body; |
|
282 |
+ hdr_f->body.s=body; |
|
283 |
+ hdr_f->body.len=tmp-1-body;; |
|
206 | 284 |
error: |
207 | 285 |
return tmp; |
208 | 286 |
} |
287 |
+#endif |
|
209 | 288 |
|
210 | 289 |
|
211 |
- |
|
212 |
-char* parse_hostport(char* buf, char** host, short int* port) |
|
290 |
+char* parse_hostport(char* buf, str* host, short int* port) |
|
213 | 291 |
{ |
214 | 292 |
char *tmp; |
215 | 293 |
char *invalid; |
216 | 294 |
|
217 |
- *host=buf; |
|
295 |
+ host->s=buf; |
|
218 | 296 |
for(tmp=buf;(*tmp)&&(*tmp!=':');tmp++); |
297 |
+ host->len=tmp-buf; |
|
219 | 298 |
if (*tmp==0){ |
220 | 299 |
*port=0; |
221 | 300 |
}else{ |
... | ... |
@@ -229,7 +308,7 @@ char* parse_hostport(char* buf, char** host, short int* port) |
229 | 308 |
/* report error? */ |
230 | 309 |
} |
231 | 310 |
} |
232 |
- return *host; |
|
311 |
+ return host->s; |
|
233 | 312 |
} |
234 | 313 |
|
235 | 314 |
|
... | ... |
@@ -265,8 +344,8 @@ int parse_uri(char *buf, int len, struct sip_uri* uri) |
265 | 344 |
next=memchr(buf,'@', end-buf); |
266 | 345 |
if (next==0){ |
267 | 346 |
/* no '@' found, => no userinfo */ |
268 |
- uri->user=0; |
|
269 |
- uri->passwd=0; |
|
347 |
+ uri->user.s=0; |
|
348 |
+ uri->passwd.s=0; |
|
270 | 349 |
host=buf; |
271 | 350 |
}else{ |
272 | 351 |
/* found it */ |
... | ... |
@@ -275,33 +354,37 @@ int parse_uri(char *buf, int len, struct sip_uri* uri) |
275 | 354 |
passwd=memchr(user,':', next-user); |
276 | 355 |
if (passwd==0){ |
277 | 356 |
/* no ':' found => no password */ |
278 |
- uri->passwd=0; |
|
279 |
- uri->user=(char*)malloc(next-user+1); |
|
280 |
- if (uri->user==0){ |
|
357 |
+ uri->passwd.s=0; |
|
358 |
+ uri->user.s=(char*)malloc(next-user+1); |
|
359 |
+ if (uri->user.s==0){ |
|
281 | 360 |
LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n"); |
282 | 361 |
ret=E_OUT_OF_MEM; |
283 | 362 |
goto error; |
284 | 363 |
} |
285 |
- memcpy(uri->user,user, next-user); |
|
286 |
- uri->user[next-user]=0; /* null terminate it, usefull for easy printing*/ |
|
364 |
+ memcpy(uri->user.s, user, next-user); |
|
365 |
+ uri->user.len=next-user; |
|
366 |
+ uri->user.s[next-user]=0; /* null terminate it, |
|
367 |
+ usefull for easy printing*/ |
|
287 | 368 |
}else{ |
288 |
- uri->user=(char*)malloc(passwd-user+1); |
|
289 |
- if (uri->user==0){ |
|
369 |
+ uri->user.s=(char*)malloc(passwd-user+1); |
|
370 |
+ if (uri->user.s==0){ |
|
290 | 371 |
LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n"); |
291 | 372 |
ret=E_OUT_OF_MEM; |
292 | 373 |
goto error; |
293 | 374 |
} |
294 |
- memcpy(uri->user,user, passwd-user); |
|
295 |
- uri->user[passwd-user]=0; |
|
375 |
+ memcpy(uri->user.s, user, passwd-user); |
|
376 |
+ uri->user.len=passwd-user; |
|
377 |
+ uri->user.s[passwd-user]=0; |
|
296 | 378 |
passwd++; /*skip ':' */ |
297 |
- uri->passwd=(char*)malloc(next-passwd+1); |
|
298 |
- if (uri->passwd==0){ |
|
379 |
+ uri->passwd.s=(char*)malloc(next-passwd+1); |
|
380 |
+ if (uri->passwd.s==0){ |
|
299 | 381 |
LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n"); |
300 | 382 |
ret=E_OUT_OF_MEM; |
301 | 383 |
goto error; |
302 | 384 |
} |
303 |
- memcpy(uri->passwd,passwd, next-passwd); |
|
304 |
- uri->passwd[next-passwd]=0; |
|
385 |
+ memcpy(uri->passwd.s, passwd, next-passwd); |
|
386 |
+ uri->passwd.len=next-passwd; |
|
387 |
+ uri->passwd.s[next-passwd]=0; |
|
305 | 388 |
} |
306 | 389 |
host=next+1; /* skip '@' */ |
307 | 390 |
} |
... | ... |
@@ -316,14 +399,15 @@ int parse_uri(char *buf, int len, struct sip_uri* uri) |
316 | 399 |
port=memchr(host,':',end-host); |
317 | 400 |
host_len=(port)?port-host:(params)?params-host:(headers)?headers-host:end-host; |
318 | 401 |
/* get host */ |
319 |
- uri->host=malloc(host_len+1); |
|
320 |
- if (uri->host==0){ |
|
402 |
+ uri->host.s=malloc(host_len+1); |
|
403 |
+ if (uri->host.s==0){ |
|
321 | 404 |
LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n"); |
322 | 405 |
ret=E_OUT_OF_MEM; |
323 | 406 |
goto error; |
324 | 407 |
} |
325 |
- memcpy(uri->host,host, host_len); |
|
326 |
- uri->host[host_len]=0; |
|
408 |
+ memcpy(uri->host.s, host, host_len); |
|
409 |
+ uri->host.len=host_len; |
|
410 |
+ uri->host.s[host_len]=0; |
|
327 | 411 |
/* get port*/ |
328 | 412 |
if ((port)&&(port+1<end)){ |
329 | 413 |
port++; |
... | ... |
@@ -334,15 +418,16 @@ int parse_uri(char *buf, int len, struct sip_uri* uri) |
334 | 418 |
goto error; |
335 | 419 |
} |
336 | 420 |
port_len=(params)?params-port:(headers)?headers-port:end-port; |
337 |
- uri->port=malloc(port_len+1); |
|
338 |
- if (uri->port==0){ |
|
421 |
+ uri->port.s=malloc(port_len+1); |
|
422 |
+ if (uri->port.s==0){ |
|
339 | 423 |
LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n"); |
340 | 424 |
ret=E_OUT_OF_MEM; |
341 | 425 |
goto error; |
342 | 426 |
} |
343 |
- memcpy(uri->port, port, port_len); |
|
344 |
- uri->port[port_len]=0; |
|
345 |
- }else uri->port=0; |
|
427 |
+ memcpy(uri->port.s, port, port_len); |
|
428 |
+ uri->port.len=port_len; |
|
429 |
+ uri->port.s[port_len]=0; |
|
430 |
+ }else uri->port.s=0; |
|
346 | 431 |
/* get params */ |
347 | 432 |
if ((params)&&(params+1<end)){ |
348 | 433 |
params++; |
... | ... |
@@ -353,28 +438,30 @@ int parse_uri(char *buf, int len, struct sip_uri* uri) |
353 | 438 |
goto error; |
354 | 439 |
} |
355 | 440 |
params_len=(headers)?headers-params:end-params; |
356 |
- uri->params=malloc(params_len+1); |
|
357 |
- if (uri->params==0){ |
|
441 |
+ uri->params.s=malloc(params_len+1); |
|
442 |
+ if (uri->params.s==0){ |
|
358 | 443 |
LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n"); |
359 | 444 |
ret=E_OUT_OF_MEM; |
360 | 445 |
goto error; |
361 | 446 |
} |
362 |
- memcpy(uri->params, params, params_len); |
|
363 |
- uri->params[params_len]=0; |
|
364 |
- }else uri->params=0; |
|
447 |
+ memcpy(uri->params.s, params, params_len); |
|
448 |
+ uri->params.len=params_len; |
|
449 |
+ uri->params.s[params_len]=0; |
|
450 |
+ }else uri->params.s=0; |
|
365 | 451 |
/*get headers */ |
366 | 452 |
if ((headers)&&(headers+1<end)){ |
367 | 453 |
headers++; |
368 | 454 |
headers_len=end-headers; |
369 |
- uri->headers=malloc(headers_len+1); |
|
370 |
- if(uri->headers==0){ |
|
455 |
+ uri->headers.s=malloc(headers_len+1); |
|
456 |
+ if(uri->headers.s==0){ |
|
371 | 457 |
LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n"); |
372 | 458 |
ret=E_OUT_OF_MEM; |
373 | 459 |
goto error; |
374 | 460 |
} |
375 |
- memcpy(uri->headers, headers, headers_len); |
|
376 |
- uri->headers[headers_len]=0; |
|
377 |
- }else uri->headers=0; |
|
461 |
+ memcpy(uri->headers.s, headers, headers_len); |
|
462 |
+ uri->headers.len=headers_len; |
|
463 |
+ uri->headers.s[headers_len]=0; |
|
464 |
+ }else uri->headers.s=0; |
|
378 | 465 |
|
379 | 466 |
return ret; |
380 | 467 |
error: |
... | ... |
@@ -396,13 +483,15 @@ char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb) |
396 | 483 |
|
397 | 484 |
char* tmp; |
398 | 485 |
char *name,*version, *transport, *comment, *params, *hostport; |
486 |
+ int name_len, version_len, transport_len, comment_len, params_len; |
|
399 | 487 |
char * next_via; |
400 |
- char * host; |
|
488 |
+ str host; |
|
401 | 489 |
short int port; |
402 | 490 |
int offset; |
403 | 491 |
|
404 | 492 |
|
405 |
- name=version=transport=comment=params=hostport=next_via=host=0; |
|
493 |
+ name=version=transport=comment=params=hostport=next_via=host.s=0; |
|
494 |
+ name_len=version_len=transport_len=comment_len=params_len=host.len=0; |
|
406 | 495 |
name=eat_space(buffer, len); |
407 | 496 |
if (name-buffer==len) goto error; |
408 | 497 |
offset=name-buffer; |
... | ... |
@@ -411,18 +500,21 @@ char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb) |
411 | 500 |
version=eat_token2(tmp,len-offset,'/'); |
412 | 501 |
if (version+1-buffer>=len) goto error; |
413 | 502 |
*version=0; |
503 |
+ name_len=version-name; |
|
414 | 504 |
version++; |
415 | 505 |
offset+=version-tmp; |
416 | 506 |
|
417 | 507 |
transport=eat_token2(tmp,len-offset,'/'); |
418 | 508 |
if (transport+1-buffer>=len) goto error; |
419 | 509 |
*transport=0; |
510 |
+ version_len=transport-version; |
|
420 | 511 |
transport++; |
421 | 512 |
offset+=transport-tmp; |
422 | 513 |
|
423 | 514 |
tmp=eat_token(transport,len-offset); |
424 | 515 |
if (tmp+1-buffer>=len) goto error; |
425 | 516 |
*tmp=0; |
517 |
+ transport_len=tmp-transport; |
|
426 | 518 |
tmp++; |
427 | 519 |
offset+=tmp-transport; |
428 | 520 |
|
... | ... |
@@ -445,6 +537,7 @@ char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb) |
445 | 537 |
for(;((tmp-buffer)<len)&& |
446 | 538 |
(*tmp!=',');tmp++); |
447 | 539 |
/* mark end of compact via (also end of comment)*/ |
540 |
+ comment_len=tmp-comment; |
|
448 | 541 |
if (tmp-buffer<len){ |
449 | 542 |
*tmp=0; |
450 | 543 |
}else break; |
... | ... |
@@ -463,6 +556,7 @@ char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb) |
463 | 556 |
/* eat till end, first space or ',' */ |
464 | 557 |
for(;((tmp-buffer)<len)&& |
465 | 558 |
(*tmp!=' '&& *tmp!=',');tmp++); |
559 |
+ params_len=tmp-params; |
|
466 | 560 |
if (tmp-buffer==len) break; |
467 | 561 |
if (*tmp==' '){ |
468 | 562 |
/* eat comment */ |
... | ... |
@@ -471,10 +565,12 @@ char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb) |
471 | 565 |
comment=tmp; |
472 | 566 |
for(;((tmp-buffer)<len)&& |
473 | 567 |
(*tmp!=',');tmp++); |
568 |
+ comment_len=tmp-comment; |
|
474 | 569 |
if (tmp-buffer==len) break; |
475 | 570 |
} |
476 | 571 |
/* mark end of via*/ |
477 | 572 |
*tmp=0; |
573 |
+ |
|
478 | 574 |
/* eat space & ',' */ |
479 | 575 |
for(tmp=tmp+1;((tmp-buffer)<len)&& |
480 | 576 |
(*tmp==' '|| *tmp==',');tmp++); |
... | ... |
@@ -496,13 +592,19 @@ char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb) |
496 | 592 |
|
497 | 593 |
/* parse hostport */ |
498 | 594 |
parse_hostport(hostport, &host, &port); |
499 |
- vb->name=name; |
|
500 |
- vb->version=version; |
|
501 |
- vb->transport=transport; |
|
502 |
- vb->host=host; |
|
595 |
+ vb->name.s=name; |
|
596 |
+ vb->name.len=name_len; |
|
597 |
+ vb->version.s=version; |
|
598 |
+ vb->version.len=version_len; |
|
599 |
+ vb->transport.s=transport; |
|
600 |
+ vb->transport.len=transport_len; |
|
601 |
+ vb->host.s=host.s; |
|
602 |
+ vb->host.len=host.len; |
|
503 | 603 |
vb->port=port; |
504 |
- vb->params=params; |
|
505 |
- vb->comment=comment; |
|
604 |
+ vb->params.s=params; |
|
605 |
+ vb->params.len=params_len; |
|
606 |
+ vb->comment.s=comment; |
|
607 |
+ vb->comment.len=comment_len; |
|
506 | 608 |
vb->next=next_via; |
507 | 609 |
vb->error=VIA_PARSE_OK; |
508 | 610 |
|
... | ... |
@@ -526,46 +628,49 @@ int parse_msg(char* buf, unsigned int len, struct sip_msg* msg) |
526 | 628 |
char* rest; |
527 | 629 |
char* first_via; |
528 | 630 |
char* second_via; |
529 |
- struct msg_start fl; |
|
631 |
+ struct msg_start *fl; |
|
530 | 632 |
struct hdr_field hf; |
531 |
- struct via_body vb1, vb2; |
|
633 |
+ struct via_body *vb1, *vb2; |
|
532 | 634 |
int offset; |
533 | 635 |
|
534 |
- |
|
636 |
+#ifdef OLD_PARSER |
|
535 | 637 |
/* init vb1 & vb2 to the null string */ |
536 |
- vb1.error=VIA_PARSE_ERROR; |
|
537 |
- vb1.hdr=vb1.name=vb1.version=vb1.transport=vb1.host=0; |
|
538 |
- vb1.params=vb1.comment=0; |
|
539 |
- vb1.next=0; |
|
540 |
- vb1.size=0; |
|
541 |
- memcpy(&vb2, &vb1, sizeof(struct via_body)); |
|
542 |
- |
|
638 |
+ /*memset(&vb1,0, sizeof(struct via_body)); |
|
639 |
+ memset(&vb2,0, sizeof(struct via_body));*/ |
|
640 |
+ vb1=&(msg->via1); |
|
641 |
+ vb2=&(msg->via2); |
|
642 |
+ vb1->error=VIA_PARSE_ERROR; |
|
643 |
+ vb2->error=VIA_PARSE_ERROR; |
|
644 |
+#else |
|
645 |
+ vb1=vb2=0; |
|
646 |
+#endif |
|
543 | 647 |
/* eat crlf from the beginning */ |
544 | 648 |
for (tmp=buf; (*tmp=='\n' || *tmp=='\r')&& |
545 | 649 |
tmp-buf < len ; tmp++); |
546 | 650 |
offset=tmp-buf; |
547 |
- rest=parse_first_line(tmp, len-offset, &fl); |
|
651 |
+ fl=&(msg->first_line); |
|
652 |
+ rest=parse_first_line(tmp, len-offset, fl); |
|
548 | 653 |
offset+=rest-tmp; |
549 | 654 |
tmp=rest; |
550 |
- switch(fl.type){ |
|
655 |
+ switch(fl->type){ |
|
551 | 656 |
case SIP_INVALID: |
552 | 657 |
DBG("parse_msg: invalid message\n"); |
553 | 658 |
goto error; |
554 | 659 |
break; |
555 | 660 |
case SIP_REQUEST: |
556 | 661 |
DBG("SIP Request:\n"); |
557 |
- DBG(" method: <%s>\n",fl.u.request.method); |
|
558 |
- DBG(" uri: <%s>\n",fl.u.request.uri); |
|
559 |
- DBG(" version: <%s>\n",fl.u.request.version); |
|
662 |
+ DBG(" method: <%s>\n",fl->u.request.method); |
|
663 |
+ DBG(" uri: <%s>\n",fl->u.request.uri); |
|
664 |
+ DBG(" version: <%s>\n",fl->u.request.version); |
|
560 | 665 |
break; |
561 | 666 |
case SIP_REPLY: |
562 | 667 |
DBG("SIP Reply (status):\n"); |
563 |
- DBG(" version: <%s>\n",fl.u.reply.version); |
|
564 |
- DBG(" status: <%s>\n",fl.u.reply.status); |
|
565 |
- DBG(" reason: <%s>\n",fl.u.reply.reason); |
|
668 |
+ DBG(" version: <%s>\n",fl->u.reply.version); |
|
669 |
+ DBG(" status: <%s>\n",fl->u.reply.status); |
|
670 |
+ DBG(" reason: <%s>\n",fl->u.reply.reason); |
|
566 | 671 |
break; |
567 | 672 |
default: |
568 |
- DBG("unknown type %d\n",fl.type); |
|
673 |
+ DBG("unknown type %d\n",fl->type); |
|
569 | 674 |
} |
570 | 675 |
|
571 | 676 |
/*find first Via: */ |
... | ... |
@@ -583,88 +688,112 @@ int parse_msg(char* buf, unsigned int len, struct sip_msg* msg) |
583 | 688 |
goto skip; |
584 | 689 |
case HDR_VIA: |
585 | 690 |
if (first_via==0){ |
586 |
- first_via=hf.body; |
|
587 |
- vb1.hdr=hf.name; |
|
691 |
+ first_via=hf.body.s; |
|
692 |
+#ifndef OLD_PARSER |
|
693 |
+ vb1=(struct via_body*)hf.parsed; |
|
694 |
+#else |
|
695 |
+ vb1->hdr.s=hf.name.s; |
|
696 |
+ vb1->hdr.len=hf.name.len; |
|
588 | 697 |
/* replace cr/lf with space in first via */ |
589 | 698 |
for (bar=first_via;(first_via) && (*bar);bar++) |
590 | 699 |
if ((*bar=='\r')||(*bar=='\n')) *bar=' '; |
700 |
+#endif |
|
591 | 701 |
#ifdef DEBUG |
592 | 702 |
DBG("first via: <%s>\n", first_via); |
593 | 703 |
#endif |
594 |
- bar=parse_via_body(first_via, strlen(first_via), &vb1); |
|
595 |
- if (vb1.error!=VIA_PARSE_OK){ |
|
704 |
+#ifdef OLD_PARSER |
|
705 |
+ bar=parse_via_body(first_via, hf.body.len, vb1); |
|
706 |
+ if (vb1->error!=VIA_PARSE_OK){ |
|
596 | 707 |
LOG(L_INFO, "ERROR: parsing via body: %s\n", |
597 | 708 |
first_via); |
598 | 709 |
goto error; |
599 | 710 |
} |
600 | 711 |
|
601 |
- vb1.size=bar-first_via+first_via-vb1.hdr; |
|
712 |
+ vb1->size=bar-first_via+first_via-vb1->hdr.s; |
|
602 | 713 |
|
714 |
+#endif |
|
603 | 715 |
/* compact via */ |
604 |
- if (vb1.next) { |
|
605 |
- second_via=vb1.next; |
|
716 |
+ if (vb1->next) { |
|
717 |
+ second_via=vb1->next; |
|
606 | 718 |
/* not interested in the rest of the header */ |
607 | 719 |
goto skip; |
608 | 720 |
}else{ |
721 |
+#ifdef OLD_PARSER |
|
609 | 722 |
/* add 1 (we don't see the trailing lf which |
610 | 723 |
* was zeroed by get_hfr_field) */ |
611 |
- vb1.size+=1; |
|
724 |
+ vb1->size+=1; |
|
725 |
+#endif |
|
612 | 726 |
} |
613 |
- if (fl.type!=SIP_REPLY) goto skip; /* we are interested in the 2nd via |
|
614 |
- only in replies */ |
|
727 |
+ if (fl->type!=SIP_REPLY) goto skip; /* we are interested |
|
728 |
+ in the 2nd via |
|
729 |
+ only in replies */ |
|
615 | 730 |
}else if (second_via==0){ |
616 |
- second_via=hf.body; |
|
617 |
- vb2.hdr=hf.name; |
|
731 |
+ second_via=hf.body.s; |
|
732 |
+#ifndef OLD_PARSER |
|
733 |
+ vb2=hf.parsed; |
|
734 |
+#else |
|
735 |
+ vb2->hdr.s=hf.name.s; |
|
736 |
+ vb2->hdr.len=hf.name.len; |
|
737 |
+#endif |
|
618 | 738 |
goto skip; |
619 | 739 |
} |
620 | 740 |
break; |
621 | 741 |
} |
622 | 742 |
#ifdef DEBUG |
623 | 743 |
DBG("header field type %d, name=<%s>, body=<%s>\n", |
624 |
- hf.type, hf.name, hf.body); |
|
744 |
+ hf.type, hf.name.s, hf.body.s); |
|
625 | 745 |
#endif |
626 | 746 |
tmp=rest; |
627 | 747 |
}while(hf.type!=HDR_EOH && rest-buf < len); |
628 | 748 |
|
629 | 749 |
skip: |
630 | 750 |
/* replace cr/lf with space in the second via */ |
751 |
+#ifdef OLD_PARSER |
|
631 | 752 |
for (tmp=second_via;(second_via) && (*tmp);tmp++) |
632 | 753 |
if ((*tmp=='\r')||(*tmp=='\n')) *tmp=' '; |
633 | 754 |
|
634 | 755 |
if (second_via) { |
635 |
- tmp=parse_via_body(second_via, strlen(second_via), &vb2); |
|
636 |
- if (vb2.error!=VIA_PARSE_OK){ |
|
756 |
+ tmp=parse_via_body(second_via, hf.body.len, vb2); |
|
757 |
+ if (vb2->error!=VIA_PARSE_OK){ |
|
637 | 758 |
LOG(L_INFO, "ERROR: parsing via2 body: %s\n", second_via); |
638 | 759 |
goto error; |
639 | 760 |
} |
640 |
- vb2.size=tmp-second_via; |
|
641 |
- if (vb2.next==0) vb2.size+=1; /* +1 from trailing lf */ |
|
642 |
- if (vb2.hdr) vb2.size+=second_via-vb2.hdr; |
|
761 |
+ vb2->size=tmp-second_via; |
|
762 |
+ if (vb2->next==0) vb2->size+=1; /* +1 from trailing lf */ |
|
763 |
+ if (vb2->hdr.s) vb2->size+=second_via-vb2->hdr.s; |
|
643 | 764 |
} |
765 |
+#endif |
|
644 | 766 |
|
645 | 767 |
|
646 | 768 |
#ifdef DEBUG |
647 | 769 |
/* dump parsed data */ |
648 | 770 |
if (first_via){ |
649 |
- DBG(" first via: <%s/%s/%s> <%s:%d>", |
|
650 |
- vb1.name, vb1.version, vb1.transport, vb1.host, vb1.port); |
|
651 |
- if (vb1.params) DBG(";<%s>", vb1.params); |
|
652 |
- if (vb1.comment) DBG(" <%s>", vb1.comment); |
|
771 |
+ DBG(" first via: <%s/%s/%s> <%s:%s(%d)>", |
|
772 |
+ vb1->name.s, vb1->version.s, vb1->transport.s, vb1->host.s, |
|
773 |
+ vb1->port_str, vb1->port); |
|
774 |
+ if (vb1->params.s) DBG(";<%s>", vb1->params.s); |
|
775 |
+ if (vb1->comment.s) DBG(" <%s>", vb1->comment.s); |
|
653 | 776 |
DBG ("\n"); |
654 | 777 |
} |
778 |
+#ifdef OLD_PARSER |
|
655 | 779 |
if (second_via){ |
656 | 780 |
DBG(" second via: <%s/%s/%s> <%s:%d>", |
657 |
- vb2.name, vb2.version, vb2.transport, vb2.host, vb2.port); |
|
658 |
- if (vb2.params) DBG(";<%s>", vb2.params); |
|
659 |
- if (vb2.comment) DBG(" <%s>", vb2.comment); |
|
781 |
+ vb2->name.s, vb2->version.s, vb2->transport.s, vb2->host.s, |
|
782 |
+ vb2->port); |
|
783 |
+ if (vb2->params.s) DBG(";<%s>", vb2->params.s); |
|
784 |
+ if (vb2->comment.s) DBG(" <%s>", vb2->comment.s); |
|
660 | 785 |
DBG("\n"); |
661 | 786 |
} |
787 |
+#endif |
|
662 | 788 |
#endif |
663 | 789 |
|
664 | 790 |
/* copy data into msg */ |
665 |
- memcpy(&(msg->first_line), &fl, sizeof(struct msg_start)); |
|
666 |
- memcpy(&(msg->via1), &vb1, sizeof(struct via_body)); |
|
667 |
- memcpy(&(msg->via2), &vb2, sizeof(struct via_body)); |
|
791 |
+#ifndef OLD_PARSER |
|
792 |
+ memcpy(&(msg->via1), vb1, sizeof(struct via_body)); |
|
793 |
+ if (second_via) memcpy(&(msg->via2), vb2, sizeof(struct via_body)); |
|
794 |
+ if (vb1) free(vb1); |
|
795 |
+ if (vb2) free(vb1); |
|
796 |
+#endif |
|
668 | 797 |
|
669 | 798 |
#ifdef DEBUG |
670 | 799 |
DBG("exiting parse_msg\n"); |
... | ... |
@@ -673,6 +802,10 @@ skip: |
673 | 802 |
return 0; |
674 | 803 |
|
675 | 804 |
error: |
805 |
+#ifndef OLD_PARSER |
|
806 |
+ if (vb1) free(vb1); |
|
807 |
+ if (vb2) free(vb1); |
|
808 |
+#endif |
|
676 | 809 |
return -1; |
677 | 810 |
} |
678 | 811 |
|
... | ... |
@@ -681,11 +814,11 @@ error: |
681 | 814 |
void free_uri(struct sip_uri* u) |
682 | 815 |
{ |
683 | 816 |
if (u){ |
684 |
- if (u->user) free(u->user); |
|
685 |
- if (u->passwd) free(u->passwd); |
|
686 |
- if (u->host) free(u->host); |
|
687 |
- if (u->port) free(u->port); |
|
688 |
- if (u->params) free(u->params); |
|
689 |
- if (u->headers) free(u->headers); |
|
817 |
+ if (u->user.s) free(u->user.s); |
|
818 |
+ if (u->passwd.s) free(u->passwd.s); |
|
819 |
+ if (u->host.s) free(u->host.s); |
|
820 |
+ if (u->port.s) free(u->port.s); |
|
821 |
+ if (u->params.s) free(u->params.s); |
|
822 |
+ if (u->headers.s) free(u->headers.s); |
|
690 | 823 |
} |
691 | 824 |
} |
... | ... |
@@ -5,7 +5,7 @@ |
5 | 5 |
#ifndef msg_parser_h |
6 | 6 |
#define msg_parser_h |
7 | 7 |
|
8 |
- |
|
8 |
+#include "str.h" |
|
9 | 9 |
#include "data_lump.h" |
10 | 10 |
|
11 | 11 |
#define SIP_REQUEST 1 |
... | ... |
@@ -13,51 +13,55 @@ |
13 | 13 |
#define SIP_INVALID 0 |
14 | 14 |
|
15 | 15 |
|
16 |
-#define HDR_ERROR 0 |
|
17 |
-/* end of header */ |
|
18 |
-#define HDR_EOH -1 |
|
19 |
-#define HDR_OTHER 1 |
|
20 |
-#define HDR_VIA 2 |
|
21 |
-#define HDR_TO 3 |
|
16 |
+enum { HDR_EOH=-1, HDR_ERROR=0, HDR_OTHER, |
|
17 |
+ HDR_VIA, HDR_TO, HDR_FROM, HDR_CSEQ, HDR_CALLID, HDR_CONTACT, |
|
18 |
+ HDR_MAXFORWARDS, HDR_ROUTE |
|
19 |
+ }; |
|
20 |
+ |
|
21 |
+ |
|
22 |
+ |
|
22 | 23 |
|
23 | 24 |
#define VIA_PARSE_OK 1 |
24 | 25 |
#define VIA_PARSE_ERROR -1 |
25 | 26 |
|
26 | 27 |
#define SIP_VERSION "SIP/2.0" |
28 |
+#define SIP_VERSION_LEN 7 |
|
27 | 29 |
|
28 | 30 |
|
29 | 31 |
struct msg_start{ |
30 | 32 |
int type; |
31 | 33 |
union { |
32 | 34 |
struct { |
33 |
- char* method; |
|
34 |
- char* uri; |
|
35 |
- char* version; |
|
35 |
+ str method; |
|
36 |
+ str uri; |
|
37 |
+ str version; |
|
36 | 38 |
}request; |
37 | 39 |
struct { |
38 |
- char* version; |
|
39 |
- char* status; |
|
40 |
- char* reason; |
|
40 |
+ str version; |
|
41 |
+ str status; |
|
42 |
+ str reason; |
|
41 | 43 |
}reply; |
42 | 44 |
}u; |
43 | 45 |
}; |
44 | 46 |
|
45 | 47 |
struct hdr_field{ /* format: name':' body */ |
46 | 48 |
int type; |
47 |
- char* name; |
|
48 |
- char* body; |
|
49 |
+ str name; |
|
50 |
+ str body; |
|
51 |
+ void* parsed; |
|
49 | 52 |
}; |
50 | 53 |
|
51 | 54 |
struct via_body{ /* format: name/version/transport host:port;params comment */ |
52 | 55 |
int error; |
53 |
- char *hdr; /* contains "Via" or "v" */ |
|
54 |
- char* name; |
|
55 |
- char* version; |
|
56 |
- char* transport; |
|
57 |
- char* host; |
|
56 |
+ str hdr; /* contains "Via" or "v" */ |
|
57 |
+ str name; |
|
58 |
+ str version; |
|
59 |
+ str transport; |
|
60 |
+ str host; |
|
58 | 61 |
int port; |
59 |
- char* params; |
|
60 |
- char* comment; |
|
62 |
+ str port_str; |
|
63 |
+ str params; |
|
64 |
+ str comment; |
|
61 | 65 |
int size; /* full size, including hdr */ |
62 | 66 |
char* next; /* pointer to next via body string if compact via or null */ |
63 | 67 |
}; |
... | ... |
@@ -76,7 +80,7 @@ struct sip_msg{ |
76 | 80 |
unsigned int len; /* message len (orig) */ |
77 | 81 |
|
78 | 82 |
/* modifications */ |
79 |
- char* new_uri; /* changed first line uri*/ |
|
83 |
+ str new_uri; /* changed first line uri*/ |
|
80 | 84 |
|
81 | 85 |
struct lump* add_rm; /* used for all the forwarded messages */ |
82 | 86 |
struct lump* repl_add_rm; /* only for localy generated replies !!!*/ |
... | ... |
@@ -85,25 +89,35 @@ struct sip_msg{ |
85 | 89 |
|
86 | 90 |
|
87 | 91 |
struct sip_uri{ |
88 |
- char* user; |
|
89 |
- char* passwd; |
|
90 |
- char* host; |
|
91 |
- char* port; |
|
92 |
- char* params; |
|
93 |
- char* headers; |
|
92 |
+ str user; |
|
93 |
+ str passwd; |
|
94 |
+ str host; |
|
95 |
+ str port; |
|
96 |
+ str params; |
|
97 |
+ str headers; |
|
94 | 98 |
}; |
95 | 99 |
|
96 | 100 |
|
97 | 101 |
|
98 | 102 |
char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl); |
103 |
+#ifdef OLD_PARSER |
|
99 | 104 |
char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field* hdr_f); |
100 |
-int field_name(char *s); |
|
101 |
-char* parse_hostport(char* buf, char** host, short int* port); |
|
105 |
+int field_name(char *s, int len); |
|
106 |
+#endif |
|
107 |
+char* parse_hostport(char* buf, str* host, short int* port); |
|
108 |
+ |
|
109 |
+#ifdef OLD_PARSER |
|
102 | 110 |
char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb); |
111 |
+#endif |
|
103 | 112 |
int parse_msg(char* buf, unsigned int len, struct sip_msg* msg); |
104 | 113 |
int parse_uri(char *buf, int len, struct sip_uri* uri); |
105 | 114 |
void free_uri(struct sip_uri* u); |
106 | 115 |
|
107 | 116 |
|
117 |
+#ifndef OLD_PARSER |
|
118 |
+char* parse_hname(char* buf, char* end, struct hdr_field* hdr); |
|
119 |
+char* parse_via(char* buffer, char* end, struct via_body *vb); |
|
120 |
+#endif |
|
121 |
+ |
|
108 | 122 |
|
109 | 123 |
#endif |
... | ... |
@@ -46,16 +46,19 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip) |
46 | 46 |
if (parse_msg(buf,len, &msg)!=0){ |
47 | 47 |
goto error; |
48 | 48 |
} |
49 |
+ DBG("Ater parse_msg...\n"); |
|
49 | 50 |
|
50 | 51 |
if (msg.first_line.type==SIP_REQUEST){ |
52 |
+ DBG("msg= request\n"); |
|
51 | 53 |
/* sanity checks */ |
52 | 54 |
if (msg.via1.error!=VIA_PARSE_OK){ |
53 | 55 |
/* no via, send back error ? */ |
54 | 56 |
goto skip; |
55 | 57 |
} |
56 |
- /* check if neccesarry to add receive? */ |
|
58 |
+ /* check if neccesarry to add receive?->moved to forward_req */ |
|
57 | 59 |
|
58 | 60 |
/* exec routing script */ |
61 |
+ DBG("preparing to run routing scripts...\n"); |
|
59 | 62 |
if (run_actions(rlist[0], &msg)<0){ |
60 | 63 |
LOG(L_WARN, "WARNING: receive_msg: " |
61 | 64 |
"error while trying script\n"); |
... | ... |
@@ -66,6 +69,7 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip) |
66 | 69 |
else stats.ok_rx_rq++; |
67 | 70 |
#endif |
68 | 71 |
}else if (msg.first_line.type==SIP_REPLY){ |
72 |
+ DBG("msg= reply\n"); |
|
69 | 73 |
/* sanity checks */ |
70 | 74 |
if (msg.via1.error!=VIA_PARSE_OK){ |
71 | 75 |
/* no via, send back error ? */ |
... | ... |
@@ -90,13 +94,13 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip) |
90 | 94 |
} |
91 | 95 |
} |
92 | 96 |
skip: |
93 |
- if (msg.new_uri) free(msg.new_uri); |
|
97 |
+ if (msg.new_uri.s) { free(msg.new_uri.s); msg.new_uri.len=0; } |
|
94 | 98 |
if (msg.add_rm) free_lump_list(msg.add_rm); |
95 | 99 |
if (msg.repl_add_rm) free_lump_list(msg.repl_add_rm); |
96 | 100 |
free(msg.orig); |
97 | 101 |
return 0; |
98 | 102 |
error: |
99 |
- if (msg.new_uri) free(msg.new_uri); |
|
103 |
+ if (msg.new_uri.s) free(msg.new_uri.s); |
|
100 | 104 |
if (msg.add_rm) free_lump_list(msg.add_rm); |
101 | 105 |
if (msg.repl_add_rm) free_lump_list(msg.repl_add_rm); |
102 | 106 |
free(msg.orig); |
... | ... |
@@ -292,15 +292,15 @@ static int eval_elem(struct expr* e, struct sip_msg* msg) |
292 | 292 |
} |
293 | 293 |
switch(e->l.operand){ |
294 | 294 |
case METHOD_O: |
295 |
- ret=comp_str(msg->first_line.u.request.method, e->r.param, |
|
295 |
+ ret=comp_str(msg->first_line.u.request.method.s, e->r.param, |
|
296 | 296 |
e->op, e->subtype); |
297 | 297 |
break; |
298 | 298 |
case URI_O: |
299 |
- if(msg->new_uri){ |
|
300 |
- ret=comp_str(msg->new_uri, e->r.param, |
|
299 |
+ if(msg->new_uri.s){ |
|
300 |
+ ret=comp_str(msg->new_uri.s, e->r.param, |
|
301 | 301 |
e->op, e->subtype); |
302 | 302 |
}else{ |
303 |
- ret=comp_str(msg->first_line.u.request.uri, e->r.param, |
|
303 |
+ ret=comp_str(msg->first_line.u.request.uri.s, e->r.param, |
|
304 | 304 |
e->op, e->subtype); |
305 | 305 |
} |
306 | 306 |
break; |
0 | 11 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,127 @@ |
1 |
+/* $Id$ */ |
|
2 |
+ |
|
3 |
+ |
|
4 |
+#include <stdio.h> |
|
5 |
+#include <stdlib.h> |
|
6 |
+#include <errno.h> |
|
7 |
+#include <string.h> |
|
8 |
+#include <ctype.h> |
|
9 |
+#include <netdb.h> |
|
10 |
+#include <unistd.h> |
|
11 |
+#include <sys/types.h> |
|
12 |
+#include <fcntl.h> |
|
13 |
+#include <sys/socket.h> |
|
14 |
+#include <netinet/in.h> |
|
15 |
+#include <arpa/inet.h> |
|
16 |
+ |
|
17 |
+ |
|
18 |
+static char *id="$Id$"; |
|
19 |
+static char *version="resolver_test 0.1"; |
|
20 |
+static char* help_msg="\ |
|
21 |
+Usage: resolver -n address [-c count] [-v]\n\ |
|
22 |
+Options:\n\ |
|
23 |
+ -n address address to be resolved\n\ |
|
24 |
+ -c count how many times to resolve it\n\ |
|
25 |
+ -v increase verbosity level\n\ |
|
26 |
+ -V version number\n\ |
|
27 |
+ -h this help message\n\ |
|
28 |
+"; |
|
29 |
+ |
|
30 |
+ |
|
31 |
+ |
|
32 |
+int main (int argc, char** argv) |
|
33 |
+{ |
|
34 |
+ char c; |
|
35 |
+ struct hostent* he; |
|
36 |
+ int ok; |
|
37 |
+ int errors; |
|
38 |
+ int r; |
|
39 |
+ char *tmp; |
|
40 |
+ |
|
41 |
+ int count; |
|
42 |
+ int verbose; |
|
43 |
+ char *address; |
|
44 |
+ |
|
45 |
+ /* init */ |
|
46 |
+ count=0; |
|
47 |
+ verbose=0; |
|
48 |
+ address=0; |
|
49 |
+ |
|
50 |
+ ok=errors=0; |
|
51 |
+ |
|
52 |
+ opterr=0; |
|
53 |
+ while ((c=getopt(argc,argv, "n:c:vhV"))!=-1){ |
|
54 |
+ switch(c){ |
|
55 |
+ case 'n': |
|
56 |
+ address=optarg; |
|
57 |
+ break; |
|
58 |
+ case 'v': |
|
59 |
+ verbose++; |
|
60 |
+ break; |
|
61 |
+ case 'c': |
|
62 |
+ count=strtol(optarg, &tmp, 10); |
|
63 |
+ if ((tmp==0)||(*tmp)){ |
|
64 |
+ fprintf(stderr, "bad count: -c %s\n", optarg); |
|
65 |
+ goto error; |
|
66 |
+ } |
|
67 |
+ break; |
|
68 |
+ case 'V': |
|
69 |
+ printf("version: %s\n", version); |
|
70 |
+ printf("%s\n",id); |
|
71 |
+ exit(0); |
|
72 |
+ break; |
|
73 |
+ case 'h': |
|
74 |
+ printf("version: %s\n", version); |
|
75 |
+ printf("%s", help_msg); |
|
76 |
+ exit(0); |
|
77 |
+ break; |
|
78 |
+ case '?': |
|
79 |
+ if (isprint(optopt)) |
|
80 |
+ fprintf(stderr, "Unknown option `-%c�\n", optopt); |
|
81 |
+ else |
|
82 |
+ fprintf(stderr, "Unknown character `\\x%x�\n", optopt); |
|
83 |
+ goto error; |
|
84 |
+ case ':': |
|
85 |
+ fprintf(stderr, "Option `-%c� requires an argument.\n", |
|
86 |
+ optopt); |
|
87 |
+ goto error; |
|
88 |
+ break; |
|
89 |
+ default: |
|
90 |
+ abort(); |
|
91 |
+ } |
|
92 |
+ } |
|
93 |
+ |
|
94 |
+ /* check if all the required params are present */ |
|
95 |
+ if (address==0){ |
|
96 |
+ fprintf(stderr, "Missing -a address\n"); |
|
97 |
+ exit(-1); |
|
98 |
+ } |
|
99 |
+ if(count==0){ |
|
100 |
+ fprintf(stderr, "Missing count (-c number)\n"); |
|
101 |
+ exit(-1); |
|
102 |
+ }else if(count<0){ |
|
103 |
+ fprintf(stderr, "Invalid count (-c %d)\n", count); |
|
104 |
+ exit(-1); |
|
105 |
+ } |
|
106 |
+ |
|
107 |
+ |
|
108 |
+ |
|
109 |
+ /* flood loop */ |
|
110 |
+ for (r=0; r<count; r++){ |
|
111 |
+ if ((verbose>1)&&(r%1000)) putchar('.'); |
|
112 |
+ /* resolve destination loop */ |
|
113 |
+ he=gethostbyname(address); |
|
114 |
+ if (he==0){ |
|
115 |
+ errors++; |
|
116 |
+ if (verbose>1) |
|
117 |
+ putchar('?'); |
|
118 |
+ }else ok++; |
|
119 |
+ } |
|
120 |
+ |
|
121 |
+ printf("\n%d requests, %d succeeded, %d errors\n", count, ok, errors); |
|
122 |
+ |
|
123 |
+ exit(0); |
|
124 |
+ |
|
125 |
+error: |
|
126 |
+ exit(-1); |
|
127 |
+} |