浏览代码

( merged the 0.8.3.4 changes back in 0.8.3.2)
- char* pointers replaced by str (char*, len) in the important structs.
- old parser is used if OLD_PARSER is defined (default)
- new parser is unstable
- small cleanups

Andrei Pelinescu-Onciul 24 年之前
父节点
当前提交
f8d46776b1
共有 11 个文件被更改,包括 534 次插入208 次删除
  1. 10 4
      Makefile
  2. 38 22
      action.c
  3. 24 30
      forward.c
  4. 13 1
      main.c
  5. 246 113
      msg_parser.c
  6. 45 31
      msg_parser.h
  7. 7 3
      receive.c
  8. 4 4
      route.c
  9. 10 0
      test/repl1.sip
  10. 10 0
      test/req-test1.sip
  11. 127 0
      test/resolver_test.c

+ 10 - 4
Makefile

@@ -23,7 +23,13 @@ NAME=ser
 # recommanded: on (speed-up)
 # STATS allows to print out number of packets processed on CTRL-C; 
 # implementation still nasty and reports per-process
-DEFS=-DNOCR -DMACROEATER -DSTATS #-DNO_DEBUG #-DNO_LOG
+# NO_DEBUG turns off some of the debug messages (DBG(...)).
+# NO_LOG completely turns of all the logging (and DBG(...))
+# DEBUG compiles in some extra debugging code
+# OLD_PARSER uses the old and stable parser (from ser 8.3.2)
+DEFS=-DNOCR -DMACROEATER -DSTATS -DOLD_PARSER #-DNO_DEBUG #-DNO_LOG
+
+PROFILE=  # -pg #set this if you want profiling
 
 # platform dependent settings
 
@@ -32,8 +38,8 @@ ARCH = $(shell uname -s)
 #common
 CC=gcc
 LD=gcc
-CFLAGS=-O3 -Wcast-align #-Wmissing-prototypes 
-LDFLAGS=-Wl,-O2 -Wl,-E
+CFLAGS=-O2 -Wcast-align $(PROFILE)#-Wmissing-prototypes 
+LDFLAGS=-Wl,-O2 -Wl,-E $(PROFILE)
 LEX=flex
 YACC=bison
 YACC_FLAGS=-d -b cfg
@@ -49,7 +55,7 @@ ifeq  ($(ARCH), SunOS)
 
 MAKE=gmake
 YACC=yacc
-LDFLAGS=-O2
+LDFLAGS=-O2 $(PROFILE)
 LIBS+=-L/usr/local/lib -lxnet # or -lnsl -lsocket or -lglibc ?
 
 endif

+ 38 - 22
action.c

