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