瀏覽代碼

- switched to new via & header parsing
- lots of new members added to sip_msg
- all headers are parsed
- merged with cvs version => compilation errors in receive.c

Andrei Pelinescu-Onciul 24 年之前
父節點
當前提交
e72b5b5057
共有 8 個文件被更改,包括 332 次插入184 次删除
  1. 3 3
      Makefile
  2. 28 24
      forward.c
  3. 1 0
      globals.h
  4. 1 1
      main.c
  5. 236 136
      msg_parser.c
  6. 40 8
      msg_parser.h
  7. 22 11
      receive.c
  8. 1 1
      test/req2.sip

+ 3 - 3
Makefile

@@ -28,7 +28,7 @@ NAME=ser
 # DEBUG compiles in some extra debugging code
 # OLD_PARSER uses the old and stable parser (from ser 8.3.2)
 # DNS_IP_HACK faster ip address resolver for ip strings (e.g "127.0.0.1")
-DEFS=-DNOCR -DMACROEATER -DSTATS -DOLD_PARSER -DDNS_IP_HACK #-DNO_DEBUG 
+DEFS=-DNOCR -DMACROEATER -DSTATS -DDNS_IP_HACK #-DNO_DEBUG 
 #-DNO_LOG
 
 PROFILE=  # -pg #set this if you want profiling
@@ -47,8 +47,8 @@ ifeq ( mode, release )
 	CFLAGS=-O2 -Wcast-align $(PROFILE) -Winline#-Wmissing-prototypes 
 	LDFLAGS=-Wl,-O2 -Wl,-E $(PROFILE)
 else
-	CFLAGS=-g
-	LDFLAGS=-g
+	CFLAGS=-g -Wcast-align -Winline
+	LDFLAGS=-g -Wl,-E
 endif
 
 LEX=flex

+ 28 - 24
forward.c

@@ -192,7 +192,7 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
 		
 	
 	/* check if received needs to be added */
