rem: LOG(L_ERR,"ERROR:parse_via:" " no host found\n"); goto error;
add: state=P_IP6HOST; break;
context: char* parse_via(char* buffer, char* end, struct via_body *vb){	char* tmp;	char* param_start;	unsigned char state;	unsigned char saved_state;	int c_nest;	int err;	struct via_param* param;parse_again:	vb->error=PARSE_ERROR;	/* parse start of via ( SIP/2.0/UDP    )*/	state=F_SIP;	param_start=0;	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 FIN_UDP:						vb->transport.len=tmp-vb->transport.s;						vb->proto=PROTO_UDP;						state=F_HOST; /* start looking for host*/						goto main_via;					case FIN_TCP:						/* finished proto parsing */						vb->transport.len=tmp-vb->transport.s;						vb->proto=PROTO_TCP;						state=F_HOST; /* start looking for host*/						goto main_via;					case FIN_TLS:						/* finished proto parsing */						vb->transport.len=tmp-vb->transport.s;						vb->proto=PROTO_TLS;						state=F_HOST; /* start looking for host*/						goto main_via;					case FIN_SIP:						vb->name.len=tmp-vb->name.s;						state=L_VER;						break;					case FIN_VER:						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 FIN_UDP:						vb->transport.len=tmp-vb->transport.s;						vb->proto=PROTO_UDP;						state=F_LF;						saved_state=F_HOST; /* start looking for host*/						goto main_via;					case FIN_TCP:						vb->transport.len=tmp-vb->transport.s;						vb->proto=PROTO_TCP;						state=F_LF;						saved_state=F_HOST; /* start looking for host*/						goto main_via;					case FIN_TLS:						vb->transport.len=tmp-vb->transport.s;						vb->proto=PROTO_TLS;						state=F_LF;						saved_state=F_HOST; /* start looking for host*/						goto main_via;					case FIN_SIP:						vb->name.len=tmp-vb->name.s;						state=F_LF;						saved_state=L_VER;						break;					case FIN_VER:						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 FIN_UDP:						vb->transport.len=tmp-vb->transport.s;						vb->proto=PROTO_UDP;						state=F_CR;						saved_state=F_HOST;						goto main_via;					case FIN_TCP:						vb->transport.len=tmp-vb->transport.s;						vb->proto=PROTO_TCP;						state=F_CR;						saved_state=F_HOST;						goto main_via;					case FIN_TLS:						vb->transport.len=tmp-vb->transport.s;						vb->proto=PROTO_TLS;						state=F_CR;						saved_state=F_HOST;						goto main_via;					case FIN_SIP:						vb->name.len=tmp-vb->name.s;						state=F_CR;						saved_state=L_VER;						break;					case FIN_VER:						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:						vb->name.len=tmp-vb->name.s;						state=F_VER;						break;					case FIN_VER:						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;					case TLS2:						state=FIN_TLS;						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;					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 UDP2:						state=FIN_UDP;						break;					case TCP2:						state=FIN_TCP;						break;					default:						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"								" state %d\n", *tmp, state);						goto error;				}				break;			case 'U':			case 'u':				switch(state){					case F_PROTO:						state=UDP1;						vb->transport.s=tmp;						break;					default:						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"								" state %d\n", *tmp, state);						goto error;				}				break;			case 'D':			case 'd':				switch(state){					case UDP1:						state=UDP2;						break;					default:						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"								" state %d\n", *tmp, state);						goto error;				}				break;			case 'T':			case 't':				switch(state){					case F_PROTO:						state=TCP_TLS1;						vb->transport.s=tmp;						break;					default:						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"								" state %d\n", *tmp, state);						goto error;				}				break;			case 'C':			case 'c':				switch(state){					case TCP_TLS1:						state=TCP2;						break;					default:						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"								" state %d\n", *tmp, state);						goto error;				}				break;			case 'L':			case 'l':				switch(state){					case TCP_TLS1:						state=TLS2;						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;					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;					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;					default:						LOG(L_ERR, "ERROR: parse_via: bad char <%c> on"								" state %d\n", *tmp, state);						goto error;				}				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:						 /*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:						/*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:						/*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:						 /*mark end of host*/						 vb->host.len=tmp-vb->host.s;						 saved_state=L_PORT;						 state=F_LF;						 break;					case P_PORT:						/*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:						 /*mark end of host*/						 vb->host.len=tmp-vb->host.s;						 saved_state=L_PORT;						 state=F_CR;						 break;					case P_PORT:						/*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:						break;					case P_HOST:						/*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:						vb->host.len=tmp-vb->host.s;						state=F_PARAM;						param_start=tmp+1;						break;					case P_PORT:						/*mark the end*/						vb->port_str.len=tmp-vb->port_str.s;					case L_PORT:					case L_PARAM:						state=F_PARAM;						param_start=tmp+1;						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;						param_start=tmp+1;						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:						/*mark the end*/						vb->host.len=tmp-vb->host.s;						state=F_VIA;						break;					case P_PORT:						/*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:						/*mark the end*/						vb->host.len=tmp-vb->host.s;						state=F_COMMENT;						c_nest++;						break;					case P_PORT:						/*mark the end*/						vb->port_str.len=tmp-vb->port_str.s;						state=F_COMMENT;						c_nest++;						break;					case P_PARAM:						/*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++;						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;								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:						/*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=param_start;						param=pkg_malloc(sizeof(struct via_param));						if (param==0){							LOG(L_ERR, "ERROR:parse_via: mem. allocation"									" error\n");							goto error;						}						memset(param,0, sizeof(struct via_param));						param->start=param_start;						tmp=parse_via_param(tmp, end, &state, &saved_state,											param);						switch(state){							case F_PARAM:								param_start=tmp+1;							case L_PARAM:							case F_LF:							case F_CR:								break;							case F_VIA:								vb->params.len=param->start+param->size												-vb->params.s;								break;							case END_OF_HEADER:								vb->params.len=param->start+param->size												-vb->params.s;								break;							case PARAM_ERROR:								pkg_free(param);								goto error;							default:								pkg_free(param);								LOG(L_ERR, "ERROR: parse_via after"										" parse_via_param: invalid"										" char <%c> on state %d\n",										*tmp, state);								goto error;						}						/*add param to the list*/						if (vb->last_param)	vb->last_param->next=param;						else				vb->param_lst=param;						vb->last_param=param;						if (param->type==PARAM_BRANCH)							vb->branch=param;						else if (param->type==PARAM_RECEIVED)							vb->received=param;						else if (param->type==PARAM_RPORT)							vb->rport=param;						else if (param->type==PARAM_I)							vb->i=param;												if (state==END_OF_HEADER){							state=saved_state;							goto endofheader;						}						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=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.len, ZSW(vb->port_str.s));					goto error;		}	}	return tmp;nextvia:	DBG("parse_via: next_via\n");	vb->error=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.len, ZSW(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:	if (end>buffer){		LOG(L_ERR, "ERROR: parse_via on: <%.*s>\n", (int)(end-buffer), ZSW(buffer));	}	if ((tmp>buffer)&&(tmp<end)){		LOG(L_ERR, "ERROR: parse_via parse error, parsed so far:<%.*s>\n",				(int)(tmp-buffer), ZSW(buffer) );	}else{		LOG(L_ERR, "ERROR: parse_via: via parse error\n");	}	vb->error=PARSE_ERROR;	return tmp;}