parse_fline.c
b6f4c1df
 /*
  * $Id$
  * 
  * sip first line parsing automaton
  * 
  */
 
 
 
 #include "dprint.h"
 #include "msg_parser.h"
 
 
 /* grammar:
 	request  =  method SP uri SP version CRLF
 	response =  version SP status  SP reason  CRLF
 	(version = "SIP/2.0")
 */
 
 /*known methods: INVITE, ACK, CANCEL, BYE*/
 
 enum{ START,
 		INVITE1, INVITE2, INVITE3, INVITE4, INVITE5,
 		ACK1,    ACK2,
 		CANCEL1, CANCEL2, CANCEL3, CANCEL4, CANCEL5,
 		BYE1, BYE2,
 		SIP1, SIP2, SIP3, SIP4, SIP5, SIP6,
 		FIN_INVITE=100, FIN_ACK, FIN_CANCEL, FIN_BYE, FIN_SIP,
 		P_METHOD=200, L_URI, P_URI, L_VER, 
 		VER1, VER2, VER3, VER4, VER5, VER6, FIN_VER,
 		L_STATUS, P_STATUS, L_REASON, P_REASON,
 		L_LF, F_CR, F_LF
 };
 
 
 
 char* parse_fline(char* buffer, char* end, struct msg_start* fl)
 {
 	char* tmp;
 	register int state;
 	unsigned short stat;
 
 	stat=0;
 	fl->type=SIP_REQUEST;
 	state=START;
 	for(tmp=buffer;tmp<end;tmp++){
 		switch(*tmp){
 			case ' ':
 			case '\t':
 				switch(state){
 					case START: /*allow space at the beginnig, althoug not
 								  legal*/
 						break;
 					case L_URI:
 					case L_VER:
 					case L_STATUS:
 					case L_REASON:
 					case L_LF:
 						 /*eat  space*/
 						break;
 					case FIN_INVITE:
 						*tmp=0;
 						fl->u.request.method.len=tmp-fl->u.request.method.s;
 						fl->u.request.method_value=METHOD_INVITE;
 						state=L_URI;
 						break;
 					case FIN_ACK:
 						*tmp=0;
 						fl->u.request.method.len=tmp-fl->u.request.method.s;
 						fl->u.request.method_value=METHOD_ACK;
 						state=L_URI;
 						break;
 					case FIN_CANCEL:
 						*tmp=0;
 						fl->u.request.method.len=tmp-fl->u.request.method.s;
 						fl->u.request.method_value=METHOD_CANCEL;
 						state=L_URI;
 						break;
 					case FIN_BYE:
 						*tmp=0;
 						fl->u.request.method.len=tmp-fl->u.request.method.s;
 						fl->u.request.method_value=METHOD_BYE;
 						state=L_URI;
 						break;
 					case FIN_SIP:
 						*tmp=0;
 						fl->u.reply.version.len=tmp-fl->u.reply.version.s;
 						state=L_STATUS;
 						fl->type=SIP_REPLY;
 						break;
 					case P_URI:
 						*tmp=0;
 						fl->u.request.uri.len=tmp-fl->u.request.uri.s;
 						state=L_VER;
 						break;
 					case FIN_VER:
 						*tmp=0;
 						fl->u.request.version.len=tmp-fl->u.request.version.s;
 						state=L_LF;
 						break;
 					case P_STATUS:
 						*tmp=0;
 						fl->u.reply.status.len=tmp-fl->u.reply.status.s;
 						state=L_REASON;
 						break;
 					case P_REASON:
 					 /*	*tmp=0;
 						fl->u.reply.reason.len=tmp-fl->u.reply.reason.s;
 						*/
 						break;
 					case VER1:
 					case VER2:
 					case VER3:
 					case VER4:
 					case VER5:
 					case VER6:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					case P_METHOD:
 					default:
 						*tmp=0;
 						fl->u.request.method.len=tmp-fl->u.request.method.s;
 						fl->u.request.method_value=METHOD_OTHER;
 						state=L_URI;
 				}
 				break;
 			case 's':
 			case 'S':
 				switch(state){
 					case START:
 						state=SIP1;
 						fl->u.reply.version.s=tmp;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 					case L_STATUS:
 						LOG(L_ERR, "ERROR: parse_first_line: non-number "
 								"character <%c> in request status\n", *tmp);
 						goto error;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 					case L_VER:
 						fl->u.request.version.s=tmp;
 						state=VER1;
 						break;
 					case VER1:
 					case VER2:
 					case VER3:
 					case VER4:
 					case VER5:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 				break;
 					
 			case 'i':
 			case 'I':
 				switch(state){
 					case START:
 						state=INVITE1;
 						fl->u.request.method.s=tmp;
 						break;
 					case INVITE3:
 						state=INVITE4;
 						break;
 					case SIP1:
 						state=SIP2;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 					case L_STATUS:
 						LOG(L_ERR, "ERROR: parse_first_line: non-number "
 								"character <%c> in request status\n", *tmp);
 						goto error;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 					case VER1:
 						state=VER2;
 						break;
 					case L_VER:
 					case VER2:
 					case VER3:
 					case VER4:
 					case VER5:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 				break;
 				
 			case 'p':
 			case 'P':
 				switch(state){
 					case START:
 						state=P_METHOD;
 						fl->u.request.method.s=tmp;
 						break;
 					case SIP2:
 						state=SIP3;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 					case L_STATUS:
 						LOG(L_ERR, "ERROR: parse_first_line: non-number "
 								"character <%c> in request status\n", *tmp);
 						goto error;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 					case VER2:
 						state=VER3;
 						break;
 					case L_VER:
 					case VER1:
 					case VER3:
 					case VER4:
 					case VER5:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 				break;
 
 			
 			case '/':
 				switch(state){
 					case START:
 						state=P_METHOD;
 						fl->u.request.method.s=tmp;
 						break;
 					case SIP3:
 						state=SIP4;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 					case L_STATUS:
 						LOG(L_ERR, "ERROR: parse_first_line: non-number "
 								"character <%c> in request status\n", *tmp);
 						goto error;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 					case VER3:
 						state=VER4;
 						break;
 					case L_VER:
 					case VER1:
 					case VER2:
 					case VER4:
 					case VER5:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 				break;
 			
 			case '2':
 				switch(state){
 					case START:
 						state=P_METHOD;
 						fl->u.request.method.s=tmp;
 						break;
 					case SIP4:
 						state=SIP5;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 						stat=stat*10+*tmp-'0';
 						break;
 					case L_STATUS:
 						stat=*tmp-'0';
 						fl->u.reply.status.s=tmp;
 						break;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 					case VER4:
 						state=VER5;
 						break;
 					case L_VER:
 					case VER1:
 					case VER2:
 					case VER3:
 					case VER5:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 				break;
 			
 			case '.':
 				switch(state){
 					case START:
 						state=P_METHOD;
 						fl->u.request.method.s=tmp;
 						break;
 					case SIP5:
 						state=SIP6;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 					case L_STATUS:
 						LOG(L_ERR, "ERROR: parse_first_line: non-number "
 								"character <%c> in request status\n", *tmp);
 						goto error;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 					case VER5:
 						state=VER6;
 						break;
 					case L_VER:
 					case VER1:
 					case VER2:
 					case VER3:
 					case VER4:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 				break;
 			
 			case '0':
 				switch(state){
 					case START:
 						state=P_METHOD;
 						fl->u.request.method.s=tmp;
 						break;
 					case SIP6:
 						state=FIN_SIP;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 						stat=stat*10;
 						break;
 					case L_STATUS:
 						stat=0;
 						fl->u.reply.status.s=tmp;
 						break;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 					case VER6:
 						state=FIN_VER;
 						break;
 					case L_VER:
 					case VER1:
 					case VER2:
 					case VER3:
 					case VER4:
 					case VER5:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 				break;
 			
 			case 'n':
 			case 'N':
 				switch(state){
 					case START:
 						state=P_METHOD;
 						fl->u.request.method.s=tmp;
 						break;
 					case INVITE1:
 						state=INVITE2;
 						break;
 					case CANCEL2:
 						state=CANCEL3;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 					case L_STATUS:
 						LOG(L_ERR, "ERROR: parse_first_line: non-number "
 								"character <%c> in request status\n", *tmp);
 						goto error;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 						state=VER3;
 						break;
 					case L_VER:
 					case VER1:
 					case VER2:
 					case VER3:
 					case VER4:
 					case VER5:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 				break;
 
 			case 'v':
 			case 'V':
 				switch(state){
 					case START:
 						state=P_METHOD;
 						fl->u.request.method.s=tmp;
 						break;
 					case INVITE2:
 						state=INVITE3;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 					case L_STATUS:
 						LOG(L_ERR, "ERROR: parse_first_line: non-number "
 								"character <%c> in request status\n", *tmp);
 						goto error;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 						state=VER3;
 						break;
 					case L_VER:
 					case VER1:
 					case VER2:
 					case VER3:
 					case VER4:
 					case VER5:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 				break;
 
 			case 't':
 			case 'T':
 				switch(state){
 					case START:
 						state=P_METHOD;
 						fl->u.request.method.s=tmp;
 						break;
 					case INVITE4:
 						state=INVITE5;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 					case L_STATUS:
 						LOG(L_ERR, "ERROR: parse_first_line: non-number "
 								"character <%c> in request status\n", *tmp);
 						goto error;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 						state=VER3;
 						break;
 					case L_VER:
 					case VER1:
 					case VER2:
 					case VER3:
 					case VER4:
 					case VER5:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 				break;
 
 			case 'e':
 			case 'E':
 				switch(state){
 					case START:
 						state=P_METHOD;
 						fl->u.request.method.s=tmp;
 						break;
 					case INVITE5:
 						state=FIN_INVITE;
 						break;
 					case CANCEL4:
 						state=CANCEL5;
 						break;
 					case BYE2:
 						state=FIN_BYE;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 					case L_STATUS:
 						LOG(L_ERR, "ERROR: parse_first_line: non-number "
 								"character <%c> in request status\n", *tmp);
 						goto error;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 						state=VER3;
 						break;
 					case L_VER:
 					case VER1:
 					case VER2:
 					case VER3:
 					case VER4:
 					case VER5:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 				break;
 
 			case 'a':
 			case 'A':
 				switch(state){
 					case START:
 						state=ACK1;
 						fl->u.request.method.s=tmp;
 						break;
 					case CANCEL1:
 						state=CANCEL2;
 						break;
 					case BYE2:
 						state=FIN_BYE;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 					case L_STATUS:
 						LOG(L_ERR, "ERROR: parse_first_line: non-number "
 								"character <%c> in request status\n", *tmp);
 						goto error;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 						state=VER3;
 						break;
 					case L_VER:
 					case VER1:
 					case VER2:
 					case VER3:
 					case VER4:
 					case VER5:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 				break;
 
 			case 'c':
 			case 'C':
 				switch(state){
 					case START:
 						state=CANCEL1;
 						fl->u.request.method.s=tmp;
 						break;
 					case CANCEL3:
 						state=CANCEL4;
 						break;
 					case ACK1:
 						state=ACK2;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 					case L_STATUS:
 						LOG(L_ERR, "ERROR: parse_first_line: non-number "
 								"character <%c> in request status\n", *tmp);
 						goto error;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 						state=VER3;
 						break;
 					case L_VER:
 					case VER1:
 					case VER2:
 					case VER3:
 					case VER4:
 					case VER5:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 				break;
 
 			case 'k':
 			case 'K':
 				switch(state){
 					case START:
 						state=P_METHOD;
 						fl->u.request.method.s=tmp;
 						break;
 					case ACK2:
 						state=FIN_ACK;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 					case L_STATUS:
 						LOG(L_ERR, "ERROR: parse_first_line: non-number "
 								"character <%c> in request status\n", *tmp);
 						goto error;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 						state=VER3;
 						break;
 					case L_VER:
 					case VER1:
 					case VER2:
 					case VER3:
 					case VER4:
 					case VER5:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 				break;
 
 			case 'l':
 			case 'L':
 				switch(state){
 					case START:
 						state=P_METHOD;
 						fl->u.request.method.s=tmp;
 						break;
 					case CANCEL5:
 						state=FIN_CANCEL;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 					case L_STATUS:
 						LOG(L_ERR, "ERROR: parse_first_line: non-number "
 								"character <%c> in request status\n", *tmp);
 						goto error;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 						state=VER3;
 						break;
 					case L_VER:
 					case VER1:
 					case VER2:
 					case VER3:
 					case VER4:
 					case VER5:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 				break;
 
 			case 'b':
 			case 'B':
 				switch(state){
 					case START:
 						state=BYE1;
 						fl->u.request.method.s=tmp;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 					case L_STATUS:
 						LOG(L_ERR, "ERROR: parse_first_line: non-number "
 								"character <%c> in request status\n", *tmp);
 						goto error;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 						state=VER3;
 						break;
 					case L_VER:
 					case VER1:
 					case VER2:
 					case VER3:
 					case VER4:
 					case VER5:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 				break;
 
 			case 'y':
 			case 'Y':
 				switch(state){
 					case START:
 						state=P_METHOD;
 						fl->u.request.method.s=tmp;
 						break;
 					case BYE1:
 						state=BYE2;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 					case L_STATUS:
 						LOG(L_ERR, "ERROR: parse_first_line: non-number "
 								"character <%c> in request status\n", *tmp);
 						goto error;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 						state=VER3;
 						break;
 					case L_VER:
 					case VER1:
 					case VER2:
 					case VER3:
 					case VER4:
 					case VER5:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 				break;
 
 			case '\r':
 				switch(state){
 					case P_REASON:
 						*tmp=0;
 						fl->u.reply.reason.len=tmp-fl->u.reply.reason.s;
 						state=F_CR;
 						break;
 					case L_LF:
 						state=F_CR;
 						break;
 					case FIN_VER:
 						*tmp=0;
 						fl->u.request.version.len=tmp-fl->u.request.version.s;
 						state=F_CR;
 						break;
 					case L_REASON:
 						state=F_CR;
 						break;
 					default:
b2dec9c6
 						LOG(L_ERR, "ERROR: parse_first_line: invalid" 
 								"message\n");
b6f4c1df
 						goto error;
 				}
 				break;
 
 			case '\n':
 				switch(state){
 					case P_REASON:
 						*tmp=0;
 						fl->u.reply.reason.len=tmp-fl->u.reply.reason.s;
 						state=F_LF;
 						goto skip;
 					case FIN_VER:
 						*tmp=0;
 						fl->u.request.version.len=tmp-fl->u.request.version.s;
 						state=F_LF;
 						goto skip;
 					case L_REASON:
 					case L_LF:
 					case F_CR:
 						state=F_LF;
 						goto skip;
 					default:
b2dec9c6
 						LOG(L_ERR, "ERROR: parse_first_line: invalid"
 								" message\n");
b6f4c1df
 						goto error;
 				}
 				break;
 
 			case '1':
 			case '3':
 			case '4':
 			case '5':
 			case '6':
 			case '7':
 			case '8':
 			case '9':
 				switch(state){
 					case START:
 						state=P_METHOD;
 						fl->u.request.method.s=tmp;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 						stat=stat*10+*tmp-'0';
 						break;
 					case L_STATUS:
 						stat=*tmp-'0';
 						state=P_STATUS;
 						fl->u.reply.status.s=tmp;
 						break;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 						state=VER3;
 						break;
 					case L_VER:
 					case VER1:
 					case VER2:
 					case VER3:
 					case VER4:
 					case VER5:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 						
 			default:
 				switch(state){
 					case START:
 						state=P_METHOD;
 						fl->u.request.method.s=tmp;
 						break;
 					case P_URI:
 					case P_REASON:
 					case P_METHOD:
 						break;
 					case L_REASON:
 						fl->u.reply.reason.s=tmp;
 						state=P_REASON;
 						break;
 					case P_STATUS:
 					case L_STATUS:
 						LOG(L_ERR, "ERROR: parse_first_line: non-number "
 								"character <%c> in request status\n", *tmp);
 						goto error;
 					case L_LF:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid "
 								"character <%c> in request\n", *tmp);
 						goto error;
 					case L_URI:
 						fl->u.request.uri.s=tmp;
 						state=P_URI;
 						break;
 						state=VER3;
 						break;
 					case L_VER:
 					case VER1:
 					case VER2:
 					case VER3:
 					case VER4:
 					case VER5:
 					case VER6:
 					case FIN_VER:
 						LOG(L_ERR, "ERROR: parse_first_line: invalid version "
 								" in request\n");
 						goto error;
 					default:
 						state=P_METHOD;
 				}
 		}
 	}
 skip:
 	if (fl->type==SIP_REPLY){
 		fl->u.reply.statuscode=stat;
dda9dab1
 		/* fl->u.reply.statusclass=stat/100; */
b6f4c1df
 	}
 	return tmp;
 	
 error:
 	LOG(L_ERR, "ERROR: while parsing first line (state=%d)\n", state);
 	fl->type=SIP_INVALID;
 	return tmp;
 }