瀏覽代碼

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

Jiri Kuthan 23 年之前
父節點
當前提交
1f377e97af
共有 18 個文件被更改,包括 308 次插入70 次删除
  1. 3 3
      Makefile.defs
  2. 54 5
      action.c
  3. 10 0
      cfg.lex
  4. 25 0
      cfg.y
  5. 1 1
      config.h
  6. 13 1
      forward.c
  7. 3 2
      main.c
  8. 12 3
      modules/tm/h_table.c
  9. 2 1
      modules/tm/h_table.h
  10. 2 2
      modules/tm/t_funcs.c
  11. 3 5
      modules/tm/t_funcs.h
  12. 95 40
      modules/tm/t_lookup.c
  13. 1 1
      modules/tm/tm.c
  14. 2 1
      parser/msg_parser.c
  15. 10 0
      parser/msg_parser.h
  16. 2 1
      route_struct.h
  17. 66 0
      test/long.sip
  18. 4 4
      ut.h

+ 3 - 3
Makefile.defs

@@ -85,11 +85,11 @@ DEFS+= -DNAME='"$(NAME)"' -DVERSION='"$(RELEASE)"' -DARCH='"$(ARCH)"' \
 	 -DSHM_MEM  -DSHM_MMAP \
 	 -DADAPTIVE_WAIT -DADAPTIVE_WAIT_LOOPS=1024 \
 	 -DWAIT -DNEW_HNAME \
+	 -DNOISY_REPLIES \
 	 -DVERY_NOISY_REPLIES\
-	 #-DSILENT_FR \
-	 #-DNO_DEBUG \
+	 -DSILENT_FR \
  	 #-DUSE_SYNONIM\
-	 #-DNOISY_REPLIES \
+	 #-DNO_DEBUG \
 	 #-DADAPTIVE_WAIT -DADAPTIVE_WAIT_LOOPS=0 \
 	 #-DNOSMP \
 	 #-DEXTRA_DEBUG 

+ 54 - 5
action.c

@@ -168,6 +168,20 @@ int do_action(struct action* a, struct sip_msg* msg)
 			ret=1;
 			break;
 
+		/* jku begin: is_length_greater_than */
+		case LEN_GT_T:
+			if (a->p1_type!=NUMBER_ST) {
+				LOG(L_CRIT, "BUG: do_action: bad len_gt type %d\n",
+					a->p1_type );
+				ret=E_BUG;
+				break;
+			}
+			/* DBG("XXX: message length %d, max %d\n", 
+				msg->len, a->p1.number ); */
+			ret = msg->len >= a->p1.number ? 1 : -1;
+			break;
+		/* jku end: is_length_greater_than */
+			
 		/* jku - begin : flag processing */
 
 		case SETFLAG_T:
@@ -262,8 +276,16 @@ int do_action(struct action* a, struct sip_msg* msg)
 		case SET_USERPASS_T:
 		case SET_PORT_T:
 		case SET_URI_T:
+		case PREFIX_T:
+		case STRIP_T:
 				user=0;
-				if (a->p1_type!=STRING_ST){
+				if (a->type==STRIP_T) {
+					if (a->p1_type!=NUMBER_ST) {
+						LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
+							a->p1_type);
+						break;
+					}
+				} else if (a->p1_type!=STRING_ST){
 					LOG(L_CRIT, "BUG: do_action: bad set*() type %d\n",
 							a->p1_type);
 					ret=E_BUG;
@@ -316,16 +338,43 @@ int do_action(struct action* a, struct sip_msg* msg)
 				/* begin copying */
 				len=strlen("sip:"); if(crt+len>end) goto error_uri;
 				memcpy(crt,"sip:",len);crt+=len;
+
 				/* user */
-				if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T))
+
+				/* prefix (-jiri) */
+				if (a->type==PREFIX_T) {
 					tmp=a->p1.string;
-				else 
-					tmp=uri.user.s;
-				if (tmp){
 					len=strlen(tmp); if(crt+len>end) goto error_uri;
 					memcpy(crt,tmp,len);crt+=len;
+					/* whateever we had before, with prefix we have username now */
+					user=1;
+				}
+
+				if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T)) {
+					tmp=a->p1.string;
+					len=strlen(tmp);
+				} else if (a->type==STRIP_T) {
+					if (a->p1.number>uri.user.len) {
+						LOG(L_WARN, "Error: too long strip asked; deleting username: "
+							"%d of %s\n", a->p1.number, uri.user.s );
+						len=0;
+					} else if (a->p1.number==uri.user.len) {
+						len=0;
+					} else {
+						tmp=uri.user.s + a->p1.number;
+						len=uri.user.len - a->p1.number;
+					}
+				} else {
+					tmp=uri.user.s;
+					len=uri.user.len;
+				}
+
+				if (len){
+					if(crt+len>end) goto error_uri;
+					memcpy(crt,tmp,len);crt+=len;
 					user=1; /* we have an user field so mark it */
 				}