@@ -51,9 +51,14 @@ int do_action(struct action* a, struct sip_msg* msg)
 		case FORWARD_T:
 			if (a->p1_type==URIHOST_ST){
 				/*parse uri*/
-				tmp=(msg->new_uri)?msg->new_uri:
-						msg->first_line.u.request.uri;
-				if (parse_uri(tmp, strlen(tmp), &uri)<0){
+				if (msg->new_uri.s){
+						tmp=msg->new_uri.s;
+						len=msg->new_uri.len;
+				}else{
+						tmp=msg->first_line.u.request.uri.s;
+						len=msg->first_line.u.request.uri.len;
+				}
+				if (parse_uri(tmp, len, &uri)<0){
 					LOG(L_ERR, "ERROR: do_action: forward: bad_uri <%s>,"
 								" dropping packet\n",tmp);
 					ret=E_UNSPEC;
@@ -61,8 +66,8 @@ int do_action(struct action* a, struct sip_msg* msg)
 				}
 				switch (a->p2_type){
 					case URIPORT_ST:
-									if (uri.port){
-										port=strtol(uri.port,&end,10);
+									if (uri.port.s){
+										port=strtol(uri.port.s,&end,10);
 										if ((end)&&(*end)){
 											LOG(L_ERR, "ERROR: do_action: "
 													"forward: bad port in "
@@ -83,7 +88,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 							goto skip;
 				}
 				/* create a temporary proxy*/
-				p=mk_proxy(uri.host, port);
+				p=mk_proxy(uri.host.s, port);
 				ret=forward_request(msg, p);
 				free_uri(&uri);
 				free_proxy(p); /* frees only p content, not p itself */
@@ -201,23 +206,33 @@ int do_action(struct action* a, struct sip_msg* msg)
 					break;
 				}
 				if (a->type==SET_URI_T){
-					if (msg->new_uri) free(msg->new_uri);
+					if (msg->new_uri.s) {
+							free(msg->new_uri.s);
+							msg->new_uri.len=0;
+					}
 					len=strlen(a->p1.string);
-					msg->new_uri=malloc(len+1);
-					if (msg->new_uri==0){
+					msg->new_uri.s=malloc(len+1);
+					if (msg->new_uri.s==0){
 						LOG(L_ERR, "ERROR: do_action: memory allocation"
 								" failure\n");
 						ret=E_OUT_OF_MEM;
 						break;
 					}
-					memcpy(msg->new_uri, a->p1.string, len);
-					msg->new_uri[len]=0;
+					memcpy(msg->new_uri.s, a->p1.string, len);
+					msg->new_uri.s[len]=0;
+					msg->new_uri.len=len;
+					
 					ret=1;
 					break;
 				}
-				if (msg->new_uri) tmp=msg->new_uri;
-				else tmp=msg->first_line.u.request.uri;
-				if (parse_uri(tmp, strlen(tmp), &uri)<0){
+				if (msg->new_uri.s) {
+					tmp=msg->new_uri.s;
+					len=msg->new_uri.len;
+				}else{
+					tmp=msg->first_line.u.request.uri.s;
+					len=msg->first_line.u.request.uri.len;
+				}
+				if (parse_uri(tmp, len, &uri)<0){
 					LOG(L_ERR, "ERROR: do_action: bad uri <%s>, dropping"
 								" packet\n", tmp);
 					ret=E_UNSPEC;
@@ -241,14 +256,14 @@ int do_action(struct action* a, struct sip_msg* msg)
 				if ((a->type==SET_USER_T)||(a->type==SET_USERPASS_T))
 					tmp=a->p1.string;
 				else 
-					tmp=uri.user;
+					tmp=uri.user.s;
 				if (tmp){
 					len=strlen(tmp); 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;
+				else tmp=uri.passwd.s;
 				/* passwd */
 				if (tmp){
 					len=strlen(":"); if(crt+len>end) goto error_uri;
@@ -264,7 +279,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 				if ((a->type==SET_HOST_T) ||(a->type==SET_HOSTPORT_T))
 					tmp=a->p1.string;
 				else
-					tmp=uri.host;
+					tmp=uri.host.s;
 				if (tmp){
 					len=strlen(tmp); if(crt+len>end) goto error_uri;
 					memcpy(crt,tmp,len);crt+=len;
@@ -272,7 +287,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 				/* port */
 				if (a->type==SET_HOSTPORT_T) tmp=0;
 				else if (a->type==SET_PORT_T) tmp=a->p1.string;
-				else tmp=uri.port;
+				else tmp=uri.port.s;
 				if (tmp){
 					len=strlen(":"); if(crt+len>end) goto error_uri;
 					memcpy(crt,":",len);crt+=len;
@@ -280,7 +295,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 					memcpy(crt,tmp,len);crt+=len;
 				}
 				/* params */
-				tmp=uri.params;
+				tmp=uri.params.s;
 				if (tmp){
 					len=strlen(";"); if(crt+len>end) goto error_uri;
 					memcpy(crt,";",len);crt+=len;
@@ -288,7 +303,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 					memcpy(crt,tmp,len);crt+=len;
 				}
 				/* headers */
-				tmp=uri.headers;
+				tmp=uri.headers.s;
 				if (tmp){
 					len=strlen("?"); if(crt+len>end) goto error_uri;
 					memcpy(crt,"?",len);crt+=len;
@@ -297,8 +312,9 @@ int do_action(struct action* a, struct sip_msg* msg)
 				}
 				*crt=0; /* null terminate the thing */
 				/* copy it to the msg */
-				if (msg->new_uri) free(msg->new_uri);
-				msg->new_uri=new_uri;
+				if (msg->new_uri.s) free(msg->new_uri.s);
+				msg->new_uri.s=new_uri;
+				msg->new_uri.len=crt-new_uri;
 				free_uri(&uri);
 				ret=1;
 				break;

+ 24 - 30
forward.c

@@ -191,7 +191,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, 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");
@@ -213,21 +213,22 @@ 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-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){
-				size= msg->via1.params-msg->via1.hdr-1; /*compensate for ';' */
+		if (msg->via1.params.s){
+				size= msg->via1.params.s-msg->via1.hdr.s-1; /*compensate 
+															  for ';' */
 		}else{
-				size= msg->via1.host-msg->via1.hdr+strlen(msg->via1.host);
+				size= msg->via1.host.s-msg->via1.hdr.s+msg->via1.host.len;
 				if (msg->via1.port!=0){
-					size+=strlen(msg->via1.hdr+size+1)+1; /* +1 for ':'*/
+					size+=strlen(msg->via1.hdr.s+size+1)+1; /* +1 for ':'*/
 				}
 		}
-		anchor=anchor_lump(&(msg->add_rm), msg->via1.hdr-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;
@@ -291,9 +292,9 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
 	}
 	
 	
-	if (msg->new_uri){ 
-		uri_len=strlen(msg->new_uri); 
-		new_len=new_len-strlen(msg->first_line.u.request.uri)+uri_len;
+	if (msg->new_uri.s){ 
+		uri_len=msg->new_uri.len; 
+		new_len=new_len-msg->first_line.u.request.uri.len+uri_len;
 	}
 	new_buf=(char*)malloc(new_len+1);
 	if (new_buf==0){
@@ -302,16 +303,16 @@ int forward_request( struct sip_msg* msg, struct proxy_l * p)
 	}
 
 	offset=s_offset=0;
-	if (msg->new_uri){
+	if (msg->new_uri.s){
 		/* copy message up to uri */
-		size=msg->first_line.u.request.uri-buf;
+		size=msg->first_line.u.request.uri.s-buf;
 		memcpy(new_buf, orig, size);
 		offset+=size;
 		s_offset+=size;
 		/* add our uri */
-		memcpy(new_buf+offset, msg->new_uri, uri_len);
+		memcpy(new_buf+offset, msg->new_uri.s, uri_len);
 		offset+=uri_len;
-		s_offset+=strlen(msg->first_line.u.request.uri); /* skip original uri */
+		s_offset+=msg->first_line.u.request.uri.len; /* skip original uri */
 	}
 /* copy msg adding/removing lumps */
 	for (t=msg->add_rm;t;t=t->next){
@@ -487,23 +488,23 @@ 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, 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);
+			LOG(L_NOTICE, "ERROR: forward_reply: host in first via!=me :"
+					" %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-buf;
+	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-=strlen(msg->via1.hdr)+1;
-		size+=strlen(msg->via1.hdr)+1;
+		via_len-=msg->via1.hdr.len+1;
+		size+=msg->via1.hdr.len+1;
 	    DBG(" adjusted via len: %d, initial size: %d\n",
 				via_len, size);
 	}
@@ -525,27 +526,20 @@ int forward_reply(struct sip_msg* msg)
 			s_offset, offset, 
 			len-s_offset );
 	DBG("Sending: to %s:%d, \n%s.\n",
-			msg->via2.host, 
+			msg->via2.host.s, 
 			(unsigned short)msg->via2.port,
 			new_buf);
 	/* fork? gethostbyname will probably block... */
-	he=gethostbyname(msg->via2.host);
+	he=gethostbyname(msg->via2.host.s);
 	if (he==0){
 		LOG(L_NOTICE, "ERROR:forward_reply:gethostbyname(%s) failure\n",
-				msg->via2.host);
+				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_addr.s_addr=*((long*)he->h_addr_list[0]);
 
-
-
-
-
-
-
-	
 #ifdef STATS
 	stats.total_tx++;
 #endif

+ 13 - 1
main.c

@@ -34,7 +34,7 @@
 
 
 static char id[]="@(#) $Id$";
-static char version[]="ser 0.8.3.2";
+static char version[]="ser 0.8.3.8";
 static char flags[]="NOCR:"
 #ifdef NOCR
 "On"
@@ -53,6 +53,18 @@ static char flags[]="NOCR:"
 #else
 "Off"
 #endif
+#ifdef NO_DEBUG
+", NO_DEBUG"
+#endif
+#ifdef NO_LOG
+", NO_LOG"
+#endif
+#ifdef DEBUG
+", DEBUG"
+#endif
+#ifdef OLD_PARSER
+", OLD_PARSER"
+#endif
 ;
 
 static char help_msg[]= "\

+ 246 - 113
msg_parser.c

@@ -33,6 +33,7 @@ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl)
 	char* third;
 	char* nl;
 	int offset;
+	int l;
 	char* end;
 	
 	/* grammar:
@@ -49,22 +50,24 @@ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl)
 		LOG(L_INFO, "ERROR:parse_first_line: empty  or bad first line\n");
 		goto error1;
 	}
-	if ((strlen(SIP_VERSION)==(tmp-buffer)) &&
-		(memcmp(buffer,SIP_VERSION,tmp-buffer)==0)){
+	l=tmp-buffer;
+	if ((SIP_VERSION_LEN==l) &&
+		(memcmp(buffer,SIP_VERSION,l)==0)){
 		
 		fl->type=SIP_REPLY;
 	}else{
 		fl->type=SIP_REQUEST;
 	}
 	
-	offset=tmp-buffer;
+	offset=l;
 	second=eat_space(tmp, len-offset);
 	offset+=second-tmp;
 	if ((second==tmp)||(tmp>=end)){
 		goto error;
 	}
 	*tmp=0; /* mark the end of the token */
-	fl->u.request.method=buffer;
+	fl->u.request.method.s=buffer;
+	fl->u.request.method.len=l;
 	
 	/* next element */
 	tmp=eat_token(second, len-offset);
@@ -78,7 +81,9 @@ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl)
 		goto error;
 	}
 	*tmp=0; /* mark the end of the token */
-	fl->u.request.uri=second;
+	fl->u.request.uri.s=second;
+	fl->u.request.uri.len=tmp-second;
+
 	/*  last part: for a request it must be the version, for a reply
 	 *  it can contain almost anything, including spaces, so we don't care
 	 *  about it*/
@@ -104,7 +109,8 @@ char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl)
 		goto error;
 	}
 	*tmp=0;
-	fl->u.request.version=third;
+	fl->u.request.version.s=third;
+	fl->u.request.version.len=tmp-third;
 	
 	return nl;
 
@@ -120,11 +126,10 @@ error1:
 }
 
 
+#ifdef OLD_PARSER
 /* returns integer field name type */
-int field_name(char *s)
+int field_name(char *s, int l)
 {
-	int l;
-	l=strlen(s);
 	if (l<1) return HDR_OTHER;
 	else if ((l==1) && ((*s=='v')||(*s=='V')))
 		return HDR_VIA;
@@ -134,10 +139,77 @@ int field_name(char *s)
 		return HDR_TO;*/
 	return HDR_OTHER;
 }
+#endif
 
 
+#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* 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");
+		hdr->type=HDR_EOH;
+		return buf;
+	}
 
+	tmp=parse_hname(buf, end, 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));
 
+		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=memchr(tmp, '\n', end-tmp);
+		if (match){
+			/* null terminate*/
+			*match=0;
+			hdr->body.len=match-tmp;
+			match++; /*skip*/
+			tmp=match;
+		}else {
+			tmp=end;
+			LOG(L_ERR, "ERROR: get_hdr_field: bad body for <%s>(%d)\n",
+					hdr->name.s, hdr->type);
+			goto error;
+		}
+	}
+	return tmp;
+error:
+	DBG("get_hdr_field: error exit\n");
+	hdr->type=HDR_ERROR;
+	return tmp;
+}
+
+#else
 /* returns pointer to next header line, and fill hdr_f */
 char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f)
 {
@@ -151,11 +223,14 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f)
 	char* nl;
 	char* body;
 	int offset;
+	int l;
 
 	
 	/* init content to the empty string */
-	hdr_f->name="";
-	hdr_f->body="";
+	hdr_f->name.s="";
+	hdr_f->name.len=0;
+	hdr_f->body.s="";
+	hdr_f->body.len=0;
 	
 	if ((*buffer=='\n')||(*buffer=='\r')){
 		/* double crlf */
@@ -175,6 +250,7 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f)
 	tmp2=eat_token(buffer, tmp-buffer);
 	/* in the worst case tmp2=buffer+tmp-buffer=tmp */
 	*tmp2=0;
+	l=tmp2-buffer;
 	if (tmp2<tmp){
 		tmp2++;
 		/* catch things like: "Via foo bar:" */
@@ -185,9 +261,10 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f)
 		}
 	}
 
