Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00029 #include "../../mem/mem.h"
00030 #include "../../parser/keys.h"
00031 #include "parse_supported.h"
00032
00033 #define _100r_ 0x72303031
00034 #define _time_ 0x656d6974
00036 #define IS_DELIM(c) (*(c) == ' ' || *(c) == '\t' || *(c) == '\r' || *(c) == '\n' || *(c) == ',')
00037
00038
00039 #define LOWER_BYTE(b) ((b) | 0x20)
00040 #define LOWER_DWORD(d) ((d) | 0x20202020)
00041 #define READ(val) \
00042 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
00043
00044
00048 static inline int parse_supported_body(str *body, unsigned int *sup)
00049 {
00050 register char* p;
00051 register unsigned int val;
00052 int len, pos = 0;
00053
00054 *sup = 0;
00055
00056 p = body->s;
00057 len = body->len;
00058
00059 while (pos < len) {
00060
00061 for (; pos < len && IS_DELIM(p); ++pos, ++p);
00062
00063 val = LOWER_DWORD(READ(p));
00064 switch (val) {
00065
00066
00067 case _path_:
00068 if(pos + 4 <= len && IS_DELIM(p+4)) {
00069 *sup |= F_SUPPORTED_PATH;
00070 pos += 5; p += 5;
00071 }
00072 break;
00073
00074
00075 case _100r_:
00076 if ( pos+6 <= len
00077 && LOWER_BYTE(*(p+4))=='e' && LOWER_BYTE(*(p+5))=='l'
00078 && IS_DELIM(p+6)) {
00079 *sup |= F_SUPPORTED_100REL;
00080 pos += SUPPORTED_100REL_LEN + 1;
00081 p += SUPPORTED_100REL_LEN + 1;
00082 }
00083 break;
00084
00085
00086 case _time_:
00087 if ( pos+5 <= len && LOWER_BYTE(*(p+4))=='r'
00088 && IS_DELIM(p+5) ) {
00089 *sup |= F_SUPPORTED_TIMER;
00090 pos += SUPPORTED_TIMER_LEN + 1;
00091 p += SUPPORTED_TIMER_LEN + 1;
00092 }
00093 break;
00094
00095
00096 default:
00097 if(pos+SUPPORTED_EVENTLIST_LEN<=len
00098 && strncasecmp(p, SUPPORTED_EVENTLIST_STR,
00099 SUPPORTED_EVENTLIST_LEN)==0
00100 && IS_DELIM(p+SUPPORTED_EVENTLIST_LEN) ) {
00101 *sup |= F_SUPPORTED_EVENTLIST;
00102 pos += SUPPORTED_EVENTLIST_LEN + 1;
00103 p += SUPPORTED_EVENTLIST_LEN + 1;
00104 } else if(pos+SUPPORTED_GRUU_LEN<=len
00105 && strncasecmp(p, SUPPORTED_GRUU_STR,
00106 SUPPORTED_GRUU_LEN)==0
00107 && IS_DELIM(p+SUPPORTED_GRUU_LEN)) {
00108 *sup |= F_SUPPORTED_GRUU;
00109 pos += SUPPORTED_GRUU_LEN + 1;
00110 p += SUPPORTED_GRUU_LEN + 1;
00111 } else if(pos+SUPPORTED_OUTBOUND_LEN<=len
00112 && strncasecmp(p, SUPPORTED_OUTBOUND_STR,
00113 SUPPORTED_OUTBOUND_LEN)==0
00114 && IS_DELIM(p+SUPPORTED_OUTBOUND_LEN)) {
00115 *sup |= F_SUPPORTED_OUTBOUND;
00116 pos += SUPPORTED_OUTBOUND_LEN + 1;
00117 p += SUPPORTED_OUTBOUND_LEN + 1;
00118 } else {
00119
00120 for (; pos < len && !IS_DELIM(p); ++pos, ++p);
00121 }
00122 break;
00123 }
00124 }
00125
00126 return 0;
00127 }
00128
00129
00133 void hf_free_supported(void *parsed)
00134 {
00135 struct supported_body *sb;
00136 sb = (struct supported_body*)parsed;
00137 free_supported(&sb);
00138 }
00139
00143 int parse_supported( struct sip_msg *msg)
00144 {
00145 unsigned int supported;
00146 struct hdr_field *hdr;
00147 struct supported_body *sb;
00148
00149
00150 if (msg->supported && msg->supported->parsed)
00151 return 0;
00152
00153
00154 if (parse_headers(msg,HDR_EOH_F,0)==-1 || !msg->supported)
00155 return -1;
00156
00157
00158 supported = 0;
00159 for( hdr=msg->supported ; hdr ; hdr=next_sibling_hdr(hdr)) {
00160 if (hdr->parsed) {
00161 supported |= ((struct supported_body*)hdr->parsed)->supported;
00162 continue;
00163 }
00164
00165 sb = (struct supported_body*)pkg_malloc(sizeof(struct supported_body));
00166 if (sb == 0) {
00167 LM_ERR("out of pkg_memory\n");
00168 return -1;
00169 }
00170
00171 parse_supported_body(&(hdr->body), &(sb->supported));
00172 sb->hfree = hf_free_supported;
00173 sb->supported_all = 0;
00174 hdr->parsed = (void*)sb;
00175 supported |= sb->supported;
00176 }
00177
00178 ((struct supported_body*)msg->supported->parsed)->supported_all =
00179 supported;
00180 return 0;
00181 }
00182
00183
00184 void free_supported(struct supported_body **sb)
00185 {
00186 if (sb && *sb) {
00187 pkg_free(*sb);
00188 *sb = 0;
00189 }
00190 }