+
 				if (a->type==SET_USERPASS_T) tmp=0;
 				else tmp=uri.passwd.s;
 				/* passwd */

+ 10 - 0
cfg.lex

@@ -49,12 +49,15 @@ EXEC	exec
 SETFLAG		setflag
 RESETFLAG	resetflag
 ISFLAGSET	isflagset
+LEN_GT		len_gt
 SET_HOST		"rewritehost"|"sethost"|"seth"
 SET_HOSTPORT	"rewritehostport"|"sethostport"|"sethp"
 SET_USER		"rewriteuser"|"setuser"|"setu"
 SET_USERPASS	"rewriteuserpass"|"setuserpass"|"setup"
 SET_PORT		"rewriteport"|"setport"|"setp"
 SET_URI			"rewriteuri"|"seturi"
+PREFIX			"prefix"
+STRIP			"strip"
 IF				"if"
 ELSE			"else"
 
@@ -62,6 +65,8 @@ ELSE			"else"
 URIHOST			"uri:host"
 URIPORT			"uri:port"
 
+MAX_LEN			"max_len"
+
 
 /* condition keywords */
 METHOD	method
@@ -137,6 +142,7 @@ EAT_ABLE	[\ \t\b\r]
 <INITIAL>{SETFLAG}	{ count(); yylval.strval=yytext; return SETFLAG; }
 <INITIAL>{RESETFLAG}	{ count(); yylval.strval=yytext; return RESETFLAG; }
 <INITIAL>{ISFLAGSET}	{ count(); yylval.strval=yytext; return ISFLAGSET; }
+<INITIAL>{LEN_GT}	{ count(); yylval.strval=yytext; return LEN_GT; }
 <INITIAL>{ROUTE}	{ count(); yylval.strval=yytext; return ROUTE; }
 <INITIAL>{EXEC}	{ count(); yylval.strval=yytext; return EXEC; }
 <INITIAL>{SET_HOST}	{ count(); yylval.strval=yytext; return SET_HOST; }
@@ -145,12 +151,16 @@ EAT_ABLE	[\ \t\b\r]
 <INITIAL>{SET_USERPASS}	{ count(); yylval.strval=yytext; return SET_USERPASS; }
 <INITIAL>{SET_PORT}	{ count(); yylval.strval=yytext; return SET_PORT; }
 <INITIAL>{SET_URI}	{ count(); yylval.strval=yytext; return SET_URI; }
+<INITIAL>{PREFIX}	{ count(); yylval.strval=yytext; return PREFIX; }
+<INITIAL>{STRIP}	{ count(); yylval.strval=yytext; return STRIP; }
 <INITIAL>{IF}	{ count(); yylval.strval=yytext; return IF; }
 <INITIAL>{ELSE}	{ count(); yylval.strval=yytext; return ELSE; }
 
 <INITIAL>{URIHOST}	{ count(); yylval.strval=yytext; return URIHOST; }
 <INITIAL>{URIPORT}	{ count(); yylval.strval=yytext; return URIPORT; }
 