-	if (check_address(source_ip, msg->via1.host.s, received_dns)!=0){
+	if (check_address(source_ip, msg->via1->host.s, received_dns)!=0){
 		received_buf=malloc(sizeof(char)*MAX_RECEIVED_SIZE);
 		if (received_buf==0){
 			LOG(L_ERR, "ERROR: forward_request: out of memory\n");
@@ -214,22 +214,23 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
 	/* add via header to the list */
 	/* try to add it before msg. 1st via */
 	/*add first via, as an anchor for second via*/
-	anchor=anchor_lump(&(msg->add_rm), msg->via1.hdr.s-buf, 0, HDR_VIA);
+	anchor=anchor_lump(&(msg->add_rm), msg->via1->hdr.s-buf, 0, HDR_VIA);
 	if (anchor==0) goto error;
 	if (insert_new_lump_before(anchor, line_buf, via_len, HDR_VIA)==0)
 		goto error;
 	/* if received needs to be added, add anchor after host and add it */
 	if (received_len){
-		if (msg->via1.params.s){
-				size= msg->via1.params.s-msg->via1.hdr.s-1; /*compensate 
+		if (msg->via1->params.s){
+				size= msg->via1->params.s-msg->via1->hdr.s-1; /*compensate 
 															  for ';' */
 		}else{
-				size= msg->via1.host.s-msg->via1.hdr.s+msg->via1.host.len;
-				if (msg->via1.port!=0){
-					size+=strlen(msg->via1.hdr.s+size+1)+1; /* +1 for ':'*/
+				size= msg->via1->host.s-msg->via1->hdr.s+msg->via1->host.len;
+				if (msg->via1->port!=0){
+					size+=strlen(msg->via1->hdr.s+size+1)+1; /* +1 for ':'*/
 				}
 		}
-		anchor=anchor_lump(&(msg->add_rm),msg->via1.hdr.s-buf+size,0, HDR_VIA);
+		anchor=anchor_lump(&(msg->add_rm),msg->via1->hdr.s-buf+size,0,
+				HDR_VIA);
 		if (anchor==0) goto error;
 		if (insert_new_lump_after(anchor, received_buf, received_len, HDR_VIA) 
 				==0 ) goto error;
@@ -492,25 +493,26 @@ int forward_reply(struct sip_msg* msg)
 	/*check if first via host = us */
 	if (check_via){
 		for (r=0; r<addresses_no; r++)
-			if(strcmp(msg->via1.host.s, names[r])==0) break;
+			if(strcmp(msg->via1->host.s, names[r])==0) break;
 		if (r==addresses_no){
 			LOG(L_NOTICE, "ERROR: forward_reply: host in first via!=me :"
-					" %s\n", msg->via1.host);
+					" %s\n", msg->via1->host);
 			/* send error msg back? */
 			goto error;
 		}
 	}
 	/* we must remove the first via */
-	via_len=msg->via1.size;
-	size=msg->via1.hdr.s-buf;
+	via_len=msg->via1->bsize;
+	size=msg->via1->hdr.s-buf;
 	DBG("via len: %d, initial size: %d\n", via_len, size);
-	if (msg->via1.next){
-		/* keep hdr =substract hdr size +1 (hdr':') and add
-		 */
-		via_len-=msg->via1.hdr.len+1;
-		size+=msg->via1.hdr.len+1;
+	if (msg->via1->next){
+		/* add hdr size*/
+		size+=msg->via1->hdr.len+1;
 	    DBG(" adjusted via len: %d, initial size: %d\n",
 				via_len, size);
+	}else{
+		/* add hdr size ("Via:")*/
+		via_len+=msg->via1->hdr.len+1;
 	}
 	new_len=len-via_len;
 	
@@ -530,26 +532,28 @@ int forward_reply(struct sip_msg* msg)
 			s_offset, offset, 
 			len-s_offset );
 	DBG("Sending: to %s:%d, \n%s.\n",
-			msg->via2.host.s, 
-			(unsigned short)msg->via2.port,
+			msg->via2->host.s, 
+			(unsigned short)msg->via2->port,
 			new_buf);
 
 #ifdef DNS_IP_HACK
-	to->sin_addr.s_addr=str2ip(msg->via2.host.s, msg->via2.host.len, &err);
+	to->sin_addr.s_addr=str2ip(msg->via2->host.s, msg->via2->host.len, &err);
 	if (err==0){
 		to->sin_family = AF_INET;
-		to->sin_port = (msg->via2.port)?htons(msg->via2.port):htons(SIP_PORT);
+		to->sin_port = (msg->via2->port)?htons(msg->via2->port):
+						htons(SIP_PORT);
 	}else{
 #endif
 		/* fork? gethostbyname will probably block... */
-		he=gethostbyname(msg->via2.host.s);
+		he=gethostbyname(msg->via2->host.s);
 		if (he==0){
 			LOG(L_NOTICE, "ERROR:forward_reply:gethostbyname(%s) failure\n",
-					msg->via2.host.s);
+					msg->via2->host.s);
 			goto error;
 		}
 		to->sin_family = AF_INET;
-		to->sin_port = (msg->via2.port)?htons(msg->via2.port):htons(SIP_PORT);
+		to->sin_port = (msg->via2->port)?htons(msg->via2->port):
+						htons(SIP_PORT);
 		to->sin_addr.s_addr=*((long*)he->h_addr_list[0]);
 
 #ifdef DNS_IP_HACK

+ 1 - 0
globals.h

@@ -32,5 +32,6 @@ extern int check_via;
 extern int received_dns;
 
 extern int cfg_errors;
+extern unsigned int msg_no;
 
 #endif

+ 1 - 1
main.c

@@ -36,7 +36,7 @@
 
 
 static char id[]="@(#) $Id$";
-static char version[]="ser 0.8.3.8";
+static char version[]="ser 0.8.3.9";
 static char flags[]="NOCR:"
 #ifdef NOCR
 "On"

+ 236 - 136
msg_parser.c

@@ -203,14 +203,13 @@ int field_name(char *s, int l)
 #ifndef OLD_PARSER
 /* returns pointer to next header line, and fill hdr_f ;
  * if at end of header returns pointer to the last crlf  (always buf)*/
-char* get_hdr_field(char* buf, unsigned int len, struct hdr_field* hdr)
+char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
 {
-	char* end;
+
 	char* tmp;
 	char *match;
 	struct via_body *vb;
 
-	end=buf+len;
 	if ((*buf)=='\n' || (*buf)=='\r'){
 		/* double crlf or lflf or crcr */
 		DBG("found end of header\n");
@@ -222,44 +221,68 @@ char* get_hdr_field(char* buf, unsigned int len, struct hdr_field* hdr)
 	if (hdr->type==HDR_ERROR){
 		LOG(L_ERR, "ERROR: get_hdr_field: bad header\n");
 		goto error;
-	}else if (hdr->type==HDR_VIA){
-		vb=malloc(sizeof(struct via_body));
-		if (vb==0){
-			LOG(L_ERR, "get_hdr_field: out of memory\n");
-			goto error;
-		}
-		memset(vb,0,sizeof(struct via_body));
+	}
+	switch(hdr->type){
+		case HDR_VIA:
+			vb=malloc(sizeof(struct via_body));
+			if (vb==0){
+				LOG(L_ERR, "get_hdr_field: out of memory\n");
+				goto error;
+			}
+			memset(vb,0,sizeof(struct via_body));
 
-		hdr->body.s=tmp;
-		tmp=parse_via(tmp, end, vb);
-		if (vb->error==VIA_PARSE_ERROR){
-			LOG(L_ERR, "ERROR: get_hdr_field: bad via\n");
-			free(vb);
-			goto error;
-		}
-		hdr->parsed=vb;
-		vb->hdr.s=hdr->name.s;
-		vb->hdr.len=hdr->name.len;
-		vb->size=tmp-hdr->name.s;
-		hdr->body.len=tmp-hdr->body.s;
-	}else{
-		/* just skip over it*/
-		hdr->body.s=tmp;
-		/* find lf*/
-		match=q_memchr(tmp, '\n', end-tmp);
-		if (match){
-			/* null terminate*/
-			*match=0;
-			hdr->body.len=match-tmp;
-			match++; /*skip*/
+			hdr->body.s=tmp;
+			tmp=parse_via(tmp, end, vb);
+			if (vb->error==VIA_PARSE_ERROR){
+				LOG(L_ERR, "ERROR: get_hdr_field: bad via\n");
+				free(vb);
+				goto error;
+			}
+			hdr->parsed=vb;
+			vb->hdr.s=hdr->name.s;
+			vb->hdr.len=hdr->name.len;
+			/*vb->size=tmp-hdr->name.s;*/
+			hdr->body.len=tmp-hdr->body.s;
+			break;
+		case HDR_TO:
+		case HDR_FROM:
+		case HDR_CSEQ:
+		case HDR_CALLID:
+		case HDR_CONTACT:
+		case HDR_OTHER:
+			/* just skip over it */
+			hdr->body.s=tmp;
+			/* find end of header */
+			
+			/* find lf */
+			do{
+				match=q_memchr(tmp, '\n', end-tmp);
+				if (match){
+					match++;
+				#if 0
+					/* null terminate*/
+					*match=0;
+					hdr->body.len=match-tmp;
+					match++; /*skip*/
+					tmp=match;
+				#endif
+				}else {
+					tmp=end;
+					LOG(L_ERR, "ERROR: get_hdr_field: bad body for <%s>(%d)\n",
+							hdr->name.s, hdr->type);
+					goto error;
+				}
+			}while( match<end &&( (*match==' ')||(*match=='\t') ) );
+			*(match-1)=0; /*null terminate*/
+			hdr->body.len=match-hdr->body.s;
 			tmp=match;
-		}else {
-			tmp=end;
-			LOG(L_ERR, "ERROR: get_hdr_field: bad body for <%s>(%d)\n",
-					hdr->name.s, hdr->type);
+			break;
+		default:
+			LOG(L_CRIT, "BUG: get_hdr_field: unknown header type %d\n",
+					hdr->type);
 			goto error;
-		}
 	}
+
 	return tmp;
 error:
 	DBG("get_hdr_field: error exit\n");
@@ -296,7 +319,7 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f)
 		hdr_f->type=HDR_EOH;
 		return tmp;
 	}
-	
+#if 0	
 	tmp=eat_token2_end(buffer, buffer+len, ':');
 	if ((tmp==buffer) || (tmp-buffer==len) ||
 		(is_empty_end(buffer, tmp))|| (*tmp!=':')){
@@ -318,11 +341,20 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f)
 			goto error;
 		}
 	}
+#endif
 
+	tmp=parse_hname(buffer, buffer+len, hdr_f);
+	if (hdr_f->type==HDR_ERROR){
+		LOG(L_ERR, "ERROR: get_hdr_field: bad header\n");
+		goto error;
+	}
+	
+#if 0
 	hdr_f->type=field_name(buffer, l);
 	body= ++tmp;
 	hdr_f->name.s=buffer;
 	hdr_f->name.len=l;
+#endif
 	offset=tmp-buffer;
 	/* get all the lines in this field  body */
 	do{
@@ -338,7 +370,7 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f)
 	}
 	*(tmp-1)=0; /* should be an LF */
 	hdr_f->body.s=body;
-	hdr_f->body.len=tmp-1-body;;
+	hdr_f->body.len=tmp-1-body;
 error:
 	return tmp;
 }
