소스 검색

- update TODO
- added test files for the new automaton based parsing
(work in progress)

Andrei Pelinescu-Onciul 24 년 전
부모
커밋
2e325b99bd
3개의 변경된 파일832개의 추가작업 그리고 0개의 파일을 삭제
  1. 1 0
      TODO
  2. 418 0
      test/auto.c
  3. 413 0
      test/via_parse.c

+ 1 - 0
TODO

@@ -5,6 +5,7 @@ $Id$
 - better Via parsing (handle ' ' in uri, eg: foo.bar : 1234 ; received=) and
  ipv6 addresses ([fec0:aa::01]).
 - fix format string vulnerability in log()
+- fix alignement access problems (warning on Sun)
 
 High priority:
 x if () {} else {}

+ 418 - 0
test/auto.c

@@ -0,0 +1,418 @@
+
+/* test program -> switch speed */
+
+
+/* parsing:           compact form:
+ * Via:               v:
+ * From:              f:
+ * To:                t:
+ * Cseq:              n/a
+ * Call-ID:           i:
+ * Contact:           m:
+ * Max-Forwards:      n/a
+ * Route:             n/a
+ */
+
+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,
+	};
+
+#include <stdio.h>
+
+int main(int argc, char** argv)
+{
+
+	char* t;
+	register int state;
+	int i;
+	int err;
+	err=0;
+
+	state=INITIAL;
+	printf(" %s (%d)\n", argv[0], argc);
+	if (argc<2){
+			fprintf(stderr, " no parameters\n");
+			exit(-1);
+	}
+	
+	for (i=0;i<10000000;i++){
+		
+	for(t=argv[1];*t;t++){
+		switch(*t){
+			case 'V':
+			case 'v':
+					switch(state){
+						case INITIAL:
+							state=VIA1;
+							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;
+							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;
+								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;
+							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;
+								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;
+								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;
+								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*/
+							case F_FROM:
+							case FROM1: /*compact form*/
+							case F_TO:
+							case TO1: /*compact form*/
+							case F_CSEQ:
+							case F_CALLID:
+							case I_START: /*compact form*/
+							case F_CONTACT:
+							case M_START: /*compact form*/
+							case F_MAXFORWARDS:
+							case F_ROUTE:
+							//	printf("found header, state=%d\n", state);
+								state=INITIAL; /* reset to test*/
+								break;
+							case UNKNOWN_HEADER:
+							default:
+								/*printf("found unkown header, state=%d\n", 
+											state);*/
+								err=1;
+								state=INITIAL;
+						}
+						break;
+			default:
+					/*fprintf(stderr, "Unexpected char <%c> encountered"
+										" state=%d\n", *t, state);
+						exit(-1);*/
+					state=UNKNOWN_HEADER;
+		}
+	}
+
+	} //for i
+	if (err) printf("Error unknown header\n");
+	printf("final state=%d\n", state);
+
+	exit(0);
+
+}
+

+ 413 - 0
test/via_parse.c

