|
@@ -0,0 +1,1134 @@
|
|
|
|
|
+/*
|
|
|
|
|
+ * $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:
|
|
|
|
|
+ LOG(L_ERR, "ERROR: parse_first_line: invalid
|
|
|
|
|
+ message\n");
|
|
|
|
|
+ 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:
|
|
|
|
|
+ LOG(L_ERR, "ERROR: parse_first_line: invalid
|
|
|
|
|
+ message\n");
|
|
|
|
|
+ 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;
|
|
|
|
|
+ fl->u.reply.statusclass=stat/100;
|
|
|
|
|
+ }
|
|
|
|
|
+ return tmp;
|
|
|
|
|
+
|
|
|
|
|
+error:
|
|
|
|
|
+ LOG(L_ERR, "ERROR: while parsing first line (state=%d)\n", state);
|
|
|
|
|
+ fl->type=SIP_INVALID;
|
|
|
|
|
+ return tmp;
|
|
|
|
|
+}
|