-	hdr_f->type=field_name(buffer);
+	hdr_f->type=field_name(buffer, l);
 	body= ++tmp;
-	hdr_f->name=buffer;
+	hdr_f->name.s=buffer;
+	hdr_f->name.len=l;
 	offset=tmp-buffer;
 	/* get all the lines in this field  body */
 	do{
@@ -202,20 +279,22 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f)
 		goto error;
 	}
 	*(tmp-1)=0; /* should be an LF */
-	hdr_f->body=body;
+	hdr_f->body.s=body;
+	hdr_f->body.len=tmp-1-body;;
 error:
 	return tmp;
 }
+#endif
 
 
-
-char* parse_hostport(char* buf, char** host, short int* port)
+char* parse_hostport(char* buf, str* host, short int* port)
 {
 	char *tmp;
 	char *invalid;
 	
-	*host=buf;
+	host->s=buf;
 	for(tmp=buf;(*tmp)&&(*tmp!=':');tmp++);
+	host->len=tmp-buf;
 	if (*tmp==0){
 		*port=0;
 	}else{
@@ -229,7 +308,7 @@ char* parse_hostport(char* buf, char** host, short int* port)
 			/* report error? */
 		}
 	}
-	return *host;
+	return host->s;
 }
 
 
@@ -265,8 +344,8 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
 	next=memchr(buf,'@', end-buf);
 	if (next==0){
 		/* no '@' found, => no userinfo */
-		uri->user=0;
-		uri->passwd=0;
+		uri->user.s=0;
+		uri->passwd.s=0;
 		host=buf;
 	}else{
 		/* found it */
@@ -275,33 +354,37 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
 		passwd=memchr(user,':', next-user);
 		if (passwd==0){
 			/* no ':' found => no password */
-			uri->passwd=0;
-			uri->user=(char*)malloc(next-user+1);
-			if (uri->user==0){
+			uri->passwd.s=0;
+			uri->user.s=(char*)malloc(next-user+1);
+			if (uri->user.s==0){
 				LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
 				ret=E_OUT_OF_MEM;
 				goto error;
 			}
-			memcpy(uri->user,user, next-user);
-			uri->user[next-user]=0; /* null terminate it, usefull for easy printing*/
+			memcpy(uri->user.s, user, next-user);
+			uri->user.len=next-user;
+			uri->user.s[next-user]=0; /* null terminate it, 
+									   usefull for easy printing*/
 		}else{
-			uri->user=(char*)malloc(passwd-user+1);
-			if (uri->user==0){
+			uri->user.s=(char*)malloc(passwd-user+1);
+			if (uri->user.s==0){
 				LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
 				ret=E_OUT_OF_MEM;
 				goto error;
 			}
-			memcpy(uri->user,user, passwd-user);
-			uri->user[passwd-user]=0;
+			memcpy(uri->user.s, user, passwd-user);
+			uri->user.len=passwd-user;
+			uri->user.s[passwd-user]=0;
 			passwd++; /*skip ':' */
-			uri->passwd=(char*)malloc(next-passwd+1);
-			if (uri->passwd==0){
+			uri->passwd.s=(char*)malloc(next-passwd+1);
+			if (uri->passwd.s==0){
 				LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
 				ret=E_OUT_OF_MEM;
 				goto error;
 			}
-			memcpy(uri->passwd,passwd, next-passwd);
-			uri->passwd[next-passwd]=0;
+			memcpy(uri->passwd.s, passwd, next-passwd);
+			uri->passwd.len=next-passwd;
+			uri->passwd.s[next-passwd]=0;
 		}
 		host=next+1; /* skip '@' */
 	}
@@ -316,14 +399,15 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
 	port=memchr(host,':',end-host);
 	host_len=(port)?port-host:(params)?params-host:(headers)?headers-host:end-host;
 	/* get host */
-	uri->host=malloc(host_len+1);
-	if (uri->host==0){
+	uri->host.s=malloc(host_len+1);
+	if (uri->host.s==0){
 		LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
 		ret=E_OUT_OF_MEM;
 		goto error;
 	}
-	memcpy(uri->host,host, host_len);
-	uri->host[host_len]=0;
+	memcpy(uri->host.s, host, host_len);
+	uri->host.len=host_len;
+	uri->host.s[host_len]=0;
 	/* get port*/
 	if ((port)&&(port+1<end)){
 		port++;
@@ -334,15 +418,16 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
 			goto error;
 		}
 		port_len=(params)?params-port:(headers)?headers-port:end-port;
-		uri->port=malloc(port_len+1);
-		if (uri->port==0){
+		uri->port.s=malloc(port_len+1);
+		if (uri->port.s==0){
 			LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
 			ret=E_OUT_OF_MEM;
 			goto error;
 		}
-		memcpy(uri->port, port, port_len);
-		uri->port[port_len]=0;
-	}else uri->port=0;
+		memcpy(uri->port.s, port, port_len);
+		uri->port.len=port_len;
+		uri->port.s[port_len]=0;
+	}else uri->port.s=0;
 	/* get params */
 	if ((params)&&(params+1<end)){
 		params++;
@@ -353,28 +438,30 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
 			goto error;
 		}
 		params_len=(headers)?headers-params:end-params;
-		uri->params=malloc(params_len+1);
-		if (uri->params==0){
+		uri->params.s=malloc(params_len+1);
+		if (uri->params.s==0){
 			LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
 			ret=E_OUT_OF_MEM;
 			goto error;
 		}
-		memcpy(uri->params, params, params_len);
-		uri->params[params_len]=0;
-	}else uri->params=0;
+		memcpy(uri->params.s, params, params_len);
+		uri->params.len=params_len;
+		uri->params.s[params_len]=0;
+	}else uri->params.s=0;
 	/*get headers */
 	if ((headers)&&(headers+1<end)){
 		headers++;
 		headers_len=end-headers;
-		uri->headers=malloc(headers_len+1);
-		if(uri->headers==0){
+		uri->headers.s=malloc(headers_len+1);
+		if(uri->headers.s==0){
 			LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
 			ret=E_OUT_OF_MEM;
 			goto error;
 		}
-		memcpy(uri->headers, headers, headers_len);
-		uri->headers[headers_len]=0;
-	}else uri->headers=0;
+		memcpy(uri->headers.s, headers, headers_len);
+		uri->headers.len=headers_len;
+		uri->headers.s[headers_len]=0;
+	}else uri->headers.s=0;
 	
 	return ret;
 error:
@@ -396,13 +483,15 @@ char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb)
 
 	char* tmp;
 	char *name,*version, *transport, *comment, *params, *hostport;
+	int name_len, version_len, transport_len, comment_len, params_len;
 	char * next_via;
-	char * host;
+	str host;
 	short int port;
 	int offset;
 	
 
-	name=version=transport=comment=params=hostport=next_via=host=0;
+	name=version=transport=comment=params=hostport=next_via=host.s=0;
+	name_len=version_len=transport_len=comment_len=params_len=host.len=0;
 	name=eat_space(buffer, len);
 	if (name-buffer==len) goto error;
 	offset=name-buffer;
@@ -411,18 +500,21 @@ char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb)
 	version=eat_token2(tmp,len-offset,'/');
 	if (version+1-buffer>=len) goto error;
 	*version=0;