@@ -0,0 +1,413 @@
+
+/* test program -> via parse */
+
+
+/* parsing:           compact form:
+ */
+
+/* 
+ * still TODO/test:
+ *  - parse next via
+ *  - return a list of header structs
+ *  - '[' ']' ipv6 parsing!
+ *  - return list of params
+ *  - test ^\s...'
+ *  - add support for parsing via front (SIP/2.0/UDP)
+ */
+
+#include <stdio.h>
+
+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_CRLF,
+				 F_LF
+	};
+
+#define LOG(lev, fmt, args...) fprintf(stderr, fmt, ## args)
+
+int main(int argc, char** argv)
+{
+
+	char* tmp;
+	register int state;
+	int saved_state;
+	int c_nest;
+	int i;
+	int port;
+	char* host;
+	char* port_str;
+	char* param;
+	char* comment;
+	char* next_via;
+
+	host=port_str=param=comment=next_via=0;
+
+	printf(" %s (%d)\n", argv[0], argc);
+	if (argc<2){
+			fprintf(stderr, " no parameters\n");
+			exit(-1);
+	}
+	
+	
+	c_nest=0;
+	state=F_HOST;
+	for(tmp=argv[1];*tmp;tmp++){
+		switch(*tmp){
+			case ' ':
+				switch(state){
+					case F_HOST:/*eat the spaces*/
+						break;
+					case P_HOST:
+						 *tmp=0;/*mark end of host*/
+						 state=L_PORT;
+						 break;
+					case L_PORT: /*eat the spaces*/
+					case F_PORT:
+						break;
+					case P_PORT:
+						*tmp=0; /*end of port */
+						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_CRLF:
+					case F_LF:
+						/*previous=crlf and now =' '*/
+						state=saved_state;
+						break;
+					default:
+						LOG(L_CRIT,"BUG: parse_via"
+							" on <%c>\n",*tmp);
+						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:
+						saved_state=state;
+						state=F_LF;
+						break;
+					case P_HOST:
+						 *tmp=0;/*mark end of host*/
+						 saved_state=L_PORT;
+						 state=F_LF;
+						 break;
+					case P_PORT:
+						*tmp=0; /*end of port */
+						saved_state=L_PARAM;
+						state=F_LF;
+						break;
+					case P_PARAM:
+					/*	*tmp=0;*/ /*!?end of param*/
+						saved_state=L_PARAM;
+						state=F_LF;
+						break;
+					default:
+						LOG(L_CRIT,"BUG: parse_via"
+							" on <%c>\n",*tmp);
+						goto  error;
+				}
+			break;
+			case ':':
+				switch(state){
+					case F_HOST:
+						LOG(L_ERR,"ERROR:parse_via:"
+							" no host found\n");
+						goto error;
+					case P_HOST:
+						*tmp=0; /*mark  end of host*/
+						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:
+					case F_COMMENT:
+					case P_COMMENT:
+						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:
+						/*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:
+						LOG(L_ERR,"ERROR:parse_via:"
+							" no host found\n");
+						goto error;
+					case P_HOST:
+					case P_PORT:
+						*tmp=0; /*mark the end*/
+					case L_PORT:
+					case L_PARAM:
+						state=F_PARAM;
+						break;
+					case F_PORT:
+					case F_COMMENT:
+					case P_COMMENT:
+						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:
+						/*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:
+						LOG(L_ERR,"ERROR:parse_via:"
+							" no host found\n");
+						goto error;
+					case P_HOST:
+					case P_PORT:
+						*tmp=0; /*mark the end*/
+					case L_PORT:
+					case L_PARAM:
+					case P_PARAM:
+					case L_VIA:
+						state=F_VIA;
+						break;
+					case F_PORT:
+					case F_PARAM:
+					case F_COMMENT:
+					case P_COMMENT:
+						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:
+						/*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:
+					case F_PORT:
+					case F_PARAM:
+					case F_VIA:
+						LOG(_ERR,"ERROR:parse_via"
+							" on <%c> state %d\n",
+							*tmp, state);
+						goto  error;
+					case P_HOST:
+					case P_PORT:
+					case P_PARAM:
+						*tmp=0; /*mark the end*/
+					case L_PORT:
+					case L_PARAM:
+					case L_VIA:
+						state=F_COMMENT;
+						c_nest++;
+						printf("found '(', state=%d, c_nest=%d\n",
+								state, c_nest);
+						*tmp=0;
+						break;
+					case P_COMMENT:
+					case F_COMMENT:
+						c_nest++;
+						break;
+					case F_CRLF:
+					case F_LF:
+						/*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;
+								printf("out of comment\n");
+								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:
+						LOG(L_ERR,"ERROR:parse_via"
+							" on <%c> state %d\n",
+							*tmp, state);
+						goto  error;
+					case F_CRLF:
+					case F_LF:
+						/*previous=crlf and now !=' '*/
+						goto endofheader;
+					default:
+						LOG(L_CRIT,"BUG: parse_via"
+							" on <%c> state %d\n",
+							*tmp, state);
+						goto  error;
+				}
+				break;
+			default:
+				switch(state){
+					case F_HOST:
+						state=P_HOST;
+						host=tmp;
+						break;
+					case P_HOST:
+						break;
+					case F_PORT:
+						state=P_PORT;
+						port_str=tmp;
+						break;
+					case P_PORT:
+						/*check if number?*/
+						break;
+					case F_PARAM:
+						state=P_PARAM;
+						param=tmp;
+						break;
+					case P_PARAM:
+						break;
+					case F_VIA:
+						next_via=tmp;
+						printf("found new via on <%c>\n", *tmp);
+						goto skip;
+					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:
+						printf("starting comment parsing on %c \n",*tmp);
+						state=P_COMMENT;
+						comment=tmp;
+						break;
+					case P_COMMENT:
+						break;
+					case F_CRLF:
+					case F_LF:
+						/*previous=crlf and now !=' '*/
+						goto endofheader;
+					default:
+						LOG(L_ERR, "BUG:parse_via:"
+							" invalid char <%c>"
+							" in state %d\n",
+							*tmp, state);
+						goto error;
+				}
+				
+					
+		}			
+	}
+goto endofheader;
+error:
+	fprintf(stderr, "error\n");
+	
+skip:
+	printf("skipping\n");
+endofheader:
+	printf("end of header reached, state=%d\n", state);
+	if (host) printf("host=%s\n", host);
+	if (port) 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);
+	printf("rest=<%s>\n", tmp);
+	
+	exit(0);
+}
+