/* * $Id$ * * Copyright (C) 2007 iptelorg GmbH * * This file is part of ser, a free SIP server. * * ser is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * For a license to use the ser software under conditions * other than those described here, or to purchase support for this * software, please contact iptel.org by e-mail at the following addresses: * info@iptel.org * * ser is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * 2007-05-28 lightweight parser implemented for build_local_reparse() * function. Basically copy-pasted from the core parser (Miklos) */ #include "../../parser/keys.h" #include "../../parser/hf.h" #include "../../parser/parser_f.h" #include "lw_parser.h" /* macros from the core parser */ #define LOWER_BYTE(b) ((b) | 0x20) #define LOWER_DWORD(d) ((d) | 0x20202020) #define READ(val) \ (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24)) /* * lightweight header field name parser * used by build_local_reparse() function in order to construct ACK or CANCEL request * from the INVITE buffer * this parser supports only the header fields which are needed by build_local_reparse() */ char *lw_get_hf_name(char *begin, char *end, enum _hdr_types_t *type) { char *p; unsigned int val; if (end - begin < 4) { *type = HDR_ERROR_T; return begin; } p = begin; val = LOWER_DWORD(READ(p)); switch(val) { case _cseq_: /* Cseq */ *type = HDR_CSEQ_T; p += 4; break; case _via1_: /* Via */ case _via2_: *type = HDR_VIA_T; p += 3; break; case _from_: /* From */ *type = HDR_FROM_T; p += 4; break; case _to12_: /* To */ *type = HDR_TO_T; p += 2; break; case _requ_: /* Require */ p += 4; val = LOWER_DWORD(READ(p)); switch(val) { case _ire1_: case _ire2_: p += 3; *type = HDR_REQUIRE_T; break; default: p -= 4; *type = HDR_OTHER_T; break; } break; case _prox_: /* Proxy-Require */ if ((LOWER_DWORD(READ(p+4)) == _y_re_) && (LOWER_DWORD(READ(p+8)) == _quir_) && (LOWER_BYTE(*(p+12)) == 'e')) { p += 13; *type = HDR_PROXYREQUIRE_T; break; } else { *type = HDR_OTHER_T; break; } case _cont_: /* Content-Length */ if ((LOWER_DWORD(READ(p+4)) == _ent__) && (LOWER_DWORD(READ(p+8)) == _leng_) && (LOWER_BYTE(*(p+12)) == 't') && (LOWER_BYTE(*(p+13)) == 'h')) { p += 14; *type = HDR_CONTENTLENGTH_T; break; } else { *type = HDR_OTHER_T; break; } case _call_: /* Call-Id */ p += 4; val = LOWER_DWORD(READ(p)); switch(val) { case __id1_: case __id2_: p += 3; *type = HDR_CALLID_T; break; default: p -= 4; *type = HDR_OTHER_T; break; } break; case _rout_: /* Route */ if (LOWER_BYTE(*(p+4)) == 'e') { p += 5; *type = HDR_ROUTE_T; break; } else { *type = HDR_OTHER_T; break; } case _max__: /* Max-Forwards */ if ((LOWER_DWORD(READ(p+4)) == _forw_) && (LOWER_DWORD(READ(p+8)) == _ards_)) { p += 12; *type = HDR_MAXFORWARDS_T; break; } else { *type = HDR_OTHER_T; break; } default: /* compact headers */ switch(LOWER_BYTE(*p)) { case 'v': /* Via */ if ((*(p+1) == ' ') || (*(p+1) == ':')) { p++; *type = HDR_VIA_T; break; } *type = HDR_OTHER_T; break; case 'f': /* From */ if ((*(p+1) == ' ') || (*(p+1) == ':')) { p++; *type = HDR_FROM_T; break; } *type = HDR_OTHER_T; break; case 't': /* To */ if (LOWER_BYTE(*(p+1)) == 'o') { p += 2; *type = HDR_TO_T; break; } if ((*(p+1) == ' ') || (*(p+1) == ':')) { p++; *type = HDR_TO_T; break; } *type = HDR_OTHER_T; break; case 'l': /* Content-Length */ if ((*(p+1) == ' ') || (*(p+1) == ':')) { p++; *type = HDR_CONTENTLENGTH_T; break; } *type = HDR_OTHER_T; break; case 'i': /* Call-Id */ if ((*(p+1) == ' ') || (*(p+1) == ':')) { p++; *type = HDR_CALLID_T; break; } *type = HDR_OTHER_T; break; default: *type = HDR_OTHER_T; break; } } return p; } /* returns a pointer to the next line */ char *lw_next_line(char *buf, char *buf_end) { char *c; c = buf; do { while ((c < buf_end) && (*c != '\n')) c++; if (c < buf_end) c++; } while ((c < buf_end) && ((*c == ' ') || (*c == '\t'))); /* next line begins with whitespace line folding */ return c; } #ifdef USE_DNS_FAILOVER /* returns the pointer to the first VIA header */ char *lw_find_via(char *buf, char *buf_end) { char *p; unsigned int val; /* skip the first line */ p = eat_line(buf, buf_end - buf); while (buf_end - p > 4) { val = LOWER_DWORD(READ(p)); if ((val == _via1_) || (val == _via2_) || ((LOWER_BYTE(*p) == 'v') /* compact header */ && ((*(p+1) == ' ') || (*(p+1) == ':')) ) ) return p; p = lw_next_line(p, buf_end); } /* not found */ return 0; } #endif