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