+<INITIAL>{MAX_LEN}	{ count(); yylval.strval=yytext; return MAX_LEN; }
+
 <INITIAL>{METHOD}	{ count(); yylval.strval=yytext; return METHOD; }
 <INITIAL>{URI}	{ count(); yylval.strval=yytext; return URI; }
 <INITIAL>{SRCIP}	{ count(); yylval.strval=yytext; return SRCIP; }

+ 25 - 0
cfg.y

@@ -20,11 +20,13 @@
 #include "sr_module.h"
 #include "modparam.h"
 
+#include "config.h"
 
 #ifdef DEBUG_DMALLOC
 #include <dmalloc.h>
 #endif
 
+
 extern int yylex();
 void yyerror(char* s);
 char* tmp;
@@ -54,6 +56,8 @@ void* f_tmp;
 %token EXEC
 %token SET_HOST
 %token SET_HOSTPORT
+%token PREFIX
+%token STRIP
 %token SET_USER
 %token SET_USERPASS
 %token SET_PORT
@@ -62,9 +66,11 @@ void* f_tmp;
 %token ELSE
 %token URIHOST
 %token URIPORT
+%token MAX_LEN
 %token SETFLAG
 %token RESETFLAG
 %token ISFLAGSET
+%token LEN_GT
 %token METHOD
 %token URI
 %token SRCIP
@@ -562,6 +568,13 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
 		| SETFLAG LPAREN NUMBER RPAREN {$$=mk_action( SETFLAG_T, NUMBER_ST, 0,
 													(void *)$3, 0 ); }
 		| SETFLAG error { $$=0; yyerror("missing '(' or ')'?"); }
+
+		| LEN_GT LPAREN NUMBER RPAREN {$$=mk_action( LEN_GT_T, NUMBER_ST, 0,
+													(void *)$3, 0 ); }
+		| LEN_GT LPAREN MAX_LEN RPAREN {$$=mk_action( LEN_GT_T, NUMBER_ST, 0,
+													(void *) BUF_SIZE, 0 ); }
+		| LEN_GT error { $$=0; yyerror("missing '(' or ')'?"); }
+
 		| RESETFLAG LPAREN NUMBER RPAREN {$$=mk_action(	RESETFLAG_T, NUMBER_ST, 0,
 													(void *)$3, 0 ); }
 		| RESETFLAG error { $$=0; yyerror("missing '(' or ')'?"); }
@@ -591,6 +604,18 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
 		| SET_HOST error { $$=0; yyerror("missing '(' or ')' ?"); }
 		| SET_HOST LPAREN error RPAREN { $$=0; yyerror("bad argument, "
 														"string expected"); }
+
+		| PREFIX LPAREN STRING RPAREN { $$=mk_action(PREFIX_T, STRING_ST,
+														0, $3, 0); }
+		| PREFIX error { $$=0; yyerror("missing '(' or ')' ?"); }
+		| PREFIX LPAREN error RPAREN { $$=0; yyerror("bad argument, "
+														"string expected"); }
+		| STRIP LPAREN NUMBER RPAREN { $$=mk_action(STRIP_T, NUMBER_ST,
+														0, (void *) $3, 0); }
+		| STRIP error { $$=0; yyerror("missing '(' or ')' ?"); }
+		| STRIP LPAREN error RPAREN { $$=0; yyerror("bad argument, "
+														"number expected"); }
+
 		| SET_HOSTPORT LPAREN STRING RPAREN { $$=mk_action( SET_HOSTPORT_T, 
 														STRING_ST, 0, $3, 0); }
 		| SET_HOSTPORT error { $$=0; yyerror("missing '(' or ')' ?"); }

+ 1 - 1
config.h

@@ -80,7 +80,7 @@
    avoid terror of excessively huge messages; they are
    useless anyway
 */
-#define BUF_SIZE (MAX_FIXED_BLOCK-32)
+#define BUF_SIZE 3040
 
 /* forwarding  -- Via buffer dimensioning */
 #define MAX_VIA_LINE_SIZE	240

+ 13 - 1
forward.c