@@ -526,7 +558,7 @@ error:
 }
 
 
-
+#ifdef OLD_PARSER
 /* parses a via body, returns next via (for compact vias) & fills vb,
  * the buffer should be null terminated! */
 char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb)
@@ -674,6 +706,108 @@ error:
 	vb->error=VIA_PARSE_ERROR;
 	return tmp;
 }
+#endif
+
+
+/* parse the headers and adds them to msg->headers and msg->to, from etc.
+ * It stops when all the headers requested in flags were parsed, on error
+ * (bad header) or end of headers */
+int parse_headers(struct sip_msg* msg, int flags)
+{
+	struct hdr_field* hf;
+	char* tmp;
+	char* rest;
+	char* end;
+	
+	end=msg->buf+msg->len;
+	tmp=msg->unparsed;
+	
+	DBG("parse_headers: flags=%d\n", flags);
+	while( tmp<end && (flags & msg->parsed_flag) != flags){
+		hf=malloc(sizeof(struct hdr_field));
+		memset(hf,0, sizeof(struct hdr_field));
+		if (hf==0){
+			LOG(L_ERR, "ERROR:parse_headers: memory allocation error\n");
+			goto error;
+		}
+		hf->type=HDR_ERROR;
+		rest=get_hdr_field(tmp, msg->buf+msg->len, hf);
+		switch (hf->type){
+			case HDR_ERROR:
+				LOG(L_INFO,"ERROR: bad header  field\n");
+				goto  error;
+			case HDR_EOH:
+				msg->eoh=tmp; /* or rest?*/
+				msg->parsed_flag|=HDR_EOH;
+				goto skip;
+			case HDR_OTHER: /*do nothing*/
+				break;
+			case HDR_CALLID:
+				if (msg->callid==0) msg->callid=hf;
+				msg->parsed_flag|=HDR_CALLID;
+				break;
+			case HDR_TO:
+				if (msg->to==0) msg->to=hf;
+				msg->parsed_flag|=HDR_TO;
+				break;
+			case HDR_CSEQ:
+				if (msg->cseq==0) msg->cseq=hf;
+				msg->parsed_flag|=HDR_CSEQ;
+				break;
+			case HDR_FROM:
+				if (msg->from==0) msg->from=hf;
+				msg->parsed_flag|=HDR_FROM;
+				break;
+			case HDR_CONTACT:
+				if (msg->contact==0) msg->contact=hf;
+				msg->parsed_flag|=HDR_CONTACT;
+				break;
+			case HDR_VIA:
+				msg->parsed_flag|=HDR_VIA;
+				DBG("parse_headers: Via1 found, flags=%d\n", flags);
+				if (msg->h_via1==0) {
+					msg->h_via1=hf;
+					msg->via1=hf->parsed;
+					if (msg->via1->next){
+						msg->via2=msg->via1->next;
+						msg->parsed_flag|=HDR_VIA2;
+					}
+				}else if (msg->h_via2==0){
+					msg->h_via2=hf;
+					msg->via2=hf->parsed;
+					msg->parsed_flag|=HDR_VIA2;
+				DBG("parse_headers: Via2 found, flags=%d\n", flags);
+				}
+				break;
+			default:
+				LOG(L_CRIT, "BUG: parse_headers: unknown header type %d\n",
+							hf->type);
+				goto error;
+		}
+		/* add the header to the list*/
+		if (msg->last_header==0){
+			msg->headers=hf;
+			msg->last_header=hf;
+		}else{
+			msg->last_header->next=hf;
+			msg->last_header=hf;
+		}
+	#ifdef DEBUG
+		DBG("header field type %d, name=<%s>, body=<%s>\n",
+			hf->type, hf->name.s, hf->body.s);
+	#endif
+		tmp=rest;
+	}
+skip:
+	msg->unparsed=tmp;
+	return 0;
+	
+error:
+	if (hf) free(hf);
+	return -1;
+}
+
+
 
 
 
