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