Browse code

new: prefix/strip, len_gt, fixes: via2sock, TM everloop (no SYNs), other TM fixes

Jiri Kuthan authored on 26/05/2002 12:10:13
Showing 18 changed files
... ...
@@ -85,11 +85,11 @@ DEFS+= -DNAME='"$(NAME)"' -DVERSION='"$(RELEASE)"' -DARCH='"$(ARCH)"' \
85 85
 	 -DSHM_MEM  -DSHM_MMAP \
86 86
 	 -DADAPTIVE_WAIT -DADAPTIVE_WAIT_LOOPS=1024 \
87 87
 	 -DWAIT -DNEW_HNAME \
88
+	 -DNOISY_REPLIES \
88 89
 	 -DVERY_NOISY_REPLIES\
89
-	 #-DSILENT_FR \
90
-	 #-DNO_DEBUG \
90
+	 -DSILENT_FR \
91 91
  	 #-DUSE_SYNONIM\
92
-	 #-DNOISY_REPLIES \
92
+	 #-DNO_DEBUG \
93 93
 	 #-DADAPTIVE_WAIT -DADAPTIVE_WAIT_LOOPS=0 \
94 94
 	 #-DNOSMP \
95 95
 	 #-DEXTRA_DEBUG 
... ...
@@ -168,6 +168,20 @@ int do_action(struct action* a, struct sip_msg* msg)
168 168
 			ret=1;
169 169
 			break;
170 170
 
171
+		/* jku begin: is_length_greater_than */
172
+		case LEN_GT_T:
173
+			if (a->p1_type!=NUMBER_ST) {
174
+				LOG(L_CRIT, "BUG: do_action: bad len_gt type %d\n",
175
+					a->p1_type );
176
+				ret=E_BUG;
177
+				break;
178
+			}
179
+			/* DBG("XXX: message length %d, max %d\n", 
180
+				msg->len, a->p1.number ); */
181
+			ret = msg->len >= a->p1.number ? 1 : -1;
182
+			break;
183
+		/* jku end: is_length_greater_than */
184
+			
171 185
 		/* jku - begin : flag processing */
172 186
 
173 187
 		case SETFLAG_T:
... ...
@@ -262,8 +276,16 @@ int do_action(struct action* a, struct sip_msg* msg)
262 262
 		case SET_USERPASS_T:
263 263
 		case SET_PORT_T:
264 264
 		case SET_URI_T:
265
+		case PREFIX_T:
266
+		case STRIP_T:
265 267
 				user=0;
266
-				if (a->p1_type!=STRING_ST){
268
+				if (a->type==STRIP_T) {
269
+					if (a->p1_type!=NUMBER_ST) {
270
+						LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
271
+							a->p1_type);
272
+						break;
273
+					}
274
+				} else if (a->p1_type!=STRING_ST){
267 275
 					LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
268 276
 							a->p1_type);
269 277
 					ret=E_BUG;
... ...
@@ -316,16 +338,43 @@ int do_action(struct action* a, struct sip_msg* msg)
316 316
 				/* begin copying */
317 317
 				len=strlen("sip:"); if(crt+len>end) goto error_uri;
318 318
 				memcpy(crt,"sip:",len);crt+=len;
319
+
319 320
 				/* user */