@@ -686,9 +820,10 @@ int parse_msg(char* buf, unsigned int len, struct sip_msg* msg)
 	char* first_via;
 	char* second_via;
 	struct msg_start *fl;
-	struct hdr_field hf;
+	struct hdr_field* hf;
 	struct via_body *vb1, *vb2;
 	int offset;
+	int flags;
 
 #ifdef OLD_PARSER
 	/* init vb1 & vb2 to the null string */
@@ -700,6 +835,7 @@ int parse_msg(char* buf, unsigned int len, struct sip_msg* msg)
 	vb2->error=VIA_PARSE_ERROR;
 #else
 	vb1=vb2=0;
+	hf=0;
 #endif
 	/* eat crlf from the beginning */
 	for (tmp=buf; (*tmp=='\n' || *tmp=='\r')&&
@@ -719,121 +855,37 @@ int parse_msg(char* buf, unsigned int len, struct sip_msg* msg)
 			DBG(" method:  <%s>\n",fl->u.request.method);
 			DBG(" uri:     <%s>\n",fl->u.request.uri);
 			DBG(" version: <%s>\n",fl->u.request.version);
+			flags=HDR_VIA;
 			break;
 		case SIP_REPLY:
 			DBG("SIP Reply  (status):\n");
 			DBG(" version: <%s>\n",fl->u.reply.version);
 			DBG(" status:  <%s>\n",fl->u.reply.status);
 			DBG(" reason:  <%s>\n",fl->u.reply.reason);
+			flags=HDR_VIA|HDR_VIA2;
 			break;
 		default:
 			DBG("unknown type %d\n",fl->type);
 	}
