1 #include <string.h>
2 #include <assert.h>
3
4 #include "log.h"
5 #include <AmSipHeaders.h>
6 #include "parse_common.h"
7 #include "parse_extensions.h"
8
9 /**
10 * some header's body = [option-tag *(COMMA option-tag)
11 * token = 1*(alphanum / "-" / "." / "!" / "%" / "*"
12 * / "_" / "+" / "`" / "'" / "~" )
13 */
14
parse_extension(const char * begin,int len)15 int parse_extension(const char *begin, int len)
16 {
17 // simple, for now: only one extension to parse here
18 if (len == SIP_HDR_LEN(SIP_EXT_100REL) &&
19 memcmp(begin, SIP_EXT_100REL, len) == 0)
20 return SIP_EXTENSION_100REL;
21 return 0;
22 }
23
parse_extensions(unsigned * extensions,const char * start,int len)24 bool parse_extensions(unsigned *extensions, const char *start, int len)
25 {
26 const char *begin;
27 const char *pos;
28 int ext;
29 unsigned mask = 0;
30
31 enum {
32 EAT_WS,
33 OVER_TAG,
34 } state = EAT_WS;
35
36 begin = 0; //g++ happy
37
38 for (pos = start; pos < start + len; pos ++) {
39 switch (*pos) {
40 case ' ':
41 case '\t':
42 case ',':
43 case CR:
44 case LF:
45 if (state == OVER_TAG) {
46 assert(begin);
47 if ((ext = parse_extension(begin, pos - begin)))
48 mask |= ext;
49 // reset stuff
50 state = EAT_WS;
51 begin = 0;
52 }
53 break;
54
55 default:
56 if (! IS_TOKEN(*pos)) {
57 INFO("invalid extensions header content <%.*s>: illegal char `%c'",
58 len, start, *pos);
59 return false;
60 }
61 if (state == EAT_WS) {
62 state = OVER_TAG;
63 begin = pos;
64 }
65 }
66 }
67
68 if (begin) {
69 if ((ext = parse_extension(begin, pos - begin)))
70 mask |= ext;
71 }
72
73 *extensions = mask;
74 DBG("mask of parsed extensions: 0x%x.\n", mask);
75 return true;
76 }
77