320
-				if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T))
321
+
322
+				/* prefix (-jiri) */
323
+				if (a->type==PREFIX_T) {
321 324
 					tmp=a->p1.string;
322
-				else 
323
-					tmp=uri.user.s;
324
-				if (tmp){
325 325
 					len=strlen(tmp); if(crt+len>end) goto error_uri;
326 326
 					memcpy(crt,tmp,len);crt+=len;
327
+					/* whateever we had before, with prefix we have username now */
328
+					user=1;
329
+				}
330
+
331
+				if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {
332
+					tmp=a->p1.string;
333
+					len=strlen(tmp);
334
+				} else if (a->type==STRIP_T) {
335
+					if (a->p1.number>uri.user.len) {
336
+						LOG(L_WARN, "Error: too long strip asked; deleting username: "
337
+							"%d of %s\n", a->p1.number, uri.user.s );
338
+						len=0;
339
+					} else if (a->p1.number==uri.user.len) {
340
+						len=0;
341
+					} else {
342
+						tmp=uri.user.s + a->p1.number;
343
+						len=uri.user.len - a->p1.number;
344
+					}
345
+				} else {
346
+					tmp=uri.user.s;
347
+					len=uri.user.len;
348
+				}
349
+
350
+				if (len){
351
+					if(crt+len>end) goto error_uri;
352
+					memcpy(crt,tmp,len);crt+=len;
327 353
 					user=1; /* we have an user field so mark it */
328 354
 				}
355
+
329 356
 				if (a->type==SET_USERPASS_T) tmp=0;
330 357
 				else tmp=uri.passwd.s;
331 358
 				/* passwd */
... ...
@@ -49,12 +49,15 @@ EXEC	exec
49 49
 SETFLAG		setflag
50 50
 RESETFLAG	resetflag
51 51
 ISFLAGSET	isflagset
52
+LEN_GT		len_gt
52 53
 SET_HOST		"rewritehost"|"sethost"|"seth"
53 54
 SET_HOSTPORT	"rewritehostport"|"sethostport"|"sethp"
54 55
 SET_USER		"rewriteuser"|"setuser"|"setu"
55 56
 SET_USERPASS	"rewriteuserpass"|"setuserpass"|"setup"
56 57
 SET_PORT		"rewriteport"|"setport"|"setp"
57 58
 SET_URI			"rewriteuri"|"seturi"
59
+PREFIX			"prefix"
60
+STRIP			"strip"
58 61
 IF				"if"
59 62
 ELSE			"else"
60 63
 
... ...
@@ -62,6 +65,8 @@ ELSE			"else"
62 62
 URIHOST			"uri:host"
63 63
 URIPORT			"uri:port"
64 64
 
65
+MAX_LEN			"max_len"
66
+
65 67
 
66 68
 /* condition keywords */
67 69
 METHOD	method
... ...
@@ -137,6 +142,7 @@ EAT_ABLE	[\ \t\b\r]
137 137
 <INITIAL>{SETFLAG}	{ count(); yylval.strval=yytext; return SETFLAG; }
138 138
 <INITIAL>{RESETFLAG}	{ count(); yylval.strval=yytext; return RESETFLAG; }
139 139
 <INITIAL>{ISFLAGSET}	{ count(); yylval.strval=yytext; return ISFLAGSET; }
140
+<INITIAL>{LEN_GT}	{ count(); yylval.strval=yytext; return LEN_GT; }
140 141
 <INITIAL>{ROUTE}	{ count(); yylval.strval=yytext; return ROUTE; }
141 142
 <INITIAL>{EXEC}	{ count(); yylval.strval=yytext; return EXEC; }
142 143
 <INITIAL>{SET_HOST}	{ count(); yylval.strval=yytext; return SET_HOST; }
... ...
@@ -145,12 +151,16 @@ EAT_ABLE	[\ \t\b\r]
145 145
 <INITIAL>{SET_USERPASS}	{ count(); yylval.strval=yytext; return SET_USERPASS; }
146 146
 <INITIAL>{SET_PORT}	{ count(); yylval.strval=yytext; return SET_PORT; }
147 147
 <INITIAL>{SET_URI}	{ count(); yylval.strval=yytext; return SET_URI; }
148
+<INITIAL>{PREFIX}	{ count(); yylval.strval=yytext; return PREFIX; }
149
+<INITIAL>{STRIP}	{ count(); yylval.strval=yytext; return STRIP; }
148 150
 <INITIAL>{IF}	{ count(); yylval.strval=yytext; return IF; }
149 151
 <INITIAL>{ELSE}	{ count(); yylval.strval=yytext; return ELSE; }
150 152
 
151 153
 <INITIAL>{URIHOST}	{ count(); yylval.strval=yytext; return URIHOST; }
152 154
 <INITIAL>{URIPORT}	{ count(); yylval.strval=yytext; return URIPORT; }
153 155
 
156
+<INITIAL>{MAX_LEN}	{ count(); yylval.strval=yytext; return MAX_LEN; }
157
+
154 158
 <INITIAL>{METHOD}	{ count(); yylval.strval=yytext; return METHOD; }
155 159
 <INITIAL>{URI}	{ count(); yylval.strval=yytext; return URI; }
156 160
 <INITIAL>{SRCIP}	{ count(); yylval.strval=yytext; return SRCIP; }
... ...
@@ -20,11 +20,13 @@
20 20
 #include "sr_module.h"
21 21
 #include "modparam.h"
22 22
 
23
+#include "config.h"
23 24
 
24 25
 #ifdef DEBUG_DMALLOC
25 26
 #include <dmalloc.h>
26 27
 #endif
27 28
 
29
+
28 30
 extern int yylex();
29 31
 void yyerror(char* s);
30 32
 char* tmp;
... ...
@@ -54,6 +56,8 @@ void* f_tmp;
54 54
 %token EXEC
55 55
 %token SET_HOST
56 56
 %token SET_HOSTPORT
57
+%token PREFIX
58
+%token STRIP
57 59
 %token SET_USER
58 60
 %token SET_USERPASS
59 61
 %token SET_PORT
... ...
@@ -62,9 +66,11 @@ void* f_tmp;
62 62
 %token ELSE
63 63
 %token URIHOST
64 64
 %token URIPORT
65
+%token MAX_LEN
65 66
 %token SETFLAG
66 67
 %token RESETFLAG
67 68
 %token ISFLAGSET
69
+%token LEN_GT
68 70
 %token METHOD
69 71
 %token URI
70 72
 %token SRCIP
... ...
@@ -562,6 +568,13 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
562 562
 		| SETFLAG LPAREN NUMBER RPAREN {$$=mk_action( SETFLAG_T, NUMBER_ST, 0,
563 563
 													(void *)$3, 0 ); }
564 564
 		| SETFLAG error { $$=0; yyerror("missing '(' or ')'?"); }
565
+
566
+		| LEN_GT LPAREN NUMBER RPAREN {$$=mk_action( LEN_GT_T, NUMBER_ST, 0,
567
+													(void *)$3, 0 ); }
568
+		| LEN_GT LPAREN MAX_LEN RPAREN {$$=mk_action( LEN_GT_T, NUMBER_ST, 0,
569
+													(void *) BUF_SIZE, 0 ); }
570
+		| LEN_GT error { $$=0; yyerror("missing '(' or ')'?"); }
571
+
565 572
 		| RESETFLAG LPAREN NUMBER RPAREN {$$=mk_action(	RESETFLAG_T, NUMBER_ST, 0,
566 573
 													(void *)$3, 0 ); }
567 574
 		| RESETFLAG error { $$=0; yyerror("missing '(' or ')'?"); }
... ...
@@ -591,6 +604,18 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
591 591
 		| SET_HOST error { $$=0; yyerror("missing '(' or ')' ?"); }
592 592
 		| SET_HOST LPAREN error RPAREN { $$=0; yyerror("bad argument, "
593 593
 														"string expected"); }
594
+
595
+		| PREFIX LPAREN STRING RPAREN { $$=mk_action(PREFIX_T, STRING_ST,
596
+														0, $3, 0); }
597
+		| PREFIX error { $$=0; yyerror("missing '(' or ')' ?"); }
598
+		| PREFIX LPAREN error RPAREN { $$=0; yyerror("bad argument, "
599
+														"string expected"); }
600
+		| STRIP LPAREN NUMBER RPAREN { $$=mk_action(STRIP_T, NUMBER_ST,
601
+														0, (void *) $3, 0); }
602
+		| STRIP error { $$=0; yyerror("missing '(' or ')' ?"); }
603
+		| STRIP LPAREN error RPAREN { $$=0; yyerror("bad argument, "
604
+														"number expected"); }
605
+
594 606
 		| SET_HOSTPORT LPAREN STRING RPAREN { $$=mk_action( SET_HOSTPORT_T, 
595 607
 														STRING_ST, 0, $3, 0); }
596 608
 		| SET_HOSTPORT error { $$=0; yyerror("missing '(' or ')' ?"); }
... ...
@@ -80,7 +80,7 @@
80 80
    avoid terror of excessively huge messages; they are
81 81
    useless anyway
82 82
 */
83
-#define BUF_SIZE (MAX_FIXED_BLOCK-32)
83
+#define BUF_SIZE 3040
84 84
 
85 85
 /* forwarding  -- Via buffer dimensioning */
86 86
 #define MAX_VIA_LINE_SIZE	240
... ...
@@ -97,6 +97,7 @@ int update_sock_struct_from_via( struct sockaddr_in* to,  struct via_body* via )
97 97
 {
98 98
 	int err;
99 99
 	struct hostent* he;
100
+	char *host_copy;
100 101
 
101 102
 	to->sin_family = AF_INET;
102 103
 	to->sin_port = (via->port)?htons(via->port): htons(SIP_PORT);
... ...
@@ -107,7 +108,18 @@ int update_sock_struct_from_via( struct sockaddr_in* to,  struct via_body* via )
107 107
 #endif
108 108
 	{
109 109
 		/* fork? gethostbyname will probably block... */
110
-		he=gethostbyname(via->host.s);
110
+		/* we do now a malloc/memcpy because gethostbyname loves \0-terminated 
111
+		   strings; -jiri */
112
+		if (!(host_copy=pkg_malloc( via->host.len+1 ))) {
113
+			LOG(L_NOTICE, "ERROR: update_sock_struct_from_via: not enough memory\n");
114
+			return -1;
115
+		}
116
+		memcpy(host_copy, via->host.s, via->host.len );
117
+		host_copy[via->host.len]=0;
118
+		he=gethostbyname(host_copy);
119
+		/* he=gethostbyname(via->host.s); */
120
+		pkg_free( host_copy );
121
+
111 122
 		if (he==0){
112 123
 			LOG(L_NOTICE, "ERROR:forward_reply:gethostbyname(%s) failure\n",
113 124
 					via->host.s);
... ...
@@ -165,8 +165,9 @@ void print_ct_constants()
165 165
 #endif
166 166
 */
167 167
 	printf("MAX_RECV_BUFFER_SIZE %d, MAX_LISTEN %d,"
168
-			" MAX_URI_SIZE %d, MAX_PROCESSES %d\n",
169
-		MAX_RECV_BUFFER_SIZE, MAX_LISTEN, MAX_URI_SIZE, MAX_PROCESSES );
168
+			" MAX_URI_SIZE %d, MAX_PROCESSES %d, BUF_SIZE %d\n",
169
+		MAX_RECV_BUFFER_SIZE, MAX_LISTEN, MAX_URI_SIZE, MAX_PROCESSES,
170
+		BUF_SIZE );
170 171
 }
171 172
 
172 173
 /* debuging function */
... ...
@@ -66,7 +66,7 @@ struct cell*  build_cell( struct sip_msg* p_msg )
66 66
 	struct cell* new_cell;
67 67
 	unsigned int i;
68 68
 #ifndef USE_SYNONIM
69
-	str          src[5];
69
+	str          src[8];
70 70
 #endif
71 71
 
72 72
 	/* do we have the source for the build process? */
... ...
@@ -129,8 +129,17 @@ struct cell*  build_cell( struct sip_msg* p_msg )
129 129
 	src[2]= p_msg->callid->body;
130 130
 	src[3]= p_msg->first_line.u.request.uri;
131 131
 	src[4]= get_cseq( p_msg )->number;
132
-	MDStringArray ( new_cell->md5, src, 5 );
133
-#endif
132
+
133
+	/* topmost Via is part of transaction key as well ! */
134
+	src[5]= p_msg->via1->host;
135
+	src[6]= p_msg->via1->port_str;
136
+	if (p_msg->via1->branch) {
137
+		src[7]= p_msg->via1->branch->value;
138
+		MDStringArray ( new_cell->md5, src, 8 );
139
+	} else {
140
+		MDStringArray ( new_cell->md5, src, 7 );
141
+	}
142
+ #endif
134 143
 
135 144
 	init_cell_lock(  new_cell );
136 145
 	return new_cell;
... ...
@@ -13,6 +13,7 @@
13 13
 
14 14
 #include "../../parser/msg_parser.h"
15 15
 #include "../../types.h"
16
+#include "../../md5utils.h"
16 17
 #include "config.h"
17 18
 /*#include "t_flags.h"*/
18 19
 
... ...
@@ -146,7 +147,7 @@ typedef struct cell
146 146
 	struct sockaddr_in ack_to;
147 147
 #ifndef	USE_SYNONIM
148 148
 	/* MD5checksum */
149
-	char md5[32];
149
+	char md5[MD5_LEN];
150 150
 #endif
151 151
 
152 152
 #ifdef	EXTRA_DEBUG
... ...
@@ -406,7 +406,7 @@ int t_build_and_send_CANCEL(struct cell *Trans,unsigned int branch)
406 406
 			req_line(p_msg).method.s);
407 407
 	}
