mirror of https://github.com/sipwise/sems.git
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.
123 lines
2.4 KiB
123 lines
2.4 KiB
|
|
#include <limits.h>
|
|
|
|
#include "log.h"
|
|
#include "AmSipHeaders.h"
|
|
#include "sip_parser.h"
|
|
#include "parse_common.h"
|
|
#include "parse_100rel.h"
|
|
|
|
|
|
#define EAT_WS(_c_, _end_) \
|
|
do { \
|
|
while ((_c_) < (_end_) && (*(_c_) == ' ' || *(_c_) == '\t')) \
|
|
(_c_) ++; \
|
|
} while (0)
|
|
|
|
#define READ_NUMBER(_no, _c_, _end_) \
|
|
do { \
|
|
bool fin; \
|
|
(_no) = 0; \
|
|
for (fin = false; !fin && (_c_) < (_end_); ) { \
|
|
switch (*(_c_)) { \
|
|
case '0' ... '9': \
|
|
if (UINT_MAX - (_no) < (unsigned)*(_c_)) { \
|
|
INFO("not an uint32_t.\n"); \
|
|
goto error; \
|
|
} \
|
|
(_no) = (_no) * 10 + *(_c_) - '0'; \
|
|
break; \
|
|
default: \
|
|
fin = true; \
|
|
continue; \
|
|
} \
|
|
(_c_) ++; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define EAT_TOKEN(_c_, _end_) \
|
|
do { \
|
|
while ((_c_) < (_end_) && IS_TOKEN(*(_c_))) \
|
|
(_c_) ++; \
|
|
} while (0)
|
|
|
|
|
|
bool parse_rseq(unsigned *_rseq, const char *start, int len)
|
|
{
|
|
unsigned rseq;
|
|
const char *pos = start;
|
|
const char *end = start + len;
|
|
const char *sav;
|
|
|
|
EAT_WS(pos, end);
|
|
|
|
sav = pos;
|
|
READ_NUMBER(rseq, pos, end);
|
|
if (sav == pos)
|
|
goto error;
|
|
|
|
*_rseq = rseq;
|
|
DBG("parsed sequence content: %u.\n", rseq);
|
|
return true;
|
|
|
|
error:
|
|
INFO("invalid content in sequence header content <%.*s>.\n", len, start);
|
|
return false;
|
|
}
|
|
|
|
|
|
bool parse_rack(sip_rack *rack, const char *start, int len)
|
|
{
|
|
const char *pos;
|
|
const char *sav;
|
|
const char *end = start + len;
|
|
unsigned rseq, cseq;
|
|
cstring method_str;
|
|
cstring cseq_str;
|
|
int method;
|
|
|
|
pos = start;
|
|
|
|
EAT_WS(pos, end);
|
|
|
|
sav = pos;
|
|
READ_NUMBER(rseq, pos, end);
|
|
if (pos == sav)
|
|
goto error;
|
|
|
|
EAT_WS(pos, end);
|
|
|
|
sav = pos;
|
|
READ_NUMBER(cseq, pos, end);
|
|
if (pos == sav)
|
|
goto error;
|
|
cseq_str.s = sav;
|
|
cseq_str.len = pos - sav;
|
|
|
|
EAT_WS(pos, end);
|
|
|
|
sav = pos;
|
|
EAT_TOKEN(pos, end);
|
|
method_str.s = sav;
|
|
method_str.len = pos - sav;
|
|
|
|
if (parse_method(&method, method_str.s, method_str.len))
|
|
goto error;
|
|
|
|
DBG("parsed '" SIP_HDR_RSEQ "' header: %u %u <%.*s> <%.*s>.\n", rseq, cseq,
|
|
cseq_str.len, cseq_str.s, method_str.len, method_str.s);
|
|
|
|
rack->rseq = rseq;
|
|
rack->cseq = cseq;
|
|
rack->cseq_str.s = cseq_str.s;
|
|
rack->cseq_str.len = cseq_str.len;
|
|
rack->method = method;
|
|
rack->method_str.s = method_str.s;
|
|
rack->method_str.len = method_str.len;
|
|
return true;
|
|
|
|
error:
|
|
INFO("failed to parse <%.*s> as '" SIP_HDR_RSEQ "' header.\n", len, start);
|
|
return false;
|
|
}
|