@@ -97,6 +97,7 @@ int update_sock_struct_from_via( struct sockaddr_in* to,  struct via_body* via )
 {
 	int err;
 	struct hostent* he;
+	char *host_copy;
 
 	to->sin_family = AF_INET;
 	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 )
 #endif
 	{
 		/* fork? gethostbyname will probably block... */
-		he=gethostbyname(via->host.s);
+		/* we do now a malloc/memcpy because gethostbyname loves \0-terminated 
+		   strings; -jiri */
+		if (!(host_copy=pkg_malloc( via->host.len+1 ))) {
+			LOG(L_NOTICE, "ERROR: update_sock_struct_from_via: not enough memory\n");
+			return -1;
+		}
+		memcpy(host_copy, via->host.s, via->host.len );
+		host_copy[via->host.len]=0;
+		he=gethostbyname(host_copy);
+		/* he=gethostbyname(via->host.s); */
+		pkg_free( host_copy );
+
 		if (he==0){
 			LOG(L_NOTICE, "ERROR:forward_reply:gethostbyname(%s) failure\n",
 					via->host.s);

+ 3 - 2
main.c

@@ -165,8 +165,9 @@ void print_ct_constants()
 #endif
 */
 	printf("MAX_RECV_BUFFER_SIZE %d, MAX_LISTEN %d,"
-			" MAX_URI_SIZE %d, MAX_PROCESSES %d\n",
-		MAX_RECV_BUFFER_SIZE, MAX_LISTEN, MAX_URI_SIZE, MAX_PROCESSES );
+			" MAX_URI_SIZE %d, MAX_PROCESSES %d, BUF_SIZE %d\n",
+		MAX_RECV_BUFFER_SIZE, MAX_LISTEN, MAX_URI_SIZE, MAX_PROCESSES,
+		BUF_SIZE );
 }
 
 /* debuging function */

+ 12 - 3
modules/tm/h_table.c

@@ -66,7 +66,7 @@ struct cell*  build_cell( struct sip_msg* p_msg )
 	struct cell* new_cell;
 	unsigned int i;
 #ifndef USE_SYNONIM
-	str          src[5];
+	str          src[8];
 #endif
 
 	/* do we have the source for the build process? */
@@ -129,8 +129,17 @@ struct cell*  build_cell( struct sip_msg* p_msg )
 	src[2]= p_msg->callid->body;
 	src[3]= p_msg->first_line.u.request.uri;
 	src[4]= get_cseq( p_msg )->number;
-	MDStringArray ( new_cell->md5, src, 5 );
-#endif
+
+	/* topmost Via is part of transaction key as well ! */
+	src[5]= p_msg->via1->host;
+	src[6]= p_msg->via1->port_str;
+	if (p_msg->via1->branch) {
+		src[7]= p_msg->via1->branch->value;
+		MDStringArray ( new_cell->md5, src, 8 );
+	} else {
+		MDStringArray ( new_cell->md5, src, 7 );
+	}
+ #endif
 
 	init_cell_lock(  new_cell );
 	return new_cell;

+ 2 - 1
modules/tm/h_table.h

@@ -13,6 +13,7 @@
 
 #include "../../parser/msg_parser.h"
 #include "../../types.h"
+#include "../../md5utils.h"
 #include "config.h"
 /*#include "t_flags.h"*/
 
@@ -146,7 +147,7 @@ typedef struct cell
 	struct sockaddr_in ack_to;
 #ifndef	USE_SYNONIM
 	/* MD5checksum */
-	char md5[32];
+	char md5[MD5_LEN];
 #endif
 
 #ifdef	EXTRA_DEBUG

+ 2 - 2
modules/tm/t_funcs.c

@@ -406,7 +406,7 @@ int t_build_and_send_CANCEL(struct cell *Trans,unsigned int branch)
 			req_line(p_msg).method.s);
 	}
 	/* changhing method name*/
-	memcpy(cancel_buf,"CANCEL",6);
+	memcpy(cancel_buf, CANCEL , CANCEL_LEN );
 	append_mem_block(p,CRLF,CRLF_LEN);
 	/* insert our via */
 	append_mem_block(p,via,via_len);