408 408
 	/* changhing method name*/
409
-	memcpy(cancel_buf,"CANCEL",6);
409
+	memcpy(cancel_buf, CANCEL , CANCEL_LEN );
410 410
 	append_mem_block(p,CRLF,CRLF_LEN);
411 411
 	/* insert our via */
412 412
 	append_mem_block(p,via,via_len);
... ...
@@ -423,7 +423,7 @@ int t_build_and_send_CANCEL(struct cell *Trans,unsigned int branch)
423 423
 		{
424 424
 			append_mem_block(p,hdr->name.s,
425 425
 				((((struct cseq_body*)hdr->parsed)->method.s)-hdr->name.s));
426
-			append_mem_block(p,"CANCEL" CRLF, 6+CRLF_LEN );
426
+			append_mem_block(p, CANCEL CRLF, CANCEL_LEN +CRLF_LEN );
427 427
 		}
428 428
 }
429 429
 
... ...
@@ -18,10 +18,13 @@
18 18
 #include "../../forward.h"
19 19
 #include "../../mem/mem.h"
20 20
 
21
+#include "../../md5utils.h"
22
+
21 23
 #include "config.h"
22 24
 #include "lock.h"
23 25
 #include "timer.h"
24 26
 
27
+
25 28
 struct s_table;