-	
+	msg->unparsed=tmp;
 	/*find first Via: */
-	hf.type=HDR_ERROR;
 	first_via=0;
 	second_via=0;
-	do{
-		rest=get_hdr_field(tmp, len-offset, &hf);
-		offset+=rest-tmp;
-		switch (hf.type){
-			case HDR_ERROR:
-				LOG(L_INFO,"ERROR: bad header  field\n");
-				goto  error;
-			case HDR_EOH: 
-				goto skip;
-			case HDR_VIA:
-				if (first_via==0){
-					first_via=hf.body.s;
-#ifndef OLD_PARSER
-					vb1=(struct via_body*)hf.parsed;
-#else
-						vb1->hdr.s=hf.name.s;
-						vb1->hdr.len=hf.name.len;
-						/* replace cr/lf with space in first via */
-						for (bar=first_via;(first_via) && (*bar);bar++)
-							if ((*bar=='\r')||(*bar=='\n'))	*bar=' ';
-#endif
-				#ifdef DEBUG
-						DBG("first via: <%s>\n", first_via);
-				#endif
-#ifdef OLD_PARSER
-						bar=parse_via_body(first_via, hf.body.len, vb1);
-						if (vb1->error!=VIA_PARSE_OK){
-							LOG(L_INFO, "ERROR: parsing via body: %s\n",
-									first_via);
-							goto error;
-						}
-						
-						vb1->size=bar-first_via+first_via-vb1->hdr.s; 
-						
-#endif
-						/* compact via */
-						if (vb1->next) {
-							second_via=vb1->next;
-							/* not interested in the rest of the header */
-							goto skip;
-						}else{
-#ifdef OLD_PARSER
-						/*  add 1 (we don't see the trailing lf which
-						 *  was zeroed by get_hfr_field) */
-							vb1->size+=1;
-#endif
-						}
-						if (fl->type!=SIP_REPLY) goto skip; /* we are interested
-															  in the 2nd via 
-															 only in replies */
-				}else if (second_via==0){
-							second_via=hf.body.s;
-#ifndef OLD_PARSER
-							vb2=hf.parsed;
-#else
-							vb2->hdr.s=hf.name.s;
-							vb2->hdr.len=hf.name.len;
-#endif
-							goto skip;
-				}
-				break;
-		}
-	#ifdef DEBUG
-		DBG("header field type %d, name=<%s>, body=<%s>\n",
-			hf.type, hf.name.s, hf.body.s);
-	#endif
-		tmp=rest;
-	}while(hf.type!=HDR_EOH && rest-buf < len);
-
-skip:
-	/* replace cr/lf with space in the second via */
-#ifdef OLD_PARSER
-	for (tmp=second_via;(second_via) && (*tmp);tmp++)
-		if ((*tmp=='\r')||(*tmp=='\n'))	*tmp=' ';
-
-	if (second_via) {
-		tmp=parse_via_body(second_via, hf.body.len, vb2);
-		if (vb2->error!=VIA_PARSE_OK){
-			LOG(L_INFO, "ERROR: parsing via2 body: %s\n", second_via);
-			goto error;
-		}
-		vb2->size=tmp-second_via; 
-		if (vb2->next==0) vb2->size+=1; /* +1 from trailing lf */
-		if (vb2->hdr.s) vb2->size+=second_via-vb2->hdr.s;
-	}
-#endif
-	
+	if (parse_headers(msg, flags)==-1) goto error;
 
 #ifdef DEBUG
 	/* dump parsed data */
