- Spelling checked
[sip-router] / ut.h
1 /*
2  *$Id$
3  *
4  * - various general purpose functions
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  * History
30  * ------
31  * 2003-01-18 un_escape function introduced for convenience of code needing
32  *            the complex&slow feature of unescaping
33  * 2003-01-28 scratchpad removed (jiri)
34  * 2003-01-29 pathmax added (jiri)
35  * 2003-02-13 strlower added (janakj)
36  * 2003-02-28 scratchpad compatibility abandoned (jiri)
37  * 2003-03-30 str2int and str2float added (janakj)
38  * 2003-04-26 ZSW (jiri)
39  * 2004-03-08 updated int2str (64 bits, INT2STR_MAX_LEN used) (andrei)
40  */
41
42
43 #ifndef ut_h
44 #define ut_h
45
46 #include "comp_defs.h"
47
48 #include <sys/types.h>
49 #include <sys/time.h>
50 #include <limits.h>
51 #include <unistd.h>
52 #include <ctype.h>
53
54 #include "config.h"
55 #include "dprint.h"
56 #include "str.h"
57
58
59 struct sip_msg;
60
61 /* zero-string wrapper */
62 #define ZSW(_c) ((_c)?(_c):"")
63
64 /* returns string beginning and length without insignificant chars */
65 #define trim_len( _len, _begin, _mystr ) \
66         do{     static char _c; \
67                 (_len)=(_mystr).len; \
68                 while ((_len) && ((_c=(_mystr).s[(_len)-1])==0 || _c=='\r' || \
69                                         _c=='\n' || _c==' ' || _c=='\t' )) \
70                         (_len)--; \
71                 (_begin)=(_mystr).s; \
72                 while ((_len) && ((_c=*(_begin))==' ' || _c=='\t')) { \
73                         (_len)--;\
74                         (_begin)++; \
75                 } \
76         }while(0)
77
78 #define trim_r( _mystr ) \
79         do{     static char _c; \
80                 while( ((_mystr).len) && ( ((_c=(_mystr).s[(_mystr).len-1]))==0 ||\
81                                                                         _c=='\r' || _c=='\n' ) \
82                                 ) \
83                         (_mystr).len--; \
84         }while(0)
85
86
87 #define  translate_pointer( _new_buf , _org_buf , _p) \
88         ( (_p)?(_new_buf + (_p-_org_buf)):(0) )
89
90 #define via_len(_via) \
91         ((_via)->bsize-((_via)->name.s-\
92                 ((_via)->hdr.s+(_via)->hdr.len)))
93
94
95 /* char to hex conversion table */
96 static char fourbits2char[16] = { '0', '1', '2', '3', '4', '5',
97         '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
98
99
100 /* converts a str to an u. short, returns the u. short and sets *err on
101  * error and if err!=null
102   */
103 static inline unsigned short str2s(char* s, unsigned int len,
104                                                                         int *err)
105 {
106         unsigned short ret;
107         int i;
108         unsigned char *limit;
109         unsigned char *init;
110         unsigned char* str;
111
112         /*init*/
113         str=(unsigned char*)s;
114         ret=i=0;
115         limit=str+len;
116         init=str;
117
118         for(;str<limit ;str++){
119                 if ( (*str <= '9' ) && (*str >= '0') ){
120                                 ret=ret*10+*str-'0';
121                                 i++;
122                                 if (i>5) goto error_digits;
123                 }else{
124                                 //error unknown char
125                                 goto error_char;
126                 }
127         }
128         if (err) *err=0;
129         return ret;
130
131 error_digits:
132         DBG("str2s: ERROR: too many letters in [%.*s]\n", (int)len, init);
133         if (err) *err=1;
134         return 0;
135 error_char:
136         DBG("str2s: ERROR: unexpected char %c in %.*s\n", *str, (int)len, init);
137         if (err) *err=1;
138         return 0;
139 }
140
141
142
143 static inline int btostr( char *p,  unsigned char val)
144 {
145         unsigned int a,b,i =0;
146
147         if ( (a=val/100)!=0 )
148                 *(p+(i++)) = a+'0';         /*first digit*/
149         if ( (b=val%100/10)!=0 || a)
150                 *(p+(i++)) = b+'0';        /*second digit*/
151         *(p+(i++)) = '0'+val%10;              /*third digit*/
152
153         return i;
154 }
155
156
157 #define INT2STR_MAX_LEN  (19+1+1) /* 2^64~= 16*10^18 => 19+1 digits + \0 */
158
159 /* returns a pointer to a static buffer containing l in asciiz & sets len */
160 static inline char* int2str(unsigned long l, int* len)
161 {
162         static char r[INT2STR_MAX_LEN];
163         int i;
164         
165         i=INT2STR_MAX_LEN-2;
166         r[INT2STR_MAX_LEN-1]=0; /* null terminate */
167         do{
168                 r[i]=l%10+'0';
169                 i--;
170                 l/=10;
171         }while(l && (i>=0));
172         if (l && (i<0)){
173                 LOG(L_CRIT, "BUG: int2str: overflow\n");
174         }
175         if (len) *len=(INT2STR_MAX_LEN-2)-i;
176         return &r[i+1];
177 }
178
179
180
181 /* faster memchr version */
182 static inline char* q_memchr(char* p, int c, unsigned int size)
183 {
184         char* end;
185
186         end=p+size;
187         for(;p<end;p++){
188                 if (*p==(unsigned char)c) return p;
189         }
190         return 0;
191 }
192         
193
194 inline static int reverse_hex2int( char *c, int len )
195 {
196         char *pc;
197         int r;
198         char mychar;
199
200         r=0;
201         for (pc=c+len-1; len>0; pc--, len--) {
202                 r <<= 4 ;
203                 mychar=*pc;
204                 if ( mychar >='0' && mychar <='9') r+=mychar -'0';
205                 else if (mychar >='a' && mychar <='f') r+=mychar -'a'+10;
206                 else if (mychar  >='A' && mychar <='F') r+=mychar -'A'+10;
207                 else return -1;
208         }
209         return r;
210 }
211
212 inline static int int2reverse_hex( char **c, int *size, int nr )
213 {
214         unsigned short digit;
215
216         if (*size && nr==0) {
217                 **c = '0';
218                 (*c)++;
219                 (*size)--;
220                 return 1;
221         }
222
223         while (*size && nr ) {
224                 digit = nr & 0xf ;
225                 **c= digit >= 10 ? digit + 'a' - 10 : digit + '0';
226                 nr >>= 4;
227                 (*c)++;
228                 (*size)--;
229         }
230         return nr ? -1 /* number not processed; too little space */ : 1;
231 }
232
233 /* double output length assumed ; does NOT zero-terminate */
234 inline static int string2hex( 
235         /* input */ unsigned char *str, int len,
236         /* output */ char *hex )
237 {
238         int orig_len;
239
240         if (len==0) {
241                 *hex='0';
242                 return 1;
243         }
244
245         orig_len=len;
246         while ( len ) {
247
248                 *hex=fourbits2char[(*str) >> 4];
249                 hex++;
250                 *hex=fourbits2char[(*str) & 0xf];
251                 hex++;
252                 len--;
253                 str++;
254
255         }
256         return orig_len-len;
257 }
258
259 /* portable sleep in microseconds (no interrupt handling now) */
260
261 inline static void sleep_us( unsigned int nusecs )
262 {
263         struct timeval tval;
264         tval.tv_sec=nusecs/100000;
265         tval.tv_usec=nusecs%1000000;
266         select(0, NULL, NULL, NULL, &tval );
267 }
268
269
270 /* portable determination of max_path */
271 inline static int pathmax()
272 {
273 #ifdef PATH_MAX
274         static int pathmax=PATH_MAX;
275 #else
276         static int pathmax=0;
277 #endif
278         if (pathmax==0) { /* init */
279                 pathmax=pathconf("/", _PC_PATH_MAX);
280                 pathmax=(pathmax<=0)?PATH_MAX_GUESS:pathmax+1;
281         }
282         return pathmax;
283 }
284
285 inline static int hex2int(char hex_digit)
286 {
287         if (hex_digit>='0' && hex_digit<='9')
288                 return hex_digit-'0';
289         if (hex_digit>='a' && hex_digit<='f')
290                 return hex_digit-'a'+10;
291         if (hex_digit>='A' && hex_digit<='F')
292                 return hex_digit-'A'+10;
293         /* no valid hex digit ... */
294         LOG(L_ERR, "ERROR: hex2int: '%c' is no hex char\n", hex_digit );
295         return -1;
296 }
297
298 /* Un-escape URI user  -- it takes a pointer to original user
299    str, as well as the new, unescaped one, which MUST have
300    an allocated buffer linked to the 'str' structure ;
301    (the buffer can be allocated with the same length as
302    the original string -- the output string is always
303    shorter (if escaped characters occur) or same-long
304    as the original one).
305
306    only printable characters are permitted
307
308         <0 is returned on an unescaping error, length of the
309         unescaped string otherwise
310 */
311 inline static int un_escape(str *user, str *new_user ) 
312 {
313         int i, j, value;
314         int hi, lo;
315
316         if( new_user==0 || new_user->s==0) {
317                 LOG(L_CRIT, "BUG: un_escape: called with invalid param\n");
318                 return -1;
319         }
320
321         new_user->len = 0;
322         j = 0;
323
324         for (i = 0; i < user->len; i++) {
325                 if (user->s[i] == '%') {
326                         if (i + 2 >= user->len) {
327                                 LOG(L_ERR, "ERROR: un_escape: escape sequence too short in"
328                                         " '%.*s' @ %d\n",
329                                         user->len, user->s, i );
330                                 goto error;
331                         }
332                         hi=hex2int(user->s[i + 1]);
333                         if (hi<0) {
334                                 LOG(L_ERR, "ERROR: un_escape: non-hex high digit in an escape sequence in"
335                                         " '%.*s' @ %d\n",
336                                         user->len, user->s, i+1 );
337                                 goto error;
338                         }
339                         lo=hex2int(user->s[i + 2]);
340                         if (lo<0) {
341                                 LOG(L_ERR, "ERROR: non-hex low digit in an escape sequence in "
342                                         "'%.*s' @ %d\n",
343                                         user->len, user->s, i+2 );
344                                 goto error;
345                         }
346                         value=(hi<<4)+lo;
347                         if (value < 32 || value > 126) {
348                                 LOG(L_ERR, "ERROR: non-ASCII escaped character in '%.*s' @ %d\n",
349                                         user->len, user->s, i );
350                                 goto error;
351                         }
352                         new_user->s[j] = value;
353                         i+=2; /* consume the two hex digits, for cycle will move to the next char */
354                 } else {
355                         new_user->s[j] = user->s[i];
356                 }
357         j++; /* good -- we translated another character */
358         }
359         new_user->len = j;
360         return j;
361
362 error:
363         new_user->len = j;
364         return -1;
365
366
367
368 /*
369  * Convert a string to lower case
370  */
371 static inline void strlower(str* _s)
372 {
373         int i;
374
375         for(i = 0; i < _s->len; i++) {
376                 _s->s[i] = tolower(_s->s[i]);
377         }
378 }
379
380
381 /*
382  * Convert a str into integer
383  */
384 static inline int str2int(str* _s, unsigned int* _r)
385 {
386         int i;
387         
388         *_r = 0;
389         for(i = 0; i < _s->len; i++) {
390                 if ((_s->s[i] >= '0') && (_s->s[i] <= '9')) {
391                         *_r *= 10;
392                         *_r += _s->s[i] - '0';
393                 } else {
394                         return -1;
395                 }
396         }
397         
398         return 0;
399 }
400
401 #endif