26 29
 struct timer;
27 30
 struct entry;
... ...
@@ -58,11 +61,6 @@ extern unsigned int     nr_forks;
58 58
 #define UNLOCK_WAIT(_t) unlock(&(_t)->wait_mutex )
59 59
 
60 60
 
61
-/* convenience short-cut macros */
62
-#define REQ_METHOD first_line.u.request.method_value
63
-#define REPLY_STATUS first_line.u.reply.statuscode
64
-#define REPLY_CLASS(_reply) ((_reply)->REPLY_STATUS/100)
65
-
66 61
 /* send a private buffer: utilize a retransmission structure
67 62
    but take a separate buffer not refered by it; healthy
68 63
    for reducing time spend in REPLIES locks
... ...
@@ -1,6 +1,30 @@
1 1
 /*
2 2
  * $Id$
3 3
  *
4
+ * This C-file takes care of matching requests and replies with
5
+ * existing transactions. Note that we do not do SIP-compliant
6
+ * request matching as asked by SIP spec. We do bitwise matching of 
7
+ * all header fields in requests which form a transaction key. 
8
+ * It is much faster and it worx pretty well -- we haven't 
9
+ * had any interop issue neither in lab nor in bake-offs. The reason
10
+ * is that retransmissions do look same as original requests
11
+ * (it would be really silly if they wuld be mangled). The only
12
+ * exception is we parse To as To in ACK is compared to To in
13
+ * reply and both  of them are constructed by different software.
14
+ * 
15
+ * As for reply matching, we match based on branch value -- that is
16
+ * faster too. There are two versions .. with SYNONYMs #define
17
+ * enabled, the branch includes ordinal number of a transaction
18
+ * in a synonym list in hash table and is somewhat faster but
19
+ * not reboot-resilient. SYNONYMs turned off are little slower
20
+ * but work across reboots as well.
21
+ *
22
+ * The branch parameter is formed as follows:
23
+ * SYNONYMS  on: hash.synonym.branch
24
+ * SYNONYMS off: md5.hash.branch
25
+ *
26
+ * -jiri
27
+ *
4 28
  */