-	if (first_via){
+	if (msg->via1){
 		DBG(" first  via: <%s/%s/%s> <%s:%s(%d)>",
-				vb1->name.s, vb1->version.s, vb1->transport.s, vb1->host.s,
-				vb1->port_str, vb1->port);
-		if (vb1->params.s)  DBG(";<%s>", vb1->params.s);
-		if (vb1->comment.s) DBG(" <%s>", vb1->comment.s);
+			msg->via1->name.s, msg->via1->version.s,
+			msg->via1->transport.s, msg->via1->host.s,
+			msg->via1->port_str, msg->via1->port);
+		if (msg->via1->params.s)  DBG(";<%s>", msg->via1->params.s);
+		if (msg->via1->comment.s) DBG(" <%s>", msg->via1->comment.s);
 		DBG ("\n");
 	}
 #ifdef OLD_PARSER
-	if (second_via){
+	if (msg->via2){
 		DBG(" second via: <%s/%s/%s> <%s:%d>",
 				vb2->name.s, vb2->version.s, vb2->transport.s, vb2->host.s,
 				vb2->port);
@@ -845,12 +897,14 @@ skip:
 #endif
 	
 	/* copy data into msg */
+#if 0
 #ifndef OLD_PARSER
 	memcpy(&(msg->via1), vb1, sizeof(struct via_body));
 	if (second_via) memcpy(&(msg->via2), vb2, sizeof(struct via_body));
 	if (vb1) free(vb1);
 	if (vb2) free(vb1);
 #endif
+#endif
 
 #ifdef DEBUG
 	DBG("exiting parse_msg\n");
@@ -859,6 +913,7 @@ skip:
 	return 0;
 	
 error:
+	if (hf) free(hf);
 #ifndef OLD_PARSER
 	if (vb1) free(vb1);
 	if (vb2) free(vb1);
@@ -879,3 +934,48 @@ void free_uri(struct sip_uri* u)
 		if (u->headers.s) free(u->headers.s);
 	}
 }