@@ -423,7 +423,7 @@ int t_build_and_send_CANCEL(struct cell *Trans,unsigned int branch)
 		{
 			append_mem_block(p,hdr->name.s,
 				((((struct cseq_body*)hdr->parsed)->method.s)-hdr->name.s));
-			append_mem_block(p,"CANCEL" CRLF, 6+CRLF_LEN );
+			append_mem_block(p, CANCEL CRLF, CANCEL_LEN +CRLF_LEN );
 		}
 }
 

+ 3 - 5
modules/tm/t_funcs.h

@@ -18,10 +18,13 @@
 #include "../../forward.h"
 #include "../../mem/mem.h"
 
+#include "../../md5utils.h"
+
 #include "config.h"
 #include "lock.h"
 #include "timer.h"
 
+
 struct s_table;
 struct timer;
 struct entry;
@@ -58,11 +61,6 @@ extern unsigned int     nr_forks;
 #define UNLOCK_WAIT(_t) unlock(&(_t)->wait_mutex )
 
 
-/* convenience short-cut macros */
-#define REQ_METHOD first_line.u.request.method_value
-#define REPLY_STATUS first_line.u.reply.statuscode
-#define REPLY_CLASS(_reply) ((_reply)->REPLY_STATUS/100)
-
 /* send a private buffer: utilize a retransmission structure
    but take a separate buffer not refered by it; healthy
    for reducing time spend in REPLIES locks

+ 95 - 40
modules/tm/t_lookup.c

@@ -1,6 +1,30 @@
 /*
  * $Id$
  *
+ * This C-file takes care of matching requests and replies with
+ * existing transactions. Note that we do not do SIP-compliant
+ * request matching as asked by SIP spec. We do bitwise matching of 
+ * all header fields in requests which form a transaction key. 
+ * It is much faster and it worx pretty well -- we haven't 
+ * had any interop issue neither in lab nor in bake-offs. The reason
+ * is that retransmissions do look same as original requests
+ * (it would be really silly if they wuld be mangled). The only
+ * exception is we parse To as To in ACK is compared to To in
+ * reply and both  of them are constructed by different software.
+ * 
+ * As for reply matching, we match based on branch value -- that is
+ * faster too. There are two versions .. with SYNONYMs #define
+ * enabled, the branch includes ordinal number of a transaction
+ * in a synonym list in hash table and is somewhat faster but
+ * not reboot-resilient. SYNONYMs turned off are little slower
+ * but work across reboots as well.
+ *
+ * The branch parameter is formed as follows:
+ * SYNONYMS  on: hash.synonym.branch
+ * SYNONYMS off: md5.hash.branch
+ *
+ * -jiri
+ *
  */
 
 #include <assert.h>
