#include "sip_parser_async.h" #include "parse_common.h" #include "log.h" #include "AmUtils.h" #include #include using std::string; static int skip_line_async(parser_state* pst, char* end) { char*& c = pst->c; int& st = pst->st; int& saved_st = pst->saved_st; for(; (c < end) && *c; c++){ switch(st){ case 0/* START */: switch(*c) { case_CR_LF; default: break; } break; case_ST_CR(*c); case ST_LF: case ST_CRLF: return 0; default: DBG("Bad state! st=%i\n",st); return -99; } } return UNEXPECTED_EOT; } static int parse_header_async(sip_header* hdr, parser_state* pst, char* end) { // // Header states // enum { H_NAME=0, H_HCOLON, H_VALUE_SWS, H_VALUE, }; int& st = pst->st; int& saved_st = pst->saved_st; char** c = &(pst->c); char*& begin = pst->beg; for(;**c && (*c < end);(*c)++){ switch(st){ case H_NAME: switch(**c){ case_CR_LF; case HCOLON: st = H_VALUE_SWS; hdr->name.set(begin,*c-begin); break; case SP: case HTAB: st = H_HCOLON; hdr->name.set(begin,*c-begin); break; } break; case H_VALUE_SWS: switch(**c){ case_CR_LF; case SP: case HTAB: break; default: st = H_VALUE; begin = *c; break; }; break; case H_VALUE: switch(**c){ case_CR_LF; }; break; case H_HCOLON: switch(**c){ case HCOLON: st = H_VALUE_SWS; break; case SP: case HTAB: break; default: DBG("Missing ':' after header name\n"); return MALFORMED_SIP_MSG; } break; case_ST_CR(**c); case ST_LF: case ST_CRLF: switch(saved_st){ case H_NAME: if((*c-(st==ST_CRLF?2:1))-begin == 0){ //DBG("Detected end of headers\n"); return 0; } DBG("Illegal CR or LF in header name: <%.*s>\n", (int)(*c-begin),begin); return MALFORMED_SIP_MSG; case H_VALUE_SWS: if(!IS_WSP(**c)){ DBG("Malformed header: <%.*s>\n",(int)(*c-begin),begin); return MALFORMED_SIP_MSG; } break; case H_VALUE: if(!IS_WSP(**c)){ hdr->value.set(begin,(*c-(st==ST_CRLF?2:1))-begin); //DBG("hdr: \"%.*s: %.*s\"\n", // hdr->name.len,hdr->name.s, // hdr->value.len,hdr->value.s); return 0; } break; default: DBG("Oooops! st=%i\n",saved_st); break; } st = saved_st; break; } } switch(st){ case H_NAME: case H_VALUE: return UNEXPECTED_EOT; case ST_LF: case ST_CRLF: switch(saved_st){ case H_NAME: if((*c-(st==ST_CRLF?2:1))-begin == 0){ //DBG("Detected end of headers\n"); return 0; } DBG("Illegal CR or LF in header name\n"); return MALFORMED_SIP_MSG; } break; } DBG("Incomplete header (st=%i;saved_st=%i)\n",st,saved_st); return UNEXPECTED_EOT; } int parse_headers_async(parser_state* pst, char* end) { char*& c = pst->c; int& st = pst->st; int& saved_st = pst->saved_st; sip_header* hdr = &(pst->hdr); while(c < end) { int err = parse_header_async(hdr, pst, end); if(err) return err; if(hdr->name.len && hdr->value.len) { int type = parse_header_type(hdr); if(type == sip_header::H_CONTENT_LENGTH) str2int(c2stlstr(hdr->value),pst->content_len); } if(!hdr->name.len && !hdr->value.len) { // end-of-headers return 0; } // reset header struct *hdr = {}; st = 0; saved_st = 0; pst->beg = c; } return UNEXPECTED_EOT; } int skip_sip_msg_async(parser_state* pst, char* end) { enum { ST_FL=0, ST_HDRS, ST_BODY }; int err=0; char*& c = pst->c; int& stage = pst->stage; int& st = pst->st; int& saved_st = pst->saved_st; while(c < end) { switch(stage) { case ST_FL: err = skip_line_async(pst,end); break; case ST_HDRS: err = parse_headers_async(pst,end); break; case ST_BODY: if(!pst->content_len) return 0; if(pst->content_len > end-c) return UNEXPECTED_EOT; else return 0; break; default: ERROR("unkown state!!!"); return -1; } if(!err) { switch(stage) { case ST_FL: stage = ST_HDRS; pst->reset_hdr_parser(); break; case ST_HDRS: if(!pst->hdr.name.len && !pst->hdr.value.len) { // End-of-Header found stage = ST_BODY; continue; } else { // End-of-one-Header pst->reset_hdr_parser(); continue; } break; } } else { return err; } } return err; }