4f95ea0ffef33275c3e7a1ae80efa1241a0fa350
[sip-router] / parser / digest / param_parser.c
1 /*
2  * $Id$
3  *
4  * 32-bit Digest parameter name parser
5  */
6
7
8 #include "param_parser.h"
9 #include "digest_keys.h"
10 #include "../../trim.h"
11 #include "../../ut.h"
12
13 /*
14  * Precalculated hash table size
15  * WARNING: The size MUST be recalculated
16  *          again if new parameter names
17  *          should be parsed
18  */
19 #define HASH_TABLE_SIZE 859
20
21
22 /*
23  * Hash function
24  */
25 #define HASH_FUNC(val) ((val) % HASH_TABLE_SIZE)
26
27
28 /*
29  * This constant marks an empty hash table element
30  */
31 #define HASH_EMPTY 0x2d2d2d2d
32
33
34 /*
35  * Hash table entry
36  */
37 struct ht_entry {
38         unsigned int key;
39         unsigned int value;
40 };
41
42
43 static struct ht_entry hash_table[HASH_TABLE_SIZE];
44
45
46 /*
47  * Pointer to the hash table
48  */
49 /*
50 static struct ht_entry *hash_table;
51 */
52
53
54 /*
55  * Declarations
56  */
57 static void set_entry (unsigned int key, unsigned int val);
58 static inline int unify (int key);
59
60
61
62 /*
63  * Used to initialize hash table
64  */
65 static void set_entry(unsigned int key, unsigned int val)
66 {
67         hash_table[HASH_FUNC(key)].key = key;
68         hash_table[HASH_FUNC(key)].value = val;
69 }
70
71
72 static inline int unify(int key)
73 {
74         register struct ht_entry* en;
75
76         en = &hash_table[HASH_FUNC(key)];
77         if (en->key == key) {
78                 return en->value;
79         } else {
80                 return key;
81         }
82 }
83
84
85 /*
86  * Parse short (less than 4 bytes) parameter names
87  */
88 #define PARSE_SHORT                                                   \
89         switch(*p) {                                                  \
90         case 'u':                                                     \
91         case 'U':                                                     \
92                 if ((*(p + 1) == 'r') || (*(p + 1) == 'R')) {         \
93                         if ((*(p + 2) == 'i') || (*(p + 2) == 'I')) { \
94                                 *_type = PAR_URI;                     \
95                                 p += 3;                               \
96                                 goto end;                             \
97                         }                                             \
98                 }                                                     \
99                 break;                                                \
100                                                                       \
101         case 'q':                                                     \
102         case 'Q':                                                     \
103                 if ((*(p + 1) == 'o') || (*(p + 1) == 'O')) {         \
104                         if ((*(p + 2) == 'p') || (*(p + 2) == 'P')) { \
105                                 *_type = PAR_QOP;                     \
106                                 p += 3;                               \
107                                 goto end;                             \
108                         }                                             \
109                 }                                                     \
110                 break;                                                \
111                                                                       \
112         case 'n':                                                     \
113         case 'N':                                                     \
114                 if ((*(p + 1) == 'c') || (*(p + 1) == 'C')) {         \
115                         *_type = PAR_NC;                              \
116                         p += 2;                                       \
117                         goto end;                                     \
118                 }                                                     \
119                 break;                                                \
120         }
121
122
123 /*
124  * Read 4-bytes from memory and store them in an integer variable
125  * Reading byte by byte ensures, that the code works also on HW which
126  * does not allow reading 4-bytes at once from unaligned memory position
127  * (Sparc for example)
128  */
129 #define READ(val) \
130 (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
131
132
133 #define name_CASE                      \
134         switch(val) {                  \
135         case _name_:                   \
136                 *_type = PAR_USERNAME; \
137                 p += 4;                \
138                 goto end;              \
139         }
140
141
142 #define user_CASE         \
143         p += 4;           \
144         val = READ(p);    \
145         name_CASE;        \
146                           \
147         val = unify(val); \
148         name_CASE;        \
149         goto other;
150
151
152 #define real_CASE                         \
153         p += 4;                           \
154         if ((*p == 'm') || (*p == 'M')) { \
155                 *_type = PAR_REALM;       \
156                 p++;                      \
157                 goto end;                 \
158         }
159
160
161 #define nonc_CASE                         \
162         p += 4;                           \
163         if ((*p == 'e') || (*p == 'E')) { \
164                 *_type = PAR_NONCE;       \
165                 p++;                      \
166                 goto end;                 \
167         }
168
169
170 #define onse_CASE                      \
171         switch(val) {                  \
172         case _onse_:                   \
173                 *_type = PAR_RESPONSE; \
174                 p += 4;                \
175                 goto end;              \
176         }
177
178
179 #define resp_CASE         \
180         p += 4;           \
181         val = READ(p);    \
182         onse_CASE;        \
183                           \
184         val = unify(val); \
185         onse_CASE;        \
186         goto other;
187
188
189 #define cnon_CASE                                 \
190         p += 4;                                   \
191         if ((*p == 'c') || (*p == 'C')) {         \
192                 p++;                              \
193                 if ((*p == 'e') || (*p == 'E')) { \
194                         *_type = PAR_CNONCE;      \
195                         p++;                      \
196                         goto end;                 \
197                 }                                 \
198         }                                         \
199         goto other;
200
201
202 #define opaq_CASE                                 \
203         p += 4;                                   \
204         if ((*p == 'u') || (*p == 'U')) {         \
205                 p++;                              \
206                 if ((*p == 'e') || (*p == 'E')) { \
207                         *_type = PAR_OPAQUE;      \
208                         p++;                      \
209                         goto end;                 \
210                 }                                 \
211         }                                         \
212         goto other;
213
214
215 #define rith_CASE                                 \
216         switch(val) {                             \
217         case _rith_:                              \
218                 p += 4;                           \
219                 if ((*p == 'm') || (*p == 'M')) { \
220                         *_type = PAR_ALGORITHM;   \
221                         p++;                      \
222                         goto end;                 \
223                 }                                 \
224                 goto other;                       \
225         }
226
227
228 #define algo_CASE         \
229         p += 4;           \
230         val = READ(p);    \
231         rith_CASE;        \
232                           \
233         val = unify(val); \
234         rith_CASE;        \
235         goto other;
236
237
238 #define FIRST_QUATERNIONS       \
239         case _user_: user_CASE; \
240         case _real_: real_CASE; \
241         case _nonc_: nonc_CASE; \
242         case _resp_: resp_CASE; \
243         case _cnon_: cnon_CASE; \
244         case _opaq_: opaq_CASE; \
245         case _algo_: algo_CASE;
246
247
248
249
250 int parse_param_name(str* _s, dig_par_t* _type)
251 {
252         register char* p;
253         register int val;
254         char* end;
255
256         end = _s->s + _s->len;
257
258         p = _s->s;
259         val = READ(p);
260
261         if (_s->len < 4) {
262                 goto other;
263         }
264
265         switch(val) {
266         FIRST_QUATERNIONS;
267         default:
268                 PARSE_SHORT;
269
270                 val = unify(val);
271                 switch(val) {
272                 FIRST_QUATERNIONS;
273                 default: goto other;
274                 }
275         }
276
277  end:
278         _s->len -= p - _s->s;
279         _s->s = p;
280
281         trim_leading(_s);
282         if (_s->s[0] == '=') {
283                 return 0;
284         }
285         
286  other:
287         p = q_memchr(p, '=', end - p);
288         if (!p) {
289                 return -1; /* Parse error */
290         } else {
291                 *_type = PAR_OTHER;
292                 _s->len -= p - _s->s;
293                 _s->s = p;
294                 return 0;
295         }
296 }
297
298
299 /* Number of distinct keys */
300 #define NUM_KEYS  160
301
302 /* Number of distinct values */
303 #define NUM_VALS 10
304
305
306 /*
307  * Create synonym-less (precalculated) hash table
308  */
309 void init_digest_htable(void)
310 {
311         int i, j, k;
312
313         unsigned int init_val[NUM_VALS] = {
314                 _user_, _name_, _real_, _nonc_,
315                 _resp_, _onse_, _cnon_, _opaq_,
316                 _algo_, _rith_
317         };
318
319         unsigned int key_nums[NUM_VALS] = {
320                 16, 16, 16, 16, 16,
321                 16, 16, 16, 16, 16
322         };
323         
324         unsigned int init_key[NUM_KEYS] = {
325                 _user_, _useR_, _usEr_, _usER_, _uSer_, _uSeR_, _uSEr_, _uSER_, 
326                 _User_, _UseR_, _UsEr_, _UsER_, _USer_, _USeR_, _USEr_, _USER_, 
327                 _name_, _namE_, _naMe_, _naME_, _nAme_, _nAmE_, _nAMe_, _nAME_, 
328                 _Name_, _NamE_, _NaMe_, _NaME_, _NAme_, _NAmE_, _NAMe_, _NAME_, 
329                 _real_, _reaL_, _reAl_, _reAL_, _rEal_, _rEaL_, _rEAl_, _rEAL_, 
330                 _Real_, _ReaL_, _ReAl_, _ReAL_, _REal_, _REaL_, _REAl_, _REAL_, 
331                 _nonc_, _nonC_, _noNc_, _noNC_, _nOnc_, _nOnC_, _nONc_, _nONC_, 
332                 _Nonc_, _NonC_, _NoNc_, _NoNC_, _NOnc_, _NOnC_, _NONc_, _NONC_, 
333                 _resp_, _resP_, _reSp_, _reSP_, _rEsp_, _rEsP_, _rESp_, _rESP_, 
334                 _Resp_, _ResP_, _ReSp_, _ReSP_, _REsp_, _REsP_, _RESp_, _RESP_, 
335                 _onse_, _onsE_, _onSe_, _onSE_, _oNse_, _oNsE_, _oNSe_, _oNSE_, 
336                 _Onse_, _OnsE_, _OnSe_, _OnSE_, _ONse_, _ONsE_, _ONSe_, _ONSE_, 
337                 _cnon_, _cnoN_, _cnOn_, _cnON_, _cNon_, _cNoN_, _cNOn_, _cNON_, 
338                 _Cnon_, _CnoN_, _CnOn_, _CnON_, _CNon_, _CNoN_, _CNOn_, _CNON_, 
339                 _opaq_, _opaQ_, _opAq_, _opAQ_, _oPaq_, _oPaQ_, _oPAq_, _oPAQ_, 
340                 _Opaq_, _OpaQ_, _OpAq_, _OpAQ_, _OPaq_, _OPaQ_, _OPAq_, _OPAQ_, 
341                 _algo_, _algO_, _alGo_, _alGO_, _aLgo_, _aLgO_, _aLGo_, _aLGO_, 
342                 _Algo_, _AlgO_, _AlGo_, _AlGO_, _ALgo_, _ALgO_, _ALGo_, _ALGO_, 
343                 _rith_, _ritH_, _riTh_, _riTH_, _rIth_, _rItH_, _rITh_, _rITH_, 
344                 _Rith_, _RitH_, _RiTh_, _RiTH_, _RIth_, _RItH_, _RITh_, _RITH_
345         };
346
347
348              /* Mark all elements as empty */
349         for(i = 0; i < HASH_TABLE_SIZE; i++) {
350                 set_entry(HASH_EMPTY, HASH_EMPTY);
351         }
352
353         k = 0;
354
355              /* Initialize hash table content */
356         for(i = 0; i < NUM_VALS; i++) {
357                 for(j = 0; j < key_nums[i]; j++) {
358                         set_entry(init_key[k++], init_val[i]);
359                 }
360         }
361 }