+
+
+
+void free_via_list(struct via_body* vb)
+{
+	struct via_body* foo;
+	while(vb){
+		foo=vb;
+		vb=vb->next;
+		free(foo);
+	}
+}
+
+
+/* frees a hdr_field structure, 
+ * WARNING: it frees only parsed (and not name.s, body.s)*/
+void clean_hdr_field(struct hdr_field* hf)
+{
+	if (hf->parsed){
+		switch(hf->type){
+			case HDR_VIA:
+				free_via_list(hf->parsed);
+				break;
+			default:
+				LOG(L_CRIT, "BUG: clean_hdr_field: unknown header type %d\n",
+						hf->type);
+		}
+	}
+}
+
+
+
+/* frees a hdr_field list,
+ * WARNING: frees only ->parsed and ->next*/
+void free_hdr_field_lst(struct hdr_field* hf)
+{
+	struct hdr_field* foo;
+	
+	while(hf){
+		foo=hf;
+		hf=hf->next;
+		clean_hdr_field(foo);
+		free(foo);
+	}
+}

+ 40 - 8
msg_parser.h

@@ -13,10 +13,21 @@
 #define SIP_INVALID 0
 
 
-enum {	HDR_EOH=-1, HDR_ERROR=0, HDR_OTHER,
-		HDR_VIA, HDR_TO, HDR_FROM, HDR_CSEQ, HDR_CALLID, HDR_CONTACT,
-		HDR_MAXFORWARDS, HDR_ROUTE
-	};
+
+/*header types and flags*/
+#define HDR_EOH           -1
+#define HDR_ERROR          0
+#define HDR_VIA            1
+#define HDR_VIA1           1
+#define HDR_VIA2           2  /*only used as flag*/
+#define HDR_TO             4
+#define HDR_FROM           8
+#define HDR_CSEQ          16
+#define HDR_CALLID        32
+#define HDR_CONTACT       64
+#define HDR_MAXFORWARDS  128
+#define HDR_ROUTE        256
+#define HDR_OTHER       65536 /*unknown header type*/
 
 #define INVITE_LEN	6
 #define ACK_LEN		3