@@ -130,7 +154,9 @@ int t_lookup_request( struct sip_msg* p_msg , int leave_new_locked )
 		else
 		{ /* it's a ACK request*/
 			/* first only the length are checked */
-			if ( t_msg->first_line.u.request.method_value==METHOD_INVITE
+			/* use shortcut; -jiri
+			if ( t_msg->first_line.u.request.method_value==METHOD_INVITE */
+			if (t_msg->REQ_METHOD==METHOD_INVITE
 			/* && (fprintf(stderr,"------Method name OK->testing callid len...\n")) */
 			&& /*callid length*/ EQ_LEN(callid)
 			/* && (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 )
 			/* && (fprintf(stderr,"------To uri OK -> testing To tag len\n")) */
 			&& /*to tag*/p_cell->uas.tag->len==get_to(p_msg)->tag_value.len
 			/* && (fprintf(stderr,"------To tag OK -> testing uri len\n")) */
+
+			/* in ACKs to 200, r-uri and Via may be different than in
+			   original INVITE; we still try to match the transaction
+			   so that we can retransmit an ACK on resent 200 -- different
+			   from SIP spec which kills transaction state after INVITE-200
+			   and considers 200-ACK a new transaction which just happens
+			   to have the same CSeq. -jiri
+			*/
+
 			&& /*req URI*/(p_cell->uas.status==200 || EQ_REQ_URI_LEN )
 			/* && (fprintf(stderr,"------uri OK -> testing via len\n")) */
 			&& /*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 ,
 #ifdef USE_SYNONIM
 		|| (entry_label=reverse_hex2int(syni, synl))<0
 #else
-		|| loopl!=32
+		|| loopl!=MD5_LEN
 #endif
 	) {
 		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 ,
 	DBG("DEBUG: t_reply_matching: hash %d label %d branch %d\n",
 		hash_index, entry_label, branch_id );
 
-	/* lock the hole entry*/
-	lock(&(hash_table->entrys[hash_index].mutex));
 
-	/*all the cells from the entry are scan to detect an entry_label matching*/
-	p_cell = hash_table->entrys[hash_index].first_cell;
-	while( p_cell )
-	{
-		/* is it the cell with the wanted entry_label? */
-		if ( (get_cseq(p_msg)->method.len ==
-		get_cseq(p_cell->uas.request)->method.len)
-		&& ((get_cseq(p_msg)->method.s[0] ==
-		get_cseq(p_cell->uas.request)->method.s[0] && (*local_cancel=0)==0)
-		|| (get_cseq(p_cell->uas.request)->method.s[0]=='I' &&
-		get_cseq(p_msg)->method.s[0]=='C'
-		&& p_cell->uac[branch_id].request.cancel!=NO_CANCEL
-		&& p_cell->uac[branch_id].request.cancel!=EXTERNAL_CANCEL
-		&& (*local_cancel=1)==1))
-#ifdef USE_SYNONIM
-		&& ( p_cell->label == entry_label )
-#else
-		&& ( p_cell->uas.request->add_to_branch_len>=32 &&
-		!memcmp(p_cell->uas.request->add_to_branch_s,loopi,32))
-#endif
-		)
-			/* has the transaction the wanted branch? */
-			if ( p_cell->nr_of_outgoings>branch_id )
-			{/* WE FOUND THE GOLDEN EGG !!!! */
-				T = p_cell;
-				*p_branch = branch_id;
-				T_REF( T );
-				unlock(&(hash_table->entrys[hash_index].mutex));
-				DBG("DEBUG: t_reply_matching: reply matched (T=%p,ref=%x)!\n",
-					T,T->ref_bitmap);
-				return 1;
-			}
-		/* next cell */
-		p_cell = p_cell->next_cell;
-	} /* while p_cell */
+	/* search the hash table list at entry 'hash_index'; lock the
+	   entry first 
+	*/
+	lock(&(hash_table->entrys[hash_index].mutex));
+	for (p_cell = hash_table->entrys[hash_index].first_cell; p_cell; 
+		p_cell=p_cell->next_cell) {
+
+		/* does method match ? */
+		if (get_cseq(p_msg)->method.len==
+			  get_cseq(p_cell->uas.request)->method.len 
+			&& get_cseq(p_msg)->method.s[0]==
+			  get_cseq(p_cell->uas.request)->method.s[0]) {
+				*local_cancel=0;
+		/* or is it perhaps a CANCEL ? */
+		} else if ( p_cell->uas.request->REQ_METHOD==METHOD_INVITE 
+			&& get_cseq(p_msg)->method.len==CANCEL_LEN 
+			&& memcmp( get_cseq(p_msg)->method.s, CANCEL, CANCEL_LEN )==0 
+			&& p_cell->uac[branch_id].request.cancel!=NO_CANCEL 
+			&& p_cell->uac[branch_id].request.cancel!=EXTERNAL_CANCEL ) {
+				*local_cancel=1;
+		} else { /* method mismatched */
+			continue;
+		};
+		#ifdef USE_SYNONIM
+		if (p_cell->label != entry_label) 
+			continue;
+		#else
+		if ( p_cell->uas.request->add_to_branch_len<MD5_LEN 
+			 || memcmp(p_cell->uas.request->add_to_branch_s,loopi,MD5_LEN)!=0)
+				continue;
+		#endif
+		/* sanity check ... too high branch ? */
+		if ( branch_id>=p_cell->nr_of_outgoings )
+			continue;
+		/* we passed all disqualifying factors .... the transaction has been
+		   matched !
+		*/
+		T=p_cell;
+		*p_branch = branch_id;
+		T_REF( T );
+		unlock(&(hash_table->entrys[hash_index].mutex));
+		DBG("DEBUG: t_reply_matching: reply matched (T=%p,ref=%x)!\n",
+			T,T->ref_bitmap);
+		return 1;
+	} /* for cycle */
 
 	/* nothing found */
 	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 )
 	char *begin;
 	int size, orig_size;
 
+	/* this is actually a hack made by Bogdan; I wanted to have a structure
+	   to which anybody can append some branch stuff which may be utilizied
+	   during reply processing; Bogdan ignored that and resets it all the
+	   time to construct multiple branches for multiple via's during
+	   forking (otherwise, the next branch would be now appended to
+	   previous branch)
+
+	   keywords: HACK
+	*/
+     	
 	p_msg->add_to_branch_len = 0; /*bogdan*/
+
+
 	begin=p_msg->add_to_branch_s+p_msg->add_to_branch_len;
 	orig_size = size=MAX_BRANCH_PARAM_LEN - p_msg->add_to_branch_len;
 
 #ifndef USE_SYNONIM
-	if (memcpy(begin,trans->md5,32)) {begin+=32;size-=32;} else return -1;
+	if (memcpy(begin,trans->md5,MD5_LEN)) {begin+=MD5_LEN;size-=MD5_LEN;} else return -1;
 	if (size) { *begin=BRANCH_SEPARATOR; begin++; size--; } else return -1;
 #endif
 	if (int2reverse_hex( &begin, &size, trans->hash_index)==-1) return -1;

+ 1 - 1
modules/tm/tm.c

@@ -492,7 +492,7 @@ static int t_relay_to( struct sip_msg  *p_msg , char *str_ip , char *str_port)
 			LOG(L_CRIT, "ERROR: unexpected addifnew return value: %d\n", ret);
 			abort();
 	};
-	if (T) {
+	if (T!=T_UNDEFINED && T!=T_NULL) {
 		T_UNREF( T );
 	}
 	return ret;

+ 2 - 1
parser/msg_parser.c

@@ -296,10 +296,11 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
 				if (match){
 					match++;
 				}else {
-					tmp=end;
 					LOG(L_ERR,
 							"ERROR: get_hdr_field: bad body for <%s>(%d)\n",
 							hdr->name.s, hdr->type);
+					/* abort(); */
+					tmp=end;
 					goto error;
 				}
 				tmp=match;

+ 10 - 0
parser/msg_parser.h

@@ -68,6 +68,16 @@ enum{
 #define ACK_LEN		3
 #define CANCEL_LEN	6
 #define BYE_LEN		3
+
+#define CANCEL	"CANCEL"
+#define ACK		"ACK"
+#define INVITE "INVITE"
+
+/* convenience short-cut macros */
+#define REQ_METHOD first_line.u.request.method_value
+#define REPLY_STATUS first_line.u.reply.statuscode
+#define REPLY_CLASS(_reply) ((_reply)->REPLY_STATUS/100)
+
 enum { METHOD_OTHER, METHOD_INVITE, METHOD_CANCEL, METHOD_ACK, METHOD_BYE };
 
 #define IFISMETHOD(methodname,firstchar)                                  \

+ 2 - 1
route_struct.h

@@ -27,7 +27,8 @@ enum { METHOD_O=1, URI_O, SRCIP_O, DSTIP_O, DEFAULT_O, ACTION_O, NUMBER_O};
 enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
 		SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T, 
 		SET_PORT_T, SET_URI_T, IF_T, MODULE_T,
-		SETFLAG_T, RESETFLAG_T, ISFLAGSET_T };
+		SETFLAG_T, RESETFLAG_T, ISFLAGSET_T ,
+		LEN_GT_T, PREFIX_T, STRIP_T };
 enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST,
 		EXPR_ST, ACTIONS_ST, CMDF_ST, MODFIXUP_ST, URIHOST_ST, URIPORT_ST };
 

