00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "asterisk.h"
00031
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 378933 $")
00033
00034 #include <ctype.h>
00035 #include <sys/stat.h>
00036 #include <sys/stat.h>
00037
00038 #ifdef HAVE_DEV_URANDOM
00039 #include <fcntl.h>
00040 #endif
00041
00042 #include "asterisk/network.h"
00043
00044 #define AST_API_MODULE
00045 #include "asterisk/lock.h"
00046 #include "asterisk/io.h"
00047 #include "asterisk/md5.h"
00048 #include "asterisk/sha1.h"
00049 #include "asterisk/cli.h"
00050 #include "asterisk/linkedlists.h"
00051
00052 #define AST_API_MODULE
00053 #include "asterisk/strings.h"
00054
00055 #define AST_API_MODULE
00056 #include "asterisk/time.h"
00057
00058 #define AST_API_MODULE
00059 #include "asterisk/stringfields.h"
00060
00061 #define AST_API_MODULE
00062 #include "asterisk/utils.h"
00063
00064 #define AST_API_MODULE
00065 #include "asterisk/threadstorage.h"
00066
00067 #define AST_API_MODULE
00068 #include "asterisk/config.h"
00069
00070 static char base64[64];
00071 static char b2a[256];
00072
00073 AST_THREADSTORAGE(inet_ntoa_buf);
00074
00075 #if !defined(HAVE_GETHOSTBYNAME_R_5) && !defined(HAVE_GETHOSTBYNAME_R_6)
00076
00077 #define ERANGE 34
00078 #undef gethostbyname
00079
00080 AST_MUTEX_DEFINE_STATIC(__mutex);
00081
00082
00083
00084
00085
00086
00087 static int gethostbyname_r (const char *name, struct hostent *ret, char *buf,
00088 size_t buflen, struct hostent **result,
00089 int *h_errnop)
00090 {
00091 int hsave;
00092 struct hostent *ph;
00093 ast_mutex_lock(&__mutex);
00094 hsave = h_errno;
00095
00096 ph = gethostbyname(name);
00097 *h_errnop = h_errno;
00098 if (ph == NULL) {
00099 *result = NULL;
00100 } else {
00101 char **p, **q;
00102 char *pbuf;
00103 int nbytes = 0;
00104 int naddr = 0, naliases = 0;
00105
00106
00107
00108 for (p = ph->h_addr_list; *p != 0; p++) {
00109 nbytes += ph->h_length;
00110 nbytes += sizeof(*p);
00111 naddr++;
00112 }
00113 nbytes += sizeof(*p);
00114
00115
00116 for (p = ph->h_aliases; *p != 0; p++) {
00117 nbytes += (strlen(*p)+1);
00118 nbytes += sizeof(*p);
00119 naliases++;
00120 }
00121 nbytes += sizeof(*p);
00122
00123
00124
00125 if (nbytes > buflen) {
00126 *result = NULL;
00127 ast_mutex_unlock(&__mutex);
00128 return ERANGE;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 *ret = *ph;
00145
00146
00147 q = (char **)buf;
00148 ret->h_addr_list = q;
00149 pbuf = buf + ((naddr + naliases + 2) * sizeof(*p));
00150 for (p = ph->h_addr_list; *p != 0; p++) {
00151 memcpy(pbuf, *p, ph->h_length);
00152 *q++ = pbuf;
00153 pbuf += ph->h_length;
00154 }
00155 *q++ = NULL;
00156
00157
00158 ret->h_aliases = q;
00159 for (p = ph->h_aliases; *p != 0; p++) {
00160 strcpy(pbuf, *p);
00161 *q++ = pbuf;
00162 pbuf += strlen(*p);
00163 *pbuf++ = 0;
00164 }
00165 *q++ = NULL;
00166
00167 strcpy(pbuf, ph->h_name);
00168 ret->h_name = pbuf;
00169 pbuf += strlen(ph->h_name);
00170 *pbuf++ = 0;
00171
00172 *result = ret;
00173
00174 }
00175 h_errno = hsave;
00176 ast_mutex_unlock(&__mutex);
00177
00178 return (*result == NULL);
00179 }
00180
00181
00182 #endif
00183
00184
00185
00186
00187 struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp)
00188 {
00189 int res;
00190 int herrno;
00191 int dots = 0;
00192 const char *s;
00193 struct hostent *result = NULL;
00194
00195
00196
00197
00198 s = host;
00199 res = 0;
00200 while (s && *s) {
00201 if (*s == '.')
00202 dots++;
00203 else if (!isdigit(*s))
00204 break;
00205 s++;
00206 }
00207 if (!s || !*s) {
00208
00209 if (dots != 3)
00210 return NULL;
00211 memset(hp, 0, sizeof(struct ast_hostent));
00212 hp->hp.h_addrtype = AF_INET;
00213 hp->hp.h_addr_list = (void *) hp->buf;
00214 hp->hp.h_addr = hp->buf + sizeof(void *);
00215
00216 hp->hp.h_length = 4;
00217 if (inet_pton(AF_INET, host, hp->hp.h_addr) > 0)
00218 return &hp->hp;
00219 return NULL;
00220
00221 }
00222 #ifdef HAVE_GETHOSTBYNAME_R_5
00223 result = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &herrno);
00224
00225 if (!result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
00226 return NULL;
00227 #else
00228 res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno);
00229
00230 if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
00231 return NULL;
00232 #endif
00233 return &hp->hp;
00234 }
00235
00236
00237 void ast_md5_hash(char *output, const char *input)
00238 {
00239 struct MD5Context md5;
00240 unsigned char digest[16];
00241 char *ptr;
00242 int x;
00243
00244 MD5Init(&md5);
00245 MD5Update(&md5, (const unsigned char *) input, strlen(input));
00246 MD5Final(digest, &md5);
00247 ptr = output;
00248 for (x = 0; x < 16; x++)
00249 ptr += sprintf(ptr, "%2.2x", digest[x]);
00250 }
00251
00252
00253 void ast_sha1_hash(char *output, const char *input)
00254 {
00255 struct SHA1Context sha;
00256 char *ptr;
00257 int x;
00258 uint8_t Message_Digest[20];
00259
00260 SHA1Reset(&sha);
00261
00262 SHA1Input(&sha, (const unsigned char *) input, strlen(input));
00263
00264 SHA1Result(&sha, Message_Digest);
00265 ptr = output;
00266 for (x = 0; x < 20; x++)
00267 ptr += sprintf(ptr, "%2.2x", Message_Digest[x]);
00268 }
00269
00270
00271 int ast_base64decode(unsigned char *dst, const char *src, int max)
00272 {
00273 int cnt = 0;
00274 unsigned int byte = 0;
00275 unsigned int bits = 0;
00276 int incnt = 0;
00277 while(*src && *src != '=' && (cnt < max)) {
00278
00279 byte <<= 6;
00280 byte |= (b2a[(int)(*src)]) & 0x3f;
00281 bits += 6;
00282 src++;
00283 incnt++;
00284
00285
00286 if (bits >= 8) {
00287 bits -= 8;
00288 *dst = (byte >> bits) & 0xff;
00289 dst++;
00290 cnt++;
00291 }
00292 }
00293
00294 return cnt;
00295 }
00296
00297
00298 int ast_base64encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks)
00299 {
00300 int cnt = 0;
00301 int col = 0;
00302 unsigned int byte = 0;
00303 int bits = 0;
00304 int cntin = 0;
00305
00306 max--;
00307 while ((cntin < srclen) && (cnt < max)) {
00308 byte <<= 8;
00309 byte |= *(src++);
00310 bits += 8;
00311 cntin++;
00312 if ((bits == 24) && (cnt + 4 <= max)) {
00313 *dst++ = base64[(byte >> 18) & 0x3f];
00314 *dst++ = base64[(byte >> 12) & 0x3f];
00315 *dst++ = base64[(byte >> 6) & 0x3f];
00316 *dst++ = base64[byte & 0x3f];
00317 cnt += 4;
00318 col += 4;
00319 bits = 0;
00320 byte = 0;
00321 }
00322 if (linebreaks && (cnt < max) && (col == 64)) {
00323 *dst++ = '\n';
00324 cnt++;
00325 col = 0;
00326 }
00327 }
00328 if (bits && (cnt + 4 <= max)) {
00329
00330
00331 byte <<= 24 - bits;
00332 *dst++ = base64[(byte >> 18) & 0x3f];
00333 *dst++ = base64[(byte >> 12) & 0x3f];
00334 if (bits == 16)
00335 *dst++ = base64[(byte >> 6) & 0x3f];
00336 else
00337 *dst++ = '=';
00338 *dst++ = '=';
00339 cnt += 4;
00340 }
00341 if (linebreaks && (cnt < max)) {
00342 *dst++ = '\n';
00343 cnt++;
00344 }
00345 *dst = '\0';
00346 return cnt;
00347 }
00348
00349 int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
00350 {
00351 return ast_base64encode_full(dst, src, srclen, max, 0);
00352 }
00353
00354 static void base64_init(void)
00355 {
00356 int x;
00357 memset(b2a, -1, sizeof(b2a));
00358
00359 for (x = 0; x < 26; x++) {
00360
00361 base64[x] = 'A' + x;
00362 b2a['A' + x] = x;
00363
00364 base64[x + 26] = 'a' + x;
00365 b2a['a' + x] = x + 26;
00366
00367 if (x < 10) {
00368 base64[x + 52] = '0' + x;
00369 b2a['0' + x] = x + 52;
00370 }
00371 }
00372 base64[62] = '+';
00373 base64[63] = '/';
00374 b2a[(int)'+'] = 62;
00375 b2a[(int)'/'] = 63;
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 char *ast_uri_encode(const char *string, char *outbuf, int buflen, int do_special_char)
00391 {
00392 const char *ptr = string;
00393 char *out = outbuf;
00394 const char *mark = "-_.!~*'()";
00395
00396 while (*ptr && out - outbuf < buflen - 1) {
00397 if ((const signed char) *ptr < 32 || *ptr == 0x7f || *ptr == '%' ||
00398 (do_special_char &&
00399 !(*ptr >= '0' && *ptr <= '9') &&
00400 !(*ptr >= 'A' && *ptr <= 'Z') &&
00401 !(*ptr >= 'a' && *ptr <= 'z') &&
00402 !strchr(mark, *ptr))) {
00403 if (out - outbuf >= buflen - 3) {
00404 break;
00405 }
00406
00407 out += sprintf(out, "%%%02X", (unsigned char) *ptr);
00408 } else {
00409 *out = *ptr;
00410 out++;
00411 }
00412 ptr++;
00413 }
00414
00415 if (buflen) {
00416 *out = '\0';
00417 }
00418
00419 return outbuf;
00420 }
00421
00422
00423 char *ast_escape_quoted(const char *string, char *outbuf, int buflen)
00424 {
00425 const char *ptr = string;
00426 char *out = outbuf;
00427 char *allow = "\t\v !";
00428
00429 while (*ptr && out - outbuf < buflen - 1) {
00430 if (!(strchr(allow, *ptr))
00431 && !(*ptr >= '#' && *ptr <= '[')
00432 && !(*ptr >= ']' && *ptr <= '~')
00433 && !((unsigned char) *ptr > 0x7f)) {
00434
00435 if (out - outbuf >= buflen - 2) {
00436 break;
00437 }
00438 out += sprintf(out, "\\%c", (unsigned char) *ptr);
00439 } else {
00440 *out = *ptr;
00441 out++;
00442 }
00443 ptr++;
00444 }
00445
00446 if (buflen) {
00447 *out = '\0';
00448 }
00449
00450 return outbuf;
00451 }
00452
00453
00454 void ast_uri_decode(char *s)
00455 {
00456 char *o;
00457 unsigned int tmp;
00458
00459 for (o = s; *s; s++, o++) {
00460 if (*s == '%' && s[1] != '\0' && s[2] != '\0' && sscanf(s + 1, "%2x", &tmp) == 1) {
00461
00462 *o = tmp;
00463 s += 2;
00464 } else
00465 *o = *s;
00466 }
00467 *o = '\0';
00468 }
00469
00470 int ast_xml_escape(const char *string, char * const outbuf, const size_t buflen)
00471 {
00472 char *dst = outbuf;
00473 char *end = outbuf + buflen - 1;
00474
00475
00476 if (buflen == 0) {
00477 return -1;
00478 }
00479
00480
00481
00482 while (*string && dst < end) {
00483 const char *entity = NULL;
00484 int len = 0;
00485
00486 switch (*string) {
00487 case '<':
00488 entity = "<";
00489 len = 4;
00490 break;
00491 case '&':
00492 entity = "&";
00493 len = 5;
00494 break;
00495 case '>':
00496
00497 entity = ">";
00498 len = 4;
00499 break;
00500 case '\'':
00501
00502 entity = "'";
00503 len = 6;
00504 break;
00505 case '"':
00506
00507 entity = """;
00508 len = 6;
00509 break;
00510 default:
00511 *dst++ = *string++;
00512 break;
00513 }
00514
00515 if (entity) {
00516 ast_assert(len == strlen(entity));
00517 if (end - dst < len) {
00518
00519 break;
00520 }
00521
00522 strcpy(dst, entity);
00523 dst += len;
00524 ++string;
00525 }
00526 }
00527
00528 *dst = '\0';
00529
00530 return *string == '\0' ? 0 : -1;
00531 }
00532
00533
00534 const char *ast_inet_ntoa(struct in_addr ia)
00535 {
00536 char *buf;
00537
00538 if (!(buf = ast_threadstorage_get(&inet_ntoa_buf, INET_ADDRSTRLEN)))
00539 return "";
00540
00541 return inet_ntop(AF_INET, &ia, buf, INET_ADDRSTRLEN);
00542 }
00543
00544 #ifdef HAVE_DEV_URANDOM
00545 static int dev_urandom_fd;
00546 #endif
00547
00548 #ifndef __linux__
00549 #undef pthread_create
00550 #endif
00551
00552 #if !defined(LOW_MEMORY)
00553
00554 #ifdef DEBUG_THREADS
00555
00556
00557 #define AST_MAX_LOCKS 64
00558
00559
00560 #undef pthread_mutex_t
00561 #undef pthread_mutex_lock
00562 #undef pthread_mutex_unlock
00563 #undef pthread_mutex_init
00564 #undef pthread_mutex_destroy
00565
00566
00567
00568
00569
00570
00571 struct thr_lock_info {
00572
00573 pthread_t thread_id;
00574
00575 const char *thread_name;
00576
00577 struct {
00578 const char *file;
00579 int line_num;
00580 const char *func;
00581 const char *lock_name;
00582 void *lock_addr;
00583 int times_locked;
00584 enum ast_lock_type type;
00585
00586 int pending:2;
00587 #ifdef HAVE_BKTR
00588 struct ast_bt *backtrace;
00589 #endif
00590 } locks[AST_MAX_LOCKS];
00591
00592
00593
00594 unsigned int num_locks;
00595
00596
00597 pthread_mutex_t lock;
00598 AST_LIST_ENTRY(thr_lock_info) entry;
00599 };
00600
00601
00602
00603
00604 AST_MUTEX_DEFINE_STATIC(lock_infos_lock);
00605
00606
00607
00608 static AST_LIST_HEAD_NOLOCK_STATIC(lock_infos, thr_lock_info);
00609
00610
00611
00612
00613
00614
00615 static void lock_info_destroy(void *data)
00616 {
00617 struct thr_lock_info *lock_info = data;
00618 int i;
00619
00620 pthread_mutex_lock(&lock_infos_lock.mutex);
00621 AST_LIST_REMOVE(&lock_infos, lock_info, entry);
00622 pthread_mutex_unlock(&lock_infos_lock.mutex);
00623
00624
00625 for (i = 0; i < lock_info->num_locks; i++) {
00626 if (lock_info->locks[i].pending == -1) {
00627
00628
00629 break;
00630 }
00631
00632 ast_log(LOG_ERROR,
00633 "Thread '%s' still has a lock! - '%s' (%p) from '%s' in %s:%d!\n",
00634 lock_info->thread_name,
00635 lock_info->locks[i].lock_name,
00636 lock_info->locks[i].lock_addr,
00637 lock_info->locks[i].func,
00638 lock_info->locks[i].file,
00639 lock_info->locks[i].line_num
00640 );
00641 }
00642
00643 pthread_mutex_destroy(&lock_info->lock);
00644 if (lock_info->thread_name)
00645 free((void *) lock_info->thread_name);
00646 free(lock_info);
00647 }
00648
00649
00650
00651
00652 AST_THREADSTORAGE_CUSTOM(thread_lock_info, NULL, lock_info_destroy);
00653 #ifdef HAVE_BKTR
00654 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
00655 int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
00656 #else
00657 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
00658 int line_num, const char *func, const char *lock_name, void *lock_addr)
00659 #endif
00660 {
00661 struct thr_lock_info *lock_info;
00662 int i;
00663
00664 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
00665 return;
00666
00667 pthread_mutex_lock(&lock_info->lock);
00668
00669 for (i = 0; i < lock_info->num_locks; i++) {
00670 if (lock_info->locks[i].lock_addr == lock_addr) {
00671 lock_info->locks[i].times_locked++;
00672 #ifdef HAVE_BKTR
00673 lock_info->locks[i].backtrace = bt;
00674 #endif
00675 pthread_mutex_unlock(&lock_info->lock);
00676 return;
00677 }
00678 }
00679
00680 if (lock_info->num_locks == AST_MAX_LOCKS) {
00681
00682 fprintf(stderr, "XXX ERROR XXX A thread holds more locks than '%d'."
00683 " Increase AST_MAX_LOCKS!\n", AST_MAX_LOCKS);
00684 pthread_mutex_unlock(&lock_info->lock);
00685 return;
00686 }
00687
00688 if (i && lock_info->locks[i - 1].pending == -1) {
00689
00690
00691
00692 i--;
00693 lock_info->num_locks--;
00694 memset(&lock_info->locks[i], 0, sizeof(lock_info->locks[0]));
00695 }
00696
00697 lock_info->locks[i].file = filename;
00698 lock_info->locks[i].line_num = line_num;
00699 lock_info->locks[i].func = func;
00700 lock_info->locks[i].lock_name = lock_name;
00701 lock_info->locks[i].lock_addr = lock_addr;
00702 lock_info->locks[i].times_locked = 1;
00703 lock_info->locks[i].type = type;
00704 lock_info->locks[i].pending = 1;
00705 #ifdef HAVE_BKTR
00706 lock_info->locks[i].backtrace = bt;
00707 #endif
00708 lock_info->num_locks++;
00709
00710 pthread_mutex_unlock(&lock_info->lock);
00711 }
00712
00713 void ast_mark_lock_acquired(void *lock_addr)
00714 {
00715 struct thr_lock_info *lock_info;
00716
00717 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
00718 return;
00719
00720 pthread_mutex_lock(&lock_info->lock);
00721 if (lock_info->locks[lock_info->num_locks - 1].lock_addr == lock_addr) {
00722 lock_info->locks[lock_info->num_locks - 1].pending = 0;
00723 }
00724 pthread_mutex_unlock(&lock_info->lock);
00725 }
00726
00727 void ast_mark_lock_failed(void *lock_addr)
00728 {
00729 struct thr_lock_info *lock_info;
00730
00731 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
00732 return;
00733
00734 pthread_mutex_lock(&lock_info->lock);
00735 if (lock_info->locks[lock_info->num_locks - 1].lock_addr == lock_addr) {
00736 lock_info->locks[lock_info->num_locks - 1].pending = -1;
00737 lock_info->locks[lock_info->num_locks - 1].times_locked--;
00738 }
00739 pthread_mutex_unlock(&lock_info->lock);
00740 }
00741
00742 int ast_find_lock_info(void *lock_addr, char *filename, size_t filename_size, int *lineno, char *func, size_t func_size, char *mutex_name, size_t mutex_name_size)
00743 {
00744 struct thr_lock_info *lock_info;
00745 int i = 0;
00746
00747 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
00748 return -1;
00749
00750 pthread_mutex_lock(&lock_info->lock);
00751
00752 for (i = lock_info->num_locks - 1; i >= 0; i--) {
00753 if (lock_info->locks[i].lock_addr == lock_addr)
00754 break;
00755 }
00756
00757 if (i == -1) {
00758
00759 pthread_mutex_unlock(&lock_info->lock);
00760 return -1;
00761 }
00762
00763 ast_copy_string(filename, lock_info->locks[i].file, filename_size);
00764 *lineno = lock_info->locks[i].line_num;
00765 ast_copy_string(func, lock_info->locks[i].func, func_size);
00766 ast_copy_string(mutex_name, lock_info->locks[i].lock_name, mutex_name_size);
00767
00768 pthread_mutex_unlock(&lock_info->lock);
00769
00770 return 0;
00771 }
00772
00773 #ifdef HAVE_BKTR
00774 void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
00775 #else
00776 void ast_remove_lock_info(void *lock_addr)
00777 #endif
00778 {
00779 struct thr_lock_info *lock_info;
00780 int i = 0;
00781
00782 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
00783 return;
00784
00785 pthread_mutex_lock(&lock_info->lock);
00786
00787 for (i = lock_info->num_locks - 1; i >= 0; i--) {
00788 if (lock_info->locks[i].lock_addr == lock_addr)
00789 break;
00790 }
00791
00792 if (i == -1) {
00793
00794 pthread_mutex_unlock(&lock_info->lock);
00795 return;
00796 }
00797
00798 if (lock_info->locks[i].times_locked > 1) {
00799 lock_info->locks[i].times_locked--;
00800 #ifdef HAVE_BKTR
00801 lock_info->locks[i].backtrace = bt;
00802 #endif
00803 pthread_mutex_unlock(&lock_info->lock);
00804 return;
00805 }
00806
00807 if (i < lock_info->num_locks - 1) {
00808
00809 memmove(&lock_info->locks[i], &lock_info->locks[i + 1],
00810 (lock_info->num_locks - (i + 1)) * sizeof(lock_info->locks[0]));
00811 }
00812
00813 lock_info->num_locks--;
00814
00815 pthread_mutex_unlock(&lock_info->lock);
00816 }
00817
00818 static const char *locktype2str(enum ast_lock_type type)
00819 {
00820 switch (type) {
00821 case AST_MUTEX:
00822 return "MUTEX";
00823 case AST_RDLOCK:
00824 return "RDLOCK";
00825 case AST_WRLOCK:
00826 return "WRLOCK";
00827 }
00828
00829 return "UNKNOWN";
00830 }
00831
00832 #ifdef HAVE_BKTR
00833 static void append_backtrace_information(struct ast_str **str, struct ast_bt *bt)
00834 {
00835 char **symbols;
00836 int num_frames;
00837
00838 if (!bt) {
00839 ast_str_append(str, 0, "\tNo backtrace to print\n");
00840 return;
00841 }
00842
00843
00844
00845 num_frames = bt->num_frames;
00846 if ((symbols = ast_bt_get_symbols(bt->addresses, num_frames))) {
00847 int frame_iterator;
00848
00849 for (frame_iterator = 0; frame_iterator < num_frames; ++frame_iterator) {
00850 ast_str_append(str, 0, "\t%s\n", symbols[frame_iterator]);
00851 }
00852
00853 free(symbols);
00854 } else {
00855 ast_str_append(str, 0, "\tCouldn't retrieve backtrace symbols\n");
00856 }
00857 }
00858 #endif
00859
00860 static void append_lock_information(struct ast_str **str, struct thr_lock_info *lock_info, int i)
00861 {
00862 int j;
00863 ast_mutex_t *lock;
00864 struct ast_lock_track *lt;
00865
00866 ast_str_append(str, 0, "=== ---> %sLock #%d (%s): %s %d %s %s %p (%d)\n",
00867 lock_info->locks[i].pending > 0 ? "Waiting for " :
00868 lock_info->locks[i].pending < 0 ? "Tried and failed to get " : "", i,
00869 lock_info->locks[i].file,
00870 locktype2str(lock_info->locks[i].type),
00871 lock_info->locks[i].line_num,
00872 lock_info->locks[i].func, lock_info->locks[i].lock_name,
00873 lock_info->locks[i].lock_addr,
00874 lock_info->locks[i].times_locked);
00875 #ifdef HAVE_BKTR
00876 append_backtrace_information(str, lock_info->locks[i].backtrace);
00877 #endif
00878
00879 if (!lock_info->locks[i].pending || lock_info->locks[i].pending == -1)
00880 return;
00881
00882
00883 if (lock_info->locks[i].type != AST_MUTEX)
00884 return;
00885
00886 lock = lock_info->locks[i].lock_addr;
00887 lt = lock->track;
00888 ast_reentrancy_lock(lt);
00889 for (j = 0; *str && j < lt->reentrancy; j++) {
00890 ast_str_append(str, 0, "=== --- ---> Locked Here: %s line %d (%s)\n",
00891 lt->file[j], lt->lineno[j], lt->func[j]);
00892 }
00893 ast_reentrancy_unlock(lt);
00894 }
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916 void log_show_lock(void *this_lock_addr)
00917 {
00918 struct thr_lock_info *lock_info;
00919 struct ast_str *str;
00920
00921 if (!(str = ast_str_create(4096))) {
00922 ast_log(LOG_NOTICE,"Could not create str\n");
00923 return;
00924 }
00925
00926
00927 pthread_mutex_lock(&lock_infos_lock.mutex);
00928 AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) {
00929 int i;
00930 pthread_mutex_lock(&lock_info->lock);
00931 for (i = 0; str && i < lock_info->num_locks; i++) {
00932
00933
00934 if (lock_info->locks[i].lock_addr == this_lock_addr) {
00935 append_lock_information(&str, lock_info, i);
00936 ast_log(LOG_NOTICE, "%s", ast_str_buffer(str));
00937 break;
00938 }
00939 }
00940 pthread_mutex_unlock(&lock_info->lock);
00941 }
00942 pthread_mutex_unlock(&lock_infos_lock.mutex);
00943 ast_free(str);
00944 }
00945
00946
00947 static char *handle_show_locks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00948 {
00949 struct thr_lock_info *lock_info;
00950 struct ast_str *str;
00951
00952 if (!(str = ast_str_create(4096)))
00953 return CLI_FAILURE;
00954
00955 switch (cmd) {
00956 case CLI_INIT:
00957 e->command = "core show locks";
00958 e->usage =
00959 "Usage: core show locks\n"
00960 " This command is for lock debugging. It prints out which locks\n"
00961 "are owned by each active thread.\n";
00962 return NULL;
00963
00964 case CLI_GENERATE:
00965 return NULL;
00966 }
00967
00968 ast_str_append(&str, 0, "\n"
00969 "=======================================================================\n"
00970 "=== Currently Held Locks ==============================================\n"
00971 "=======================================================================\n"
00972 "===\n"
00973 "=== <pending> <lock#> (<file>): <lock type> <line num> <function> <lock name> <lock addr> (times locked)\n"
00974 "===\n");
00975
00976 if (!str)
00977 return CLI_FAILURE;
00978
00979 pthread_mutex_lock(&lock_infos_lock.mutex);
00980 AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) {
00981 int i;
00982 if (lock_info->num_locks) {
00983 ast_str_append(&str, 0, "=== Thread ID: 0x%lx (%s)\n", (long) lock_info->thread_id,
00984 lock_info->thread_name);
00985 pthread_mutex_lock(&lock_info->lock);
00986 for (i = 0; str && i < lock_info->num_locks; i++) {
00987 append_lock_information(&str, lock_info, i);
00988 }
00989 pthread_mutex_unlock(&lock_info->lock);
00990 if (!str)
00991 break;
00992 ast_str_append(&str, 0, "=== -------------------------------------------------------------------\n"
00993 "===\n");
00994 if (!str)
00995 break;
00996 }
00997 }
00998 pthread_mutex_unlock(&lock_infos_lock.mutex);
00999
01000 if (!str)
01001 return CLI_FAILURE;
01002
01003 ast_str_append(&str, 0, "=======================================================================\n"
01004 "\n");
01005
01006 if (!str)
01007 return CLI_FAILURE;
01008
01009 ast_cli(a->fd, "%s", ast_str_buffer(str));
01010
01011 ast_free(str);
01012
01013 return CLI_SUCCESS;
01014 }
01015
01016 static struct ast_cli_entry utils_cli[] = {
01017 AST_CLI_DEFINE(handle_show_locks, "Show which locks are held by which thread"),
01018 };
01019
01020 #endif
01021
01022
01023
01024
01025
01026
01027 struct thr_arg {
01028 void *(*start_routine)(void *);
01029 void *data;
01030 char *name;
01031 };
01032
01033
01034
01035
01036
01037
01038
01039
01040 static void *dummy_start(void *data)
01041 {
01042 void *ret;
01043 struct thr_arg a = *((struct thr_arg *) data);
01044 #ifdef DEBUG_THREADS
01045 struct thr_lock_info *lock_info;
01046 pthread_mutexattr_t mutex_attr;
01047
01048 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
01049 return NULL;
01050
01051 lock_info->thread_id = pthread_self();
01052 lock_info->thread_name = strdup(a.name);
01053
01054 pthread_mutexattr_init(&mutex_attr);
01055 pthread_mutexattr_settype(&mutex_attr, AST_MUTEX_KIND);
01056 pthread_mutex_init(&lock_info->lock, &mutex_attr);
01057 pthread_mutexattr_destroy(&mutex_attr);
01058
01059 pthread_mutex_lock(&lock_infos_lock.mutex);
01060 AST_LIST_INSERT_TAIL(&lock_infos, lock_info, entry);
01061 pthread_mutex_unlock(&lock_infos_lock.mutex);
01062 #endif
01063
01064
01065
01066
01067
01068
01069 ast_free(data);
01070 ast_register_thread(a.name);
01071 pthread_cleanup_push(ast_unregister_thread, (void *) pthread_self());
01072
01073 ret = a.start_routine(a.data);
01074
01075 pthread_cleanup_pop(1);
01076
01077 return ret;
01078 }
01079
01080 #endif
01081
01082 int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
01083 void *data, size_t stacksize, const char *file, const char *caller,
01084 int line, const char *start_fn)
01085 {
01086 #if !defined(LOW_MEMORY)
01087 struct thr_arg *a;
01088 #endif
01089
01090 if (!attr) {
01091 attr = ast_alloca(sizeof(*attr));
01092 pthread_attr_init(attr);
01093 }
01094
01095 #ifdef __linux__
01096
01097
01098
01099
01100
01101
01102
01103 if ((errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED)))
01104 ast_log(LOG_WARNING, "pthread_attr_setinheritsched: %s\n", strerror(errno));
01105 #endif
01106
01107 if (!stacksize)
01108 stacksize = AST_STACKSIZE;
01109
01110 if ((errno = pthread_attr_setstacksize(attr, stacksize ? stacksize : AST_STACKSIZE)))
01111 ast_log(LOG_WARNING, "pthread_attr_setstacksize: %s\n", strerror(errno));
01112
01113 #if !defined(LOW_MEMORY)
01114 if ((a = ast_malloc(sizeof(*a)))) {
01115 a->start_routine = start_routine;
01116 a->data = data;
01117 start_routine = dummy_start;
01118 if (ast_asprintf(&a->name, "%-20s started at [%5d] %s %s()",
01119 start_fn, line, file, caller) < 0) {
01120 a->name = NULL;
01121 }
01122 data = a;
01123 }
01124 #endif
01125
01126 return pthread_create(thread, attr, start_routine, data);
01127 }
01128
01129
01130 int ast_pthread_create_detached_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
01131 void *data, size_t stacksize, const char *file, const char *caller,
01132 int line, const char *start_fn)
01133 {
01134 unsigned char attr_destroy = 0;
01135 int res;
01136
01137 if (!attr) {
01138 attr = ast_alloca(sizeof(*attr));
01139 pthread_attr_init(attr);
01140 attr_destroy = 1;
01141 }
01142
01143 if ((errno = pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED)))
01144 ast_log(LOG_WARNING, "pthread_attr_setdetachstate: %s\n", strerror(errno));
01145
01146 res = ast_pthread_create_stack(thread, attr, start_routine, data,
01147 stacksize, file, caller, line, start_fn);
01148
01149 if (attr_destroy)
01150 pthread_attr_destroy(attr);
01151
01152 return res;
01153 }
01154
01155 int ast_wait_for_input(int fd, int ms)
01156 {
01157 struct pollfd pfd[1];
01158 memset(pfd, 0, sizeof(pfd));
01159 pfd[0].fd = fd;
01160 pfd[0].events = POLLIN|POLLPRI;
01161 return ast_poll(pfd, 1, ms);
01162 }
01163
01164 static int ast_wait_for_output(int fd, int timeoutms)
01165 {
01166 struct pollfd pfd = {
01167 .fd = fd,
01168 .events = POLLOUT,
01169 };
01170 int res;
01171 struct timeval start = ast_tvnow();
01172 int elapsed = 0;
01173
01174
01175 while ((res = ast_poll(&pfd, 1, timeoutms - elapsed)) <= 0) {
01176 if (res == 0) {
01177
01178 #ifndef STANDALONE
01179 ast_debug(1, "Timed out trying to write\n");
01180 #endif
01181 return -1;
01182 } else if (res == -1) {
01183
01184
01185 if (errno == EINTR || errno == EAGAIN) {
01186 elapsed = ast_tvdiff_ms(ast_tvnow(), start);
01187 if (elapsed >= timeoutms) {
01188 return -1;
01189 }
01190
01191 continue;
01192 }
01193
01194
01195 ast_log(LOG_ERROR, "poll returned error: %s\n", strerror(errno));
01196
01197 return -1;
01198 }
01199 elapsed = ast_tvdiff_ms(ast_tvnow(), start);
01200 if (elapsed >= timeoutms) {
01201 return -1;
01202 }
01203 }
01204
01205 return 0;
01206 }
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217 int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
01218 {
01219 struct timeval start = ast_tvnow();
01220 int res = 0;
01221 int elapsed = 0;
01222
01223 while (len) {
01224 if (ast_wait_for_output(fd, timeoutms - elapsed)) {
01225 return -1;
01226 }
01227
01228 res = write(fd, s, len);
01229
01230 if (res < 0 && errno != EAGAIN && errno != EINTR) {
01231
01232 ast_log(LOG_ERROR, "write() returned error: %s\n", strerror(errno));
01233 return -1;
01234 }
01235
01236 if (res < 0) {
01237
01238 res = 0;
01239 }
01240
01241
01242 len -= res;
01243 s += res;
01244 res = 0;
01245
01246 elapsed = ast_tvdiff_ms(ast_tvnow(), start);
01247 if (elapsed >= timeoutms) {
01248
01249
01250 res = len ? -1 : 0;
01251 break;
01252 }
01253 }
01254
01255 return res;
01256 }
01257
01258 int ast_careful_fwrite(FILE *f, int fd, const char *src, size_t len, int timeoutms)
01259 {
01260 struct timeval start = ast_tvnow();
01261 int n = 0;
01262 int elapsed = 0;
01263
01264 while (len) {
01265 if (ast_wait_for_output(fd, timeoutms - elapsed)) {
01266
01267 return -1;
01268 }
01269
01270
01271 clearerr(f);
01272
01273 n = fwrite(src, 1, len, f);
01274
01275 if (ferror(f) && errno != EINTR && errno != EAGAIN) {
01276
01277 if (!feof(f)) {
01278
01279 ast_log(LOG_ERROR, "fwrite() returned error: %s\n", strerror(errno));
01280 }
01281 n = -1;
01282 break;
01283 }
01284
01285
01286 len -= n;
01287 src += n;
01288
01289 elapsed = ast_tvdiff_ms(ast_tvnow(), start);
01290 if (elapsed >= timeoutms) {
01291
01292
01293 n = len ? -1 : 0;
01294 break;
01295 }
01296 }
01297
01298 while (fflush(f)) {
01299 if (errno == EAGAIN || errno == EINTR) {
01300 continue;
01301 }
01302 if (!feof(f)) {
01303
01304 ast_log(LOG_ERROR, "fflush() returned error: %s\n", strerror(errno));
01305 }
01306 n = -1;
01307 break;
01308 }
01309
01310 return n < 0 ? -1 : 0;
01311 }
01312
01313 char *ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
01314 {
01315 char *e;
01316 char *q;
01317
01318 s = ast_strip(s);
01319 if ((q = strchr(beg_quotes, *s)) && *q != '\0') {
01320 e = s + strlen(s) - 1;
01321 if (*e == *(end_quotes + (q - beg_quotes))) {
01322 s++;
01323 *e = '\0';
01324 }
01325 }
01326
01327 return s;
01328 }
01329
01330 char *ast_unescape_semicolon(char *s)
01331 {
01332 char *e;
01333 char *work = s;
01334
01335 while ((e = strchr(work, ';'))) {
01336 if ((e > work) && (*(e-1) == '\\')) {
01337 memmove(e - 1, e, strlen(e) + 1);
01338 work = e;
01339 } else {
01340 work = e + 1;
01341 }
01342 }
01343
01344 return s;
01345 }
01346
01347
01348
01349 char *ast_unescape_c(char *src)
01350 {
01351 char c, *ret, *dst;
01352
01353 if (src == NULL)
01354 return NULL;
01355 for (ret = dst = src; (c = *src++); *dst++ = c ) {
01356 if (c != '\\')
01357 continue;
01358 switch ((c = *src++)) {
01359 case '\0':
01360 c = '\\';
01361 break;
01362 case 'b':
01363 c = '\b';
01364 break;
01365 case 'f':
01366 c = '\f';
01367 break;
01368 case 'n':
01369 c = '\n';
01370 break;
01371 case 'r':
01372 c = '\r';
01373 break;
01374 case 't':
01375 c = '\t';
01376 break;
01377 }
01378
01379 }
01380 *dst = '\0';
01381 return ret;
01382 }
01383
01384 int ast_build_string_va(char **buffer, size_t *space, const char *fmt, va_list ap)
01385 {
01386 int result;
01387
01388 if (!buffer || !*buffer || !space || !*space)
01389 return -1;
01390
01391 result = vsnprintf(*buffer, *space, fmt, ap);
01392
01393 if (result < 0)
01394 return -1;
01395 else if (result > *space)
01396 result = *space;
01397
01398 *buffer += result;
01399 *space -= result;
01400 return 0;
01401 }
01402
01403 int ast_build_string(char **buffer, size_t *space, const char *fmt, ...)
01404 {
01405 va_list ap;
01406 int result;
01407
01408 va_start(ap, fmt);
01409 result = ast_build_string_va(buffer, space, fmt, ap);
01410 va_end(ap);
01411
01412 return result;
01413 }
01414
01415 int ast_true(const char *s)
01416 {
01417 if (ast_strlen_zero(s))
01418 return 0;
01419
01420
01421 if (!strcasecmp(s, "yes") ||
01422 !strcasecmp(s, "true") ||
01423 !strcasecmp(s, "y") ||
01424 !strcasecmp(s, "t") ||
01425 !strcasecmp(s, "1") ||
01426 !strcasecmp(s, "on"))
01427 return -1;
01428
01429 return 0;
01430 }
01431
01432 int ast_false(const char *s)
01433 {
01434 if (ast_strlen_zero(s))
01435 return 0;
01436
01437
01438 if (!strcasecmp(s, "no") ||
01439 !strcasecmp(s, "false") ||
01440 !strcasecmp(s, "n") ||
01441 !strcasecmp(s, "f") ||
01442 !strcasecmp(s, "0") ||
01443 !strcasecmp(s, "off"))
01444 return -1;
01445
01446 return 0;
01447 }
01448
01449 #define ONE_MILLION 1000000
01450
01451
01452
01453
01454 static struct timeval tvfix(struct timeval a)
01455 {
01456 if (a.tv_usec >= ONE_MILLION) {
01457 ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
01458 (long)a.tv_sec, (long int) a.tv_usec);
01459 a.tv_sec += a.tv_usec / ONE_MILLION;
01460 a.tv_usec %= ONE_MILLION;
01461 } else if (a.tv_usec < 0) {
01462 ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
01463 (long)a.tv_sec, (long int) a.tv_usec);
01464 a.tv_usec = 0;
01465 }
01466 return a;
01467 }
01468
01469 struct timeval ast_tvadd(struct timeval a, struct timeval b)
01470 {
01471
01472 a = tvfix(a);
01473 b = tvfix(b);
01474 a.tv_sec += b.tv_sec;
01475 a.tv_usec += b.tv_usec;
01476 if (a.tv_usec >= ONE_MILLION) {
01477 a.tv_sec++;
01478 a.tv_usec -= ONE_MILLION;
01479 }
01480 return a;
01481 }
01482
01483 struct timeval ast_tvsub(struct timeval a, struct timeval b)
01484 {
01485
01486 a = tvfix(a);
01487 b = tvfix(b);
01488 a.tv_sec -= b.tv_sec;
01489 a.tv_usec -= b.tv_usec;
01490 if (a.tv_usec < 0) {
01491 a.tv_sec-- ;
01492 a.tv_usec += ONE_MILLION;
01493 }
01494 return a;
01495 }
01496
01497 int ast_remaining_ms(struct timeval start, int max_ms)
01498 {
01499 int ms;
01500
01501 if (max_ms < 0) {
01502 ms = max_ms;
01503 } else {
01504 ms = max_ms - ast_tvdiff_ms(ast_tvnow(), start);
01505 if (ms < 0) {
01506 ms = 0;
01507 }
01508 }
01509
01510 return ms;
01511 }
01512
01513 #undef ONE_MILLION
01514
01515
01516
01517
01518 #ifndef linux
01519 AST_MUTEX_DEFINE_STATIC(randomlock);
01520 #endif
01521
01522 long int ast_random(void)
01523 {
01524 long int res;
01525 #ifdef HAVE_DEV_URANDOM
01526 if (dev_urandom_fd >= 0) {
01527 int read_res = read(dev_urandom_fd, &res, sizeof(res));
01528 if (read_res > 0) {
01529 long int rm = RAND_MAX;
01530 res = res < 0 ? ~res : res;
01531 rm++;
01532 return res % rm;
01533 }
01534 }
01535 #endif
01536 #ifdef linux
01537 res = random();
01538 #else
01539 ast_mutex_lock(&randomlock);
01540 res = random();
01541 ast_mutex_unlock(&randomlock);
01542 #endif
01543 return res;
01544 }
01545
01546 char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
01547 {
01548 char *dataPut = start;
01549 int inEscape = 0;
01550 int inQuotes = 0;
01551
01552 for (; *start; start++) {
01553 if (inEscape) {
01554 *dataPut++ = *start;
01555 inEscape = 0;
01556 } else {
01557 if (*start == '\\') {
01558 inEscape = 1;
01559 } else if (*start == '\'') {
01560 inQuotes = 1 - inQuotes;
01561 } else {
01562
01563 *dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
01564 }
01565 }
01566 }
01567 if (start != dataPut)
01568 *dataPut = 0;
01569 return dataPut;
01570 }
01571
01572 void ast_join(char *s, size_t len, const char * const w[])
01573 {
01574 int x, ofs = 0;
01575 const char *src;
01576
01577
01578 if (!s)
01579 return;
01580 for (x = 0; ofs < len && w[x]; x++) {
01581 if (x > 0)
01582 s[ofs++] = ' ';
01583 for (src = w[x]; *src && ofs < len; src++)
01584 s[ofs++] = *src;
01585 }
01586 if (ofs == len)
01587 ofs--;
01588 s[ofs] = '\0';
01589 }
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602 static const struct {
01603 ast_string_field_allocation allocation;
01604 char string[1];
01605 } __ast_string_field_empty_buffer;
01606
01607 ast_string_field __ast_string_field_empty = __ast_string_field_empty_buffer.string;
01608
01609 #define ALLOCATOR_OVERHEAD 48
01610
01611 static size_t optimal_alloc_size(size_t size)
01612 {
01613 unsigned int count;
01614
01615 size += ALLOCATOR_OVERHEAD;
01616
01617 for (count = 1; size; size >>= 1, count++);
01618
01619 return (1 << count) - ALLOCATOR_OVERHEAD;
01620 }
01621
01622
01623
01624
01625
01626 static int add_string_pool(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
01627 size_t size, const char *file, int lineno, const char *func)
01628 {
01629 struct ast_string_field_pool *pool;
01630 size_t alloc_size = optimal_alloc_size(sizeof(*pool) + size);
01631
01632 #if defined(__AST_DEBUG_MALLOC)
01633 if (!(pool = __ast_calloc(1, alloc_size, file, lineno, func))) {
01634 return -1;
01635 }
01636 #else
01637 if (!(pool = ast_calloc(1, alloc_size))) {
01638 return -1;
01639 }
01640 #endif
01641
01642 pool->prev = *pool_head;
01643 pool->size = alloc_size - sizeof(*pool);
01644 *pool_head = pool;
01645 mgr->last_alloc = NULL;
01646
01647 return 0;
01648 }
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662 int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
01663 int needed, const char *file, int lineno, const char *func)
01664 {
01665 const char **p = (const char **) pool_head + 1;
01666 struct ast_string_field_pool *cur = NULL;
01667 struct ast_string_field_pool *preserve = NULL;
01668
01669
01670 while ((struct ast_string_field_mgr *) p != mgr) {
01671 *p++ = __ast_string_field_empty;
01672 }
01673
01674 mgr->last_alloc = NULL;
01675 #if defined(__AST_DEBUG_MALLOC)
01676 mgr->owner_file = file;
01677 mgr->owner_func = func;
01678 mgr->owner_line = lineno;
01679 #endif
01680 if (needed > 0) {
01681 *pool_head = NULL;
01682 mgr->embedded_pool = NULL;
01683 return add_string_pool(mgr, pool_head, needed, file, lineno, func);
01684 }
01685
01686
01687
01688
01689
01690
01691
01692 if ((needed < 0) && mgr->embedded_pool) {
01693 needed = 0;
01694 }
01695
01696 if (needed < 0) {
01697 cur = *pool_head;
01698 } else if (mgr->embedded_pool) {
01699 preserve = mgr->embedded_pool;
01700 cur = *pool_head;
01701 } else {
01702 if (*pool_head == NULL) {
01703 ast_log(LOG_WARNING, "trying to reset empty pool\n");
01704 return -1;
01705 }
01706 preserve = *pool_head;
01707 cur = preserve->prev;
01708 }
01709
01710 if (preserve) {
01711 preserve->prev = NULL;
01712 preserve->used = preserve->active = 0;
01713 }
01714
01715 while (cur) {
01716 struct ast_string_field_pool *prev = cur->prev;
01717
01718 if (cur != preserve) {
01719 ast_free(cur);
01720 }
01721 cur = prev;
01722 }
01723
01724 *pool_head = preserve;
01725
01726 return 0;
01727 }
01728
01729 ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr,
01730 struct ast_string_field_pool **pool_head, size_t needed)
01731 {
01732 char *result = NULL;
01733 size_t space = (*pool_head)->size - (*pool_head)->used;
01734 size_t to_alloc;
01735
01736
01737 to_alloc = ast_make_room_for(needed, ast_string_field_allocation);
01738 ast_assert(to_alloc % ast_alignof(ast_string_field_allocation) == 0);
01739
01740 if (__builtin_expect(to_alloc > space, 0)) {
01741 size_t new_size = (*pool_head)->size;
01742
01743 while (new_size < to_alloc) {
01744 new_size *= 2;
01745 }
01746
01747 #if defined(__AST_DEBUG_MALLOC)
01748 if (add_string_pool(mgr, pool_head, new_size, mgr->owner_file, mgr->owner_line, mgr->owner_func))
01749 return NULL;
01750 #else
01751 if (add_string_pool(mgr, pool_head, new_size, __FILE__, __LINE__, __FUNCTION__))
01752 return NULL;
01753 #endif
01754 }
01755
01756
01757
01758
01759
01760 result = (*pool_head)->base + (*pool_head)->used;
01761 (*pool_head)->used += to_alloc;
01762 (*pool_head)->active += needed;
01763 result += ast_alignof(ast_string_field_allocation);
01764 AST_STRING_FIELD_ALLOCATION(result) = needed;
01765 mgr->last_alloc = result;
01766
01767 return result;
01768 }
01769
01770 int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr,
01771 struct ast_string_field_pool **pool_head, size_t needed,
01772 const ast_string_field *ptr)
01773 {
01774 ssize_t grow = needed - AST_STRING_FIELD_ALLOCATION(*ptr);
01775 size_t space = (*pool_head)->size - (*pool_head)->used;
01776
01777 if (*ptr != mgr->last_alloc) {
01778 return 1;
01779 }
01780
01781 if (space < grow) {
01782 return 1;
01783 }
01784
01785 (*pool_head)->used += grow;
01786 (*pool_head)->active += grow;
01787 AST_STRING_FIELD_ALLOCATION(*ptr) += grow;
01788
01789 return 0;
01790 }
01791
01792 void __ast_string_field_release_active(struct ast_string_field_pool *pool_head,
01793 const ast_string_field ptr)
01794 {
01795 struct ast_string_field_pool *pool, *prev;
01796
01797 if (ptr == __ast_string_field_empty) {
01798 return;
01799 }
01800
01801 for (pool = pool_head, prev = NULL; pool; prev = pool, pool = pool->prev) {
01802 if ((ptr >= pool->base) && (ptr <= (pool->base + pool->size))) {
01803 pool->active -= AST_STRING_FIELD_ALLOCATION(ptr);
01804 if ((pool->active == 0) && prev) {
01805 prev->prev = pool->prev;
01806 ast_free(pool);
01807 }
01808 break;
01809 }
01810 }
01811 }
01812
01813 void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
01814 struct ast_string_field_pool **pool_head,
01815 ast_string_field *ptr, const char *format, va_list ap1, va_list ap2)
01816 {
01817 size_t needed;
01818 size_t available;
01819 size_t space = (*pool_head)->size - (*pool_head)->used;
01820 ssize_t grow;
01821 char *target;
01822
01823
01824
01825
01826
01827 if (*ptr != __ast_string_field_empty) {
01828 target = (char *) *ptr;
01829 available = AST_STRING_FIELD_ALLOCATION(*ptr);
01830 if (*ptr == mgr->last_alloc) {
01831 available += space;
01832 }
01833 } else {
01834
01835
01836
01837 target = (*pool_head)->base + (*pool_head)->used + ast_alignof(ast_string_field_allocation);
01838 available = space - ast_alignof(ast_string_field_allocation);
01839 }
01840
01841 needed = vsnprintf(target, available, format, ap1) + 1;
01842
01843 if (needed > available) {
01844
01845
01846
01847
01848 if (!(target = (char *) __ast_string_field_alloc_space(mgr, pool_head, needed))) {
01849 return;
01850 }
01851 vsprintf(target, format, ap2);
01852 __ast_string_field_release_active(*pool_head, *ptr);
01853 *ptr = target;
01854 } else if (*ptr != target) {
01855
01856
01857
01858 __ast_string_field_release_active(*pool_head, *ptr);
01859 mgr->last_alloc = *ptr = target;
01860 AST_STRING_FIELD_ALLOCATION(target) = needed;
01861 (*pool_head)->used += ast_make_room_for(needed, ast_string_field_allocation);
01862 (*pool_head)->active += needed;
01863 } else if ((grow = (needed - AST_STRING_FIELD_ALLOCATION(*ptr))) > 0) {
01864
01865
01866
01867 AST_STRING_FIELD_ALLOCATION(*ptr) += grow;
01868 (*pool_head)->used += ast_align_for(grow, ast_string_field_allocation);
01869 (*pool_head)->active += grow;
01870 }
01871 }
01872
01873 void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
01874 struct ast_string_field_pool **pool_head,
01875 ast_string_field *ptr, const char *format, ...)
01876 {
01877 va_list ap1, ap2;
01878
01879 va_start(ap1, format);
01880 va_start(ap2, format);
01881
01882 __ast_string_field_ptr_build_va(mgr, pool_head, ptr, format, ap1, ap2);
01883
01884 va_end(ap1);
01885 va_end(ap2);
01886 }
01887
01888 void *__ast_calloc_with_stringfields(unsigned int num_structs, size_t struct_size, size_t field_mgr_offset,
01889 size_t field_mgr_pool_offset, size_t pool_size, const char *file,
01890 int lineno, const char *func)
01891 {
01892 struct ast_string_field_mgr *mgr;
01893 struct ast_string_field_pool *pool;
01894 struct ast_string_field_pool **pool_head;
01895 size_t pool_size_needed = sizeof(*pool) + pool_size;
01896 size_t size_to_alloc = optimal_alloc_size(struct_size + pool_size_needed);
01897 void *allocation;
01898 unsigned int x;
01899
01900 #if defined(__AST_DEBUG_MALLOC)
01901 if (!(allocation = __ast_calloc(num_structs, size_to_alloc, file, lineno, func))) {
01902 return NULL;
01903 }
01904 #else
01905 if (!(allocation = ast_calloc(num_structs, size_to_alloc))) {
01906 return NULL;
01907 }
01908 #endif
01909
01910 for (x = 0; x < num_structs; x++) {
01911 void *base = allocation + (size_to_alloc * x);
01912 const char **p;
01913
01914 mgr = base + field_mgr_offset;
01915 pool_head = base + field_mgr_pool_offset;
01916 pool = base + struct_size;
01917
01918 p = (const char **) pool_head + 1;
01919 while ((struct ast_string_field_mgr *) p != mgr) {
01920 *p++ = __ast_string_field_empty;
01921 }
01922
01923 mgr->embedded_pool = pool;
01924 *pool_head = pool;
01925 pool->size = size_to_alloc - struct_size - sizeof(*pool);
01926 #if defined(__AST_DEBUG_MALLOC)
01927 mgr->owner_file = file;
01928 mgr->owner_func = func;
01929 mgr->owner_line = lineno;
01930 #endif
01931 }
01932
01933 return allocation;
01934 }
01935
01936
01937
01938 AST_MUTEX_DEFINE_STATIC(fetchadd_m);
01939
01940 int ast_atomic_fetchadd_int_slow(volatile int *p, int v)
01941 {
01942 int ret;
01943 ast_mutex_lock(&fetchadd_m);
01944 ret = *p;
01945 *p += v;
01946 ast_mutex_unlock(&fetchadd_m);
01947 return ret;
01948 }
01949
01950
01951
01952
01953 int ast_get_timeval(const char *src, struct timeval *dst, struct timeval _default, int *consumed)
01954 {
01955 long double dtv = 0.0;
01956 int scanned;
01957
01958 if (dst == NULL)
01959 return -1;
01960
01961 *dst = _default;
01962
01963 if (ast_strlen_zero(src))
01964 return -1;
01965
01966
01967 if (sscanf(src, "%30Lf%n", &dtv, &scanned) > 0) {
01968 dst->tv_sec = dtv;
01969 dst->tv_usec = (dtv - dst->tv_sec) * 1000000.0;
01970 if (consumed)
01971 *consumed = scanned;
01972 return 0;
01973 } else
01974 return -1;
01975 }
01976
01977
01978
01979
01980 int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
01981 {
01982 long t;
01983 int scanned;
01984
01985 if (dst == NULL)
01986 return -1;
01987
01988 *dst = _default;
01989
01990 if (ast_strlen_zero(src))
01991 return -1;
01992
01993
01994 if (sscanf(src, "%30ld%n", &t, &scanned) == 1) {
01995 *dst = t;
01996 if (consumed)
01997 *consumed = scanned;
01998 return 0;
01999 } else
02000 return -1;
02001 }
02002
02003 void ast_enable_packet_fragmentation(int sock)
02004 {
02005 #if defined(HAVE_IP_MTU_DISCOVER)
02006 int val = IP_PMTUDISC_DONT;
02007
02008 if (setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val)))
02009 ast_log(LOG_WARNING, "Unable to disable PMTU discovery. Large UDP packets may fail to be delivered when sent from this socket.\n");
02010 #endif
02011 }
02012
02013 int ast_mkdir(const char *path, int mode)
02014 {
02015 char *ptr;
02016 int len = strlen(path), count = 0, x, piececount = 0;
02017 char *tmp = ast_strdupa(path);
02018 char **pieces;
02019 char *fullpath = ast_alloca(len + 1);
02020 int res = 0;
02021
02022 for (ptr = tmp; *ptr; ptr++) {
02023 if (*ptr == '/')
02024 count++;
02025 }
02026
02027
02028 pieces = ast_alloca(count * sizeof(*pieces));
02029 for (ptr = tmp; *ptr; ptr++) {
02030 if (*ptr == '/') {
02031 *ptr = '\0';
02032 pieces[piececount++] = ptr + 1;
02033 }
02034 }
02035
02036 *fullpath = '\0';
02037 for (x = 0; x < piececount; x++) {
02038
02039 strcat(fullpath, "/");
02040 strcat(fullpath, pieces[x]);
02041 res = mkdir(fullpath, mode);
02042 if (res && errno != EEXIST)
02043 return errno;
02044 }
02045 return 0;
02046 }
02047
02048 int ast_utils_init(void)
02049 {
02050 #ifdef HAVE_DEV_URANDOM
02051 dev_urandom_fd = open("/dev/urandom", O_RDONLY);
02052 #endif
02053 base64_init();
02054 #ifdef DEBUG_THREADS
02055 #if !defined(LOW_MEMORY)
02056 ast_cli_register_multiple(utils_cli, ARRAY_LEN(utils_cli));
02057 #endif
02058 #endif
02059 return 0;
02060 }
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070 int ast_parse_digest(const char *digest, struct ast_http_digest *d, int request, int pedantic) {
02071 char *c;
02072 struct ast_str *str = ast_str_create(16);
02073
02074
02075 const struct x {
02076 const char *key;
02077 const ast_string_field *field;
02078 } *i, keys[] = {
02079 { "username=", &d->username },
02080 { "realm=", &d->realm },
02081 { "nonce=", &d->nonce },
02082 { "uri=", &d->uri },
02083 { "domain=", &d->domain },
02084 { "response=", &d->response },
02085 { "cnonce=", &d->cnonce },
02086 { "opaque=", &d->opaque },
02087
02088 { "algorithm=", NULL },
02089 { "qop=", NULL },
02090 { "nc=", NULL },
02091 { NULL, 0 },
02092 };
02093
02094 if (ast_strlen_zero(digest) || !d || !str) {
02095 ast_free(str);
02096 return -1;
02097 }
02098
02099 ast_str_set(&str, 0, "%s", digest);
02100
02101 c = ast_skip_blanks(ast_str_buffer(str));
02102
02103 if (strncasecmp(c, "Digest ", strlen("Digest "))) {
02104 ast_log(LOG_WARNING, "Missing Digest.\n");
02105 ast_free(str);
02106 return -1;
02107 }
02108 c += strlen("Digest ");
02109
02110
02111 while (c && *c && *(c = ast_skip_blanks(c))) {
02112
02113 for (i = keys; i->key != NULL; i++) {
02114 char *src, *separator;
02115 int unescape = 0;
02116 if (strncasecmp(c, i->key, strlen(i->key)) != 0) {
02117 continue;
02118 }
02119
02120
02121 c += strlen(i->key);
02122 if (*c == '"') {
02123 src = ++c;
02124 separator = "\"";
02125 unescape = 1;
02126 } else {
02127 src = c;
02128 separator = ",";
02129 }
02130 strsep(&c, separator);
02131 if (unescape) {
02132 ast_unescape_c(src);
02133 }
02134 if (i->field) {
02135 ast_string_field_ptr_set(d, i->field, src);
02136 } else {
02137
02138 if (!strcasecmp(i->key, "algorithm=")) {
02139 if (strcasecmp(src, "MD5")) {
02140 ast_log(LOG_WARNING, "Digest algorithm: \"%s\" not supported.\n", src);
02141 ast_free(str);
02142 return -1;
02143 }
02144 } else if (!strcasecmp(i->key, "qop=") && !strcasecmp(src, "auth")) {
02145 d->qop = 1;
02146 } else if (!strcasecmp(i->key, "nc=")) {
02147 unsigned long u;
02148 if (sscanf(src, "%30lx", &u) != 1) {
02149 ast_log(LOG_WARNING, "Incorrect Digest nc value: \"%s\".\n", src);
02150 ast_free(str);
02151 return -1;
02152 }
02153 ast_string_field_set(d, nc, src);
02154 }
02155 }
02156 break;
02157 }
02158 if (i->key == NULL) {
02159 strsep(&c, ",");
02160 }
02161 }
02162 ast_free(str);
02163
02164
02165 if (ast_strlen_zero(d->realm) || ast_strlen_zero(d->nonce)) {
02166
02167 return -1;
02168 }
02169
02170 if (!request) {
02171
02172 if (ast_strlen_zero(d->username) || ast_strlen_zero(d->uri) || ast_strlen_zero(d->response)) {
02173 return -1;
02174 }
02175
02176 if (pedantic && d->qop && (ast_strlen_zero(d->cnonce) || ast_strlen_zero(d->nc))) {
02177 return -1;
02178 }
02179 }
02180
02181 return 0;
02182 }
02183
02184 #ifndef __AST_DEBUG_MALLOC
02185 int _ast_asprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, ...)
02186 {
02187 int res;
02188 va_list ap;
02189
02190 va_start(ap, fmt);
02191 if ((res = vasprintf(ret, fmt, ap)) == -1) {
02192 MALLOC_FAILURE_MSG;
02193 }
02194 va_end(ap);
02195
02196 return res;
02197 }
02198 #endif
02199
02200 char *ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size)
02201 {
02202 const char *envPATH = getenv("PATH");
02203 char *tpath, *path;
02204 struct stat unused;
02205 if (!envPATH) {
02206 return NULL;
02207 }
02208 tpath = ast_strdupa(envPATH);
02209 while ((path = strsep(&tpath, ":"))) {
02210 snprintf(fullpath, fullpath_size, "%s/%s", path, binary);
02211 if (!stat(fullpath, &unused)) {
02212 return fullpath;
02213 }
02214 }
02215 return NULL;
02216 }
02217
02218 void ast_do_crash(void)
02219 {
02220 #if defined(DO_CRASH)
02221 abort();
02222
02223
02224
02225
02226 *((int *) 0) = 0;
02227 #endif
02228 }
02229
02230 #if defined(AST_DEVMODE)
02231 void __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function)
02232 {
02233
02234
02235
02236
02237 ast_log(__LOG_ERROR, file, line, function, "FRACK!, Failed assertion %s (%d)\n",
02238 condition_str, condition);
02239 fprintf(stderr, "FRACK!, Failed assertion %s (%d) at line %d in %s of %s\n",
02240 condition_str, condition, line, function, file);
02241
02242
02243
02244
02245
02246 usleep(1);
02247 ast_do_crash();
02248 }
02249 #endif