*** empty log message ***
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Fri, 23 Nov 2001 09:15:13 +0000 (09:15 +0000)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Fri, 23 Nov 2001 09:15:13 +0000 (09:15 +0000)
config.h
data_lump.c
main.c
msg_parser.c
msg_parser.h
parse_hname.c [new file with mode: 0644]
parse_via.c [new file with mode: 0644]
receive.c
udp_server.c

index e43bcc5..b454130 100644 (file)
--- a/config.h
+++ b/config.h
@@ -41,5 +41,8 @@
 #define RECEIVED ";received="
 #define RECEIVED_LEN 10
 
+/*used only if PKG_MALLOC is defined*/
+#define PKG_MEM_POOL_SIZE 1024*1024
+
 
 #endif
index 1ebbd26..5fd84d7 100644 (file)
@@ -23,7 +23,7 @@ struct lump* append_new_lump(struct lump** list, char* new_hdr,
        
        for (t=list;*t;t=&((*t)->next));
 
-       tmp=malloc(sizeof(struct lump));
+       tmp=pkg_malloc(sizeof(struct lump));
        if (tmp==0){
                LOG(L_ERR, "ERROR: append_new_lump: out of memory\n");
                return 0;
@@ -47,7 +47,7 @@ struct lump* insert_new_lump(struct lump** list, char* new_hdr,
 {
        struct lump* tmp;
 
-       tmp=malloc(sizeof(struct lump));
+       tmp=pkg_malloc(sizeof(struct lump));
        if (tmp==0){
                LOG(L_ERR, "ERROR: insert_new_lump: out of memory\n");
                return 0;
@@ -71,7 +71,7 @@ struct lump* insert_new_lump_after( struct lump* after, char* new_hdr,
 {
        struct lump* tmp;
 
-       tmp=malloc(sizeof(struct lump));
+       tmp=pkg_malloc(sizeof(struct lump));
        if (tmp==0){
                LOG(L_ERR, "ERROR: insert_new_lump_after: out of memory\n");
                return 0;
@@ -95,7 +95,7 @@ struct lump* insert_new_lump_before( struct lump* before, char* new_hdr,
 {
        struct lump* tmp;
 
-       tmp=malloc(sizeof(struct lump));
+       tmp=pkg_malloc(sizeof(struct lump));
        if (tmp==0){
                LOG(L_ERR,"ERROR: insert_new_lump_before: out of memory\n");
                return 0;
@@ -118,7 +118,7 @@ struct lump* del_lump(struct lump** list, int offset, int len, int type)
        struct lump* tmp;
        struct lump* prev, *t;
 
-       tmp=malloc(sizeof(struct lump));
+       tmp=pkg_malloc(sizeof(struct lump));
        if (tmp==0){
                LOG(L_ERR, "ERROR: insert_new_lump_before: out of memory\n");
                return 0;
@@ -148,7 +148,7 @@ struct lump* anchor_lump(struct lump** list, int offset, int len, int type)
        struct lump* tmp;
        struct lump* prev, *t;
 
-       tmp=malloc(sizeof(struct lump));
+       tmp=pkg_malloc(sizeof(struct lump));
        if (tmp==0){
                LOG(L_ERR, "ERROR: insert_new_lump_before: out of memory\n");
                return 0;
@@ -176,7 +176,7 @@ struct lump* anchor_lump(struct lump** list, int offset, int len, int type)
 void free_lump(struct lump* lmp)
 {
        if (lmp && (lmp->op==LUMP_ADD)){
-               if (lmp->u.value) free(lmp->u.value);
+               if (lmp->u.value) pkg_free(lmp->u.value);
                lmp->u.value=0;
                lmp->len=0;
        }
@@ -200,18 +200,18 @@ void free_lump_list(struct lump* l)
                r=crt->before;
                while(r){
                        foo=r; r=r->before;
-                       free_lump(foo);
-                       free(foo);
+                       pkg_free_lump(foo);
+                       pkg_free(foo);
                }
                r=crt->after;
                while(r){
                        foo=r; r=r->after;
-                       free_lump(foo);
-                       free(foo);
+                       pkg_free_lump(foo);
+                       pkg_free(foo);
                }
                
                /*clean current elem*/
-               free_lump(crt);
-               free(crt);
+               pkg_free_lump(crt);
+               pkg_free(crt);
        }
 }
diff --git a/main.c b/main.c
index 8901932..40cd119 100644 (file)
--- a/main.c
+++ b/main.c
@@ -23,6 +23,8 @@
 #include "route.h"
 #include "udp_server.h"
 #include "globals.h"
+#include "mem.h"
+
 
 #include <signal.h>
 
@@ -502,11 +504,21 @@ int main(int argc, char** argv)
        if (init_stats(  dont_fork ? 1 : children_no  )==-1) goto error;
 #endif
 
+       
        /* init_daemon? */
        if (!dont_fork){
                if ( daemonize(argv[0]) <0 ) goto error;
        }
-               
+
+#ifdef PKG_MALLOC
+       /*init mem*/
+       mem_block=qm_malloc_init(mem_pool, MEM_POOL_SIZE);
+       if (mem_block==0){
+               LOG(L_CRIT, "could not initialize memory pool\n");
+               goto error;
+       }
+#endif
+
        
        return main_loop();
 
index 65e1b33..79e3807 100644 (file)
@@ -184,23 +184,7 @@ error1:
 }
 
 
-#ifdef OLD_PARSER
-/* returns integer field name type */
-int field_name(char *s, int l)
-{
-       if (l<1) return HDR_OTHER;
-       else if ((l==1) && ((*s=='v')||(*s=='V')))
-               return HDR_VIA;
-       else if (strcasecmp(s, "Via")==0)
-               return  HDR_VIA;
-/*     if ((strcmp(s, "To")==0)||(strcmp(s,"t")==0))
-               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, char* end, struct hdr_field* hdr)
@@ -225,7 +209,7 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
        }
        switch(hdr->type){
                case HDR_VIA:
-                       vb=malloc(sizeof(struct via_body));
+                       vb=pkg_malloc(sizeof(struct via_body));
                        if (vb==0){
                                LOG(L_ERR, "get_hdr_field: out of memory\n");
                                goto error;
@@ -236,7 +220,7 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
                        tmp=parse_via(tmp, end, vb);
                        if (vb->error==VIA_PARSE_ERROR){
                                LOG(L_ERR, "ERROR: get_hdr_field: bad via\n");
-                               free(vb);
+                               pkg_free(vb);
                                goto error;
                        }
                        hdr->parsed=vb;
@@ -245,7 +229,7 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
                        hdr->body.len=tmp-hdr->body.s;
                        break;
                case HDR_CSEQ:
-                       cseq_b=malloc(sizeof(struct cseq_body));
+                       cseq_b=pkg_malloc(sizeof(struct cseq_body));
                        if (cseq_b==0){
                                LOG(L_ERR, "get_hdr_field: out of memory\n");
                                goto error;
@@ -255,7 +239,7 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
                        tmp=parse_cseq(tmp, end, cseq_b);
                        if (cseq_b->error==PARSE_ERROR){
                                LOG(L_ERR, "ERROR: get_hdr_field: bad cseq\n");
-                               free(cseq_b);
+                               pkg_free(cseq_b);
                                goto error;
                        }
                        hdr->parsed=cseq_b;
@@ -277,13 +261,6 @@ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr)
                                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,
@@ -309,91 +286,6 @@ 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)
-{
-       /* grammar (rfc822):
-               field = field-name ":" field-body CRLF
-               field-body = text [ CRLF SP field-body ]
-          (CRLF in the field body must be removed)
-       */
-
-       char* tmp, *tmp2;
-       char* nl;
-       char* body;
-       int offset;
-       int l;
-
-       
-       /* init content to the empty string */
-       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 */
-               tmp=eat_line(buffer,len);
-               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!=':')){
-               hdr_f->type=HDR_ERROR;
-               goto error;
-       }
-       *tmp=0;
-       /* take care of possible spaces (e.g: "Via  :") */
-       tmp2=eat_token_end(buffer, tmp);
-       /* in the worst case tmp2=buffer+tmp-buffer=tmp */
-       *tmp2=0;
-       l=tmp2-buffer;
-       if (tmp2<tmp){
-               tmp2++;
-               /* catch things like: "Via foo bar:" */
-               tmp2=eat_space_end(tmp2, tmp);
-               if (tmp2!=tmp){
-                       hdr_f->type=HDR_ERROR;
-                       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{
-               nl=eat_line(tmp, len-offset);
-               offset+=nl-tmp;
-               tmp=nl;
-       
-       }while( (*tmp==' ' ||  *tmp=='\t') && (offset<len) );
-       if (offset==len){
-               hdr_f->type=HDR_ERROR;
-               LOG(L_INFO, "ERROR: get_hdr_field: field body too  long\n");
-               goto error;
-       }
-       *(tmp-1)=0; /* should be an LF */
-       hdr_f->body.s=body;
-       hdr_f->body.len=tmp-1-body;
-error:
-       return tmp;
-}
-#endif
 
 
 char* parse_hostport(char* buf, str* host, short int* port)
@@ -511,7 +403,7 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
                if (passwd==0){
                        /* no ':' found => no password */
                        uri->passwd.s=0;
-                       uri->user.s=(char*)malloc(next-user+1);
+                       uri->user.s=(char*)pkg_malloc(next-user+1);
                        if (uri->user.s==0){
                                LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
                                ret=E_OUT_OF_MEM;
@@ -522,7 +414,7 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
                        uri->user.s[next-user]=0; /* null terminate it, 
                                                                           usefull for easy printing*/
                }else{
-                       uri->user.s=(char*)malloc(passwd-user+1);
+                       uri->user.s=(char*)pkg_malloc(passwd-user+1);
                        if (uri->user.s==0){
                                LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
                                ret=E_OUT_OF_MEM;
@@ -532,7 +424,7 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
                        uri->user.len=passwd-user;
                        uri->user.s[passwd-user]=0;
                        passwd++; /*skip ':' */
-                       uri->passwd.s=(char*)malloc(next-passwd+1);
+                       uri->passwd.s=(char*)pkg_malloc(next-passwd+1);
                        if (uri->passwd.s==0){
                                LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n");
                                ret=E_OUT_OF_MEM;
@@ -555,7 +447,7 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
        port=q_memchr(host,':',end-host);
        host_len=(port)?port-host:(params)?params-host:(headers)?headers-host:end-host;
        /* get host */
-       uri->host.s=malloc(host_len+1);
+       uri->host.s=pkg_malloc(host_len+1);
        if (uri->host.s==0){
                LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
                ret=E_OUT_OF_MEM;
@@ -574,7 +466,7 @@ 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.s=malloc(port_len+1);
+               uri->port.s=pkg_malloc(port_len+1);
                if (uri->port.s==0){
                        LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
                        ret=E_OUT_OF_MEM;
@@ -594,7 +486,7 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
                        goto error;
                }
                params_len=(headers)?headers-params:end-params;
-               uri->params.s=malloc(params_len+1);
+               uri->params.s=pkg_malloc(params_len+1);
                if (uri->params.s==0){
                        LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
                        ret=E_OUT_OF_MEM;
@@ -608,7 +500,7 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
        if ((headers)&&(headers+1<end)){
                headers++;
                headers_len=end-headers;
-               uri->headers.s=malloc(headers_len+1);
+               uri->headers.s=pkg_malloc(headers_len+1);
                if(uri->headers.s==0){
                        LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n");
                        ret=E_OUT_OF_MEM;
@@ -791,7 +683,7 @@ int parse_headers(struct sip_msg* msg, int flags)
        
        DBG("parse_headers: flags=%d\n", flags);
        while( tmp<end && (flags & msg->parsed_flag) != flags){
-               hf=malloc(sizeof(struct hdr_field));
+               hf=pkg_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");
@@ -870,7 +762,7 @@ skip:
        return 0;
        
 error:
-       if (hf) free(hf);
+       if (hf) pkg_free(hf);
        return -1;
 }
 
@@ -887,23 +779,9 @@ 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 via_body *vb1, *vb2;
        int offset;
        int flags;
 
-#ifdef OLD_PARSER
-       /* init vb1 & vb2 to the null string */
-       /*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;
-       hf=0;
-#endif
        /* eat crlf from the beginning */
        for (tmp=buf; (*tmp=='\n' || *tmp=='\r')&&
                        tmp-buf < len ; tmp++);
@@ -951,27 +829,17 @@ int parse_msg(char* buf, unsigned int len, struct sip_msg* msg)
                if (msg->via1->comment.s) DBG(" <%s>", msg->via1->comment.s);
                DBG ("\n");
        }
-#ifdef OLD_PARSER
        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);
-               if (vb2->params.s)  DBG(";<%s>", vb2->params.s);
-               if (vb2->comment.s) DBG(" <%s>", vb2->comment.s);
-               DBG("\n");
+               DBG(" first  via: <%s/%s/%s> <%s:%s(%d)>",
+                       msg->via2->name.s, msg->via2->version.s,
+                       msg->via2->transport.s, msg->via2->host.s,
+                       msg->via2->port_str, msg->via2->port);
+               if (msg->via2->params.s)  DBG(";<%s>", msg->via2->params.s);
+               if (msg->via2->comment.s) DBG(" <%s>", msg->via2->comment.s);
+               DBG ("\n");
        }
 #endif
-#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");
@@ -980,11 +848,6 @@ int parse_msg(char* buf, unsigned int len, struct sip_msg* msg)
        return 0;
        
 error:
-       if (hf) free(hf);
-#ifndef OLD_PARSER
-       if (vb1) free(vb1);
-       if (vb2) free(vb1);
-#endif
        return -1;
 }
 
@@ -993,12 +856,12 @@ error:
 void free_uri(struct sip_uri* u)
 {
        if (u){
-               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);
+               if (u->user.s)    pkg_free(u->user.s);
+               if (u->passwd.s)  pkg_free(u->passwd.s);
+               if (u->host.s)    pkg_free(u->host.s);
+               if (u->port.s)    pkg_free(u->port.s);
+               if (u->params.s)  pkg_free(u->params.s);
+               if (u->headers.s) pkg_free(u->headers.s);
        }
 }
 
@@ -1010,7 +873,7 @@ void free_via_list(struct via_body* vb)
        while(vb){
                foo=vb;
                vb=vb->next;
-               free(foo);
+               pkg_free(foo);
        }
 }
 
@@ -1025,7 +888,7 @@ void clean_hdr_field(struct hdr_field* hf)
                                free_via_list(hf->parsed);
                                break;
                        case HDR_CSEQ:
-                               free(hf->parsed);
+                               pkg_free(hf->parsed);
                                break;
                        default:
                                LOG(L_CRIT, "BUG: clean_hdr_field: unknown header type %d\n",
@@ -1046,6 +909,23 @@ void free_hdr_field_lst(struct hdr_field* hf)
                foo=hf;
                hf=hf->next;
                clean_hdr_field(foo);
-               free(foo);
+               pkg_free(foo);
        }
 }
+
+
+
+/*only the content*/
+void free_sip_msg(struct sip_msg* msg)
+{
+       if (msg->new_uri.s) { pkg_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);
+       free(msg->buf);
+}
+
+
+
+}
index ad5f453..6aa2b98 100644 (file)
@@ -181,6 +181,7 @@ char* parse_cseq(char* buffer, char* end, struct cseq_body *cb);
 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);
+void free_sip_msg(struct sip_msg* msg);
 
 
 #endif
diff --git a/parse_hname.c b/parse_hname.c
new file mode 100644 (file)
index 0000000..49929e2
--- /dev/null
@@ -0,0 +1,468 @@
+/*
+ * $Id§
+ *
+ * header name parsing automaton:
+
+ * parsing:           compact form:
+ * Via:               v:
+ * From:              f:
+ * To:                t:
+ * Cseq:              n/a
+ * Call-ID:           i:
+ * Contact:           m:
+ * Max-Forwards:      n/a
+ * Route:             n/a
+ */
+
+
+#include "msg_parser.h"
+#include "dprint.h"
+
+enum { INITIAL=0,
+               VIA1, VIA2,
+               FROM1, FROM2, FROM3,
+               TO1,
+               C_START, CSEQ2, CSEQ3,
+                        CALLID2, CALLID3, CALLID4, CALLID5, CALLID6,
+                        CONTACT2, CONTACT3, CONTACT4, CONTACT5, CONTACT6,
+               M_START,      MAXFORWARDS2, MAXFORWARDS3, MAXFORWARDS4, MAXFORWARDS5,
+               MAXFORWARDS6, MAXFORWARDS7, MAXFORWARDS8, MAXFORWARDS9, MAXFORWARDS10,
+               MAXFORWARDS11,
+               ROUTE1, ROUTE2, ROUTE3, ROUTE4,
+               /* final states*/
+               F_VIA=1000, F_FROM, F_TO, F_CSEQ, F_CALLID, F_CONTACT, F_MAXFORWARDS,
+               F_ROUTE,
+               I_START,
+
+               UNKNOWN_HEADER=200,
+               BODY=220,
+               LF=25000,
+       };
+
+
+/* returns end or pointer to next elem*/
+char* parse_hname(char* p, char* end, struct hdr_field* hdr)
+{
+
+       char* t;
+       register int state;
+       int i;
+       int err;
+       err=0;
+
+       state=INITIAL;
+               
+       for(t=p;t<end;t++){
+               switch(*t){
+                       case 'V':
+                       case 'v':
+                                       switch(state){
+                                               case INITIAL:
+                                                       state=VIA1;
+                                                       hdr->name.s=t;
+                                                       break;
+                                               case UNKNOWN_HEADER: break;
+                                               default:
+                                                       state=UNKNOWN_HEADER;
+                                       }
+                                       break;
+                       case 'I':
+                       case 'i':
+                                       switch(state){
+                                               case VIA1:
+                                                       state=VIA2;
+                                                       break;
+                                               case CALLID5:
+                                                       state=CALLID6;
+                                                       break;
+                                               case INITIAL:
+                                                       state=I_START;
+                                                       hdr->name.s=t;
+                                                       break;
+                                               case UNKNOWN_HEADER: break;
+                                               default:
+                                                       state=UNKNOWN_HEADER;
+                                       }
+                                       break;
+                       case 'A':
+                       case 'a':
+                                       switch(state){
+                                               case VIA2:
+                                                               state=F_VIA;
+                                                               break;
+                                               case C_START:  /*CALLID1*/
+                                                               state=CALLID2;
+                                                               break;
+                                               case CONTACT4:
+                                                               state=CONTACT5;
+                                                               break;
+                                               case M_START:
+                                                               state=MAXFORWARDS2;
+                                                               break;
+                                               case MAXFORWARDS8:
+                                                               state=MAXFORWARDS9;
+                                                               break;
+                                               case UNKNOWN_HEADER: break;
+                                               default:
+                                                               state=UNKNOWN_HEADER;
+                                       }
+                                       break;
+                       case 'F':
+                       case 'f':
+                                       switch(state){
+                                               case INITIAL:
+                                                               state=FROM1;
+                                                               hdr->name.s=t;
+                                                               break;
+                                               case MAXFORWARDS4:
+                                                               state=MAXFORWARDS5;
+                                                               break;
+                                               case UNKNOWN_HEADER: break;
+                                               default:
+                                                               state=UNKNOWN_HEADER;
+                                       }
+                                       break;
+                       case 'R':
+                       case 'r':
+                                       switch(state){
+                                               case INITIAL:
+                                                       state=ROUTE1;
+                                                       hdr->name.s=t;
+                                                       break;
+                                               case FROM1:
+                                                       state=FROM2;
+                                                       break;
+                                               case MAXFORWARDS6:
+                                                       state=MAXFORWARDS7;
+                                                       break;
+                                               case MAXFORWARDS9:
+                                                       state=MAXFORWARDS10;
+                                                       break;
+                                               case UNKNOWN_HEADER: break;
+                                               default:
+                                                       state=UNKNOWN_HEADER;
+                                       }
+                                       break;
+                       case 'O':
+                       case 'o':
+                                       switch(state){
+                                               case FROM2:
+                                                       state=FROM3;
+                                                       break;
+                                               case TO1:
+                                                       state=F_TO;
+                                                       break;
+                                               case C_START: /*CONTACT1 */
+                                                       state=CONTACT2;
+                                                       break;
+                                               case ROUTE1:
+                                                       state=ROUTE2;
+                                                       break;
+                                               case MAXFORWARDS5:
+                                                       state=MAXFORWARDS6;
+                                                       break;
+                                               case UNKNOWN_HEADER: break;
+                                               default:
+                                                       state=UNKNOWN_HEADER;
+                                       }
+                                       break;
+                       case 'M':
+                       case 'm':
+                                               switch(state){
+                                                       case INITIAL:
+                                                               state=M_START;
+                                                               hdr->name.s=t;
+                                                               break;
+                                                       case FROM3:
+                                                               state=F_FROM;
+                                                               break;
+                                                       case UNKNOWN_HEADER: break;
+                                                       default:
+                                                               state=UNKNOWN_HEADER;
+                                               }
+                                               break;
+                       case 'T':
+                       case 't':
+                                               switch(state){
+                                                       case INITIAL:
+                                                               state=TO1;
+                                                               hdr->name.s=t;
+                                                               break;
+                                                       case CONTACT3:
+                                                               state=CONTACT4;
+                                                               break;
+                                                       case CONTACT6:
+                                                               state=F_CONTACT;
+                                                               break;
+                                                       case ROUTE3:
+                                                               state=ROUTE4;
+                                                               break;
+                                                       case UNKNOWN_HEADER: break;
+                                                       default:
+                                                               state=UNKNOWN_HEADER;
+                                               }
+                                               break;
+                       case 'C':
+                       case 'c':
+                                               switch(state){
+                                                       case INITIAL:
+                                                               state=C_START;
+                                                               hdr->name.s=t;
+                                                               break;
+                                                       case CONTACT5:
+                                                               state=CONTACT6;
+                                                               break;
+                                                       case UNKNOWN_HEADER: break;
+                                                       default:
+                                                               state=UNKNOWN_HEADER;
+                                               }
+                                               break;
+                       case 'S':
+                       case 's':
+                                               switch(state){
+                                                       case C_START:
+                                                               state=CSEQ2;
+                                                               break;
+                                                       case MAXFORWARDS11:
+                                                               state=F_MAXFORWARDS;
+                                                               break;
+                                                       case UNKNOWN_HEADER: break;
+                                                       default:
+                                                               state=UNKNOWN_HEADER;
+                                               }
+                                               break;
+                       case 'E':
+                       case 'e':
+                                               switch(state){
+                                                       case CSEQ2:
+                                                               state=CSEQ3;
+                                                               break;
+                                                       case ROUTE4:
+                                                               state=F_ROUTE;
+                                                               break;
+                                                       case UNKNOWN_HEADER: break;
+                                                       default:
+                                                               state=UNKNOWN_HEADER;
+                                               }
+                                               break;
+                       case 'Q':
+                       case 'q':
+                                               switch(state){
+                                                       case CSEQ3:
+                                                               state=F_CSEQ;
+                                                               break;
+                                                       case UNKNOWN_HEADER: break;
+                                                       default:
+                                                               state=UNKNOWN_HEADER;
+                                               }
+                                               break;
+                       case 'L':
+                       case 'l':
+                                               switch(state){
+                                                       case CALLID2:
+                                                               state=CALLID3;
+                                                               break;
+                                                       case CALLID3:
+                                                               state=CALLID4;
+                                                               break;
+                                                       case UNKNOWN_HEADER: break;
+                                                       default:
+                                                               state=UNKNOWN_HEADER;
+                                               }
+                                               break;
+                       case 'D':
+                       case 'd':
+                                               switch(state){
+                                                       case CALLID6:
+                                                               state=F_CALLID;
+                                                               break;
+                                                       case MAXFORWARDS10:
+                                                               state=MAXFORWARDS11;
+                                                               break;
+                                                       case UNKNOWN_HEADER: break;
+                                                       default:
+                                                               state=UNKNOWN_HEADER;
+                                               }
+                                               break;
+                       case 'N':
+                       case 'n':
+                                               switch(state){
+                                                       case CONTACT2:
+                                                               state=CONTACT3;
+                                                               break;
+                                                       case UNKNOWN_HEADER: break;
+                                                       default:
+                                                               state=UNKNOWN_HEADER;
+                                               }
+                                               break;
+                       case 'X':
+                       case 'x':
+                                               switch(state){
+                                                       case MAXFORWARDS2:
+                                                               state=MAXFORWARDS3;
+                                                               break;
+                                                       case UNKNOWN_HEADER: break;
+                                                       default:
+                                                               state=UNKNOWN_HEADER;
+                                               }
+                                               break;
+                       case '-':
+                                               switch(state){
+                                                       case CALLID4:
+                                                               state=CALLID5;
+                                                               break;
+                                                       case MAXFORWARDS3:
+                                                               state=MAXFORWARDS4;
+                                                               break;
+                                                       case UNKNOWN_HEADER: break;
+                                                       default:
+                                                               state=UNKNOWN_HEADER;
+                                               }
+                                               break;
+                       case 'W':
+                       case 'w':
+                                               switch(state){
+                                                       case MAXFORWARDS7:
+                                                               state=MAXFORWARDS8;
+                                                               break;
+                                                       case UNKNOWN_HEADER: break;
+                                                       default:
+                                                               state=UNKNOWN_HEADER;
+                                               }
+                                               break;
+                       case 'U':
+                       case 'u':
+                                               switch(state){
+                                                       case ROUTE2:
+                                                               state=ROUTE3;
+                                                               break;
+                                                       case UNKNOWN_HEADER: break;
+                                                       default:
+                                                               state=UNKNOWN_HEADER;
+                                               }
+                                               break;
+                       case ' ':
+                                               switch(state){
+                                                       case INITIAL:
+                                                               break; /*eat space */
+                                                       case F_VIA:
+                                                       case F_FROM:
+                                                       case F_TO:
+                                                       case F_CSEQ:
+                                                       case F_CALLID:
+                                                       case F_CONTACT:
+                                                       case F_MAXFORWARDS:
+                                                       case F_ROUTE:
+                                                               break; /* eat trailing space*/
+                                                       case VIA1:
+                                                               /*compact form: v: */
+                                                               state=F_VIA;
+                                                               break;
+                                                       case FROM1:
+                                                               /*compact form f:*/
+                                                               state=F_FROM;
+                                                               break;
+                                                       case TO1:
+                                                               /*compact form t:*/
+                                                               state=F_TO;
+                                                               break;
+                                                       case I_START:
+                                                               /*compact form i: (Call-ID)*/
+                                                               state=F_CALLID;
+                                                               break;
+                                                       case M_START:
+                                                               /*compact form m: (Contact)*/
+                                                               state=F_CONTACT;
+                                                               break;
+                                                       case UNKNOWN_HEADER: break;
+                                                       default:
+                                                               state=UNKNOWN_HEADER;
+                                               }
+                                               break;
+                       case ':':
+                                               switch(state){
+                                                       case F_VIA:
+                                                       case VIA1: /* compact form*/
+                                                               *t=0;
+                                                               hdr->name.len=t-hdr->name.s;
+                                                               hdr->type=HDR_VIA;
+                                                               goto skip;
+                                                       case F_FROM:
+                                                       case FROM1: /*compact form*/
+                                                               *t=0;
+                                                               hdr->name.len=t-hdr->name.s;
+                                                               hdr->type=HDR_FROM;
+                                                               goto skip;
+                                                       case F_TO:
+                                                       case TO1: /*compact form*/
+                                                               *t=0;
+                                                               hdr->name.len=t-hdr->name.s;
+                                                               hdr->type=HDR_TO;
+                                                               goto skip;
+                                                       case F_CSEQ:
+                                                               *t=0;
+                                                               hdr->name.len=t-hdr->name.s;
+                                                               hdr->type=HDR_CSEQ;
+                                                               goto skip;
+                                                       case F_CALLID:
+                                                       case I_START: /*compact form*/
+                                                               *t=0;
+                                                               hdr->name.len=t-hdr->name.s;
+                                                               hdr->type=HDR_CALLID;
+                                                               goto skip;
+                                                       case F_CONTACT:
+                                                       case M_START: /*compact form*/
+                                                               *t=0;
+                                                               hdr->name.len=t-hdr->name.s;
+                                                               hdr->type=HDR_CONTACT;
+                                                               goto skip;
+                                                       case F_MAXFORWARDS:
+                                                               *t=0;
+                                                               hdr->name.len=t-hdr->name.s;
+                                                               hdr->type=HDR_MAXFORWARDS;
+                                                               goto skip;
+                                                       case F_ROUTE:
+                                                               *t=0;
+                                                               hdr->name.len=t-hdr->name.s;
+                                                               hdr->type=HDR_ROUTE;
+                                                               goto skip;
+                                                       case UNKNOWN_HEADER:
+                                                               *t=0;
+                                                               hdr->name.len=t-hdr->name.s;
+                                                               hdr->type=HDR_OTHER;
+                                                               goto skip;
+                                                       default:
+                                                               /*printf("found unkown header, state=%d\n", 
+                                                                                       state);*/
+                                                               LOG(L_ERR, "ERROR : bug?: parse_hname:"
+                                                                               " on char <%c> state %d\n",
+                                                                               *t, state);
+                                                               goto error;
+                                               }
+                                               break;
+                       default:
+                                       switch(state){
+                                               case INITIAL:
+                                                       hdr->name.s=t;
+                                                       state=UNKNOWN_HEADER;
+                                                       break;
+                                               case UNKNOWN_HEADER:
+                                                       break;
+                                               default:
+                                                       state=UNKNOWN_HEADER;
+                                       }
+               }
+       }
+/* if we are here => we didn't find ':' => error*/
+       
+error:
+       hdr->type=HDR_ERROR;
+       return t;
+
+skip:
+       DBG("end of header name found, state=%d\n", state);
+       t++;
+       return t;
+
+}
+
diff --git a/parse_via.c b/parse_via.c
new file mode 100644 (file)
index 0000000..d0e54b6
--- /dev/null
@@ -0,0 +1,1646 @@
+/* 
+ * $Id$ 
+ *
+ * via parsing automaton
+ * 
+ */
+
+/* parsing:           compact form:
+ */
+
+/* 
+ * still TODO/test:
+ *  - parse next via
+ *  - return a list of header structs
+ *  - return list of params
+ */
+
+
+#ifndef OLD_PARSER
+
+#include <stdlib.h>
+#include "dprint.h"
+#include "msg_parser.h"
+#include "ut.h"
+
+
+
+/* main via states (uri:port ...) */
+enum{           F_HOST,    P_HOST,
+               L_PORT,  F_PORT,    P_PORT,
+               L_PARAM, F_PARAM,   P_PARAM,
+               L_VIA,   F_VIA,
+                        F_COMMENT, P_COMMENT,
+                                F_IP6HOST, P_IP6HOST,
+                                F_CRLF,
+                                F_LF,
+                                F_CR,
+                                END_OF_HEADER
+       };
+
+/* first via part state */
+enum{           F_SIP=100,
+               SIP1, SIP2, FIN_SIP,
+               L_VER, F_VER,
+               VER1, VER2, FIN_VER,
+               L_PROTO, F_PROTO, P_PROTO
+       };
+
+/* param realated states */
+enum{  L_VALUE=200,   F_VALUE, P_VALUE, P_STRING,
+               HIDDEN1,   HIDDEN2,   HIDDEN3,   HIDDEN4,   HIDDEN5,
+               TTL1,      TTL2,
+               BRANCH1,   BRANCH2,   BRANCH3,   BRANCH4,   BRANCH5,
+               MADDR1,    MADDR2,    MADDR3,    MADDR4,
+               RECEIVED1, RECEIVED2, RECEIVED3, RECEIVED4, RECEIVED5, RECEIVED6,
+               RECEIVED7,
+               /* fin states (227-...)*/
+               FIN_HIDDEN, FIN_TTL, FIN_BRANCH, FIN_MADDR, FIN_RECEIVED,
+               GEN_PARAM
+       };
+
+
+
+/* entry state must be F_PARAM, or saved_state=F_PARAM and 
+ * state=F_{LF,CR,CRLF}!
+ * output state = L_PARAM or F_PARAM or END_OF_HEADER 
+ * (and saved_state= last state); everything else => error */
+__inline char* parse_via_param(        char* p, char* end, int* pstate, 
+                                                               int* psaved_state)
+{
+       char* tmp;
+       register int state;
+       int saved_state;
+       int param_type;
+       char* param_name;
+       char* param_value;
+       
+       state=*pstate;
+       saved_state=*psaved_state;
+       param_name=param_value=0;
+       param_type=0;
+       
+       for (tmp=p;tmp<end;tmp++){
+               switch(*tmp){
+                       case ' ':
+                       case '\t':
+                               switch(state){
+                                       case FIN_HIDDEN:
+                                               *tmp=0;
+                                               param_type=state;
+                                               state=L_PARAM;
+                                               goto endofparam;
+                                       case FIN_BRANCH:
+                                       case FIN_TTL:
+                                       case FIN_MADDR:
+                                       case FIN_RECEIVED:
+                                               *tmp=0;
+                                               param_type=state;
+                                               state=L_VALUE;
+                                               goto find_value;
+                                       case F_PARAM:
+                                               break;
+                                       case F_LF:
+                                       case F_CR:
+                                       case F_CRLF:
+                                               state=saved_state;
+                                               break;
+                                       case GEN_PARAM:
+                                       default:
+                                               *tmp=0;
+                                               param_type=GEN_PARAM;
+                                               state=L_VALUE;
+                                               goto find_value;
+                               }
+                               break;
+                       /* \n and \r*/
+                       case '\n':
+                               switch(state){
+                                       case FIN_HIDDEN:
+                                               *tmp=0;
+                                               param_type=state;
+                                               saved_state=L_PARAM;
+                                               state=F_LF;
+                                               goto endofparam;
+                                       case FIN_BRANCH:
+                                       case FIN_TTL:
+                                       case FIN_MADDR:
+                                       case FIN_RECEIVED:
+                                               *tmp=0;
+                                               param_type=state;
+                                               saved_state=L_VALUE;
+                                               state=F_LF;
+                                               goto find_value;
+                                       case F_PARAM:
+                                               saved_state=state;
+                                               state=F_LF;
+                                               break;
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       case F_CR:
+                                               state=F_CRLF;
+                                               break;
+                                       case GEN_PARAM:
+                                       default:
+                                               *tmp=0;
+                                               param_type=GEN_PARAM;
+                                               saved_state=L_VALUE;
+                                               state=F_LF;
+                                               goto find_value;
+                               }
+                               break;
+                       case '\r':
+                               switch(state){
+                                       case FIN_HIDDEN:
+                                               *tmp=0;
+                                               param_type=state;
+                                               saved_state=L_PARAM;
+                                               state=F_CR;
+                                               goto endofparam;
+                                       case FIN_BRANCH:
+                                       case FIN_TTL:
+                                       case FIN_MADDR:
+                                       case FIN_RECEIVED:
+                                               *tmp=0;
+                                               param_type=state;
+                                               saved_state=L_VALUE;
+                                               state=F_CR;
+                                               goto find_value;
+                                       case F_PARAM:
+                                               saved_state=state;
+                                               state=F_CR;
+                                               break;
+                                       case F_CR:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       case GEN_PARAM:
+                                       default:
+                                               *tmp=0;
+                                               param_type=GEN_PARAM;
+                                               saved_state=L_VALUE;
+                                               state=F_CR;
+                                               goto find_value;
+                               }
+                               break;
+
+                       case '=':
+                               switch(state){
+                                       case FIN_BRANCH:
+                                       case FIN_TTL:
+                                       case FIN_MADDR:
+                                       case FIN_RECEIVED:
+                                               *tmp=0;
+                                               param_type=state;
+                                               state=F_VALUE;
+                                               goto find_value;
+                                       case F_PARAM:
+                                       case FIN_HIDDEN:
+                                               LOG(L_ERR, "ERROR: parse_via: invalid char <%c> in"
+                                                               " state %d\n");
+                                               goto error;
+                                       case F_CR:
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       case GEN_PARAM:
+                                       default:
+                                               *tmp=0;
+                                               param_type=GEN_PARAM;
+                                               state=F_VALUE;
+                                               goto find_value;
+                               }
+                               break;
+                       case ';':
+                               switch(state){
+                                       case FIN_HIDDEN:
+                                               *tmp=0;
+                                               param_type=state;
+                                               state=F_PARAM;
+                                               goto endofparam;
+                                       case FIN_BRANCH:
+                                       case FIN_MADDR:
+                                       case FIN_TTL:
+                                       case FIN_RECEIVED:
+                                               LOG(L_ERR, "ERROR: parse_via: invalid char <%c> in"
+                                                               " state %d\n");
+                                               goto error;
+                                       case F_CR:
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       case GEN_PARAM:
+                                       default:
+                                               *tmp=0;
+                                               param_type=GEN_PARAM;
+                                               state=F_PARAM;
+                                               goto endofparam;
+                               }
+                               break;
+                               
+                               /* param names */
+                       case 'h':
+                       case 'H':
+                               switch(state){
+                                       case F_PARAM:
+                                               state=HIDDEN1;
+                                               param_name=tmp;
+                                               break;
+                                       case GEN_PARAM:
+                                               break;
+                                       case F_CR:
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               state=GEN_PARAM;
+                               }
+                               break;
+                       case 'i':
+                       case 'I':
+                               switch(state){
+                                       case HIDDEN1:
+                                               state=HIDDEN2;
+                                               break;
+                                       case RECEIVED4:
+                                               state=RECEIVED5;
+                                               break;
+                                       case GEN_PARAM:
+                                               break;
+                                       case F_CR:
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               state=GEN_PARAM;
+                               }
+                               break;
+                       case 'd':
+                       case 'D':
+                               switch(state){
+                                       case HIDDEN2:
+                                               state=HIDDEN3;
+                                               break;
+                                       case HIDDEN3:
+                                               state=HIDDEN4;
+                                               break;
+                                       case MADDR2:
+                                               state=MADDR3;
+                                               break;
+                                       case MADDR3:
+                                               state=MADDR4;
+                                               break;
+                                       case RECEIVED7:
+                                               state=FIN_RECEIVED;
+                                               break;
+                                       case GEN_PARAM:
+                                               break;
+                                       case F_CR:
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               state=GEN_PARAM;
+                               }
+                               break;
+                       case 'e':
+                       case 'E':
+                               switch(state){
+                                       case HIDDEN4:
+                                               state=HIDDEN5;
+                                               break;
+                                       case RECEIVED1:
+                                               state=RECEIVED2;
+                                               break;
+                                       case RECEIVED3:
+                                               state=RECEIVED4;
+                                               break;
+                                       case RECEIVED6:
+                                               state=RECEIVED7;
+                                               break;
+                                       case GEN_PARAM:
+                                               break;
+                                       case F_CR:
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               state=GEN_PARAM;
+                               }
+                               break;
+                       case 'n':
+                       case 'N':
+                               switch(state){
+                                       case HIDDEN5:
+                                               state=FIN_HIDDEN;
+                                               break;
+                                       case BRANCH3:
+                                               state=BRANCH4;
+                                               break;
+                                       case GEN_PARAM:
+                                               break;
+                                       case F_CR:
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               state=GEN_PARAM;
+                               }
+                               break;
+                       case 't':
+                       case 'T':
+                               switch(state){
+                                       case F_PARAM:
+                                               state=TTL1;
+                                               param_name=tmp;
+                                               break;
+                                       case TTL1:
+                                               state=TTL2;
+                                               break;
+                                       case GEN_PARAM:
+                                               break;
+                                       case F_CR:
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               state=GEN_PARAM;
+                               }
+                               break;
+                       case 'l':
+                       case 'L':
+                               switch(state){
+                                       case TTL2:
+                                               state=FIN_TTL;
+                                               break;
+                                       case GEN_PARAM:
+                                               break;
+                                       case F_CR:
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               state=GEN_PARAM;
+                               }
+                               break;
+                       case 'm':
+                       case 'M':
+                               switch(state){
+                                       case F_PARAM:
+                                               state=MADDR1;
+                                               param_name=tmp;
+                                               break;
+                                       case GEN_PARAM:
+                                               break;
+                                       case F_CR:
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               state=GEN_PARAM;
+                               }
+                               break;
+                       case 'a':
+                       case 'A':
+                               switch(state){
+                                       case MADDR1:
+                                               state=MADDR2;
+                                               break;
+                                       case BRANCH2:
+                                               state=BRANCH3;
+                                               break;
+                                       case GEN_PARAM:
+                                               break;
+                                       case F_CR:
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               state=GEN_PARAM;
+                               }
+                               break;
+                       case 'r':
+                       case 'R':
+                               switch(state){
+                                       case MADDR4:
+                                               state=FIN_MADDR;
+                                               break;
+                                       case F_PARAM:
+                                               state=RECEIVED1;
+                                               param_name=tmp;
+                                               break;
+                                       case BRANCH1:
+                                               state=BRANCH2;
+                                               break;
+                                       case GEN_PARAM:
+                                               break;
+                                       case F_CR:
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               state=GEN_PARAM;
+                               }
+                               break;
+                       case 'c':
+                       case 'C':
+                               switch(state){
+                                       case RECEIVED2:
+                                               state=RECEIVED3;
+                                               break;
+                                       case BRANCH4:
+                                               state=BRANCH5;
+                                               break;
+                                       case GEN_PARAM:
+                                               break;
+                                       case F_CR:
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               state=GEN_PARAM;
+                               }
+                               break;
+                       case 'v':
+                       case 'V':
+                               switch(state){
+                                       case RECEIVED5:
+                                               state=RECEIVED6;
+                                               break;
+                                       case GEN_PARAM:
+                                               break;
+                                       case F_CR:
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               state=GEN_PARAM;
+                               }
+                               break;
+                       case 'b':
+                       case 'B':
+                               switch(state){
+                                       case F_PARAM:
+                                               state=BRANCH1;
+                                               param_name=tmp;
+                                               break;
+                                       case GEN_PARAM:
+                                               break;
+                                       case F_CR:
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               state=GEN_PARAM;
+                               }
+                               break;
+
+                       default:
+                               switch(state){
+                                       case F_PARAM:
+                                               state=GEN_PARAM;
+                                               param_name=tmp;
+                                               break;
+                                       case  GEN_PARAM:
+                                               break;
+                                       case F_CR:
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               state=GEN_PARAM;
+                               }
+               }
+       }/* for tmp*/
+
+/* end of packet?*/
+saved_state=state;
+param_type=state;
+state=END_OF_HEADER;
+goto end_via;
+
+find_value:
+       tmp++;
+       for(tmp;*tmp;tmp++){
+               switch(*tmp){
+                       case ' ':
+                       case '\t':
+                               switch(state){
+                                       case L_VALUE:
+                                       case F_VALUE: /*eat space*/
+                                               break; 
+                                       case P_VALUE:
+                                               *tmp=0;
+                                               state=L_PARAM;
+                                               goto endofvalue;
+                                       case P_STRING:
+                                               break;
+                                       case F_CR:
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=saved_state;
+                                               break;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
+                                                               " in state %d\n", state);
+                                               goto error;
+                               }
+                               break;
+                       case '\n':
+                               switch(state){
+                                       case L_VALUE:
+                                       case F_VALUE: /*eat space*/
+                                       case P_STRING:
+                                               saved_state=state;
+                                               state=F_LF;
+                                               break; 
+                                       case P_VALUE:
+                                               *tmp=0;
+                                               saved_state=L_PARAM;
+                                               state=F_LF;
+                                               goto endofvalue;
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       case F_CR:
+                                               state=F_CRLF;
+                                               break;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
+                                                               " in state %d\n", state);
+                                               goto error;
+                               }
+                               break;
+                       case '\r':
+                               switch(state){
+                                       case L_VALUE:
+                                       case F_VALUE: /*eat space*/
+                                       case P_STRING:
+                                               saved_state=state;
+                                               state=F_CR;
+                                               break; 
+                                       case P_VALUE:
+                                               *tmp=0;
+                                               saved_state=L_PARAM;
+                                               state=F_CR;
+                                               goto endofvalue;
+                                       case F_LF:
+                                       case F_CR:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
+                                                               " in state %d\n", state);
+                                               goto error;
+                               }
+                               break;
+
+                       case '=':
+                               switch(state){
+                                       case L_VALUE:
+                                               state=F_VALUE;
+                                               break;
+                                       case P_STRING:
+                                               break;
+                                       case F_LF:
+                                       case F_CR:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
+                                                               " in state %d\n", state);
+                                               goto error;
+                               }
+                               break;
+                       case ';':
+                               switch(state){
+                                       case P_VALUE:
+                                               *tmp=0;
+                                               state=F_PARAM;
+                                               goto endofvalue;
+                                       case P_STRING:
+                                               break; /* what to do? */
+                                       case F_LF:
+                                       case F_CR:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
+                                                               " in state %d\n", state);
+                                               goto error;
+                               }
+                               break;
+                       
+                       case '"':
+                               switch(state){
+                                       case F_VALUE:
+                                               state=P_STRING;
+                                               param_value=tmp+1;
+                                               break;
+                                       case P_STRING:
+                                               *tmp=0;
+                                               state=L_PARAM;
+                                               goto endofvalue;
+                                       case F_LF:
+                                       case F_CR:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
+                                                               " in state %d\n", state);
+                                               goto error;
+                               }
+                               break;
+                       default:
+                               switch(state){
+                                       case F_VALUE:
+                                               state=P_VALUE;
+                                               param_value=tmp;
+                                               break;
+                                       case P_VALUE:
+                                       case P_STRING:
+                                               break;
+                                       case F_LF:
+                                       case F_CR:
+                                       case F_CRLF:
+                                               state=END_OF_HEADER;
+                                               goto end_via;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: invalid char <%c>"
+                                                               " in state %d\n", state);
+                                               goto error;
+                               }
+               }
+       } /* for2 tmp*/
+
+       /* if generic_param => it can have no value */
+       if ((state==L_VALUE)&&(param_type==GEN_PARAM)) state=L_PARAM;
+       saved_state=state;
+       state=END_OF_HEADER;
+       goto end_via;
+
+endofparam:
+endofvalue:
+
+end_via:
+       *pstate=state;
+       *psaved_state=saved_state;
+       DBG("Found param type %d, <%s> = <%s>\n", param_type, param_name,
+                       param_value);
+       return tmp;
+
+error:
+       LOG(L_ERR, "error: via_parse_param\n");
+       *pstate=state;
+       *psaved_state=saved_state;
+       return tmp;
+}
+
+
+
+
+
+
+char* parse_via(char* buffer, char* end, struct via_body *vb)
+{
+
+       char* tmp;
+       int state;
+       int saved_state;
+       int c_nest;
+       int i;
+       int err;
+
+       char* tmp_param;
+
+
+parse_again:
+       vb->error=VIA_PARSE_ERROR;
+       /* parse start of via ( SIP/2.0/UDP    )*/
+       state=F_SIP;
+       for(tmp=buffer;tmp<end;tmp++){
+               switch(*tmp){
+                       case ' ':
+                       case'\t':
+                               switch(state){
+                                       case L_VER: /* eat space */
+                                       case L_PROTO:
+                                       case F_SIP:
+                                       case F_VER:
+                                       case F_PROTO:
+                                               break;
+                                       case P_PROTO:
+                                               *tmp=0;  /* finished proto parsing */
+                                               vb->transport.len=tmp-vb->transport.s;
+                                               state=F_HOST; /* start looking for host*/
+                                               goto main_via;
+                                       case FIN_SIP:
+                                               *tmp=0;
+                                               vb->name.len=tmp-vb->name.s;
+                                               state=L_VER;
+                                               break;
+                                       case FIN_VER:
+                                               *tmp=0;
+                                               vb->version.len=tmp-vb->version.s;
+                                               state=L_PROTO;
+                                               break;
+                                       case F_LF:
+                                       case F_CRLF:
+                                       case F_CR: /* header continues on this line */
+                                               state=saved_state;
+                                               break;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+                                                               " state %d\n", *tmp, state);
+                                               goto error;
+                               }
+                               break;
+                       case '\n':
+                               switch(state){
+                                       case L_VER:
+                                       case F_SIP:
+                                       case F_VER:
+                                       case F_PROTO:
+                                       case L_PROTO:
+                                               saved_state=state;
+                                               state=F_LF;
+                                               break;
+                                       case P_PROTO:
+                                               *tmp=0;
+                                               vb->transport.len=tmp-vb->transport.s;
+                                               state=F_LF;
+                                               saved_state=F_HOST; /* start looking for host*/
+                                               goto main_via;
+                                       case FIN_SIP:
+                                               *tmp=0;
+                                               vb->name.len=tmp-vb->name.s;
+                                               state=F_LF;
+                                               saved_state=L_VER;
+                                               break;
+                                       case FIN_VER:
+                                               *tmp=0;
+                                               vb->version.len=tmp-vb->version.s;
+                                               state=F_LF;
+                                               saved_state=L_PROTO;
+                                               break;
+                                       case F_CR:
+                                               state=F_CRLF;
+                                               break;
+                                       case F_LF:
+                                       case F_CRLF:
+                                               state=saved_state;
+                                               goto endofheader;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+                                                               " state %d\n", *tmp, state);
+                                               goto error;
+                               }
+                               break;
+                       case '\r':
+                               switch(state){
+                                       case L_VER:
+                                       case F_SIP:
+                                       case F_VER:
+                                       case F_PROTO:
+                                       case L_PROTO:
+                                               saved_state=state;
+                                               state=F_CR;
+                                               break;
+                                       case P_PROTO:
+                                               *tmp=0;
+                                               vb->transport.len=tmp-vb->transport.s;
+                                               state=F_CR;
+                                               saved_state=F_HOST;
+                                               goto main_via;
+                                       case FIN_SIP:
+                                               *tmp=0;
+                                               vb->name.len=tmp-vb->name.s;
+                                               state=F_CR;
+                                               saved_state=L_VER;
+                                               break;
+                                       case FIN_VER:
+                                               *tmp=0;
+                                               vb->version.len=tmp-vb->version.s;
+                                               state=F_CR;
+                                               saved_state=L_PROTO;
+                                               break;
+                                       case F_LF: /*end of line ?next header?*/
+                                       case F_CR:
+                                       case F_CRLF:
+                                               state=saved_state;
+                                               goto endofheader;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+                                                               " state %d\n", *tmp, state);
+                                               goto error;
+                               }
+                               break;
+                       
+                       case '/':
+                               switch(state){
+                                       case FIN_SIP:
+                                               *tmp=0;
+                                               vb->name.len=tmp-vb->name.s;
+                                               state=F_VER;
+                                               break;
+                                       case FIN_VER:
+                                               *tmp=0;
+                                               vb->version.len=tmp-vb->version.s;
+                                               state=F_PROTO;
+                                               break;
+                                       case L_VER:
+                                               state=F_VER;
+                                               break;
+                                       case L_PROTO:
+                                               state=F_PROTO;
+                                               break;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+                                                               " state %d\n", *tmp, state);
+                                               goto error;
+                               }
+                               break;
+                               /* match SIP*/
+                       case 'S':
+                       case 's':
+                               switch(state){
+                                       case F_SIP:
+                                               state=SIP1;
+                                               vb->name.s=tmp;
+                                               break;
+                                       /* allow S in PROTO */
+                                       case F_PROTO:
+                                               state=P_PROTO;
+                                               vb->transport.s=tmp;
+                                               break;
+                                       case P_PROTO:
+                                               break;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+                                                               " state %d\n", *tmp, state);
+                                               goto error;
+                               }
+                               break;
+                       case 'I':
+                       case 'i':
+                               switch(state){
+                                       case SIP1:
+                                               state=SIP2;
+                                               break;
+                                       /* allow i in PROTO */
+                                       case F_PROTO:
+                                               vb->transport.s=tmp;
+                                               state=P_PROTO;
+                                               break;
+                                       case P_PROTO:
+                                               break;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+                                                               " state %d\n", *tmp, state);
+                                               goto error;
+                               }
+                               break;
+                       case 'p':
+                       case 'P':
+                               switch(state){
+                                       case SIP2:
+                                               state=FIN_SIP;
+                                               break;
+                                       /* allow p in PROTO */
+                                       case F_PROTO:
+                                               state=P_PROTO;
+                                               vb->transport.s=tmp;
+                                               break;
+                                       case P_PROTO:
+                                               break;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+                                                               " state %d\n", *tmp, state);
+                                               goto error;
+                               }
+                               break;
+                       /*match 2.0*/
+                       case '2':
+                               switch(state){
+                                       case F_VER:
+                                               state=VER1;
+                                               vb->version.s=tmp;
+                                               break;
+                                       /* allow 2 in PROTO*/
+                                       case F_PROTO:
+                                               vb->transport.s=tmp;
+                                               state=P_PROTO;
+                                               break;
+                                       case P_PROTO:
+                                               break;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+                                                               " state %d\n", *tmp, state);
+                                               goto error;
+                               }
+                               break;
+                       case '.':
+                               switch(state){
+                                       case VER1:
+                                               state=VER2;
+                                               break;
+                                       /* allow . in PROTO */
+                                       case F_PROTO:
+                                               vb->transport.s=tmp;
+                                               state=P_PROTO;
+                                               break;
+                                       case P_PROTO:
+                                               break;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+                                                               " state %d\n", *tmp, state);
+                                               goto error;
+                               }
+                                break;
+                       case '0':
+                               switch(state){
+                                       case VER2:
+                                               state=FIN_VER;
+                                               break;
+                                       /* allow 0 in PROTO*/
+                                       case F_PROTO:
+                                               vb->transport.s=tmp;
+                                               state=P_PROTO;
+                                               break;
+                                       case P_PROTO:
+                                               break;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+                                                               " state %d\n", *tmp, state);
+                                               goto error;
+                               }
+                               break;
+                       
+                       default:
+                               switch(state){
+                                       case F_PROTO:
+                                               vb->transport.s=tmp;
+                                               state=P_PROTO;
+                                               break;
+                                       case P_PROTO:
+                                               break;
+                                       default:
+                                               LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"
+                                                               " state %d\n", *tmp, state);
+                                               goto error;
+                               }
+                               break;
+               }
+       } /* for tmp*/
+
+/* we should not be here! if everything is ok > main_via*/
+       LOG(L_ERR, "ERROR: parse_via: bad via: end of packet on state=%d\n",
+                       state);
+       goto error;
+
+main_via:
+/* inc tmp to point to the next char*/
+       tmp++;
+       c_nest=0;
+       /*state should always be F_HOST here*/;
+       for(;*tmp;tmp++){
+               switch(*tmp){
+                       case ' ':
+                       case '\t':
+                               switch(state){
+                                       case F_HOST:/*eat the spaces*/
+                                               break;
+                                       case P_HOST:
+                                                *tmp=0;/*mark end of host*/
+                                                vb->host.len=tmp-vb->host.s;
+                                                state=L_PORT;
+                                                break;
+                                       case L_PORT: /*eat the spaces*/
+                                       case F_PORT:
+                                               break;
+                                       case P_PORT:
+                                               *tmp=0; /*end of port */
+                                               vb->port_str.len=tmp-vb->port_str.s;
+                                               state=L_PARAM;
+                                               break;
+                                       case L_PARAM: /* eat the space */
+                                       case F_PARAM:
+                                               break;
+                                       case P_PARAM:
+                                       /*      *tmp=0;*/ /*!?end of param*/
+                                               state=L_PARAM;
+                                               break;
+                                       case L_VIA:
+                                       case F_VIA: /* eat the space */
+                                               break;
+                                       case F_COMMENT:
+                                       case P_COMMENT:
+                                               break;
+                                       case F_IP6HOST: /*eat the spaces*/
+                                               break;
+                                       case P_IP6HOST:
+                                               *tmp=0; /*mark end of host*/
+                                               vb->host.len=tmp-vb->host.s;
+                                               state=L_PORT; 
+                                               break;
+                                       case F_CRLF:
+                                       case F_LF:
+                                       case F_CR:
+                                               /*previous=crlf and now =' '*/
+                                               state=saved_state;
+                                               break;
+                                       default:
+                                               LOG(L_CRIT,"BUG: parse_via"
+                                                       " on <%c>, state=%d\n",*tmp, state);
+                                               goto  error;
+                               }
+                       break;
+                       case '\n':
+                               switch(state){
+                                       case F_HOST:/*eat the spaces*/
+                                       case L_PORT: /*eat the spaces*/
+                                       case F_PORT:
+                                       case L_PARAM: /* eat the space */
+                                       case F_PARAM:
+                                       case F_VIA: /* eat the space */
+                                       case L_VIA:
+                                       case F_COMMENT:
+                                       case P_COMMENT:
+                                       case F_IP6HOST:
+                                       case P_IP6HOST:
+                                               saved_state=state;
+                                               state=F_LF;
+                                               break;
+                                       case P_HOST:
+                                                *tmp=0;/*mark end of host*/
+                                                vb->host.len=tmp-vb->host.s;
+                                                saved_state=L_PORT;
+                                                state=F_LF;
+                                                break;
+                                       case P_PORT:
+                                               *tmp=0; /*end of port */
+                                               vb->port_str.len=tmp-vb->port_str.s;
+                                               saved_state=L_PARAM;
+                                               state=F_LF;
+                                               break;
+                                       case P_PARAM:
+                                       /*      *tmp=0;*/ /*!?end of param*/
+                                               saved_state=L_PARAM;
+                                               state=F_LF;
+                                               break;
+                                       case F_CR:
+                                               state=F_CRLF;
+                                               break;
+                                       case F_CRLF:
+                                       case F_LF:
+                                               state=saved_state;
+                                               goto endofheader;
+                                       default:
+                                               LOG(L_CRIT,"BUG: parse_via"
+                                                       " on <%c>\n",*tmp);
+                                               goto  error;
+                               }
+                       break;
+               case '\r':
+                               switch(state){
+                                       case F_HOST:/*eat the spaces*/
+                                       case L_PORT: /*eat the spaces*/
+                                       case F_PORT:
+                                       case L_PARAM: /* eat the space */
+                                       case F_PARAM:
+                                       case F_VIA: /* eat the space */
+                                       case L_VIA:
+                                       case F_COMMENT:
+                                       case P_COMMENT:
+                                       case F_IP6HOST:
+                                       case P_IP6HOST:
+                                               saved_state=state;
+                                               state=F_CR;
+                                               break;
+                                       case P_HOST:
+                                                *tmp=0;/*mark end of host*/
+                                                vb->host.len=tmp-vb->host.s;
+                                                saved_state=L_PORT;
+                                                state=F_CR;
+                                                break;
+                                       case P_PORT:
+                                               *tmp=0; /*end of port */
+                                               vb->port_str.len=tmp-vb->port_str.s;
+                                               saved_state=L_PARAM;
+                                               state=F_CR;
+                                               break;
+                                       case P_PARAM:
+                                       /*      *tmp=0;*/ /*!?end of param*/
+                                               saved_state=L_PARAM;
+                                               state=F_CR;
+                                               break;
+                                       case F_CRLF:
+                                       case F_CR:
+                                       case F_LF:
+                                               state=saved_state;
+                                               goto endofheader;
+                                       default:
+                                               LOG(L_CRIT,"BUG: parse_via"
+                                                       " on <%c>\n",*tmp);
+                                               goto  error;
+                               }
+                       break;
+                       
+                       case ':':
+                               switch(state){
+                                       case F_HOST:
+                                       case F_IP6HOST:
+                                               LOG(L_ERR,"ERROR:parse_via:"
+                                                       " no host found\n");
+                                               goto error;
+                                       case P_IP6HOST:
+                                               LOG(L_ERR, "ERROR:parse_via: bad ipv6 reference\n");
+                                               goto error;
+                                       case P_HOST:
+                                               *tmp=0; /*mark  end of host*/
+                                               vb->host.len=tmp-vb->host.s;
+                                               state=F_PORT;
+                                               break;
+                                       case L_PORT:
+                                               state=F_PORT;
+                                               break;
+                                       case P_PORT:
+                                               LOG(L_ERR, "ERROR:parse_via:"
+                                                       " bad port\n");
+                                               goto error;
+                                       case L_PARAM:
+                                       case F_PARAM:
+                                       case P_PARAM:
+                                               LOG(L_ERR, "ERROR:parse_via:"
+                                               " bad char <%c> in state %d\n",
+                                                       *tmp,state);
+                                               goto error;
+                                       case L_VIA:
+                                       case F_VIA:
+                                               LOG(L_ERR, "ERROR:parse_via:"
+                                               " bad char in compact via\n");
+                                               goto error;
+                                       case F_CRLF:
+                                       case F_LF:
+                                       case F_CR:
+                                               /*previous=crlf and now !=' '*/
+                                               goto endofheader;
+                                       case F_COMMENT:/*everything is allowed in a comment*/
+                                               vb->comment.s=tmp;
+                                               state=P_COMMENT;
+                                               break;
+                                       case P_COMMENT: /*everything is allowed in a comment*/
+                                               break;
+                                       default:
+                                               LOG(L_CRIT,"BUG: parse_via"
+                                                       " on <%c> state %d\n",
+                                                       *tmp, state);
+                                               goto error;
+                               }
+                               break;
+                       case ';':
+                               switch(state){
+                                       case F_HOST:
+                                       case F_IP6HOST:
+                                               LOG(L_ERR,"ERROR:parse_via:"
+                                                       " no host found\n");
+                                               goto error;
+                                       case P_IP6HOST:
+                                               LOG(L_ERR, "ERROR:parse_via: bad ipv6 reference\n");
+                                               goto error;
+                                       case P_HOST:
+                                               *tmp=0;
+                                               vb->host.len=tmp-vb->host.s;
+                                               state=F_PARAM;
+                                               break;
+                                       case P_PORT:
+                                               *tmp=0; /*mark the end*/
+                                               vb->port_str.len=tmp-vb->port_str.s;
+                                       case L_PORT:
+                                       case L_PARAM:
+                                               state=F_PARAM;
+                                               break;
+                                       case F_PORT:
+                                               LOG(L_ERR, "ERROR:parse_via:"
+                                               " bad char <%c> in state %d\n",
+                                                       *tmp,state);
+                                               goto error;
+                                       case F_PARAM:
+                                               LOG(L_ERR,  "ERROR:parse_via:"
+                                                       " null param?\n");
+                                               goto error;
+                                       case P_PARAM:
+                                               /*hmm next, param?*/
+                                               state=F_PARAM;
+                                               break;
+                                       case L_VIA:
+                                       case F_VIA:
+                                               LOG(L_ERR, "ERROR:parse_via:"
+                                               " bad char <%c> in next via\n",
+                                                       *tmp);
+                                               goto error;
+                                       case F_CRLF:
+                                       case F_LF:
+                                       case F_CR:
+                                               /*previous=crlf and now !=' '*/
+                                               goto endofheader;
+                                       case F_COMMENT:/*everything is allowed in a comment*/
+                                               vb->comment.s=tmp;
+                                               state=P_COMMENT;
+                                               break;
+                                       case P_COMMENT: /*everything is allowed in a comment*/
+                                               break;
+                                       
+                                       default:
+                                               LOG(L_CRIT,"BUG: parse_via"
+                                                       " on <%c> state %d\n",
+                                                       *tmp, state);
+                                               goto  error;
+                               }
+                       break;
+                       case ',':
+                               switch(state){
+                                       case F_HOST:
+                                       case F_IP6HOST:
+                                               LOG(L_ERR,"ERROR:parse_via:"
+                                                       " no host found\n");
+                                               goto error;
+                                       case P_IP6HOST:
+                                               LOG(L_ERR, "ERROR:parse_via: bad ipv6 reference\n");
+                                               goto error;
+                                       case P_HOST:
+                                               *tmp=0; /*mark the end*/
+                                               vb->host.len=tmp-vb->host.s;
+                                               state=F_VIA;
+                                               break;
+                                       case P_PORT:
+                                               *tmp=0; /*mark the end*/
+                                               vb->port_str.len=tmp-vb->port_str.s;
+                                               state=F_VIA;
+                                               break;
+                                       case L_PORT:
+                                       case L_PARAM:
+                                       case P_PARAM:
+                                       case L_VIA:
+                                               state=F_VIA;
+                                               break;
+                                       case F_PORT:
+                                       case F_PARAM:
+                                               LOG(L_ERR, "ERROR:parse_via:"
+                                               " invalid char <%c> in state"
+                                               " %d\n", *tmp,state);
+                                               goto error;
+                                       case F_VIA:
+                                               /* do  nothing,  eat ","*/
+                                               break;  
+                                       case F_CRLF:
+                                       case F_LF:
+                                       case F_CR:
+                                               /*previous=crlf and now !=' '*/
+                                               goto endofheader;
+                                       case F_COMMENT:/*everything is allowed in a comment*/
+                                               vb->comment.s=tmp;
+                                               state=P_COMMENT;
+                                               break;
+                                       case P_COMMENT: /*everything is allowed in a comment*/
+                                               break;
+                                       default:
+                                               LOG(L_CRIT,"BUG: parse_via"
+                                                       " on <%c> state %d\n",
+                                                       *tmp, state);
+                                               goto  error;
+                               }
+                       break;
+                       case '(':
+                               switch(state){
+                                       case F_HOST:
+                                       case F_PORT:
+                                       case F_PARAM:
+                                       case F_VIA:
+                                       case F_IP6HOST:
+                                       case P_IP6HOST: /*must be terminated in ']'*/
+                                               LOG(L_ERR,"ERROR:parse_via"
+                                                       " on <%c> state %d\n",
+                                                       *tmp, state);
+                                               goto  error;
+                                       case P_HOST:
+                                               *tmp=0; /*mark the end*/
+                                               vb->host.len=tmp-vb->host.s;
+                                               state=F_COMMENT;
+                                               c_nest++;
+                                               break;
+                                       case P_PORT:
+                                               *tmp=0; /*mark the end*/
+                                               vb->port_str.len=tmp-vb->port_str.s;
+                                               state=F_COMMENT;
+                                               c_nest++;
+                                               break;
+                                       case P_PARAM:
+                                               *tmp=0; /*mark the end*/
+                                               vb->params.len=tmp-vb->params.s;
+                                               state=F_COMMENT;
+                                               c_nest++;
+                                               break;
+                                       case L_PORT:
+                                       case L_PARAM:
+                                       case L_VIA:
+                                               state=F_COMMENT;
+                                               vb->params.len=tmp-vb->params.s;
+                                               c_nest++;
+                                               *tmp=0;
+                                               break;
+                                       case P_COMMENT:
+                                       case F_COMMENT:
+                                               c_nest++;
+                                               break;
+                                       case F_CRLF:
+                                       case F_LF:
+                                       case F_CR:
+                                               /*previous=crlf and now !=' '*/
+                                               goto endofheader;
+                                       default:
+                                               LOG(L_CRIT,"BUG: parse_via"
+                                                       " on <%c> state %d\n",
+                                                       *tmp, state);
+                                               goto  error;
+                               }
+                       break;
+                       case ')':
+                               switch(state){
+                                       case F_COMMENT:
+                                       case P_COMMENT:
+                                               if (c_nest){
+                                                       c_nest--;
+                                                       if(c_nest==0){
+                                                               state=L_VIA;
+                                                               *tmp=0;
+                                                               vb->comment.len=tmp-vb->comment.s;
+                                                               break;
+                                                       }
+                                               }else{
+                                                       LOG(L_ERR,"ERROR:"
+                                                           "parse_via: "
+                                                           "missing '(' - "
+                                                           "nesting = %d\n",
+                                                           c_nest);
+                                                        goto error;
+                                               }
+                                               break;
+                                       case F_HOST:
+                                       case F_PORT:
+                                       case F_PARAM:
+                                       case F_VIA:
+                                       case P_HOST:
+                                       case P_PORT:
+                                       case P_PARAM:
+                                       case L_PORT:
+                                       case L_PARAM:
+                                       case L_VIA:
+                                       case F_IP6HOST:
+                                       case P_IP6HOST:
+                                               LOG(L_ERR,"ERROR:parse_via"
+                                                       " on <%c> state %d\n",
+                                                       *tmp, state);
+                                               goto  error;
+                                       case F_CRLF:
+                                       case F_LF:
+                                       case F_CR:
+                                               /*previous=crlf and now !=' '*/
+                                               goto endofheader;
+                                       default:
+                                               LOG(L_CRIT,"BUG: parse_via"
+                                                       " on <%c> state %d\n",
+                                                       *tmp, state);
+                                               goto  error;
+                               }
+                               break;
+                       case '[':
+                               switch(state){
+                                       case F_HOST:
+                                               state=F_IP6HOST;
+                                               break;
+                                       case F_COMMENT:/*everything is allowed in a comment*/
+                                               vb->comment.s=tmp;
+                                               state=P_COMMENT;
+                                               break;
+                                       case P_COMMENT:
+                                               break;
+                                       case F_CRLF:
+                                       case F_LF:
+                                       case F_CR:
+                                               /*previous=crlf and now !=' '*/
+                                               goto endofheader;
+                                       default:
+                                               LOG(L_ERR,"ERROR:parse_via"
+                                                       " on <%c> state %d\n",
+                                                       *tmp, state);
+                                               goto  error;
+                               }
+                               break;
+                       case ']':
+                               switch(state){
+                                       case P_IP6HOST:
+                                               *tmp=0; /*mark the end*/
+                                               vb->host.len=tmp-vb->host.s;
+                                               state=L_PORT;
+                                               break;
+                                       case F_CRLF:
+                                       case F_LF:
+                                       case F_CR:
+                                               /*previous=crlf and now !=' '*/
+                                               goto endofheader;
+                                       case F_COMMENT:/*everything is allowed in a comment*/
+                                               vb->comment.s=tmp;
+                                               state=P_COMMENT;
+                                               break;
+                                       case P_COMMENT:
+                                               break;
+                                       default:
+                                               LOG(L_ERR,"ERROR:parse_via"
+                                                       " on <%c> state %d\n",
+                                                       *tmp, state);
+                                               goto  error;
+                               }
+                               break;
+                                               
+                       default:
+                               switch(state){
+                                       case F_HOST:
+                                               state=P_HOST;
+                                               vb->host.s=tmp;
+                                               break;
+                                       case P_HOST:
+                                               break;
+                                       case F_PORT:
+                                               state=P_PORT;
+                                               vb->port_str.s=tmp;
+                                               break;
+                                       case P_PORT:
+                                               /*check if number?*/
+                                               break;
+                                       case F_PARAM:
+                                               /*state=P_PARAM*/;
+                                               if(vb->params.s==0) vb->params.s=tmp;
+                                               tmp=parse_via_param(tmp, end, &state, &saved_state);
+                                               switch(state){
+                                                       case L_PARAM:
+                                                       case F_PARAM:
+                                                       case F_LF:
+                                                       case F_CR:
+                                                               break;
+                                                       case F_VIA:
+                                                               vb->params.len=tmp-vb->params.s;
+                                                               *tmp=0;
+                                                               break;
+                                                       case END_OF_HEADER:
+                                                               vb->params.len=tmp-vb->params.s;
+                                                               state=saved_state;
+                                                               goto endofheader;
+                                                       default:
+                                                               LOG(L_ERR, "ERROR: parse_via after"
+                                                                               " parse_via_param: invalid"
+                                                                               " char <%c> on state %d\n",
+                                                                               *tmp, state);
+                                                               goto error;
+                                               }
+                                               break;
+                                       case P_PARAM:
+                                               break;
+                                       case F_VIA:
+                                               /*vb->next=tmp;*/ /*???*/
+                                               goto nextvia;
+                                       case L_PORT:
+                                       case L_PARAM:
+                                       case L_VIA:
+                                               LOG(L_ERR,"ERROR:parse_via"
+                                                       " on <%c> state %d (default)\n",
+                                                       *tmp, state);
+                                               goto  error;
+                                       case F_COMMENT:
+                                               state=P_COMMENT;
+                                               vb->comment.s=tmp;
+                                               break;
+                                       case P_COMMENT:
+                                               break;
+                                       case F_IP6HOST:
+                                               state=P_IP6HOST;
+                                               vb->host.s=tmp;
+                                               break;
+                                       case P_IP6HOST:
+                                               break;
+                                       case F_CRLF:
+                                       case F_LF:
+                                       case F_CR:
+                                               /*previous=crlf and now !=' '*/
+                                               goto endofheader;
+                                       default:
+                                               LOG(L_ERR, "BUG:parse_via:"
+                                                       " invalid char <%c>"
+                                                       " in state %d\n",
+                                                       *tmp, state);
+                                               goto error;
+                               }
+                               
+                                       
+               }                       
+       }
+
+       DBG("end of packet reached, state=%d\n", state);
+       goto endofpacket; /*end of packet, probably should be goto error*/
+       
+endofheader:
+       state=saved_state;
+       DBG("end of header reached, state=%d\n", state);
+endofpacket:
+       /* check if error*/
+       switch(state){
+               case P_HOST:
+               case L_PORT:
+               case P_PORT:
+               case L_PARAM:
+               case P_PARAM:
+               case P_VALUE:
+               case GEN_PARAM:
+               case FIN_HIDDEN:
+               case L_VIA:
+                       break;
+               default:
+                       LOG(L_ERR, "ERROR: parse_via: invalid via - end of header in"
+                                       " state %d\n", state);
+                       goto error;
+       }
+       
+
+       /*
+       if (proto) printf("<SIP/2.0/%s>\n", proto);
+       if (host) printf("host= <%s>\n", host);
+       if (port_str) printf("port= <%s>\n", port_str);
+       if (param) printf("params= <%s>\n", param);
+       if (comment) printf("comment= <%s>\n", comment);
+       if(next_via) printf("next_via= <%s>\n", next_via);
+       */
+       /*DBG("parse_via: rest=<%s>\n", tmp);*/
+       
+       vb->error=VIA_PARSE_OK;
+       vb->bsize=tmp-buffer;
+       if (vb->port_str.s){
+               vb->port=str2s(vb->port_str.s, vb->port_str.len, &err);
+               if (err){
+                                       LOG(L_ERR, "ERROR: parse_via: invalid port number <%s>\n",
+                                               vb->port_str.s);
+                                       goto error;
+               }
+       }
+       return tmp;
+nextvia:
+       vb->error=VIA_PARSE_OK;
+       vb->bsize=tmp-buffer;
+       if (vb->port_str.s){
+               vb->port=str2s(vb->port_str.s, vb->port_str.len, &err);
+               if (err){
+                                       LOG(L_ERR, "ERROR: parse_via: invalid port number <%s>\n",
+                                               vb->port_str.s);
+                                       goto error;
+               }
+       }
+       vb->next=pkg_malloc(sizeof(struct via_body));
+       if (vb->next==0){
+               LOG(L_ERR, "ERROR: parse_via: out of memory\n");
+               goto error;
+       }
+       vb=vb->next;
+       memset(vb, 0, sizeof(struct via_body));
+       buffer=tmp;
+       goto parse_again;
+
+error:
+       LOG(L_ERR, "via parse error\n");
+       vb->error=VIA_PARSE_ERROR;
+       return tmp;
+}
+
+
+#endif
index 143bccd..a9e8785 100644 (file)
--- a/receive.c
+++ b/receive.c
@@ -25,36 +25,39 @@ unsigned int msg_no=0;
 
 int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
 {
-       struct sip_msg msg;
+       struct sip_msg* msg;
 
+       msg=pkt_malloc(sizeof(struct sip_msg));
+       if (msg==0) goto error1;
        msg_no++;
 #ifdef STATS
        skipped = 1;
 #endif
 
-       memset(&msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
+       memset(msg,0, sizeof(struct sip_msg)); /* init everything to 0 */
        /* fill in msg */
-       msg.buf=buf;
-       msg.len=len;
-       msg.src_ip=src_ip;
-       msg.id=msg_no;
+       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){
+       msg->orig=(char*) pkt_malloc(len+1);
+       if (msg->orig==0){
                LOG(L_ERR, "ERROR:receive_msg: memory allocation failure\n");
                goto error1;
        }
-       memcpy(msg.orig, buf, len);
-       msg.orig[len]=0; /* null terminate it,good for using str* functions on it*/
+       memcpy(msg->orig, buf, len);
+       msg->orig[len]=0; /* null terminate it,good for using str* functions
+                                                on it*/
        
-       if (parse_msg(buf,len, &msg)!=0){
+       if (parse_msg(buf,len, msg)!=0){
                goto error;
        }
        DBG("After parse_msg...\n");
-       if (msg.first_line.type==SIP_REQUEST){
+       if (msg->first_line.type==SIP_REQUEST){
                DBG("msg= request\n");
                /* sanity checks */
-               if ((msg.via1==0) || (msg.via1->error!=VIA_PARSE_OK)){
+               if ((msg->via1==0) || (msg->via1->error!=VIA_PARSE_OK)){
                        /* no via, send back error ? */
                        LOG(L_ERR, "ERROR: receive_msg: no via found in request\n");
                        goto error;
@@ -63,24 +66,24 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
                
                /* exec routing script */
                DBG("preparing to run routing scripts...\n");
-               if (run_actions(rlist[0], &msg)<0){
+               if (run_actions(rlist[0], msg)<0){
                        LOG(L_WARN, "WARNING: receive_msg: "
                                        "error while trying script\n");
                        goto error;
                }
 #ifdef STATS
                /* jku -- update request statistics  */
-               else update_received_request(  msg.first_line.u.request.method_value );
+               else update_received_request(msg->first_line.u.request.method_value );
 #endif
-       }else if (msg.first_line.type==SIP_REPLY){
+       }else if (msg->first_line.type==SIP_REPLY){
                DBG("msg= reply\n");
                /* sanity checks */
-               if ((msg.via1==0) || (msg.via1->error!=VIA_PARSE_OK)){
+               if ((msg->via1==0) || (msg->via1->error!=VIA_PARSE_OK)){
                        /* no via, send back error ? */
                        LOG(L_ERR, "ERROR: receive_msg: no via found in reply\n");
                        goto error;
                }
-               if ((msg.via2==0) || (msg.via2->error!=VIA_PARSE_OK)){
+               if ((msg->via2==0) || (msg->via2->error!=VIA_PARSE_OK)){
                        /* no second via => error? */
                        LOG(L_ERR, "ERROR: receive_msg: no 2nd via found in reply\n");
                        goto error;
@@ -89,14 +92,14 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
 
 #ifdef STATS
                /* jku -- update statistics  */
-               update_received_response(  msg.first_line.u.reply.statusclass );
+               update_received_response( msg->first_line.u.reply.statusclass );
 #endif
                
                /* send the msg */
-               if (forward_reply(&msg)==0){
+               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
@@ -104,23 +107,23 @@ int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
 #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);
+       free_sip_msg(msg);
+       pkt_free(msg);
 #ifdef STATS
        if (skipped) update_received_drops;
 #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);
+       free_sip_msg(msg);
+       pkt_free(msg);
+#ifdef STATS
+       update_received_drops;
+#endif
+       return -1;
 error1:
+       if (msg) pkt_free(msg);
+       pkt_free(buf);
 #ifdef STATS
        update_received_drops;
 #endif
index cca50f8..a2fb5fa 100644 (file)
@@ -149,10 +149,16 @@ error:
 int udp_rcv_loop()
 {
        unsigned len;
-       char buf[BUF_SIZE+1];
+       char* buf;
        struct sockaddr* from;
        int fromlen;
 
+       buf=pkt_malloc(BUF_SIZE+1);
+       if (buf==0){
+               LOG(L_ERR, "ERROR: udp_rcv_loop: could not allocate receive"
+                                " buffer\n");
+               goto error;
+       }
        from=(struct sockaddr*) malloc(sizeof(struct sockaddr));
        if (from==0){
                LOG(L_ERR, "ERROR: udp_rcv_loop: out of memory\n");
@@ -170,7 +176,8 @@ int udp_rcv_loop()
                }
                /*debugging, make print* msg work */
                buf[len+1]=0;
-
+               
+               /* receive_msg must free buf too!*/
                receive_msg(buf, len, ((struct sockaddr_in*)from)->sin_addr.s_addr);
                
        skip: /* do other stuff */