@@ -65,6 +76,7 @@ struct hdr_field{   /* format: name':' body */
 	str name;
 	str body;
 	void* parsed;
+	struct hdr_field* next;
 };
 
 struct via_body{  /* format: name/version/transport host:port;params comment */
@@ -78,14 +90,30 @@ struct via_body{  /* format: name/version/transport host:port;params comment */
 	str port_str;
 	str params;
 	str comment;
-	int size;    /* full size, including hdr */
-	char* next; /* pointer to next via body string if compact via or null */
+	int bsize;    /* body size, not including hdr */
+	struct via_body* next; /* pointer to next via body string if
+							  compact via or null */
 };
 
 struct sip_msg{
+	unsigned int id; /* message id, unique/process*/
 	struct msg_start first_line;
-	struct via_body via1;
-	struct via_body via2;
+	struct via_body* via1;
+	struct via_body* via2;
+	struct hdr_field* headers; /* all the parsed headers*/
+	struct hdr_field* last_header; /* pointer to the last parsed header*/
+	int parsed_flag;
+	/* via, to, cseq, call-id, from, end of header*/
+	struct hdr_field* h_via1;
+	struct hdr_field* h_via2;
+	struct hdr_field* callid;
+	struct hdr_field* to;
+	struct hdr_field* cseq;
+	struct hdr_field* from;
+	struct hdr_field* contact;
+	char* eoh; /* pointer to the end of header (if found) or null */
+
+	char* unparsed; /* here we stopped parsing*/
 
 	unsigned int src_ip;
 	unsigned int dst_ip;
@@ -135,5 +163,9 @@ char* parse_hname(char* buf, char* end, struct hdr_field* hdr);
 char* parse_via(char* buffer, char* end, struct via_body *vb);
 #endif
 
+void free_via_list(struct via_body *vb);
+void clean_hdr_field(struct hdr_field* hf);
+void free_hdr_field_lst(struct hdr_field* hf);
+
 
 #endif

+ 22 - 11
receive.c

@@ -21,11 +21,15 @@
 #include "stats.h"
 #endif
 
+unsigned int msg_no=0;
+
 int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
 {
 	struct sip_msg msg;
+
+	msg_no++;
 #ifdef STATS
-	int skipped = 1;
+	skipped = 1;
 #endif
 
 	memset(&msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
@@ -33,6 +37,7 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
 	msg.buf=buf;
 	msg.len=len;
 	msg.src_ip=src_ip;
+	msg.id=msg_no;
 	/* make a copy of the message */
 	msg.orig=(char*) malloc(len+1);
 	if (msg.orig==0){
@@ -45,14 +50,14 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
 	if (parse_msg(buf,len, &msg)!=0){
 		goto error;
 	}
-	DBG("Ater parse_msg...\n");
-	
+	DBG("After parse_msg...\n");
 	if (msg.first_line.type==SIP_REQUEST){
 		DBG("msg= request\n");
 		/* sanity checks */
-		if (msg.via1.error!=VIA_PARSE_OK){
+		if ((msg.via1==0) || (msg.via1->error!=VIA_PARSE_OK)){
 			/* no via, send back error ? */
-			goto skip;
+			LOG(L_ERR, "ERROR: receive_msg: no via found in request\n");
+			goto error;
 		}
 		/* check if neccesarry to add receive?->moved to forward_req */
 		
@@ -70,13 +75,15 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
 	}else if (msg.first_line.type==SIP_REPLY){
 		DBG("msg= reply\n");
 		/* sanity checks */
-		if (msg.via1.error!=VIA_PARSE_OK){
+		if ((msg.via1==0) || (msg.via1->error!=VIA_PARSE_OK)){
 			/* no via, send back error ? */
-			goto skip;
+			LOG(L_ERR, "ERROR: receive_msg: no via found in reply\n");
+			goto error;
 		}
-		if (msg.via2.error!=VIA_PARSE_OK){
+		if ((msg.via2==0) || (msg.via2->error!=VIA_PARSE_OK)){
 			/* no second via => error? */
-			goto skip;
+			LOG(L_ERR, "ERROR: receive_msg: no 2nd via found in reply\n");
+			goto error;
 		}
 		/* check if via1 == us */
 
@@ -88,15 +95,17 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
 		/* send the msg */
 		if (forward_reply(&msg)==0){
 			DBG(" reply forwarded to %s:%d\n", 
-						msg.via2.host.s,
-						(unsigned short) msg.via2.port);
+						msg.via2->host.s,
+						(unsigned short) msg.via2->port);
 		}
 	}
 #ifdef STATS
 	skipped = 0;
 #endif
 skip:
+	DBG("skip:...\n");
 	if (msg.new_uri.s) { free(msg.new_uri.s); msg.new_uri.len=0; }
+	if (msg.headers) free_hdr_field_lst(msg.headers);
 	if (msg.add_rm) free_lump_list(msg.add_rm);
 	if (msg.repl_add_rm) free_lump_list(msg.repl_add_rm);
 	free(msg.orig);
@@ -105,7 +114,9 @@ skip:
 #endif
 	return 0;
 error:
+	DBG("error:...\n");
 	if (msg.new_uri.s) free(msg.new_uri.s);
+	if (msg.headers) free_hdr_field_lst(msg.headers);
 	if (msg.add_rm) free_lump_list(msg.add_rm);
 	if (msg.repl_add_rm) free_lump_list(msg.repl_add_rm);
 	free(msg.orig);

+ 1 - 1
test/req2.sip

@@ -1,5 +1,5 @@
 INVITE sip:andrei@localhost:5061;a=b?c=d SIP/2.0
-Via: SIP/2.0/UDP localhost
+Via: SIP/2.0/UDP localhost, SIP/2.0/UDP 127.0.0.1:5061