+	name_len=version-name;
 	version++;
 	offset+=version-tmp;
 	
 	transport=eat_token2(tmp,len-offset,'/');
 	if (transport+1-buffer>=len) goto error;
 	*transport=0;
+	version_len=transport-version;
 	transport++;
 	offset+=transport-tmp;
 	
 	tmp=eat_token(transport,len-offset);
 	if (tmp+1-buffer>=len) goto error;
 	*tmp=0;
+	transport_len=tmp-transport;
 	tmp++;
 	offset+=tmp-transport;
 	
@@ -445,6 +537,7 @@ char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb)
 					for(;((tmp-buffer)<len)&&
 						(*tmp!=',');tmp++);
 					/* mark end of compact via (also end of comment)*/
+					comment_len=tmp-comment;
 					if (tmp-buffer<len){
 						*tmp=0;
 					}else break;
@@ -463,6 +556,7 @@ char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb)
 				/* eat till end, first space  or ',' */
 				for(;((tmp-buffer)<len)&&
 					(*tmp!=' '&& *tmp!=',');tmp++);
+				params_len=tmp-params;
 				if (tmp-buffer==len)  break;
 				if (*tmp==' '){
 					/* eat comment */
@@ -471,10 +565,12 @@ char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb)
 					comment=tmp;
 					for(;((tmp-buffer)<len)&&
 						(*tmp!=',');tmp++);