5 29
 
6 30
 #include <assert.h>
... ...
@@ -130,7 +154,9 @@ int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
130 130
 		else
131 131
 		{ /* it's a ACK request*/
132 132
 			/* first only the length are checked */
133
-			if ( t_msg->first_line.u.request.method_value==METHOD_INVITE
133
+			/* use shortcut; -jiri
134
+			if ( t_msg->first_line.u.request.method_value==METHOD_INVITE */
135
+			if (t_msg->REQ_METHOD==METHOD_INVITE
134 136
 			/* && (fprintf(stderr,"------Method name OK->testing callid len...\n")) */
135 137
 			&& /*callid length*/ EQ_LEN(callid)
136 138
 			/* && (fprintf(stderr,"------CallID OK -> testing cseq nr len\n")) */
... ...
@@ -142,6 +168,15 @@ int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
142 142
 			/* && (fprintf(stderr,"------To uri OK -> testing To tag len\n")) */
143 143
 			&& /*to tag*/p_cell->uas.tag->len==get_to(p_msg)->tag_value.len
144 144
 			/* && (fprintf(stderr,"------To tag OK -> testing uri len\n")) */
145
+
146
+			/* in ACKs to 200, r-uri and Via may be different than in
147
+			   original INVITE; we still try to match the transaction
148
+			   so that we can retransmit an ACK on resent 200 -- different
149
+			   from SIP spec which kills transaction state after INVITE-200
150
+			   and considers 200-ACK a new transaction which just happens
151
+			   to have the same CSeq. -jiri
152
+			*/
153
+
145 154
 			&& /*req URI*/(p_cell->uas.status==200 || EQ_REQ_URI_LEN )
146 155
 			/* && (fprintf(stderr,"------uri OK -> testing via len\n")) */
147 156
 			&& /*VIA*/(p_cell->uas.status==200 || EQ_VIA_LEN(via1)) )
... ...
@@ -394,7 +429,7 @@ int t_reply_matching( struct sip_msg *p_msg , int *p_branch ,
394 394
 #ifdef USE_SYNONIM
395 395
 		|| (entry_label=reverse_hex2int(syni, synl))<0
396 396
 #else
397
-		|| loopl!=32
397
+		|| loopl!=MD5_LEN
398 398
 #endif
399 399
 	) {
400 400
 		DBG("DEBUG: t_reply_matching: poor reply lables %d label %d "
... ...
@@ -406,44 +441,52 @@ int t_reply_matching( struct sip_msg *p_msg , int *p_branch ,
406 406
 	DBG("DEBUG: t_reply_matching: hash %d label %d branch %d\n",
407 407
 		hash_index, entry_label, branch_id );
408 408
 
409
-	/* lock the hole entry*/
410
-	lock(&(hash_table->entrys[hash_index].mutex));
411 409
 
412
-	/*all the cells from the entry are scan to detect an entry_label matching*/
413
-	p_cell = hash_table->entrys[hash_index].first_cell;
414
-	while( p_cell )
415
-	{
416
-		/* is it the cell with the wanted entry_label? */
417
-		if ( (get_cseq(p_msg)->method.len ==
418
-		get_cseq(p_cell->uas.request)->method.len)
419
-		&& ((get_cseq(p_msg)->method.s[0] ==
420
-		get_cseq(p_cell->uas.request)->method.s[0] && (*local_cancel=0)==0)
421
-		|| (get_cseq(p_cell->uas.request)->method.s[0]=='I' &&
422
-		get_cseq(p_msg)->method.s[0]=='C'
423
-		&& p_cell->uac[branch_id].request.cancel!=NO_CANCEL
424
-		&& p_cell->uac[branch_id].request.cancel!=EXTERNAL_CANCEL
425
-		&& (*local_cancel=1)==1))
426
-#ifdef USE_SYNONIM
427
-		&& ( p_cell->label == entry_label )
428
-#else
429
-		&& ( p_cell->uas.request->add_to_branch_len>=32 &&
430
-		!memcmp(p_cell->uas.request->add_to_branch_s,loopi,32))
431
-#endif
432
-		)
433
-			/* has the transaction the wanted branch? */
434
-			if ( p_cell->nr_of_outgoings>branch_id )
435
-			{/* WE FOUND THE GOLDEN EGG !!!! */
436
-				T = p_cell;
437
-				*p_branch = branch_id;
438
-				T_REF( T );
439
-				unlock(&(hash_table->entrys[hash_index].mutex));
440
-				DBG("DEBUG: t_reply_matching: reply matched (T=%p,ref=%x)!\n",
441
-					T,T->ref_bitmap);
442
-				return 1;
443
-			}
444
-		/* next cell */
445
-		p_cell = p_cell->next_cell;
446
-	} /* while p_cell */
410
+	/* search the hash table list at entry 'hash_index'; lock the
411
+	   entry first 
412
+	*/
413
+	lock(&(hash_table->entrys[hash_index].mutex));
414
+	for (p_cell = hash_table->entrys[hash_index].first_cell; p_cell; 
415
+		p_cell=p_cell->next_cell) {
416
+
417
+		/* does method match ? */
418
+		if (get_cseq(p_msg)->method.len==
419
+			  get_cseq(p_cell->uas.request)->method.len 
420
+			&& get_cseq(p_msg)->method.s[0]==
421
+			  get_cseq(p_cell->uas.request)->method.s[0]) {
422
+				*local_cancel=0;
423
+		/* or is it perhaps a CANCEL ? */
424
+		} else if ( p_cell->uas.request->REQ_METHOD==METHOD_INVITE 
425
+			&& get_cseq(p_msg)->method.len==CANCEL_LEN 
426
+			&& memcmp( get_cseq(p_msg)->method.s, CANCEL, CANCEL_LEN )==0 
427
+			&& p_cell->uac[branch_id].request.cancel!=NO_CANCEL 
428
+			&& p_cell->uac[branch_id].request.cancel!=EXTERNAL_CANCEL ) {
429
+				*local_cancel=1;
430
+		} else { /* method mismatched */
431
+			continue;
432
+		};
433
+		#ifdef USE_SYNONIM
434
+		if (p_cell->label != entry_label) 
435
+			continue;
436
+		#else
437
+		if ( p_cell->uas.request->add_to_branch_len<MD5_LEN 
438
+			 || memcmp(p_cell->uas.request->add_to_branch_s,loopi,MD5_LEN)!=0)
439
+				continue;
440
+		#endif
441
+		/* sanity check ... too high branch ? */
442
+		if ( branch_id>=p_cell->nr_of_outgoings )
443
+			continue;
444
+		/* we passed all disqualifying factors .... the transaction has been
445
+		   matched !
446
+		*/
447
+		T=p_cell;
448
+		*p_branch = branch_id;
449
+		T_REF( T );
450
+		unlock(&(hash_table->entrys[hash_index].mutex));
451
+		DBG("DEBUG: t_reply_matching: reply matched (T=%p,ref=%x)!\n",
452
+			T,T->ref_bitmap);
453
+		return 1;
454
+	} /* for cycle */
447 455
 
448 456
 	/* nothing found */
449 457
 	unlock(&(hash_table->entrys[hash_index].mutex));
... ...
@@ -519,12 +562,24 @@ int add_branch_label( struct cell *trans, struct sip_msg *p_msg, int branch )
519 519
 	char *begin;
520 520
 	int size, orig_size;
521 521
 
522
+	/* this is actually a hack made by Bogdan; I wanted to have a structure
523
+	   to which anybody can append some branch stuff which may be utilizied
524
+	   during reply processing; Bogdan ignored that and resets it all the
525
+	   time to construct multiple branches for multiple via's during
526
+	   forking (otherwise, the next branch would be now appended to
527
+	   previous branch)
528
+
529
+	   keywords: HACK
530
+	*/
531
+     	
522 532
 	p_msg->add_to_branch_len = 0; /*bogdan*/
533
+
534
+
523 535
 	begin=p_msg->add_to_branch_s+p_msg->add_to_branch_len;
524 536
 	orig_size = size=MAX_BRANCH_PARAM_LEN - p_msg->add_to_branch_len;
525 537
 
526 538
 #ifndef USE_SYNONIM
527
-	if (memcpy(begin,trans->md5,32)) {begin+=32;size-=32;} else return -1;
539
+	if (memcpy(begin,trans->md5,MD5_LEN)) {begin+=MD5_LEN;size-=MD5_LEN;} else return -1;
528 540
 	if (size) { *begin=BRANCH_SEPARATOR; begin++; size--; } else return -1;
529 541
 #endif
530 542
 	if (int2reverse_hex( &begin, &size, trans->hash_index)==-1) return -1;
... ...
@@ -492,7 +492,7 @@ static int t_relay_to( struct sip_msg  *p_msg , char *str_ip , char *str_port)
492 492
 			LOG(L_CRIT, "ERROR: unexpected addifnew return value: %d\n", ret);
493 493
 			abort();
494 494
 	};
495
-	if (T) {
495
+	if (T!=T_UNDEFINED && T!=T_NULL) {
496 496
 		T_UNREF( T );
497 497
 	}
498 498
 	return ret;
... ...
@@ -296,10 +296,11 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
296 296
 				if (match){
297 297
 					match++;
298 298
 				}else {
299
-					tmp=end;
300 299
 					LOG(L_ERR,
301 300
 							"ERROR: get_hdr_field: bad body for <%s>(%d)\n",
302 301
 							hdr->name.s, hdr->type);
302
+					/* abort(); */
303
+					tmp=end;
303 304
 					goto error;
304 305
 				}
305 306
 				tmp=match;
... ...
@@ -68,6 +68,16 @@ enum{
68 68
 #define ACK_LEN		3
69 69
 #define CANCEL_LEN	6
70 70
 #define BYE_LEN		3
71
+
72
+#define CANCEL	"CANCEL"
73
+#define ACK		"ACK"
74
+#define INVITE "INVITE"
75
+
76
+/* convenience short-cut macros */
77
+#define REQ_METHOD first_line.u.request.method_value
78
+#define REPLY_STATUS first_line.u.reply.statuscode
79
+#define REPLY_CLASS(_reply) ((_reply)->REPLY_STATUS/100)
80
+
71 81
 enum { METHOD_OTHER, METHOD_INVITE, METHOD_CANCEL, METHOD_ACK, METHOD_BYE };
72 82
 
73 83
 #define IFISMETHOD(methodname,firstchar)                                  \
... ...
@@ -27,7 +27,8 @@ enum { METHOD_O=1, URI_O, SRCIP_O, DSTIP_O, DEFAULT_O, ACTION_O, NUMBER_O};
27 27
 enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
28 28
 		SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T, 
29 29
 		SET_PORT_T, SET_URI_T, IF_T, MODULE_T,
30
-		SETFLAG_T, RESETFLAG_T, ISFLAGSET_T };
30
+		SETFLAG_T, RESETFLAG_T, ISFLAGSET_T ,
31
+		LEN_GT_T, PREFIX_T, STRIP_T };
31 32
 enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST,
32 33
 		EXPR_ST, ACTIONS_ST, CMDF_ST, MODFIXUP_ST, URIHOST_ST, URIPORT_ST };
33 34
 
34 35
new file mode 100644
... ...
@@ -0,0 +1,66 @@
0
+INVITE sip:jiri@bat.iptel.org SIP/2.0
1
+Max-Forwards: 10
2
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
3
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
4
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
5
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
6
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
7
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
8
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
9
+Via: SIP/2.0/UDP 195.37.77.100;branch=1848eaf6f622ebaf1762f34e5d08ec2e.836.0
10
+Via: SIP/2.0/UDP 195.37.77.100;branch=2848eaf6f622ebaf1762f34e5d08ec2e.836.0
11
+Via: SIP/2.0/UDP 195.37.77.100;branch=3848eaf6f622ebaf1762f34e5d08ec2e.836.0
12
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
13
+Via: SIP/2.0/UDP 195.37.77.100;branch=8848eaf6f622ebaf1762f34e5d08ec2e.836.0
14
+Via: SIP/2.0/UDP 195.37.77.100;branch=9848eaf6f622ebaf1762f34e5d08ec2e.836.0
15
+Via: SIP/2.0/UDP 195.37.77.100;branch=5848eaf6f622ebaf1762f34e5d08ec2e.836.0
16
+Via: SIP/2.0/UDP 195.37.77.100;branch=6848eaf6f622ebaf1762f34e5d08ec2e.836.0
17
+Via: SIP/2.0/UDP 195.37.77.100;branch=7848eaf6f622ebaf1762f34e5d08ec2e.836.0
18
+Via: SIP/2.0/UDP 195.37.77.100;branch=b03d645a795fe2572631dbe15438fabd.836.0
19
+Via: SIP/2.0/UDP 195.37.77.100;branch=59c7c421d731de1ce1e1e4c6e83150f2.836.0
20
+Via: SIP/2.0/UDP 195.37.77.100;branch=3b33b0d029964ec5330922ff50b34c79.836.0
21
+Via: SIP/2.0/UDP 195.37.77.100;branch=781aa36a12b7b99b2316a8ed32123fc9.836.0
22
+Via: SIP/2.0/UDP 195.37.77.100;branch=a93680d322702022416a5a661aaf573d.836.0
23
+Via: SIP/2.0/UDP 195.37.77.100;branch=5a94858405aeaae679632efed7e1ff0b.836.0
24
+Via: SIP/2.0/UDP 195.37.77.100;branch=70509dba8d202a0116d2e51cd474a1d4.836.0
25
+Via: SIP/2.0/UDP 195.37.77.100;branch=7056d40a2cfa30ff299705fc791f4303.836.0
26
+Via: SIP/2.0/UDP 195.37.77.100;branch=ac7cf460ba831233121eead26af76d5a.836.0
27
+Via: SIP/2.0/UDP 195.37.77.100;branch=2c4d2ac0b10115c704d28c2b360bcb6f.836.0
28
+Via: SIP/2.0/UDP 195.37.77.100;branch=e0282bc88aed37191911cbb5ded27379.836.0
29
+Via: SIP/2.0/UDP 195.37.77.100;branch=c7d6a97d4b6762877410653db5643775.836.0
30
+Via: SIP/2.0/UDP 195.37.77.100;branch=a0c4944760b9f9693209f719e7aa177c.836.0
31
+Via: SIP/2.0/UDP 195.37.77.100;branch=4147b5297bc5a8e0c3ec58fe6fd9bf6c.836.0
32
+Via: SIP/2.0/UDP 195.37.77.100;branch=557cfe12fa9372a0a309ffebcdef3110.836.0
33
+Via: SIP/2.0/UDP 195.37.77.100;branch=ce741cd8b427d1722d4f746922a9d3a2.836.0
34
+Via: SIP/2.0/UDP 195.37.77.101;branch=838cccacb7d33e12c5e097f9090adfe1.836.0
35
+Via: SIP/2.0/UDP 213.20.128.35:9315
36
+From: "jiri" <sip:jiri@iptel.org>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
37
+To: <sip:jiri@bat.iptel.org>
38
+Call-ID: d10815e0-bf17-4afa-8412-d9130a793d96@213.20.128.35
39
+CSeq: 2 INVITE
40
+Contact: <sip:213.20.128.35:9315>
41
+User-Agent: Windows RTC/1.0
42
+Proxy-Authorization: Digest username="jiri", realm="iptel.org", algorithm="MD5", uri="sip:jiri@bat.iptel.org", nonce="3cef753900000001771328f5ae1b8b7f0d742da1feb5753c", response="53fe98db10e1074b03b3e06438bda70f"
43
+Content-Type: application/sdp
44
+Content-Length: 451
45
+
46
+v=0
47
+o=jku2 0 0 IN IP4 213.20.128.35
48
+s=session
49
+c=IN IP4 213.20.128.35
50
+b=CT:1000
51
+t=0 0
52
+m=audio 54742 RTP/AVP 97 111 112 6 0 8 4 5 3 101
53
+a=rtpmap:97 red/8000
54
+a=rtpmap:111 SIREN/16000
55
+a=fmtp:111 bitrate=16000
56
+a=rtpmap:112 G7221/16000
57
+a=fmtp:112 bitrate=24000
58
+a=rtpmap:6 DVI4/16000
59
+a=rtpmap:0 PCMU/8000
60
+a=rtpmap:8 PCMA/8000
61
+a=rtpmap:4 G723/8000
62
+a=rtpmap:5 DVI4/8000
63
+a=rtpmap: 3 GSM/8000
64
+a=rtpmap:101 telephone-event/8000
65
+a=fmtp:101 0-16
... ...
@@ -74,11 +74,11 @@ static inline unsigned short str2s(unsigned char* str, unsigned int len,
74 74
 	return ret;
75 75
 
76 76
 error_digits:
77
-	DBG("str2s: ERROR: too many letters in [%s]\n", init);
77
+	DBG("str2s: ERROR: too many letters in [%.*s]\n", len, init);
78 78
 	if (err) *err=1;
79 79
 	return 0;
80 80
 error_char:
81
-	DBG("str2s: ERROR: unexpected char %c in %s\n", *str, init);
81
+	DBG("str2s: ERROR: unexpected char %c in %.*s\n", *str, len, init);
82 82
 	if (err) *err=1;
83 83
 	return 0;
84 84
 }
... ...
@@ -117,11 +117,11 @@ static inline unsigned int str2ip(unsigned char* str, unsigned int len,
117 117
 	return ret;
118 118
 
119 119
 error_dots:
120
-	DBG("str2ip: ERROR: too many dots in [%s]\n", init);
120
+	DBG("str2ip: ERROR: too many dots in [%.*s]\n", len, init);
121 121
 	if (err) *err=1;
122 122
 	return 0;
123 123
 error_char:
124
-	DBG("str2ip: WARNING: unexpected char %c in %s\n", *str, init);
124
+	DBG("str2ip: WARNING: unexpected char %c in %.*s\n", *str, len, init);
125 125
 	if (err) *err=1;
126 126
 	return 0;
127 127
 }