... | ... |
@@ -32,6 +32,8 @@ DEFS=-DNOCR -DMACROEATER -DSTATS -DOLD_PARSER -DDNS_IP_HACK #-DNO_DEBUG |
32 | 32 |
#-DNO_LOG |
33 | 33 |
|
34 | 34 |
PROFILE= # -pg #set this if you want profiling |
35 |
+#mode=release |
|
36 |
+mode=debug |
|
35 | 37 |
|
36 | 38 |
# platform dependent settings |
37 | 39 |
|
... | ... |
@@ -40,8 +42,15 @@ ARCH = $(shell uname -s) |
40 | 42 |
#common |
41 | 43 |
CC=gcc |
42 | 44 |
LD=gcc |
43 |
-CFLAGS=-O2 -Wcast-align $(PROFILE) -Winline#-Wmissing-prototypes |
|
44 |
-LDFLAGS=-Wl,-O2 -Wl,-E $(PROFILE) |
|
45 |
+ |
|
46 |
+ifeq ( mode, release ) |
|
47 |
+ CFLAGS=-O2 -Wcast-align $(PROFILE) -Winline#-Wmissing-prototypes |
|
48 |
+ LDFLAGS=-Wl,-O2 -Wl,-E $(PROFILE) |
|
49 |
+else |
|
50 |
+ CFLAGS=-g |
|
51 |
+ LDFLAGS=-g |
|
52 |
+endif |
|
53 |
+ |
|
45 | 54 |
LEX=flex |
46 | 55 |
YACC=bison |
47 | 56 |
YACC_FLAGS=-d -b cfg |
... | ... |
@@ -127,3 +136,5 @@ proper: clean |
127 | 136 |
|
128 | 137 |
include $(depends) |
129 | 138 |
|
139 |
+dbg: ser |
|
140 |
+ gdb -command debug.gdb |
... | ... |
@@ -81,6 +81,7 @@ LISTEN listen |
81 | 81 |
DNS dns |
82 | 82 |
REV_DNS rev_dns |
83 | 83 |
PORT port |
84 |
+STAT statistics |
|
84 | 85 |
MAXBUFFER maxbuffer |
85 | 86 |
CHILDREN children |
86 | 87 |
CHECK_VIA check_via |
... | ... |
@@ -154,6 +155,7 @@ EAT_ABLE [\ \t\b\r] |
154 | 155 |
<INITIAL>{DNS} { count(); yylval.strval=yytext; return DNS; } |
155 | 156 |
<INITIAL>{REV_DNS} { count(); yylval.strval=yytext; return REV_DNS; } |
156 | 157 |
<INITIAL>{PORT} { count(); yylval.strval=yytext; return PORT; } |
158 |
+<INITIAL>{STAT} { count(); yylval.strval=yytext; return STAT; } |
|
157 | 159 |
<INITIAL>{MAXBUFFER} { count(); yylval.strval=yytext; return MAXBUFFER; } |
158 | 160 |
<INITIAL>{CHILDREN} { count(); yylval.strval=yytext; return CHILDREN; } |
159 | 161 |
<INITIAL>{CHECK_VIA} { count(); yylval.strval=yytext; return CHECK_VIA; } |
... | ... |
@@ -19,6 +19,7 @@ |
19 | 19 |
#include "dprint.h" |
20 | 20 |
#include "sr_module.h" |
21 | 21 |
|
22 |
+ |
|
22 | 23 |
#ifdef DEBUG_DMALLOC |
23 | 24 |
#include <dmalloc.h> |
24 | 25 |
#endif |
... | ... |
@@ -73,6 +74,7 @@ void* f_tmp; |
73 | 74 |
%token DNS |
74 | 75 |
%token REV_DNS |
75 | 76 |
%token PORT |
77 |
+%token STAT |
|
76 | 78 |
%token CHILDREN |
77 | 79 |
%token CHECK_VIA |
78 | 80 |
%token LOADMODULE |
... | ... |
@@ -147,6 +149,7 @@ assign_stm: DEBUG EQUAL NUMBER { debug=$3; } |
147 | 149 |
| REV_DNS EQUAL NUMBER { received_dns|= ($3)?DO_REV_DNS:0; } |
148 | 150 |
| REV_DNS EQUAL error { yyerror("boolean value expected"); } |
149 | 151 |
| PORT EQUAL NUMBER { port_no=$3; } |
152 |
+ | STAT EQUAL STRING { stat_file=$3; } |
|
150 | 153 |
| MAXBUFFER EQUAL NUMBER { maxbuffer=$3; } |
151 | 154 |
| MAXBUFFER EQUAL error { yyerror("number expected"); } |
152 | 155 |
| PORT EQUAL error { yyerror("number expected"); } |
... | ... |
@@ -431,20 +431,20 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p) |
431 | 431 |
|
432 | 432 |
p->tx++; |
433 | 433 |
p->tx_bytes+=new_len; |
434 |
-#ifdef STATS |
|
435 |
- stats.total_tx++; |
|
436 |
-#endif |
|
437 | 434 |
|
438 | 435 |
if (udp_send(new_buf, new_len, (struct sockaddr*) to, |
439 | 436 |
sizeof(struct sockaddr_in))==-1){ |
440 | 437 |
p->errors++; |
441 | 438 |
p->ok=0; |
439 |
+#ifdef STATS |
|
440 |
+ update_fail_on_send; |
|
441 |
+#endif |
|
442 | 442 |
goto error; |
443 | 443 |
} |
444 | 444 |
#ifdef STATS |
445 |
- else stats.ok_tx_rq++; |
|
445 |
+ /* sent requests stats */ |
|
446 |
+ else update_sent_request( msg->first_line.u.request.method_value ); |
|
446 | 447 |
#endif |
447 |
- |
|
448 | 448 |
free(new_buf); |
449 | 449 |
free(to); |
450 | 450 |
/* received_buf & line_buf will be freed in receiv_msg by free_lump_list*/ |
... | ... |
@@ -552,17 +552,19 @@ int forward_reply(struct sip_msg* msg) |
552 | 552 |
to->sin_port = (msg->via2.port)?htons(msg->via2.port):htons(SIP_PORT); |
553 | 553 |
to->sin_addr.s_addr=*((long*)he->h_addr_list[0]); |
554 | 554 |
|
555 |
-#ifdef STATS |
|
556 |
- stats.total_tx++; |
|
557 |
-#endif |
|
558 | 555 |
#ifdef DNS_IP_HACK |
559 | 556 |
} |
560 | 557 |
#endif |
561 | 558 |
if (udp_send(new_buf,new_len, (struct sockaddr*) to, |
562 |
- sizeof(struct sockaddr_in))==-1) |
|
559 |
+ sizeof(struct sockaddr_in))==-1) |
|
560 |
+ { |
|
561 |
+#ifdef STATS |
|
562 |
+ update_fail_on_send; |
|
563 |
+#endif |
|
563 | 564 |
goto error; |
565 |
+ } |
|
564 | 566 |
#ifdef STATS |
565 |
- else stats.ok_tx_rs++; |
|
567 |
+ else update_sent_response( msg->first_line.u.reply.statusclass ); |
|
566 | 568 |
#endif |
567 | 569 |
|
568 | 570 |
free(new_buf); |
... | ... |
@@ -13,6 +13,10 @@ |
13 | 13 |
#include <netinet/in.h> |
14 | 14 |
#include <arpa/inet.h> |
15 | 15 |
#include <sys/utsname.h> |
16 |
+#include <sys/types.h> |
|
17 |
+#include <sys/mman.h> |
|
18 |
+#include <sys/fcntl.h> |
|
19 |
+#include <sys/time.h> |
|
16 | 20 |
|
17 | 21 |
#include "config.h" |
18 | 22 |
#include "dprint.h" |
... | ... |
@@ -26,8 +30,6 @@ |
26 | 30 |
#include "stats.h" |
27 | 31 |
#endif |
28 | 32 |
|
29 |
- |
|
30 |
- |
|
31 | 33 |
#ifdef DEBUG_DMALLOC |
32 | 34 |
#include <dmalloc.h> |
33 | 35 |
#endif |
... | ... |
@@ -94,8 +96,11 @@ Options:\n\ |
94 | 96 |
-V Version number\n\ |
95 | 97 |
-h This help message\n\ |
96 | 98 |
-b nr Maximum receive buffer size which will not be exceeded by\n\ |
97 |
- auto-probing procedure even if OS allows\n\ |
|
98 |
-"; |
|
99 |
+ auto-probing procedure even if OS allows\n" |
|
100 |
+#ifdef STATS |
|
101 |
+" -s file File to which statistics is dumped (disabled otherwise)\n" |
|
102 |
+#endif |
|
103 |
+; |
|
99 | 104 |
|
100 | 105 |
/* print compile-time constants */ |
101 | 106 |
void print_ct_constants() |
... | ... |
@@ -127,9 +132,9 @@ char* cfg_file = 0; |
127 | 132 |
unsigned short port_no = 0; /* port on which we listen */ |
128 | 133 |
char port_no_str[MAX_PORT_LEN]; |
129 | 134 |
int port_no_str_len=0; |
130 |
-unsigned int maxbuffer = 128*1024; /* maximum buffer size we do not want to exceed |
|
131 |
- durig the auto-probing procedure; may be |
|
132 |
- re-configured */ |
|
135 |
+unsigned int maxbuffer = MAX_RECV_BUFFER_SIZE; /* maximum buffer size we do not want to exceed |
|
136 |
+ durig the auto-probing procedure; may be |
|
137 |
+ re-configured */ |
|
133 | 138 |
int children_no = 0; /* number of children processing requests */ |
134 | 139 |
int debug = 0; |
135 | 140 |
int dont_fork = 0; |
... | ... |
@@ -151,11 +156,6 @@ int process_no = 0; |
151 | 156 |
/* cfg parsing */ |
152 | 157 |
int cfg_errors=0; |
153 | 158 |
|
154 |
-#ifdef STATS |
|
155 |
-/* jku: RX/TX statistics -- remember, they are process specific */ |
|
156 |
-struct stats_s stats; |
|
157 |
-#endif |
|
158 |
- |
|
159 | 159 |
|
160 | 160 |
#define MAX_FD 32 /* maximum number of inherited open file descriptors, |
161 | 161 |
(normally it shouldn't be bigger than 3) */ |
... | ... |
@@ -226,6 +226,9 @@ int main_loop() |
226 | 226 |
|
227 | 227 |
|
228 | 228 |
if (dont_fork){ |
229 |
+#ifdef STATS |
|
230 |
+ setstats( 0 ); |
|
231 |
+#endif |
|
229 | 232 |
/* only one address */ |
230 | 233 |
if (udp_init(addresses[0],port_no)==-1) goto error; |
231 | 234 |
/* receive loop */ |
... | ... |
@@ -241,6 +244,9 @@ int main_loop() |
241 | 244 |
} |
242 | 245 |
if (pid==0){ |
243 | 246 |
/* child */ |
247 |
+#ifdef STATS |
|
248 |
+ setstats( i ); |
|
249 |
+#endif |
|
244 | 250 |
return udp_rcv_loop(); |
245 | 251 |
} |
246 | 252 |
} |
... | ... |
@@ -260,6 +266,7 @@ int main_loop() |
260 | 266 |
|
261 | 267 |
} |
262 | 268 |
|
269 |
+ |
|
263 | 270 |
/* added by jku; allows for regular exit on a specific signal; |
264 | 271 |
good for profiling which only works if exited regularly and |
265 | 272 |
not by default signal handlers |
... | ... |
@@ -267,17 +274,25 @@ int main_loop() |
267 | 274 |
|
268 | 275 |
static void sig_usr(int signo) |
269 | 276 |
{ |
270 |
- DPrint("INT received, program terminates\n"); |
|
277 |
+ if (signo==SIGINT) { /* exit gracefuly */ |
|
271 | 278 |
#ifdef STATS |
272 |
- DPrint("ok_rx_rq\t%d\nok_rx_rs\t%d\nok_tx_rq\t%d\nok_tx_rs\t%d\ntotal_rx\t%d\ntotal_tx\t%d\n\n", |
|
273 |
- stats.ok_rx_rq, stats.ok_rx_rs, stats.ok_tx_rq, stats.ok_tx_rs, stats.total_rx, stats.total_tx ); |
|
274 |
- DPrint("Thank you for flying ser\n"); |
|
279 |
+ /* print statistics on exit only for the first process */ |
|
280 |
+ |
|
281 |
+ if (stats->process_index==0 && stat_file ) |
|
282 |
+ if (dump_all_statistic()==0) |
|
283 |
+ printf("statistic dumped to %s\n", stat_file ); |
|
284 |
+ else |
|
285 |
+ printf("statistics dump to %s failed\n", stat_file ); |
|
275 | 286 |
#endif |
276 |
- exit(0); |
|
287 |
+ DPrint("INT received, program terminates\n"); |
|
288 |
+ DPrint("Thank you for flying ser\n"); |
|
289 |
+ exit(0); |
|
290 |
+ } else if (signo==SIGUSR1) { /* statistic */ |
|
291 |
+ dump_all_statistic(); |
|
292 |
+ } |
|
277 | 293 |
} |
278 | 294 |
|
279 | 295 |
|
280 |
- |
|
281 | 296 |
int main(int argc, char** argv) |
282 | 297 |
{ |
283 | 298 |
|
... | ... |
@@ -286,20 +301,36 @@ int main(int argc, char** argv) |
286 | 301 |
int c,r; |
287 | 302 |
char *tmp; |
288 | 303 |
struct utsname myname; |
304 |
+ char *options; |
|
289 | 305 |
|
290 | 306 |
/* added by jku: add exit handler */ |
291 | 307 |
if (signal(SIGINT, sig_usr) == SIG_ERR ) { |
292 |
- DPrint("ERROR: no signal handler can be installed\n"); |
|
308 |
+ DPrint("ERROR: no SIGINT signal handler can be installed\n"); |
|
309 |
+ goto error; |
|
310 |
+ } |
|
311 |
+#ifdef STATS |
|
312 |
+ if (signal(SIGUSR1, sig_usr) == SIG_ERR ) { |
|
313 |
+ DPrint("ERROR: no SIGUSR1 signal handler can be installed\n"); |
|
293 | 314 |
goto error; |
294 | 315 |
} |
316 |
+#endif |
|
295 | 317 |
|
296 | 318 |
/* process command line (get port no, cfg. file path etc) */ |
297 | 319 |
opterr=0; |
298 |
- while((c=getopt(argc,argv,"f:p:b:l:n:rRvdDEVh"))!=-1){ |
|
320 |
+ options= |
|
321 |
+#ifdef STATS |
|
322 |
+ "s:" |
|
323 |
+#endif |
|
324 |
+ "f:p:b:l:n:rRvdDEVh"; |
|
325 |
+ |
|
326 |
+ while((c=getopt(argc,argv,options))!=-1){ |
|
299 | 327 |
switch(c){ |
300 | 328 |
case 'f': |
301 | 329 |
cfg_file=optarg; |
302 | 330 |
break; |
331 |
+ case 's': |
|
332 |
+ stat_file=optarg; |
|
333 |
+ break; |
|
303 | 334 |
case 'p': |
304 | 335 |
port_no=strtol(optarg, &tmp, 10); |
305 | 336 |
if (tmp &&(*tmp)){ |
... | ... |
@@ -448,10 +479,6 @@ int main(int argc, char** argv) |
448 | 479 |
names_len[r]=strlen(names[r]); |
449 | 480 |
} |
450 | 481 |
|
451 |
-#ifdef STATS |
|
452 |
- /* jku: initialize statistic */ |
|
453 |
- memset(&stats,0,sizeof(struct stats_s)); |
|
454 |
-#endif |
|
455 | 482 |
|
456 | 483 |
/* get ips */ |
457 | 484 |
printf("Listening on "); |
... | ... |
@@ -467,6 +494,10 @@ int main(int argc, char** argv) |
467 | 494 |
(unsigned short)port_no); |
468 | 495 |
} |
469 | 496 |
|
497 |
+#ifdef STATS |
|
498 |
+ if (init_stats( dont_fork ? 1 : children_no )==-1) goto error; |
|
499 |
+#endif |
|
500 |
+ |
|
470 | 501 |
/* init_daemon? */ |
471 | 502 |
if (!dont_fork){ |
472 | 503 |
if ( daemonize(argv[0]) <0 ) goto error; |
... | ... |
@@ -34,8 +34,9 @@ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl) |
34 | 34 |
char* third; |
35 | 35 |
char* nl; |
36 | 36 |
int offset; |
37 |
- int l; |
|
37 |
+ /* int l; */ |
|
38 | 38 |
char* end; |
39 |
+ char s1,s2,s3; |
|
39 | 40 |
|
40 | 41 |
/* grammar: |
41 | 42 |
request = method SP uri SP version CRLF |
... | ... |
@@ -46,37 +47,72 @@ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl) |
46 | 47 |
|
47 | 48 |
end=buffer+len; |
48 | 49 |
/* see if it's a reply (status) */ |
49 |
- tmp=eat_token(buffer, len); |
|
50 |
- if ((tmp==buffer)||(tmp>=end)){ |
|
51 |
- LOG(L_INFO, "ERROR:parse_first_line: empty or bad first line\n"); |
|
50 |
+ |
|
51 |
+ /* jku -- parse well-known methods */ |
|
52 |
+ |
|
53 |
+ /* drop messages which are so short they are for sure useless; |
|
54 |
+ utilize knowledge of minimum size in parsing the first |
|
55 |
+ token |
|
56 |
+ */ |
|
57 |
+ if (len <=16 ) { |
|
58 |
+ LOG(L_INFO, "ERROR: parse_first_line: message too short\n"); |
|
52 | 59 |
goto error1; |
53 | 60 |
} |
54 |
- l=tmp-buffer; |
|
55 |
- if ((SIP_VERSION_LEN==l) && |
|
56 |
- (memcmp(buffer,SIP_VERSION,l)==0)){ |
|
57 |
- |
|
58 |
- fl->type=SIP_REPLY; |
|
59 |
- }else{ |
|
61 |
+ |
|
62 |
+ tmp=buffer; |
|
63 |
+ /* is it perhaps a reply, ie does it start with "SIP...." ? */ |
|
64 |
+ if ( (*tmp=='S' || *tmp=='s') && |
|
65 |
+ strncasecmp( tmp+1, SIP_VERSION+1, SIP_VERSION_LEN-1)==0 && |
|
66 |
+ (*(tmp+SIP_VERSION_LEN)==' ')) { |
|
67 |
+ fl->type=SIP_REPLY; |
|
68 |
+ fl->u.reply.version.len=SIP_VERSION_LEN; |
|
69 |
+ tmp=buffer+SIP_VERSION_LEN; |
|
70 |
+ } else IFISMETHOD( INVITE, 'I' ) |
|
71 |
+ else IFISMETHOD( CANCEL, 'C') |
|
72 |
+ else IFISMETHOD( ACK, 'A' ) |
|
73 |
+ else IFISMETHOD( BYE, 'B' ) |
|
74 |
+ /* if you want to add another method XXX, include METHOD_XXX in |
|
75 |
+ H-file (this is the value which you will take later in |
|
76 |
+ processing and define XXX_LEN as length of method name; |
|
77 |
+ then just call IFISMETHOD( XXX, 'X' ) ... 'X' is the first |
|
78 |
+ latter; everything must be capitals |
|
79 |
+ */ |
|
80 |
+ else { |
|
81 |
+ /* neither reply, nor any of known method requests, |
|
82 |
+ let's believe it is an unknown method request |
|
83 |
+ */ |
|
84 |
+ tmp=eat_token_end(buffer,buffer+len); |
|
85 |
+ if ((tmp==buffer)||(tmp>=end)){ |
|
86 |
+ LOG(L_INFO, "ERROR:parse_first_line: empty or bad first line\n"); |
|
87 |
+ goto error1; |
|
88 |
+ } |
|
89 |
+ if (*tmp!=' ') { |
|
90 |
+ LOG(L_INFO, "ERROR:parse_first_line: method not followed by SP\n"); |
|
91 |
+ goto error1; |
|
92 |
+ } |
|
60 | 93 |
fl->type=SIP_REQUEST; |
94 |
+ fl->u.request.method_value=METHOD_OTHER; |
|
95 |
+ fl->u.request.method.len=tmp-buffer; |
|
61 | 96 |
} |
62 |
- |
|
63 |
- offset=l; |
|
64 |
- second=eat_space(tmp, len-offset); |
|
65 |
- offset+=second-tmp; |
|
66 |
- if ((second==tmp)||(tmp>=end)){ |
|
67 |
- goto error; |
|
68 |
- } |
|
69 |
- *tmp=0; /* mark the end of the token */ |
|
70 |
- fl->u.request.method.s=buffer; |
|
71 |
- fl->u.request.method.len=l; |
|
97 |
+ |
|
98 |
+ |
|
99 |
+ /* identifying type of message over now; |
|
100 |
+ tmp points at space after; go ahead */ |
|
101 |
+ |
|
102 |
+ fl->u.request.method.s=buffer; /* store ptr to first token */ |
|
103 |
+ (*tmp)=0; /* mark the 1st token end */ |
|
104 |
+ second=tmp+1; /* jump to second token */ |
|
105 |
+ offset=second-buffer; |
|
106 |
+ |
|
107 |
+/* EoJku */ |
|
72 | 108 |
|
73 | 109 |
/* next element */ |
74 |
- tmp=eat_token(second, len-offset); |
|
110 |
+ tmp=eat_token_end(second, second+len-offset); |
|
75 | 111 |
if (tmp>=end){ |
76 | 112 |
goto error; |
77 | 113 |
} |
78 | 114 |
offset+=tmp-second; |
79 |
- third=eat_space(tmp, len-offset); |
|
115 |
+ third=eat_space_end(tmp, tmp+len-offset); |
|
80 | 116 |
offset+=third-tmp; |
81 | 117 |
if ((third==tmp)||(tmp>=end)){ |
82 | 118 |
goto error; |
... | ... |
@@ -85,20 +121,41 @@ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl) |
85 | 121 |
fl->u.request.uri.s=second; |
86 | 122 |
fl->u.request.uri.len=tmp-second; |
87 | 123 |
|
124 |
+ /* jku: parse status code */ |
|
125 |
+ if (fl->type==SIP_REPLY) { |
|
126 |
+ if (fl->u.request.uri.len!=3) { |
|
127 |
+ LOG(L_INFO, "ERROR:parse_first_line: len(status code)!=3: %s\n", |
|
128 |
+ second ); |
|
129 |
+ goto error; |
|
130 |
+ } |
|
131 |
+ s1=*second; s2=*(second+1);s3=*(second+2); |
|
132 |
+ if (s1>='0' && s1<='9' && |
|
133 |
+ s2>='0' && s2<='9' && |
|
134 |
+ s3>='0' && s3<='9' ) { |
|
135 |
+ fl->u.reply.statusclass=s1-'0'; |
|
136 |
+ fl->u.reply.statuscode=fl->u.reply.statusclass*100+10*(s2-'0')+(s3-'0'); |
|
137 |
+ } else { |
|
138 |
+ LOG(L_INFO, "ERROR:parse_first_line: status_code non-numerical: %s\n", |
|
139 |
+ second ); |
|
140 |
+ goto error; |
|
141 |
+ } |
|
142 |
+ } |
|
143 |
+ /* EoJku */ |
|
144 |
+ |
|
88 | 145 |
/* last part: for a request it must be the version, for a reply |
89 | 146 |
* it can contain almost anything, including spaces, so we don't care |
90 | 147 |
* about it*/ |
91 | 148 |
if (fl->type==SIP_REQUEST){ |
92 |
- tmp=eat_token(third,len-offset); |
|
149 |
+ tmp=eat_token_end(third,third+len-offset); |
|
93 | 150 |
offset+=tmp-third; |
94 | 151 |
if ((tmp==third)||(tmp>=end)){ |
95 | 152 |
goto error; |
96 | 153 |
} |
97 |
- if (! is_empty(tmp, len-offset)){ |
|
154 |
+ if (! is_empty_end(tmp, tmp+len-offset)){ |
|
98 | 155 |
goto error; |
99 | 156 |
} |
100 | 157 |
}else{ |
101 |
- tmp=eat_token2(third,len-offset,'\r'); /* find end of line |
|
158 |
+ tmp=eat_token2_end(third,third+len-offset,'\r'); /* find end of line |
|
102 | 159 |
('\n' or '\r') */ |
103 | 160 |
if (tmp>=end){ /* no crlf in packet => invalid */ |
104 | 161 |
goto error; |
... | ... |
@@ -240,22 +297,22 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field* hdr_f) |
240 | 297 |
return tmp; |
241 | 298 |
} |
242 | 299 |
|
243 |
- tmp=eat_token2(buffer, len, ':'); |
|
300 |
+ tmp=eat_token2_end(buffer, buffer+len, ':'); |
|
244 | 301 |
if ((tmp==buffer) || (tmp-buffer==len) || |
245 |
- (is_empty(buffer, tmp-buffer))|| (*tmp!=':')){ |
|
302 |
+ (is_empty_end(buffer, tmp))|| (*tmp!=':')){ |
|
246 | 303 |
hdr_f->type=HDR_ERROR; |
247 | 304 |
goto error; |
248 | 305 |
} |
249 | 306 |
*tmp=0; |
250 | 307 |
/* take care of possible spaces (e.g: "Via :") */ |
251 |
- tmp2=eat_token(buffer, tmp-buffer); |
|
308 |
+ tmp2=eat_token_end(buffer, tmp); |
|
252 | 309 |
/* in the worst case tmp2=buffer+tmp-buffer=tmp */ |
253 | 310 |
*tmp2=0; |
254 | 311 |
l=tmp2-buffer; |
255 | 312 |
if (tmp2<tmp){ |
256 | 313 |
tmp2++; |
257 | 314 |
/* catch things like: "Via foo bar:" */ |
258 |
- tmp2=eat_space(tmp2, tmp-tmp2); |
|
315 |
+ tmp2=eat_space_end(tmp2, tmp); |
|
259 | 316 |
if (tmp2!=tmp){ |
260 | 317 |
hdr_f->type=HDR_ERROR; |
261 | 318 |
goto error; |
... | ... |
@@ -492,33 +549,33 @@ char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb) |
492 | 549 |
|
493 | 550 |
name=version=transport=comment=params=hostport=next_via=host.s=0; |
494 | 551 |
name_len=version_len=transport_len=comment_len=params_len=host.len=0; |
495 |
- name=eat_space(buffer, len); |
|
552 |
+ name=eat_space_end(buffer, buffer+len); |
|
496 | 553 |
if (name-buffer==len) goto error; |
497 | 554 |
offset=name-buffer; |
498 | 555 |
tmp=name; |
499 | 556 |
|
500 |
- version=eat_token2(tmp,len-offset,'/'); |
|
557 |
+ version=eat_token2_end(tmp,tmp+len-offset,'/'); |
|
501 | 558 |
if (version+1-buffer>=len) goto error; |
502 | 559 |
*version=0; |
503 | 560 |
name_len=version-name; |
504 | 561 |
version++; |
505 | 562 |
offset+=version-tmp; |
506 | 563 |
|
507 |
- transport=eat_token2(tmp,len-offset,'/'); |
|
564 |
+ transport=eat_token2_end(tmp,tmp+len-offset,'/'); |
|
508 | 565 |
if (transport+1-buffer>=len) goto error; |
509 | 566 |
*transport=0; |
510 | 567 |
version_len=transport-version; |
511 | 568 |
transport++; |
512 | 569 |
offset+=transport-tmp; |
513 | 570 |
|
514 |
- tmp=eat_token(transport,len-offset); |
|
571 |
+ tmp=eat_token_end(transport,transport+len-offset); |
|
515 | 572 |
if (tmp+1-buffer>=len) goto error; |
516 | 573 |
*tmp=0; |
517 | 574 |
transport_len=tmp-transport; |
518 | 575 |
tmp++; |
519 | 576 |
offset+=tmp-transport; |
520 | 577 |
|
521 |
- hostport=eat_space(tmp,len-offset); |
|
578 |
+ hostport=eat_space_end(tmp,tmp+len-offset); |
|
522 | 579 |
if (hostport+1-buffer>=len) goto error; |
523 | 580 |
offset+=hostport-tmp; |
524 | 581 |
|
... | ... |
@@ -18,7 +18,21 @@ enum { HDR_EOH=-1, HDR_ERROR=0, HDR_OTHER, |
18 | 18 |
HDR_MAXFORWARDS, HDR_ROUTE |
19 | 19 |
}; |
20 | 20 |
|
21 |
- |
|
21 |
+#define INVITE_LEN 6 |
|
22 |
+#define ACK_LEN 3 |
|
23 |
+#define CANCEL_LEN 6 |
|
24 |
+#define BYE_LEN 3 |
|
25 |
+enum { METHOD_OTHER, METHOD_INVITE, METHOD_CANCEL, METHOD_ACK, METHOD_BYE }; |
|
26 |
+ |
|
27 |
+#define IFISMETHOD(methodname,firstchar) \ |
|
28 |
+if ( (*tmp==(firstchar) || *tmp==((firstchar) | 32)) && \ |
|
29 |
+ strncasecmp( tmp+1, #methodname +1, methodname##_LEN-1)==0 && \ |
|
30 |
+ *(tmp+methodname##_LEN)==' ') { \ |
|
31 |
+ fl->type=SIP_REQUEST; \ |
|
32 |
+ fl->u.request.method.len=methodname##_LEN; \ |
|
33 |
+ fl->u.request.method_value=METHOD_##methodname; \ |
|
34 |
+ tmp=buffer+methodname##_LEN; \ |
|
35 |
+} |
|
22 | 36 |
|
23 | 37 |
|
24 | 38 |
#define VIA_PARSE_OK 1 |
... | ... |
@@ -35,11 +49,13 @@ struct msg_start{ |
35 | 49 |
str method; |
36 | 50 |
str uri; |
37 | 51 |
str version; |
52 |
+ short method_value; |
|
38 | 53 |
}request; |
39 | 54 |
struct { |
40 | 55 |
str version; |
41 | 56 |
str status; |
42 | 57 |
str reason; |
58 |
+ unsigned short statusclass, statuscode; |
|
43 | 59 |
}reply; |
44 | 60 |
}u; |
45 | 61 |
}; |
... | ... |
@@ -41,6 +41,9 @@ char* eat_line(char* buffer, unsigned int len) |
41 | 41 |
|
42 | 42 |
/* returns pointer to first non white char or after the end of the buffer */ |
43 | 43 |
|
44 |
+/* MACROEATER no more optional */ |
|
45 |
+ |
|
46 |
+/* |
|
44 | 47 |
#ifndef MACROEATER |
45 | 48 |
|
46 | 49 |
char* eat_space(char* buffer, unsigned int len) |
... | ... |
@@ -52,7 +55,7 @@ char* eat_space(char* buffer, unsigned int len) |
52 | 55 |
} |
53 | 56 |
|
54 | 57 |
|
55 |
-/* returns pointer after the token (first whitespace char or CR/LF) */ |
|
58 |
+// returns pointer after the token (first whitespace char or CR/LF) |
|
56 | 59 |
char* eat_token(char* buffer, unsigned int len) |
57 | 60 |
{ |
58 | 61 |
char *p; |
... | ... |
@@ -65,7 +68,7 @@ char* eat_token(char* buffer, unsigned int len) |
65 | 68 |
|
66 | 69 |
|
67 | 70 |
|
68 |
-/* returns pointer after the token (first delim char or CR/LF) */ |
|
71 |
+// returns pointer after the token (first delim char or CR/LF) |
|
69 | 72 |
char* eat_token2(char* buffer, unsigned int len, char delim) |
70 | 73 |
{ |
71 | 74 |
char *p; |
... | ... |
@@ -75,18 +78,8 @@ char* eat_token2(char* buffer, unsigned int len, char delim) |
75 | 78 |
p++); |
76 | 79 |
return p; |
77 | 80 |
} |
78 |
- |
|
79 |
-/* EoMACROEATER */ |
|
80 | 81 |
#endif |
82 |
+*/ |
|
81 | 83 |
|
84 |
+/* EoMACROEATER */ |
|
82 | 85 |
|
83 |
- |
|
84 |
-/* returns true if line started at buffer contains only white space */ |
|
85 |
-int is_empty(char* buffer, unsigned int len) |
|
86 |
-{ |
|
87 |
- char *p; |
|
88 |
- |
|
89 |
- p=eat_space(buffer, len); |
|
90 |
- if ((p < buffer+len ) && (*p=='\r' || *p=='\n')) return 1; |
|
91 |
- return 0; |
|
92 |
-} |
... | ... |
@@ -6,36 +6,47 @@ |
6 | 6 |
#define parser_f_h |
7 | 7 |
|
8 | 8 |
char* eat_line(char* buffer, unsigned int len); |
9 |
+ |
|
10 |
+/* macro now |
|
9 | 11 |
int is_empty(char* buffer, unsigned int len); |
12 |
+*/ |
|
10 | 13 |
|
11 |
-#ifdef MACROEATER |
|
14 |
+/* MACROEATER no more optional */ |
|
15 |
+/* #ifdef MACROEATER */ |
|
12 | 16 |
|
13 | 17 |
/* turn the most frequently called functions into macros */ |
14 | 18 |
|
15 | 19 |
|
16 |
-#define eat_space(buffer,len) \ |
|
17 |
- ( { char *p; \ |
|
18 |
- for(p=(buffer);(p<(buffer)+(len))&& (*p==' ' || *p=='\t') ;p++);\ |
|
20 |
+#define eat_space_end(buffer,pend) \ |
|
21 |
+ ( { char *p; \ |
|
22 |
+ for(p=(buffer);(p<pend)&& (*p==' ' || *p=='\t') ;p++); \ |
|
19 | 23 |
p; \ |
20 | 24 |
} ) |
21 | 25 |
|
22 |
-#define eat_token(buffer,len) \ |
|
23 |
- ( { char *p; \ |
|
24 |
- for (p=(buffer);(p<(buffer)+(len))&& \ |
|
26 |
+#define eat_token_end(buffer,pend) \ |
|
27 |
+ ( { char *p ; \ |
|
28 |
+ for (p=(buffer);(p<pend)&& \ |
|
25 | 29 |
(*p!=' ')&&(*p!='\t')&&(*p!='\n')&&(*p!='\r'); \ |
26 | 30 |
p++); \ |
27 | 31 |
p; \ |
28 | 32 |
} ) |
29 | 33 |
|
30 |
-#define eat_token2(buffer,len,delim) \ |
|
31 |
- ( { char *p; \ |
|
32 |
- for (p=(buffer);(p<(buffer)+(len))&& \ |
|
34 |
+#define eat_token2_end(buffer,pend,delim) \ |
|
35 |
+ ( { char *p ; \ |
|
36 |
+ for (p=(buffer);(p<pend)&& \ |
|
33 | 37 |
(*p!=(delim))&&(*p!='\n')&&(*p!='\r'); \ |
34 | 38 |
p++); \ |
35 | 39 |
p; \ |
36 | 40 |
} ) |
37 | 41 |
|
42 |
+#define is_empty_end(buffer, pend ) \ |
|
43 |
+ ( { char *p; \ |
|
44 |
+ p=eat_space_end( buffer, pend ); \ |
|
45 |
+ ((p<pend ) && (*p=='\r' || *p=='\n')) ? 1 : 0; \ |
|
46 |
+ } ) |
|
47 |
+ |
|
38 | 48 |
|
49 |
+/* |
|
39 | 50 |
#else |
40 | 51 |
|
41 | 52 |
|
... | ... |
@@ -43,7 +54,8 @@ char* eat_space(char* buffer, unsigned int len); |
43 | 54 |
char* eat_token(char* buffer, unsigned int len); |
44 | 55 |
char* eat_token2(char* buffer, unsigned int len, char delim); |
45 | 56 |
|
46 |
-/* EoMACROEATER */ |
|
47 | 57 |
#endif |
58 |
+*/ |
|
59 |
+/* EoMACROEATER */ |
|
48 | 60 |
|
49 | 61 |
#endif |
... | ... |
@@ -24,9 +24,8 @@ |
24 | 24 |
int receive_msg(char* buf, unsigned int len, unsigned long src_ip) |
25 | 25 |
{ |
26 | 26 |
struct sip_msg msg; |
27 |
- |
|
28 | 27 |
#ifdef STATS |
29 |
- stats.total_rx++; |
|
28 |
+ int skipped = 1; |
|
30 | 29 |
#endif |
31 | 30 |
|
32 | 31 |
memset(&msg,0, sizeof(struct sip_msg)); /* init everything to 0 */ |
... | ... |
@@ -65,8 +64,8 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip) |
65 | 64 |
goto error; |
66 | 65 |
} |
67 | 66 |
#ifdef STATS |
68 |
- /* jku -- update statistics */ |
|
69 |
- else stats.ok_rx_rq++; |
|
67 |
+ /* jku -- update request statistics */ |
|
68 |
+ else update_received_request( msg.first_line.u.request.method_value ); |
|
70 | 69 |
#endif |
71 | 70 |
}else if (msg.first_line.type==SIP_REPLY){ |
72 | 71 |
DBG("msg= reply\n"); |
... | ... |
@@ -83,7 +82,7 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip) |
83 | 82 |
|
84 | 83 |
#ifdef STATS |
85 | 84 |
/* jku -- update statistics */ |
86 |
- stats.ok_rx_rs++; |
|
85 |
+ update_received_response( msg.first_line.u.reply.statusclass ); |
|
87 | 86 |
#endif |
88 | 87 |
|
89 | 88 |
/* send the msg */ |
... | ... |
@@ -93,11 +92,17 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip) |
93 | 92 |
(unsigned short) msg.via2.port); |
94 | 93 |
} |
95 | 94 |
} |
95 |
+#ifdef STATS |
|
96 |
+ skipped = 0; |
|
97 |
+#endif |
|
96 | 98 |
skip: |
97 | 99 |
if (msg.new_uri.s) { free(msg.new_uri.s); msg.new_uri.len=0; } |
98 | 100 |
if (msg.add_rm) free_lump_list(msg.add_rm); |
99 | 101 |
if (msg.repl_add_rm) free_lump_list(msg.repl_add_rm); |
100 | 102 |
free(msg.orig); |
103 |
+#ifdef STATS |
|
104 |
+ if (skipped) update_received_drops; |
|
105 |
+#endif |
|
101 | 106 |
return 0; |
102 | 107 |
error: |
103 | 108 |
if (msg.new_uri.s) free(msg.new_uri.s); |
... | ... |
@@ -105,6 +110,9 @@ error: |
105 | 110 |
if (msg.repl_add_rm) free_lump_list(msg.repl_add_rm); |
106 | 111 |
free(msg.orig); |
107 | 112 |
error1: |
113 |
+#ifdef STATS |
|
114 |
+ update_received_drops; |
|
115 |
+#endif |
|
108 | 116 |
return -1; |
109 | 117 |
} |
110 | 118 |
|
... | ... |
@@ -1,22 +1,120 @@ |
1 | 1 |
#ifndef stats_h |
2 | 2 |
#define stats_h |
3 | 3 |
|
4 |
+#include <ctype.h> |
|
5 |
+#include <sys/mman.h> |
|
6 |
+#include <sys/fcntl.h> |
|
7 |
+#include <sys/time.h> |
|
8 |
+#include <time.h> |
|
9 |
+#include <sys/utsname.h> |
|
10 |
+#include <stdio.h> |
|
11 |
+#include <stdlib.h> |
|
12 |
+#include <errno.h> |
|
13 |
+ |
|
14 |
+ |
|
15 |
+ |
|
4 | 16 |
#ifdef STATS |
5 | 17 |
|
18 |
+ |
|
6 | 19 |
struct stats_s { |
7 | 20 |
|
8 |
- /* total/valid, received/sent, request/response */ |
|
9 |
- unsigned long ok_rx_rq, |
|
10 |
- ok_rx_rs, |
|
11 |
- ok_tx_rq, |
|
12 |
- ok_tx_rs, |
|
13 |
- total_rx, |
|
14 |
- total_tx; |
|
21 |
+ unsigned int process_index; |
|
22 |
+ pid_t pid; |
|
23 |
+ time_t start_time; |
|
24 |
+ |
|
25 |
+ unsigned long |
|
26 |
+ |
|
27 |
+ /* received packets */ |
|
28 |
+ |
|
29 |
+ received_requests_inv, /* received_requests */ |
|
30 |
+ received_requests_ack, |
|
31 |
+ received_requests_cnc, |
|
32 |
+ received_requests_bye, |
|
33 |
+ received_requests_other, |
|
34 |
+ |
|
35 |
+ received_responses_1, /* received_requests */ |
|
36 |
+ received_responses_2, |
|
37 |
+ received_responses_3, |
|
38 |
+ received_responses_4, |
|
39 |
+ received_responses_5, |
|
40 |
+ received_responses_6, |
|
41 |
+ received_responses_other, |
|
42 |
+ |
|
43 |
+ received_drops, /* all messages we received and did not process |
|
44 |
+ successfully; reasons include SIP sanity checks |
|
45 |
+ (missing Vias, neither request nor response, |
|
46 |
+ failed parsing), ser errors (malloc, action |
|
47 |
+ failure) |
|
48 |
+ */ |
|
49 |
+ |
|
50 |
+ /* sent */ |
|
51 |
+ |
|
52 |
+ /* sent_requests */ |
|
53 |
+ sent_requests_inv, |
|
54 |
+ sent_requests_ack, |
|
55 |
+ sent_requests_cnc, |
|
56 |
+ sent_requests_bye, |
|
57 |
+ sent_requests_other, |
|
58 |
+ |
|
59 |
+ /* sent responses */ |
|
60 |
+ sent_responses_1, |
|
61 |
+ sent_responses_2, |
|
62 |
+ sent_responses_3, |
|
63 |
+ sent_responses_4, |
|
64 |
+ sent_responses_5, |
|
65 |
+ sent_responses_6, |
|
66 |
+ |
|
67 |
+ failed_on_send; |
|
68 |
+ |
|
15 | 69 |
}; |
16 | 70 |
|
17 | 71 |
|
18 |
-extern struct stats_s stats; |
|
72 |
+extern struct stats_s *stats; |
|
19 | 73 |
|
20 |
-#endif |
|
74 |
+void setstats( int child_index ); |
|
75 |
+void dump_statistic( FILE *fp, struct stats_s *istats ); |
|
76 |
+int dump_all_statistic(); |
|
77 |
+int init_stats( int nr_of_processes ); |
|
78 |
+ |
|
79 |
+#define _update_request( method, dir ) \ |
|
80 |
+ { if (stat_file!=NULL) switch( method ) { \ |
|
81 |
+ case METHOD_INVITE: stats->dir##_requests_inv++; break; \ |
|
82 |
+ case METHOD_ACK: stats->dir##_requests_ack++; break; \ |
|
83 |
+ case METHOD_CANCEL: stats->dir##_requests_cnc++; break; \ |
|
84 |
+ case METHOD_BYE: stats->dir##_requests_bye++; break; \ |
|
85 |
+ case METHOD_OTHER: stats->dir##_requests_other++; break; \ |
|
86 |
+ default: LOG(L_ERR, "ERROR: unknown method in rq stats (%s)\n", #dir); \ |
|
87 |
+ } \ |
|
88 |
+ } |
|
89 |
+ |
|
90 |
+#define update_received_request( method ) _update_request( method, received ) |
|
91 |
+#define update_sent_request( method ) _update_request( method, sent ) |
|
92 |
+ |
|
93 |
+#define _statusline(class, dir ) case class: stats->dir##_responses_##class++; break; |
|
94 |
+/* |
|
95 |
+#define statusline( class ) _statusline( class, received ) |
|
96 |
+#define statusline2( class ) _statusline( class, sent ) |
|
97 |
+*/ |
|
21 | 98 |
|
99 |
+#define _update_response( statusclass, dir ) \ |
|
100 |
+ { if (stat_file!=NULL) \ |
|
101 |
+ switch( statusclass ) { \ |
|
102 |
+ _statusline(1, dir) \ |
|
103 |
+ _statusline(2, dir) \ |
|
104 |
+ _statusline(3, dir) \ |
|
105 |
+ _statusline(4, dir) \ |
|
106 |
+ _statusline(5, dir) \ |
|
107 |
+ _statusline(6, dir) \ |
|
108 |
+ default: LOG(L_INFO, "ERROR: unusual status code received in stats (%s)\n", #dir); \ |
|
109 |
+ } \ |
|
110 |
+ } |
|
111 |
+ |
|
112 |
+#define update_received_response( statusclass ) _update_response( statusclass, received ) |
|
113 |
+#define update_sent_response( statusclass ) _update_response( statusclass, sent ) |
|
114 |
+ |
|
115 |
+#define update_received_drops { stats->received_drops++; } |
|
116 |
+#define update_fail_on_send { stats->failed_on_send++; } |
|
117 |
+ |
|
118 |
+ |
|
119 |
+#endif |
|
22 | 120 |
#endif |
23 | 121 |
similarity index 78% |
24 | 122 |
rename from test/shoot.cpp |
25 | 123 |
rename to test/shoot.c |
... | ... |
@@ -8,45 +8,23 @@ bouquets and brickbats to farhan@hotfoon.com |
8 | 8 |
/* changes by jiri@iptel.org; now messages can be really received; |
9 | 9 |
status code returned is 2 for some local errors , 0 for success |
10 | 10 |
and 1 for remote error -- ICMP/timeout; can be used to test if |
11 |
- a server is alive; 1xx messages are now ignored |
|
11 |
+ a server is alive; 1xx messages are now ignored; windows support |
|
12 |
+ dropped |
|
12 | 13 |
*/ |
13 | 14 |
|
14 |
-/* currently, compiles only for Solaris; Linux returns |
|
15 |
- /usr/include/regexp.h:131: cannot convert `char *' to `unsigned char *' |
|
16 |
-*/ |
|
17 |
- |
|
18 |
-int regerr; |
|
19 |
- |
|
20 |
-#define INIT register char *sp = instring; |
|
21 |
-#define GETC() (*sp++) |
|
22 |
-#define PEEKC() (*sp) |
|
23 |
-#define UNGETC(c) (--sp) |
|
24 |
-/*#define RETURN(*c) return; */ |
|
25 |
-#define RETURN(c) return c; |
|
26 |
-#define ERROR(c) regerr |
|
27 |
-#include <regexp.h> |
|
28 |
- |
|
29 |
- |
|
15 |
+#include <stdlib.h> |
|
30 | 16 |
#include <stdio.h> |
17 |
+#include <sys/types.h> |
|
18 |
+#include <sys/time.h> |
|
31 | 19 |
#include <string.h> |
32 | 20 |
#include <ctype.h> |
33 | 21 |
#include <time.h> |
34 |
-#include <sys/types.h> |
|
35 |
-#include <stdlib.h> |
|
36 |
-/* windows specific headers */ |
|
37 |
-#ifdef WIN32 |
|
38 |
-#include <windows.h> |
|
39 |
-#include <winsock.h> |
|
40 |
-#define close(a) closesocket(a) |
|
41 |
-#else |
|
42 |
-/* *nix specific networking headers */ |
|
43 |
-#include <sys/time.h> |
|
44 | 22 |
#include <unistd.h> |
45 | 23 |
#include <netdb.h> |
46 |
-#include <arpa/inet.h> |
|
47 | 24 |
#include <sys/socket.h> |
48 |
-#include <netinet/in.h> |
|
49 |
-#endif |
|
25 |
+ |
|
26 |
+#include <regex.h> |
|
27 |
+regex_t* regexp; |
|
50 | 28 |
|
51 | 29 |
#define RESIZE 1024 |
52 | 30 |
|
... | ... |
@@ -67,8 +45,8 @@ long getaddress(char *host) |
67 | 45 |
{ |
68 | 46 |
int i, dotcount=0; |
69 | 47 |
char *p = host; |
70 |
- struct hostent *pent; |
|
71 |
- /* struct sockaddr_in addr; */ /* see the note on portabilit at the end of the routine */ |
|
48 |
+ struct hostent* pent; |
|
49 |
+ long l, *lp; |
|
72 | 50 |
|
73 | 51 |
/*try understanding if this is a valid ip address |
74 | 52 |
we are skipping the values of the octets specified here. |
... | ... |
@@ -106,11 +84,9 @@ long getaddress(char *host) |
106 | 84 |
exit(2); |
107 | 85 |
} |
108 | 86 |
|
109 |
- /* PORTABILITY-ISSUE: replacing a costly memcpy call with a hack, may not work on |
|
110 |
- some systems. |
|
111 |
- memcpy(&addr.sin_addr, (pent->h_addr), pent->h_length); |
|
112 |
- return addr.sin_addr.s_addr; */ |
|
113 |
- return *((long *)(pent->h_addr)); |
|
87 |
+ lp = (long *) (pent->h_addr); |
|
88 |
+ l = *lp; |
|
89 |
+ return l; |
|
114 | 90 |
} |
115 | 91 |
|
116 | 92 |
|
... | ... |
@@ -129,18 +105,20 @@ at 5 seconds (5000 milliseconds). |
129 | 105 |
we are detecting the final response without a '1' as the first |
130 | 106 |
letter. |
131 | 107 |
*/ |
132 |
-void shoot(char *buff, long address, int port) |
|
108 |
+void shoot(char *buff, long address, int lport, int rport ) |
|
133 | 109 |
{ |
134 | 110 |
struct sockaddr_in addr; |
135 | 111 |
/* jku - b server structures */ |
136 | 112 |
struct sockaddr_in sockname; |
137 | 113 |
int ssock; |
114 |
+ /* |
|
138 | 115 |
char compiledre[ RESIZE ]; |
116 |
+ */ |
|
139 | 117 |
/* jku - e */ |
140 | 118 |
int retryAfter = 500, i, len, ret; |
141 | 119 |
int nretries = 10; |
142 | 120 |
int sock; |
143 |
- timeval tv; |
|
121 |
+ struct timeval tv; |
|
144 | 122 |
fd_set fd; |
145 | 123 |
char reply[1600]; |
146 | 124 |
|
... | ... |
@@ -160,26 +138,28 @@ void shoot(char *buff, long address, int port) |
160 | 138 |
|
161 | 139 |
sockname.sin_family=AF_INET; |
162 | 140 |
sockname.sin_addr.s_addr = htonl( INADDR_ANY ); |
163 |
- sockname.sin_port = htons((short)port); |
|
164 |
- if (bind( ssock, (sockaddr *) &sockname, sizeof(sockname) )==-1) { |
|
141 |
+ sockname.sin_port = htons((short)lport); |
|
142 |
+ if (bind( ssock, (struct sockaddr *) &sockname, sizeof(sockname) )==-1) { |
|
165 | 143 |
perror("no bind"); |
166 | 144 |
exit(2); |
167 | 145 |
} |
168 | 146 |
|
169 | 147 |
/* should capture: SIP/2.0 100 Trying */ |
170 |
- compile("^SIP/[0-9]\\.[0-9] 1[0-9][0-9] ", compiledre, &compiledre[RESIZE], '\0'); |
|
148 |
+ /* compile("^SIP/[0-9]\\.[0-9] 1[0-9][0-9] ", compiledre, &compiledre[RESIZE], '\0'); */ |
|
149 |
+ regexp=(regex_t*)malloc(sizeof(regex_t)); |
|
150 |
+ regcomp(regexp, "^SIP/[0-9]\\.[0-9] 1[0-9][0-9] ", REG_EXTENDED|REG_NOSUB|REG_ICASE); |
|
171 | 151 |
|
172 | 152 |
|
173 | 153 |
/* jku - e */ |
174 | 154 |
|
175 | 155 |
addr.sin_addr.s_addr = address; |
176 |
- addr.sin_port = htons((short)port); |
|
156 |
+ addr.sin_port = htons((short)rport); |
|
177 | 157 |
addr.sin_family = AF_INET; |
178 | 158 |
|
179 | 159 |
/* we connect as per the RFC 2543 recommendations |
180 | 160 |
modified from sendto/recvfrom */ |
181 | 161 |
|
182 |
- ret = connect(sock, (sockaddr *)&addr, sizeof(addr)); |
|
162 |
+ ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr)); |
|
183 | 163 |
if (ret==-1) { |
184 | 164 |
perror("no connect"); |
185 | 165 |
exit(2); |
... | ... |
@@ -241,7 +221,8 @@ void shoot(char *buff, long address, int port) |
241 | 221 |
puts("/* reply */"); |
242 | 222 |
puts(reply); |
243 | 223 |
putchar('\n'); |
244 |
- if (step( reply, compiledre )) { |
|
224 |
+ /* if (step( reply, compiledre )) { */ |
|
225 |
+ if (regexec((regex_t*)regexp, reply, 0, 0, 0)==0) { |
|
245 | 226 |
puts(" provisional received; still waiting for a final response\n "); |
246 | 227 |
continue; |
247 | 228 |
} else { |
... | ... |
@@ -266,21 +247,12 @@ int main(int argc, char *argv[]) |
266 | 247 |
FILE *pf; |
267 | 248 |
char buff[1600]; |
268 | 249 |
int length; |
269 |
- int port; |
|
270 |
-#ifdef WIN32 |
|
271 |
- WSADATA wsadata; |
|
272 |
- int err = WSAStartup(0x0101, &wsadata); |
|
273 |
- if (err != 0) |
|
274 |
- { |
|
275 |
- printf("shoot cannot be used as TCP/IP is not available.\n"); |
|
276 |
- exit(0); |
|
277 |
- } |
|
278 |
-#endif |
|
250 |
+ int lport=0; |
|
251 |
+ int rport=5060; |
|
279 | 252 |
|
280 |
- |
|
281 |
- if (argc != 3 && argc != 4) |
|
253 |
+ if (! (argc >= 3 && argc <= 5)) |
|
282 | 254 |
{ |
283 |
- puts("usage: shoot file host [port]"); |
|
255 |
+ puts("usage: shoot file host [rport] [lport]"); |
|
284 | 256 |
exit(2); |
285 | 257 |
} |
286 | 258 |
|
... | ... |
@@ -292,14 +264,21 @@ int main(int argc, char *argv[]) |
292 | 264 |
} |
293 | 265 |
|
294 | 266 |
/* take the port as 5060 even if it is incorrectly specified */ |
295 |
- if (argc == 4) |
|
267 |
+ if (argc >= 4) |
|
296 | 268 |
{ |
297 |
- port = atoi(argv[3]); |
|
298 |
- if (!port) |
|
299 |
- port = 5060; |
|
269 |
+ rport = atoi(argv[3]); |
|
270 |
+ if (!rport) { |
|
271 |
+ puts("error: non-numerical remote port number"); |
|
272 |
+ exit(1); |
|
273 |
+ } |
|
274 |
+ if (argc==5) { |
|
275 |
+ lport=atoi(argv[4]); |
|
276 |
+ if (!lport) { |
|
277 |
+ puts("error: non-numerical local port number"); |
|
278 |
+ exit(1); |
|
279 |
+ } |
|
280 |
+ } |
|
300 | 281 |
} |
301 |
- else |
|
302 |
- port = 5060; |
|
303 | 282 |
|
304 | 283 |
/* file is opened in binary mode so that the cr-lf is preserved */ |
305 | 284 |
pf = fopen(argv[1], "rb"); |
... | ... |
@@ -317,7 +296,7 @@ int main(int argc, char *argv[]) |
317 | 296 |
fclose(pf); |
318 | 297 |
buff[length] = 0; |
319 | 298 |
|
320 |
- shoot(buff, address, port); |
|
299 |
+ shoot(buff, address, lport, rport ); |
|
321 | 300 |
|
322 | 301 |
/* visual studio closes the debug console as soon as the |
323 | 302 |
program terminates. this is to hold the window from collapsing |