+					comment_len=tmp-comment;
 					if (tmp-buffer==len)  break;
 				}
 				/* mark end of via*/
 				*tmp=0;
+				
 				/* eat space & ',' */
 				for(tmp=tmp+1;((tmp-buffer)<len)&&
 					(*tmp==' '|| *tmp==',');tmp++);
@@ -496,13 +592,19 @@ char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb)
 	
 	/* parse hostport */
 	parse_hostport(hostport, &host, &port);
-	vb->name=name;
-	vb->version=version;
-	vb->transport=transport;
-	vb->host=host;
+	vb->name.s=name;
+	vb->name.len=name_len;
+	vb->version.s=version;
+	vb->version.len=version_len;
+	vb->transport.s=transport;
+	vb->transport.len=transport_len;
+	vb->host.s=host.s;
+	vb->host.len=host.len;
 	vb->port=port;
-	vb->params=params;
-	vb->comment=comment;
+	vb->params.s=params;
+	vb->params.len=params_len;
+	vb->comment.s=comment;
+	vb->comment.len=comment_len;
 	vb->next=next_via;
 	vb->error=VIA_PARSE_OK;
 
@@ -526,46 +628,49 @@ int parse_msg(char* buf, unsigned int len, struct sip_msg* msg)
 	char* rest;
 	char* first_via;
 	char* second_via;
