ab71677f59891c0c21063b35428f502420b2b062
[asterisk/asterisk.git] / utils.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Utility functions
5  *
6  * Copyright (C)  2004 - 2005, Digium, Inc.
7  *
8  * This program is free software, distributed under the terms of
9  * the GNU General Public License
10  */
11
12 #ifdef Linux    /* For strcasestr */
13 #define __USE_GNU
14 #endif
15 #include <ctype.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <errno.h>
20 #include <stdio.h>
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
25 #include <asterisk/lock.h>
26 #include <asterisk/utils.h>
27 #include <asterisk/io.h>
28 #include <asterisk/logger.h>
29 #include <asterisk/md5.h>
30
31 static char base64[64];
32 static char b2a[256];
33
34 char *ast_strip(char *buf)
35 {
36         char *start;
37         /* Strip off trailing whitespace, returns, etc */
38         while (!ast_strlen_zero(buf) && (buf[strlen(buf)-1]<33))
39                 buf[strlen(buf)-1] = '\0';
40         start = buf;
41         /* Strip off leading whitespace, returns, etc */
42         while (*start && (*start < 33))
43                 *start++ = '\0';
44         return start;
45 }
46
47 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__)
48
49 /* duh? ERANGE value copied from web... */
50 #define ERANGE 34
51 #undef gethostbyname
52
53 AST_MUTEX_DEFINE_STATIC(__mutex);
54
55 /* Recursive replacement for gethostbyname for BSD-based systems */
56 static int gethostbyname_r (const char *name, struct hostent *ret, char *buf,
57                                 size_t buflen, struct hostent **result, 
58                                 int *h_errnop) 
59 {
60         int hsave;
61         struct hostent *ph;
62         ast_mutex_lock(&__mutex); /* begin critical area */
63         hsave = h_errno;
64
65         ph = gethostbyname(name);
66         *h_errnop = h_errno; /* copy h_errno to *h_herrnop */
67         if (ph == NULL) {
68                 *result = NULL;
69         } else {
70                 char **p, **q;
71                 char *pbuf;
72                 int nbytes=0;
73                 int naddr=0, naliases=0;
74                 /* determine if we have enough space in buf */
75
76                 /* count how many addresses */
77                 for (p = ph->h_addr_list; *p != 0; p++) {
78                         nbytes += ph->h_length; /* addresses */
79                         nbytes += sizeof(*p); /* pointers */
80                         naddr++;
81                 }
82                 nbytes += sizeof(*p); /* one more for the terminating NULL */
83
84                 /* count how many aliases, and total length of strings */
85                 for (p = ph->h_aliases; *p != 0; p++) {
86                         nbytes += (strlen(*p)+1); /* aliases */
87                         nbytes += sizeof(*p);  /* pointers */
88                         naliases++;
89                 }
90                 nbytes += sizeof(*p); /* one more for the terminating NULL */
91
92                 /* here nbytes is the number of bytes required in buffer */
93                 /* as a terminator must be there, the minimum value is ph->h_length */
94                 if(nbytes > buflen) {
95                         *result = NULL;
96                         ast_mutex_unlock(&__mutex); /* end critical area */
97                         return ERANGE; /* not enough space in buf!! */
98                 }
99
100                 /* There is enough space. Now we need to do a deep copy! */
101                 /* Allocation in buffer:
102                         from [0] to [(naddr-1) * sizeof(*p)]:
103                         pointers to addresses
104                         at [naddr * sizeof(*p)]:
105                         NULL
106                         from [(naddr+1) * sizeof(*p)] to [(naddr+naliases) * sizeof(*p)] :
107                         pointers to aliases
108                         at [(naddr+naliases+1) * sizeof(*p)]:
109                         NULL
110                         then naddr addresses (fixed length), and naliases aliases (asciiz).
111                 */
112
113                 *ret = *ph;   /* copy whole structure (not its address!) */
114
115                 /* copy addresses */
116                 q = (char **)buf; /* pointer to pointers area (type: char **) */
117                 ret->h_addr_list = q; /* update pointer to address list */
118                 pbuf = buf + ((naddr+naliases+2)*sizeof(*p)); /* skip that area */
119                 for (p = ph->h_addr_list; *p != 0; p++) {
120                         memcpy(pbuf, *p, ph->h_length); /* copy address bytes */
121                         *q++ = pbuf; /* the pointer is the one inside buf... */
122                         pbuf += ph->h_length; /* advance pbuf */
123                 }
124                 *q++ = NULL; /* address list terminator */
125
126                 /* copy aliases */
127                 ret->h_aliases = q; /* update pointer to aliases list */
128                 for (p = ph->h_aliases; *p != 0; p++) {
129                         strcpy(pbuf, *p); /* copy alias strings */
130                         *q++ = pbuf; /* the pointer is the one inside buf... */
131                         pbuf += strlen(*p); /* advance pbuf */
132                         *pbuf++ = 0; /* string terminator */
133                 }
134                 *q++ = NULL; /* terminator */
135
136                 strcpy(pbuf, ph->h_name); /* copy alias strings */
137                 ret->h_name = pbuf;
138                 pbuf += strlen(ph->h_name); /* advance pbuf */
139                 *pbuf++ = 0; /* string terminator */
140
141                 *result = ret;  /* and let *result point to structure */
142
143         }
144         h_errno = hsave;  /* restore h_errno */
145         ast_mutex_unlock(&__mutex); /* end critical area */
146
147         return (*result == NULL); /* return 0 on success, non-zero on error */
148 }
149
150
151 #endif
152
153 /* Recursive thread safe version of gethostbyname that replaces the 
154    standard gethostbyname (which is not recursive)
155 */
156 struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp)
157 {
158         int res;
159         int herrno;
160         const char *s;
161         struct hostent *result = NULL;
162         /* Although it is perfectly legitimate to lookup a pure integer, for
163            the sake of the sanity of people who like to name their peers as
164            integers, we break with tradition and refuse to look up a
165            pure integer */
166         s = host;
167         while(s && *s) {
168                 if (!isdigit(*s))
169                         break;
170                 s++;
171         }
172         if (!s || !*s)
173                 return NULL;
174 #ifdef SOLARIS
175         result = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &herrno);
176
177         if (!result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
178                 return NULL;
179 #else
180         res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno);
181
182         if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
183                 return NULL;
184 #endif
185         return &hp->hp;
186 }
187
188
189 /* This is a regression test for recursive mutexes.
190    test_for_thread_safety() will return 0 if recursive mutex locks are
191    working properly, and non-zero if they are not working properly. */
192
193 AST_MUTEX_DEFINE_STATIC(test_lock);
194 AST_MUTEX_DEFINE_STATIC(test_lock2);
195 static pthread_t test_thread; 
196 static int lock_count = 0;
197 static int test_errors = 0;
198
199 static void *test_thread_body(void *data) 
200
201         ast_mutex_lock(&test_lock);
202         lock_count += 10;
203         if (lock_count != 10) 
204                 test_errors++;
205         ast_mutex_lock(&test_lock);
206         lock_count += 10;
207         if (lock_count != 20) 
208                 test_errors++;
209         ast_mutex_lock(&test_lock2);
210         ast_mutex_unlock(&test_lock);
211         lock_count -= 10;
212         if (lock_count != 10) 
213                 test_errors++;
214         ast_mutex_unlock(&test_lock);
215         lock_count -= 10;
216         ast_mutex_unlock(&test_lock2);
217         if (lock_count != 0) 
218                 test_errors++;
219         return NULL;
220
221
222 int test_for_thread_safety(void)
223
224         ast_mutex_lock(&test_lock2);
225         ast_mutex_lock(&test_lock);
226         lock_count += 1;
227         ast_mutex_lock(&test_lock);
228         lock_count += 1;
229         ast_pthread_create(&test_thread, NULL, test_thread_body, NULL); 
230         usleep(100);
231         if (lock_count != 2) 
232                 test_errors++;
233         ast_mutex_unlock(&test_lock);
234         lock_count -= 1;
235         usleep(100); 
236         if (lock_count != 1) 
237                 test_errors++;
238         ast_mutex_unlock(&test_lock);
239         lock_count -= 1;
240         if (lock_count != 0) 
241                 test_errors++;
242         ast_mutex_unlock(&test_lock2);
243         usleep(100);
244         if (lock_count != 0) 
245                 test_errors++;
246         pthread_join(test_thread, NULL);
247         return(test_errors);          /* return 0 on success. */
248 }
249
250 /*--- ast_md5_hash: Produce 16 char MD5 hash of value. ---*/
251 void ast_md5_hash(char *output, char *input)
252 {
253                 struct MD5Context md5;
254                 unsigned char digest[16];
255                 char *ptr;
256                 int x;
257                 MD5Init(&md5);
258                 MD5Update(&md5, input, strlen(input));
259                 MD5Final(digest, &md5);
260                 ptr = output;
261                 for (x=0;x<16;x++)
262                         ptr += sprintf(ptr, "%2.2x", digest[x]);
263 }
264
265 int ast_base64decode(unsigned char *dst, char *src, int max)
266 {
267         int cnt = 0;
268         unsigned int byte = 0;
269         unsigned int bits = 0;
270         int incnt = 0;
271 #if 0
272         unsigned char *odst = dst;
273 #endif
274         while(*src && (cnt < max)) {
275                 /* Shift in 6 bits of input */
276                 byte <<= 6;
277                 byte |= (b2a[(int)(*src)]) & 0x3f;
278                 bits += 6;
279 #if 0
280                 printf("Add: %c %s\n", *src, binary(b2a[(int)(*src)] & 0x3f, 6));
281 #endif
282                 src++;
283                 incnt++;
284                 /* If we have at least 8 bits left over, take that character 
285                    off the top */
286                 if (bits >= 8)  {
287                         bits -= 8;
288                         *dst = (byte >> bits) & 0xff;
289 #if 0
290                         printf("Remove: %02x %s\n", *dst, binary(*dst, 8));
291 #endif
292                         dst++;
293                         cnt++;
294                 }
295         }
296 #if 0
297         dump(odst, cnt);
298 #endif
299         /* Dont worry about left over bits, they're extra anyway */
300         return cnt;
301 }
302
303 int ast_base64encode(char *dst, unsigned char *src, int srclen, int max)
304 {
305         int cnt = 0;
306         unsigned int byte = 0;
307         int bits = 0;
308         int index;
309         int cntin = 0;
310 #if 0
311         char *odst = dst;
312         dump(src, srclen);
313 #endif
314         /* Reserve one bit for end */
315         max--;
316         while((cntin < srclen) && (cnt < max)) {
317                 byte <<= 8;
318 #if 0
319                 printf("Add: %02x %s\n", *src, binary(*src, 8));
320 #endif
321                 byte |= *(src++);
322                 bits += 8;
323                 cntin++;
324                 while((bits >= 6) && (cnt < max)) {
325                         bits -= 6;
326                         /* We want only the top */
327                         index = (byte >> bits) & 0x3f;
328                         *dst = base64[index];
329 #if 0
330                         printf("Remove: %c %s\n", *dst, binary(index, 6));
331 #endif
332                         dst++;
333                         cnt++;
334                 }
335         }
336         if (bits && (cnt < max)) {
337                 /* Add one last character for the remaining bits, 
338                    padding the rest with 0 */
339                 byte <<= (6 - bits);
340                 index = (byte) & 0x3f;
341                 *(dst++) = base64[index];
342                 cnt++;
343         }
344         *dst = '\0';
345         return cnt;
346 }
347
348 static void base64_init(void)
349 {
350         int x;
351         memset(b2a, -1, sizeof(b2a));
352         /* Initialize base-64 Conversion table */
353         for (x=0;x<26;x++) {
354                 /* A-Z */
355                 base64[x] = 'A' + x;
356                 b2a['A' + x] = x;
357                 /* a-z */
358                 base64[x + 26] = 'a' + x;
359                 b2a['a' + x] = x + 26;
360                 /* 0-9 */
361                 if (x < 10) {
362                         base64[x + 52] = '0' + x;
363                         b2a['0' + x] = x + 52;
364                 }
365         }
366         base64[62] = '+';
367         base64[63] = '/';
368         b2a[(int)'+'] = 62;
369         b2a[(int)'/'] = 63;
370 #if 0
371         for (x=0;x<64;x++) {
372                 if (b2a[(int)base64[x]] != x) {
373                         fprintf(stderr, "!!! %d failed\n", x);
374                 } else
375                         fprintf(stderr, "--- %d passed\n", x);
376         }
377 #endif
378 }
379
380 /* Recursive thread safe replacement of inet_ntoa */
381 const char *ast_inet_ntoa(char *buf, int bufsiz, struct in_addr ia)
382 {
383         return inet_ntop(AF_INET, &ia, buf, bufsiz);
384 }
385
386 int ast_utils_init(void)
387 {
388         base64_init();
389         return 0;
390 }
391
392
393 int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize)
394 {
395         pthread_attr_t lattr;
396         if (!attr) {
397                 pthread_attr_init(&lattr);
398                 attr = &lattr;
399         }
400         if (!stacksize)
401                 stacksize = AST_STACKSIZE;
402         errno = pthread_attr_setstacksize(attr, stacksize);
403         if (errno)
404                 ast_log(LOG_WARNING, "pthread_attr_setstacksize returned non-zero: %s\n", strerror(errno));
405         return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
406 }
407
408 int ast_wait_for_input(int fd, int ms)
409 {
410         struct pollfd pfd[1];
411         memset(pfd, 0, sizeof(pfd));
412         pfd[0].fd = fd;
413         pfd[0].events = POLLIN|POLLPRI;
414         return poll(pfd, 1, ms);
415 }
416
417 /* Case-insensitive substring matching */
418 #ifndef LINUX
419 static char *upper(const char *orig, char *buf, int bufsize)
420 {
421         int i;
422         memset(buf, 0, bufsize);
423         for (i=0; i<bufsize - 1; i++) {
424                 buf[i] = toupper(orig[i]);
425                 if (orig[i] == '\0') {
426                         break;
427                 }
428         }
429         return buf;
430 }
431
432 char *ast_strcasestr(const char *haystack, const char *needle)
433 {
434         char *u1, *u2;
435         int u1len = strlen(haystack) + 1, u2len = strlen(needle) + 1;
436
437         u1 = alloca(u1len);
438         u2 = alloca(u2len);
439         if (u1 && u2) {
440                 char *offset;
441                 if (u2len > u1len) {
442                         /* Needle bigger than haystack */
443                         return NULL;
444                 }
445                 offset = strstr(upper(haystack, u1, u1len), upper(needle, u2, u2len));
446                 if (offset) {
447                         /* Return the offset into the original string */
448                         return ((char *)((unsigned int)haystack + (unsigned int)(offset - u1)));
449                 } else {
450                         return NULL;
451                 }
452         } else {
453                 ast_log(LOG_ERROR, "Out of memory\n");
454                 return NULL;
455         }
456 }
457 #endif