+ 66 - 0
test/long.sip

@@ -0,0 +1,66 @@
+INVITE sip:[email protected] SIP/2.0
+Max-Forwards: 10
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=1848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=2848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=3848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=4848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=8848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=9848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=5848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=6848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=7848eaf6f622ebaf1762f34e5d08ec2e.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=b03d645a795fe2572631dbe15438fabd.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=59c7c421d731de1ce1e1e4c6e83150f2.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=3b33b0d029964ec5330922ff50b34c79.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=781aa36a12b7b99b2316a8ed32123fc9.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=a93680d322702022416a5a661aaf573d.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=5a94858405aeaae679632efed7e1ff0b.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=70509dba8d202a0116d2e51cd474a1d4.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=7056d40a2cfa30ff299705fc791f4303.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=ac7cf460ba831233121eead26af76d5a.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=2c4d2ac0b10115c704d28c2b360bcb6f.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=e0282bc88aed37191911cbb5ded27379.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=c7d6a97d4b6762877410653db5643775.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=a0c4944760b9f9693209f719e7aa177c.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=4147b5297bc5a8e0c3ec58fe6fd9bf6c.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=557cfe12fa9372a0a309ffebcdef3110.836.0
+Via: SIP/2.0/UDP 195.37.77.100;branch=ce741cd8b427d1722d4f746922a9d3a2.836.0
+Via: SIP/2.0/UDP 195.37.77.101;branch=838cccacb7d33e12c5e097f9090adfe1.836.0
+Via: SIP/2.0/UDP 213.20.128.35:9315
+From: "jiri" <sip:[email protected]>;tag=76ff7a07-c091-4192-84a0-d56e91fe104f
+To: <sip:[email protected]>
+Call-ID: [email protected]
+CSeq: 2 INVITE
+Contact: <sip:213.20.128.35:9315>
+User-Agent: Windows RTC/1.0
+Proxy-Authorization: Digest username="jiri", realm="iptel.org", algorithm="MD5", uri="sip:[email protected]", nonce="3cef753900000001771328f5ae1b8b7f0d742da1feb5753c", response="53fe98db10e1074b03b3e06438bda70f"
+Content-Type: application/sdp
+Content-Length: 451
+
+v=0
+o=jku2 0 0 IN IP4 213.20.128.35
+s=session
+c=IN IP4 213.20.128.35
+b=CT:1000
+t=0 0
+m=audio 54742 RTP/AVP 97 111 112 6 0 8 4 5 3 101
+a=rtpmap:97 red/8000
+a=rtpmap:111 SIREN/16000
+a=fmtp:111 bitrate=16000
+a=rtpmap:112 G7221/16000
+a=fmtp:112 bitrate=24000
+a=rtpmap:6 DVI4/16000
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+a=rtpmap:4 G723/8000
+a=rtpmap:5 DVI4/8000
+a=rtpmap: 3 GSM/8000
+a=rtpmap:101 telephone-event/8000
+a=fmtp:101 0-16

+ 4 - 4
ut.h

@@ -74,11 +74,11 @@ static inline unsigned short str2s(unsigned char* str, unsigned int len,
 	return ret;
 
 error_digits:
-	DBG("str2s: ERROR: too many letters in [%s]\n", init);
+	DBG("str2s: ERROR: too many letters in [%.*s]\n", len, init);
 	if (err) *err=1;
 	return 0;
 error_char:
-	DBG("str2s: ERROR: unexpected char %c in %s\n", *str, init);
+	DBG("str2s: ERROR: unexpected char %c in %.*s\n", *str, len, init);
 	if (err) *err=1;
 	return 0;
 }
@@ -117,11 +117,11 @@ static inline unsigned int str2ip(unsigned char* str, unsigned int len,
 	return ret;
 
 error_dots:
-	DBG("str2ip: ERROR: too many dots in [%s]\n", init);
+	DBG("str2ip: ERROR: too many dots in [%.*s]\n", len, init);
 	if (err) *err=1;
 	return 0;
 error_char:
-	DBG("str2ip: WARNING: unexpected char %c in %s\n", *str, init);
+	DBG("str2ip: WARNING: unexpected char %c in %.*s\n", *str, len, init);
 	if (err) *err=1;
 	return 0;
 }