-	struct msg_start fl;
+	struct msg_start *fl;
 	struct hdr_field hf;
-	struct via_body vb1, vb2;
+	struct via_body *vb1, *vb2;
 	int offset;
 
-	
+#ifdef OLD_PARSER
 	/* init vb1 & vb2 to the null string */
-	vb1.error=VIA_PARSE_ERROR;
-	vb1.hdr=vb1.name=vb1.version=vb1.transport=vb1.host=0;
-	vb1.params=vb1.comment=0;
-	vb1.next=0;
-	vb1.size=0;
-	memcpy(&vb2, &vb1, sizeof(struct via_body));
-
+	/*memset(&vb1,0, sizeof(struct via_body));
+	memset(&vb2,0, sizeof(struct via_body));*/
+	vb1=&(msg->via1);
+	vb2=&(msg->via2);
+	vb1->error=VIA_PARSE_ERROR;
+	vb2->error=VIA_PARSE_ERROR;
+#else
+	vb1=vb2=0;
+#endif
 	/* eat crlf from the beginning */
 	for (tmp=buf; (*tmp=='\n' || *tmp=='\r')&&
 			tmp-buf < len ; tmp++);
 	offset=tmp-buf;
-	rest=parse_first_line(tmp, len-offset, &fl);
+	fl=&(msg->first_line);
+	rest=parse_first_line(tmp, len-offset, fl);
 	offset+=rest-tmp;
 	tmp=rest;
-	switch(fl.type){
+	switch(fl->type){
 		case SIP_INVALID:
 			DBG("parse_msg: invalid message\n");
 			goto error;
 			break;
 		case SIP_REQUEST:
 			DBG("SIP Request:\n");
-			DBG(" method:  <%s>\n",fl.u.request.method);
-			DBG(" uri:     <%s>\n",fl.u.request.uri);
-			DBG(" version: <%s>\n",fl.u.request.version);
+			DBG(" method:  <%s>\n",fl->u.request.method);
+			DBG(" uri:     <%s>\n",fl->u.request.uri);
+			DBG(" version: <%s>\n",fl->u.request.version);
 			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);
+			DBG(" version: <%s>\n",fl->u.reply.version);
+			DBG(" status:  <%s>\n",fl->u.reply.status);
+			DBG(" reason:  <%s>\n",fl->u.reply.reason);
 			break;
 		default:
-			DBG("unknown type %d\n",fl.type);
+			DBG("unknown type %d\n",fl->type);
 	}
 	
 	/*find first Via: */
@@ -583,88 +688,112 @@ int parse_msg(char* buf, unsigned int len, struct sip_msg* msg)
 				goto skip;
 			case HDR_VIA:
 				if (first_via==0){
-						first_via=hf.body;
-						vb1.hdr=hf.name;
+					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
-						bar=parse_via_body(first_via, strlen(first_via), &vb1);
-						if (vb1.error!=VIA_PARSE_OK){
+#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; 
+						vb1->size=bar-first_via+first_via-vb1->hdr.s; 
 						
+#endif
 						/* compact via */
-						if (vb1.next) {
-							second_via=vb1.next;
+						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;
+							vb1->size+=1;
+#endif
 						}
-						if (fl.type!=SIP_REPLY) goto skip; /* we are interested in the 2nd via 
-															   only in replies */
+						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;
-							vb2.hdr=hf.name;
+							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, hf.body);
+			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, strlen(second_via), &vb2);
-		if (vb2.error!=VIA_PARSE_OK){
+		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) vb2.size+=second_via-vb2.hdr;
+		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
 	
 
 #ifdef DEBUG
 	/* dump parsed data */
 	if (first_via){
-		DBG(" first  via: <%s/%s/%s> <%s:%d>",
-				vb1.name, vb1.version, vb1.transport, vb1.host, vb1.port);
-		if (vb1.params)  DBG(";<%s>", vb1.params);
-		if (vb1.comment) DBG(" <%s>", vb1.comment);
+		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);
 		DBG ("\n");
 	}
+#ifdef OLD_PARSER
 	if (second_via){
 		DBG(" second via: <%s/%s/%s> <%s:%d>",
-				vb2.name, vb2.version, vb2.transport, vb2.host, vb2.port);
-		if (vb2.params)  DBG(";<%s>", vb2.params);
-		if (vb2.comment) DBG(" <%s>", vb2.comment);
+				vb2->name.s, vb2->version.s, vb2->transport.s, vb2->host.s,
+				vb2->port);
+		if (vb2->params.s)  DBG(";<%s>", vb2->params.s);
+		if (vb2->comment.s) DBG(" <%s>", vb2->comment.s);
 		DBG("\n");
 	}
