You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kamailio/modules/tm/lw_parser.c

282 lines
5.3 KiB

/*
* $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