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