+#endif
 #endif
 	
 	/* copy data into msg */
-	memcpy(&(msg->first_line), &fl, sizeof(struct msg_start));
-	memcpy(&(msg->via1), &vb1, sizeof(struct via_body));
-	memcpy(&(msg->via2), &vb2, sizeof(struct via_body));
+#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
 
 #ifdef DEBUG
 	DBG("exiting parse_msg\n");
@@ -673,6 +802,10 @@ skip:
 	return 0;
 	
 error:
+#ifndef OLD_PARSER
+	if (vb1) free(vb1);
+	if (vb2) free(vb1);
+#endif
 	return -1;
 }
 
@@ -681,11 +814,11 @@ error:
 void free_uri(struct sip_uri* u)
 {
 	if (u){
-		if (u->user) free(u->user);
-		if (u->passwd) free(u->passwd);
-		if (u->host) free(u->host);
-		if (u->port) free(u->port);
-		if (u->params) free(u->params);
-		if (u->headers) free(u->headers);
+		if (u->user.s) free(u->user.s);
+		if (u->passwd.s) free(u->passwd.s);
+		if (u->host.s) free(u->host.s);
+		if (u->port.s) free(u->port.s);
+		if (u->params.s) free(u->params.s);
+		if (u->headers.s) free(u->headers.s);
 	}
 }

+ 45 - 31
msg_parser.h

@@ -5,7 +5,7 @@
 #ifndef msg_parser_h
 #define msg_parser_h
 
-
+#include "str.h"
 #include "data_lump.h"
 
 #define SIP_REQUEST 1
@@ -13,51 +13,55 @@
 #define SIP_INVALID 0
 
 
-#define HDR_ERROR 0
-/* end of header */
-#define HDR_EOH   -1
-#define HDR_OTHER 1
-#define HDR_VIA   2
-#define HDR_TO    3
+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
+	};
+
+
+
 
 #define VIA_PARSE_OK	1
 #define VIA_PARSE_ERROR -1
 
 #define SIP_VERSION	"SIP/2.0"
+#define SIP_VERSION_LEN 7
 
 
 struct msg_start{
 	int type;
 	union {
 		struct {
-			char* method;
-			char* uri;
-			char* version;
+			str method;
+			str uri;
+			str version;
 		}request;
 		struct {
-			char* version;
-			char* status;
-			char* reason;
+			str version;
+			str status;
+			str reason;
 		}reply;
 	}u;
 };
 
 struct hdr_field{   /* format: name':' body */
 	int type;
-	char* name;
-	char* body;
+	str name;
+	str body;
+	void* parsed;
 };
 
 struct via_body{  /* format: name/version/transport host:port;params comment */
 	int error;
-	char *hdr;   /* contains "Via" or "v" */
-	char* name;
-	char* version;
-	char* transport;
-	char* host;
+	str hdr;   /* contains "Via" or "v" */
+	str name;
+	str version;
+	str transport;
+	str host;
 	int port;
-	char* params;
-	char* 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 */
 };
@@ -76,7 +80,7 @@ struct sip_msg{
 	unsigned int len; /* message len (orig) */
 
 	/* modifications */
-	char* new_uri; /* changed first line uri*/
+	str new_uri; /* changed first line uri*/
 
 	struct lump* add_rm;      /* used for all the forwarded messages */
 	struct lump* repl_add_rm; /* only for localy generated replies !!!*/
@@ -85,25 +89,35 @@ struct sip_msg{
 
 
 struct sip_uri{
-	char* user;
-	char* passwd;
-	char* host;
-	char* port;
-	char* params;
-	char* headers;
+	str user;
+	str passwd;
+	str host;
+	str port;
+	str params;
+	str headers;
 };
 
 
 
 char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl);
+#ifdef OLD_PARSER 
 char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f);
-int field_name(char *s);
-char* parse_hostport(char* buf, char** host, short int* port);
+int field_name(char *s, int len);
+#endif
+char* parse_hostport(char* buf, str* host, short int* port);
+
+#ifdef OLD_PARSER 
 char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb);
+#endif
 int parse_msg(char* buf, unsigned int len, struct sip_msg* msg);
 int parse_uri(char *buf, int len, struct sip_uri* uri);
 void free_uri(struct sip_uri* u);
 
 
+#ifndef OLD_PARSER
+char* parse_hname(char* buf, char* end, struct hdr_field* hdr);
+char* parse_via(char* buffer, char* end, struct via_body *vb);
+#endif
+
 
 #endif

+ 7 - 3
receive.c

@@ -46,16 +46,19 @@ 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");
 	
 	if (msg.first_line.type==SIP_REQUEST){
+		DBG("msg= request\n");
 		/* sanity checks */
 		if (msg.via1.error!=VIA_PARSE_OK){
 			/* no via, send back error ? */
 			goto skip;
 		}
-		/* check if neccesarry to add receive? */
+		/* check if neccesarry to add receive?->moved to forward_req */
 		
 		/* exec routing script */
+		DBG("preparing to run routing scripts...\n");
 		if (run_actions(rlist[0], &msg)<0){
 			LOG(L_WARN, "WARNING: receive_msg: "
 					"error while trying script\n");
@@ -66,6 +69,7 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
 		else stats.ok_rx_rq++;	
 #endif
 	}else if (msg.first_line.type==SIP_REPLY){
+		DBG("msg= reply\n");
 		/* sanity checks */
 		if (msg.via1.error!=VIA_PARSE_OK){
 			/* no via, send back error ? */
@@ -90,13 +94,13 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
 		}
 	}
 skip:
-	if (msg.new_uri) free(msg.new_uri);
+	if (msg.new_uri.s) { free(msg.new_uri.s); msg.new_uri.len=0; }
 	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);
 	return 0;
 error:
-	if (msg.new_uri) free(msg.new_uri);
+	if (msg.new_uri.s) free(msg.new_uri.s);
 	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);

+ 4 - 4
route.c

@@ -292,15 +292,15 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
 	}
 	switch(e->l.operand){
 		case METHOD_O:
-				ret=comp_str(msg->first_line.u.request.method, e->r.param,
+				ret=comp_str(msg->first_line.u.request.method.s, e->r.param,
 								e->op, e->subtype);
 				break;
 		case URI_O:
-				if(msg->new_uri){
-					ret=comp_str(msg->new_uri, e->r.param,
+				if(msg->new_uri.s){
+					ret=comp_str(msg->new_uri.s, e->r.param,
 									e->op, e->subtype);
 				}else{
-					ret=comp_str(msg->first_line.u.request.uri, e->r.param,
+					ret=comp_str(msg->first_line.u.request.uri.s, e->r.param,
 									e->op, e->subtype);
 				}
 				break;

+ 10 - 0
test/repl1.sip

@@ -0,0 +1,10 @@
+SIP/2.0 200 Ok
+Via: SIP/2.0/UDP 127.0.0.1
+Via: SIP/2.0/UDP 127.0.0.1:5061
+From: <sip:[email protected]>
+To: <sip:[email protected]>
+Call-ID:[email protected]
+CSeq: 143 INVITE
+Contact: <sip:[email protected]>
+
+

+ 10 - 0
test/req-test1.sip

@@ -0,0 +1,10 @@
+INVITE sip:[email protected]:5061 SIP/2.0
+Via: SIP/2.0/UDP 127.0.0.1
+Via: SIP/2.0/UDP 127.0.0.1:5061
+From: <sip:[email protected]>
+To: <sip:[email protected]>
+Call-ID:[email protected]
+CSeq: 143 INVITE
+Contact: <sip:[email protected]>
+
+

+ 127 - 0
test/resolver_test.c

@@ -0,0 +1,127 @@
+/* $Id$ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+static char *id="$Id$";
+static char *version="resolver_test 0.1";
+static char* help_msg="\
+Usage: resolver -n address [-c count] [-v]\n\
+Options:\n\
+    -n address    address to be resolved\n\
+    -c count      how many times to resolve it\n\
+    -v            increase verbosity level\n\
+    -V            version number\n\
+    -h            this help message\n\
+";
+
+
+
+int main (int argc, char** argv)
+{
+	char c;
+	struct hostent* he;
+	int ok;
+	int errors;
+	int r;
+	char *tmp;
+	
+	int count;
+	int verbose;
+	char *address;
+	
+	/* init */
+	count=0;
+	verbose=0;
+	address=0;
+
+	ok=errors=0;
+
+	opterr=0;
+	while ((c=getopt(argc,argv, "n:c:vhV"))!=-1){
+		switch(c){
+			case 'n':
+				address=optarg;
+				break;
+			case 'v':
+				verbose++;
+				break;
+			case 'c':
+				count=strtol(optarg, &tmp, 10);
+				if ((tmp==0)||(*tmp)){
+					fprintf(stderr, "bad count: -c %s\n", optarg);
+					goto error;
+				}
+				break;
+			case 'V':
+				printf("version: %s\n", version);
+				printf("%s\n",id);
+				exit(0);
+				break;
+			case 'h':
+				printf("version: %s\n", version);
+				printf("%s", help_msg);
+				exit(0);
+				break;
+			case '?':
+				if (isprint(optopt))
+					fprintf(stderr, "Unknown option `-%c´\n", optopt);
+				else
+					fprintf(stderr, "Unknown character `\\x%x´\n", optopt);
+				goto error;
+			case ':':
+				fprintf(stderr, "Option `-%c´ requires an argument.\n",
+						optopt);
+				goto error;
+				break;
+			default:
+					abort();
+		}
+	}
+	
+	/* check if all the required params are present */
+	if (address==0){
+		fprintf(stderr, "Missing -a address\n");
+		exit(-1);
+	}
+	if(count==0){
+		fprintf(stderr, "Missing count (-c number)\n");
+		exit(-1);
+	}else if(count<0){
+		fprintf(stderr, "Invalid count (-c %d)\n", count);
+		exit(-1);
+	}
+	
+
+
+	/* flood loop */
+	for (r=0; r<count; r++){
+		if ((verbose>1)&&(r%1000))  putchar('.');
+		/* resolve destination loop */
+		he=gethostbyname(address);
+		if (he==0){
+			errors++;
+			if (verbose>1) 
+				putchar('?');
+		}else ok++;
+	}
+
+	printf("\n%d requests, %d succeeded, %d errors\n", count, ok, errors);
+
+	exit(0);
+
+error:
+	exit(-1);
+}