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: 371690 $")
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
00471 const char *ast_inet_ntoa(struct in_addr ia)
00472 {
00473 char *buf;
00474
00475 if (!(buf = ast_threadstorage_get(&inet_ntoa_buf, INET_ADDRSTRLEN)))
00476 return "";
00477
00478 return inet_ntop(AF_INET, &ia, buf, INET_ADDRSTRLEN);
00479 }
00480
00481 #ifdef HAVE_DEV_URANDOM
00482 static int dev_urandom_fd;
00483 #endif
00484
00485 #ifndef __linux__
00486 #undef pthread_create
00487 #endif
00488
00489 #if !defined(LOW_MEMORY)
00490
00491 #ifdef DEBUG_THREADS
00492
00493
00494 #define AST_MAX_LOCKS 64
00495
00496
00497 #undef pthread_mutex_t
00498 #undef pthread_mutex_lock
00499 #undef pthread_mutex_unlock
00500 #undef pthread_mutex_init
00501 #undef pthread_mutex_destroy
00502
00503
00504
00505
00506
00507
00508 struct thr_lock_info {
00509
00510 pthread_t thread_id;
00511
00512 const char *thread_name;
00513
00514 struct {
00515 const char *file;
00516 int line_num;
00517 const char *func;
00518 const char *lock_name;
00519 void *lock_addr;
00520 int times_locked;
00521 enum ast_lock_type type;
00522
00523 int pending:2;
00524 #ifdef HAVE_BKTR
00525 struct ast_bt *backtrace;
00526 #endif
00527 } locks[AST_MAX_LOCKS];
00528
00529
00530
00531 unsigned int num_locks;
00532
00533
00534 pthread_mutex_t lock;
00535 AST_LIST_ENTRY(thr_lock_info) entry;
00536 };
00537
00538
00539
00540
00541 AST_MUTEX_DEFINE_STATIC(lock_infos_lock);
00542
00543
00544
00545 static AST_LIST_HEAD_NOLOCK_STATIC(lock_infos, thr_lock_info);
00546
00547
00548
00549
00550
00551
00552 static void lock_info_destroy(void *data)
00553 {
00554 struct thr_lock_info *lock_info = data;
00555 int i;
00556
00557 pthread_mutex_lock(&lock_infos_lock.mutex);
00558 AST_LIST_REMOVE(&lock_infos, lock_info, entry);
00559 pthread_mutex_unlock(&lock_infos_lock.mutex);
00560
00561
00562 for (i = 0; i < lock_info->num_locks; i++) {
00563 if (lock_info->locks[i].pending == -1) {
00564
00565
00566 break;
00567 }
00568
00569 ast_log(LOG_ERROR,
00570 "Thread '%s' still has a lock! - '%s' (%p) from '%s' in %s:%d!\n",
00571 lock_info->thread_name,
00572 lock_info->locks[i].lock_name,
00573 lock_info->locks[i].lock_addr,
00574 lock_info->locks[i].func,
00575 lock_info->locks[i].file,
00576 lock_info->locks[i].line_num
00577 );
00578 }
00579
00580 pthread_mutex_destroy(&lock_info->lock);
00581 if (lock_info->thread_name)
00582 free((void *) lock_info->thread_name);
00583 free(lock_info);
00584 }
00585
00586
00587
00588
00589 AST_THREADSTORAGE_CUSTOM(thread_lock_info, NULL, lock_info_destroy);
00590 #ifdef HAVE_BKTR
00591 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
00592 int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
00593 #else
00594 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
00595 int line_num, const char *func, const char *lock_name, void *lock_addr)
00596 #endif
00597 {
00598 struct thr_lock_info *lock_info;
00599 int i;
00600
00601 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
00602 return;
00603
00604 pthread_mutex_lock(&lock_info->lock);
00605
00606 for (i = 0; i < lock_info->num_locks; i++) {
00607 if (lock_info->locks[i].lock_addr == lock_addr) {
00608 lock_info->locks[i].times_locked++;
00609 #ifdef HAVE_BKTR
00610 lock_info->locks[i].backtrace = bt;
00611 #endif
00612 pthread_mutex_unlock(&lock_info->lock);
00613 return;
00614 }
00615 }
00616
00617 if (lock_info->num_locks == AST_MAX_LOCKS) {
00618
00619 fprintf(stderr, "XXX ERROR XXX A thread holds more locks than '%d'."
00620 " Increase AST_MAX_LOCKS!\n", AST_MAX_LOCKS);
00621 pthread_mutex_unlock(&lock_info->lock);
00622 return;
00623 }
00624
00625 if (i && lock_info->locks[i - 1].pending == -1) {
00626
00627
00628
00629 i--;
00630 lock_info->num_locks--;
00631 memset(&lock_info->locks[i], 0, sizeof(lock_info->locks[0]));
00632 }
00633
00634 lock_info->locks[i].file = filename;
00635 lock_info->locks[i].line_num = line_num;
00636 lock_info->locks[i].func = func;
00637 lock_info->locks[i].lock_name = lock_name;
00638 lock_info->locks[i].lock_addr = lock_addr;
00639 lock_info->locks[i].times_locked = 1;
00640 lock_info->locks[i].type = type;
00641 lock_info->locks[i].pending = 1;
00642 #ifdef HAVE_BKTR
00643 lock_info->locks[i].backtrace = bt;
00644 #endif
00645 lock_info->num_locks++;
00646
00647 pthread_mutex_unlock(&lock_info->lock);
00648 }
00649
00650 void ast_mark_lock_acquired(void *lock_addr)
00651 {
00652 struct thr_lock_info *lock_info;
00653
00654 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
00655 return;
00656
00657 pthread_mutex_lock(&lock_info->lock);
00658 if (lock_info->locks[lock_info->num_locks - 1].lock_addr == lock_addr) {
00659 lock_info->locks[lock_info->num_locks - 1].pending = 0;
00660 }
00661 pthread_mutex_unlock(&lock_info->lock);
00662 }
00663
00664 void ast_mark_lock_failed(void *lock_addr)
00665 {
00666 struct thr_lock_info *lock_info;
00667
00668 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
00669 return;
00670
00671 pthread_mutex_lock(&lock_info->lock);
00672 if (lock_info->locks[lock_info->num_locks - 1].lock_addr == lock_addr) {
00673 lock_info->locks[lock_info->num_locks - 1].pending = -1;
00674 lock_info->locks[lock_info->num_locks - 1].times_locked--;
00675 }
00676 pthread_mutex_unlock(&lock_info->lock);
00677 }
00678
00679 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)
00680 {
00681 struct thr_lock_info *lock_info;
00682 int i = 0;
00683
00684 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
00685 return -1;
00686
00687 pthread_mutex_lock(&lock_info->lock);
00688
00689 for (i = lock_info->num_locks - 1; i >= 0; i--) {
00690 if (lock_info->locks[i].lock_addr == lock_addr)
00691 break;
00692 }
00693
00694 if (i == -1) {
00695
00696 pthread_mutex_unlock(&lock_info->lock);
00697 return -1;
00698 }
00699
00700 ast_copy_string(filename, lock_info->locks[i].file, filename_size);
00701 *lineno = lock_info->locks[i].line_num;
00702 ast_copy_string(func, lock_info->locks[i].func, func_size);
00703 ast_copy_string(mutex_name, lock_info->locks[i].lock_name, mutex_name_size);
00704
00705 pthread_mutex_unlock(&lock_info->lock);
00706
00707 return 0;
00708 }
00709
00710 #ifdef HAVE_BKTR
00711 void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
00712 #else
00713 void ast_remove_lock_info(void *lock_addr)
00714 #endif
00715 {
00716 struct thr_lock_info *lock_info;
00717 int i = 0;
00718
00719 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
00720 return;
00721
00722 pthread_mutex_lock(&lock_info->lock);
00723
00724 for (i = lock_info->num_locks - 1; i >= 0; i--) {
00725 if (lock_info->locks[i].lock_addr == lock_addr)
00726 break;
00727 }
00728
00729 if (i == -1) {
00730
00731 pthread_mutex_unlock(&lock_info->lock);
00732 return;
00733 }
00734
00735 if (lock_info->locks[i].times_locked > 1) {
00736 lock_info->locks[i].times_locked--;
00737 #ifdef HAVE_BKTR
00738 lock_info->locks[i].backtrace = bt;
00739 #endif
00740 pthread_mutex_unlock(&lock_info->lock);
00741 return;
00742 }
00743
00744 if (i < lock_info->num_locks - 1) {
00745
00746 memmove(&lock_info->locks[i], &lock_info->locks[i + 1],
00747 (lock_info->num_locks - (i + 1)) * sizeof(lock_info->locks[0]));
00748 }
00749
00750 lock_info->num_locks--;
00751
00752 pthread_mutex_unlock(&lock_info->lock);
00753 }
00754
00755 static const char *locktype2str(enum ast_lock_type type)
00756 {
00757 switch (type) {
00758 case AST_MUTEX:
00759 return "MUTEX";
00760 case AST_RDLOCK:
00761 return "RDLOCK";
00762 case AST_WRLOCK:
00763 return "WRLOCK";
00764 }
00765
00766 return "UNKNOWN";
00767 }
00768
00769 #ifdef HAVE_BKTR
00770 static void append_backtrace_information(struct ast_str **str, struct ast_bt *bt)
00771 {
00772 char **symbols;
00773 int num_frames;
00774
00775 if (!bt) {
00776 ast_str_append(str, 0, "\tNo backtrace to print\n");
00777 return;
00778 }
00779
00780
00781
00782 num_frames = bt->num_frames;
00783 if ((symbols = ast_bt_get_symbols(bt->addresses, num_frames))) {
00784 int frame_iterator;
00785
00786 for (frame_iterator = 0; frame_iterator < num_frames; ++frame_iterator) {
00787 ast_str_append(str, 0, "\t%s\n", symbols[frame_iterator]);
00788 }
00789
00790 free(symbols);
00791 } else {
00792 ast_str_append(str, 0, "\tCouldn't retrieve backtrace symbols\n");
00793 }
00794 }
00795 #endif
00796
00797 static void append_lock_information(struct ast_str **str, struct thr_lock_info *lock_info, int i)
00798 {
00799 int j;
00800 ast_mutex_t *lock;
00801 struct ast_lock_track *lt;
00802
00803 ast_str_append(str, 0, "=== ---> %sLock #%d (%s): %s %d %s %s %p (%d)\n",
00804 lock_info->locks[i].pending > 0 ? "Waiting for " :
00805 lock_info->locks[i].pending < 0 ? "Tried and failed to get " : "", i,
00806 lock_info->locks[i].file,
00807 locktype2str(lock_info->locks[i].type),
00808 lock_info->locks[i].line_num,
00809 lock_info->locks[i].func, lock_info->locks[i].lock_name,
00810 lock_info->locks[i].lock_addr,
00811 lock_info->locks[i].times_locked);
00812 #ifdef HAVE_BKTR
00813 append_backtrace_information(str, lock_info->locks[i].backtrace);
00814 #endif
00815
00816 if (!lock_info->locks[i].pending || lock_info->locks[i].pending == -1)
00817 return;
00818
00819
00820 if (lock_info->locks[i].type != AST_MUTEX)
00821 return;
00822
00823 lock = lock_info->locks[i].lock_addr;
00824 lt = lock->track;
00825 ast_reentrancy_lock(lt);
00826 for (j = 0; *str && j < lt->reentrancy; j++) {
00827 ast_str_append(str, 0, "=== --- ---> Locked Here: %s line %d (%s)\n",
00828 lt->file[j], lt->lineno[j], lt->func[j]);
00829 }
00830 ast_reentrancy_unlock(lt);
00831 }
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853 void log_show_lock(void *this_lock_addr)
00854 {
00855 struct thr_lock_info *lock_info;
00856 struct ast_str *str;
00857
00858 if (!(str = ast_str_create(4096))) {
00859 ast_log(LOG_NOTICE,"Could not create str\n");
00860 return;
00861 }
00862
00863
00864 pthread_mutex_lock(&lock_infos_lock.mutex);
00865 AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) {
00866 int i;
00867 pthread_mutex_lock(&lock_info->lock);
00868 for (i = 0; str && i < lock_info->num_locks; i++) {
00869
00870
00871 if (lock_info->locks[i].lock_addr == this_lock_addr) {
00872 append_lock_information(&str, lock_info, i);
00873 ast_log(LOG_NOTICE, "%s", ast_str_buffer(str));
00874 break;
00875 }
00876 }
00877 pthread_mutex_unlock(&lock_info->lock);
00878 }
00879 pthread_mutex_unlock(&lock_infos_lock.mutex);
00880 ast_free(str);
00881 }
00882
00883
00884 static char *handle_show_locks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00885 {
00886 struct thr_lock_info *lock_info;
00887 struct ast_str *str;
00888
00889 if (!(str = ast_str_create(4096)))
00890 return CLI_FAILURE;
00891
00892 switch (cmd) {
00893 case CLI_INIT:
00894 e->command = "core show locks";
00895 e->usage =
00896 "Usage: core show locks\n"
00897 " This command is for lock debugging. It prints out which locks\n"
00898 "are owned by each active thread.\n";
00899 return NULL;
00900
00901 case CLI_GENERATE:
00902 return NULL;
00903 }
00904
00905 ast_str_append(&str, 0, "\n"
00906 "=======================================================================\n"
00907 "=== Currently Held Locks ==============================================\n"
00908 "=======================================================================\n"
00909 "===\n"
00910 "=== <pending> <lock#> (<file>): <lock type> <line num> <function> <lock name> <lock addr> (times locked)\n"
00911 "===\n");
00912
00913 if (!str)
00914 return CLI_FAILURE;
00915
00916 pthread_mutex_lock(&lock_infos_lock.mutex);
00917 AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) {
00918 int i;
00919 if (lock_info->num_locks) {
00920 ast_str_append(&str, 0, "=== Thread ID: 0x%lx (%s)\n", (long) lock_info->thread_id,
00921 lock_info->thread_name);
00922 pthread_mutex_lock(&lock_info->lock);
00923 for (i = 0; str && i < lock_info->num_locks; i++) {
00924 append_lock_information(&str, lock_info, i);
00925 }
00926 pthread_mutex_unlock(&lock_info->lock);
00927 if (!str)
00928 break;
00929 ast_str_append(&str, 0, "=== -------------------------------------------------------------------\n"
00930 "===\n");
00931 if (!str)
00932 break;
00933 }
00934 }
00935 pthread_mutex_unlock(&lock_infos_lock.mutex);
00936
00937 if (!str)
00938 return CLI_FAILURE;
00939
00940 ast_str_append(&str, 0, "=======================================================================\n"
00941 "\n");
00942
00943 if (!str)
00944 return CLI_FAILURE;
00945
00946 ast_cli(a->fd, "%s", ast_str_buffer(str));
00947
00948 ast_free(str);
00949
00950 return CLI_SUCCESS;
00951 }
00952
00953 static struct ast_cli_entry utils_cli[] = {
00954 AST_CLI_DEFINE(handle_show_locks, "Show which locks are held by which thread"),
00955 };
00956
00957 #endif
00958
00959
00960
00961
00962
00963
00964 struct thr_arg {
00965 void *(*start_routine)(void *);
00966 void *data;
00967 char *name;
00968 };
00969
00970
00971
00972
00973
00974
00975
00976
00977 static void *dummy_start(void *data)
00978 {
00979 void *ret;
00980 struct thr_arg a = *((struct thr_arg *) data);
00981 #ifdef DEBUG_THREADS
00982 struct thr_lock_info *lock_info;
00983 pthread_mutexattr_t mutex_attr;
00984 #endif
00985
00986
00987
00988
00989
00990
00991 ast_free(data);
00992 ast_register_thread(a.name);
00993 pthread_cleanup_push(ast_unregister_thread, (void *) pthread_self());
00994
00995 #ifdef DEBUG_THREADS
00996 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
00997 return NULL;
00998
00999 lock_info->thread_id = pthread_self();
01000 lock_info->thread_name = strdup(a.name);
01001
01002 pthread_mutexattr_init(&mutex_attr);
01003 pthread_mutexattr_settype(&mutex_attr, AST_MUTEX_KIND);
01004 pthread_mutex_init(&lock_info->lock, &mutex_attr);
01005 pthread_mutexattr_destroy(&mutex_attr);
01006
01007 pthread_mutex_lock(&lock_infos_lock.mutex);
01008 AST_LIST_INSERT_TAIL(&lock_infos, lock_info, entry);
01009 pthread_mutex_unlock(&lock_infos_lock.mutex);
01010 #endif
01011
01012 ret = a.start_routine(a.data);
01013
01014 pthread_cleanup_pop(1);
01015
01016 return ret;
01017 }
01018
01019 #endif
01020
01021 int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
01022 void *data, size_t stacksize, const char *file, const char *caller,
01023 int line, const char *start_fn)
01024 {
01025 #if !defined(LOW_MEMORY)
01026 struct thr_arg *a;
01027 #endif
01028
01029 if (!attr) {
01030 attr = ast_alloca(sizeof(*attr));
01031 pthread_attr_init(attr);
01032 }
01033
01034 #ifdef __linux__
01035
01036
01037
01038
01039
01040
01041
01042 if ((errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED)))
01043 ast_log(LOG_WARNING, "pthread_attr_setinheritsched: %s\n", strerror(errno));
01044 #endif
01045
01046 if (!stacksize)
01047 stacksize = AST_STACKSIZE;
01048
01049 if ((errno = pthread_attr_setstacksize(attr, stacksize ? stacksize : AST_STACKSIZE)))
01050 ast_log(LOG_WARNING, "pthread_attr_setstacksize: %s\n", strerror(errno));
01051
01052 #if !defined(LOW_MEMORY)
01053 if ((a = ast_malloc(sizeof(*a)))) {
01054 a->start_routine = start_routine;
01055 a->data = data;
01056 start_routine = dummy_start;
01057 if (ast_asprintf(&a->name, "%-20s started at [%5d] %s %s()",
01058 start_fn, line, file, caller) < 0) {
01059 a->name = NULL;
01060 }
01061 data = a;
01062 }
01063 #endif
01064
01065 return pthread_create(thread, attr, start_routine, data);
01066 }
01067
01068
01069 int ast_pthread_create_detached_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
01070 void *data, size_t stacksize, const char *file, const char *caller,
01071 int line, const char *start_fn)
01072 {
01073 unsigned char attr_destroy = 0;
01074 int res;
01075
01076 if (!attr) {
01077 attr = ast_alloca(sizeof(*attr));
01078 pthread_attr_init(attr);
01079 attr_destroy = 1;
01080 }
01081
01082 if ((errno = pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED)))
01083 ast_log(LOG_WARNING, "pthread_attr_setdetachstate: %s\n", strerror(errno));
01084
01085 res = ast_pthread_create_stack(thread, attr, start_routine, data,
01086 stacksize, file, caller, line, start_fn);
01087
01088 if (attr_destroy)
01089 pthread_attr_destroy(attr);
01090
01091 return res;
01092 }
01093
01094 int ast_wait_for_input(int fd, int ms)
01095 {
01096 struct pollfd pfd[1];
01097 memset(pfd, 0, sizeof(pfd));
01098 pfd[0].fd = fd;
01099 pfd[0].events = POLLIN|POLLPRI;
01100 return ast_poll(pfd, 1, ms);
01101 }
01102
01103 static int ast_wait_for_output(int fd, int timeoutms)
01104 {
01105 struct pollfd pfd = {
01106 .fd = fd,
01107 .events = POLLOUT,
01108 };
01109 int res;
01110 struct timeval start = ast_tvnow();
01111 int elapsed = 0;
01112
01113
01114 while ((res = ast_poll(&pfd, 1, timeoutms - elapsed)) <= 0) {
01115 if (res == 0) {
01116
01117 #ifndef STANDALONE
01118 ast_debug(1, "Timed out trying to write\n");
01119 #endif
01120 return -1;
01121 } else if (res == -1) {
01122
01123
01124 if (errno == EINTR || errno == EAGAIN) {
01125 elapsed = ast_tvdiff_ms(ast_tvnow(), start);
01126 if (elapsed >= timeoutms) {
01127 return -1;
01128 }
01129
01130 continue;
01131 }
01132
01133
01134 ast_log(LOG_ERROR, "poll returned error: %s\n", strerror(errno));
01135
01136 return -1;
01137 }
01138 elapsed = ast_tvdiff_ms(ast_tvnow(), start);
01139 if (elapsed >= timeoutms) {
01140 return -1;
01141 }
01142 }
01143
01144 return 0;
01145 }
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156 int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
01157 {
01158 struct timeval start = ast_tvnow();
01159 int res = 0;
01160 int elapsed = 0;
01161
01162 while (len) {
01163 if (ast_wait_for_output(fd, timeoutms - elapsed)) {
01164 return -1;
01165 }
01166
01167 res = write(fd, s, len);
01168
01169 if (res < 0 && errno != EAGAIN && errno != EINTR) {
01170
01171 ast_log(LOG_ERROR, "write() returned error: %s\n", strerror(errno));
01172 return -1;
01173 }
01174
01175 if (res < 0) {
01176
01177 res = 0;
01178 }
01179
01180
01181 len -= res;
01182 s += res;
01183 res = 0;
01184
01185 elapsed = ast_tvdiff_ms(ast_tvnow(), start);
01186 if (elapsed >= timeoutms) {
01187
01188
01189 res = len ? -1 : 0;
01190 break;
01191 }
01192 }
01193
01194 return res;
01195 }
01196
01197 int ast_careful_fwrite(FILE *f, int fd, const char *src, size_t len, int timeoutms)
01198 {
01199 struct timeval start = ast_tvnow();
01200 int n = 0;
01201 int elapsed = 0;
01202
01203 while (len) {
01204 if (ast_wait_for_output(fd, timeoutms - elapsed)) {
01205
01206 return -1;
01207 }
01208
01209
01210 clearerr(f);
01211
01212 n = fwrite(src, 1, len, f);
01213
01214 if (ferror(f) && errno != EINTR && errno != EAGAIN) {
01215
01216 if (!feof(f)) {
01217
01218 ast_log(LOG_ERROR, "fwrite() returned error: %s\n", strerror(errno));
01219 }
01220 n = -1;
01221 break;
01222 }
01223
01224
01225 len -= n;
01226 src += n;
01227
01228 elapsed = ast_tvdiff_ms(ast_tvnow(), start);
01229 if (elapsed >= timeoutms) {
01230
01231
01232 n = len ? -1 : 0;
01233 break;
01234 }
01235 }
01236
01237 while (fflush(f)) {
01238 if (errno == EAGAIN || errno == EINTR) {
01239 continue;
01240 }
01241 if (!feof(f)) {
01242
01243 ast_log(LOG_ERROR, "fflush() returned error: %s\n", strerror(errno));
01244 }
01245 n = -1;
01246 break;
01247 }
01248
01249 return n < 0 ? -1 : 0;
01250 }
01251
01252 char *ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
01253 {
01254 char *e;
01255 char *q;
01256
01257 s = ast_strip(s);
01258 if ((q = strchr(beg_quotes, *s)) && *q != '\0') {
01259 e = s + strlen(s) - 1;
01260 if (*e == *(end_quotes + (q - beg_quotes))) {
01261 s++;
01262 *e = '\0';
01263 }
01264 }
01265
01266 return s;
01267 }
01268
01269 char *ast_unescape_semicolon(char *s)
01270 {
01271 char *e;
01272 char *work = s;
01273
01274 while ((e = strchr(work, ';'))) {
01275 if ((e > work) && (*(e-1) == '\\')) {
01276 memmove(e - 1, e, strlen(e) + 1);
01277 work = e;
01278 } else {
01279 work = e + 1;
01280 }
01281 }
01282
01283 return s;
01284 }
01285
01286
01287
01288 char *ast_unescape_c(char *src)
01289 {
01290 char c, *ret, *dst;
01291
01292 if (src == NULL)
01293 return NULL;
01294 for (ret = dst = src; (c = *src++); *dst++ = c ) {
01295 if (c != '\\')
01296 continue;
01297 switch ((c = *src++)) {
01298 case '\0':
01299 c = '\\';
01300 break;
01301 case 'b':
01302 c = '\b';
01303 break;
01304 case 'f':
01305 c = '\f';
01306 break;
01307 case 'n':
01308 c = '\n';
01309 break;
01310 case 'r':
01311 c = '\r';
01312 break;
01313 case 't':
01314 c = '\t';
01315 break;
01316 }
01317
01318 }
01319 *dst = '\0';
01320 return ret;
01321 }
01322
01323 int ast_build_string_va(char **buffer, size_t *space, const char *fmt, va_list ap)
01324 {
01325 int result;
01326
01327 if (!buffer || !*buffer || !space || !*space)
01328 return -1;
01329
01330 result = vsnprintf(*buffer, *space, fmt, ap);
01331
01332 if (result < 0)
01333 return -1;
01334 else if (result > *space)
01335 result = *space;
01336
01337 *buffer += result;
01338 *space -= result;
01339 return 0;
01340 }
01341
01342 int ast_build_string(char **buffer, size_t *space, const char *fmt, ...)
01343 {
01344 va_list ap;
01345 int result;
01346
01347 va_start(ap, fmt);
01348 result = ast_build_string_va(buffer, space, fmt, ap);
01349 va_end(ap);
01350
01351 return result;
01352 }
01353
01354 int ast_true(const char *s)
01355 {
01356 if (ast_strlen_zero(s))
01357 return 0;
01358
01359
01360 if (!strcasecmp(s, "yes") ||
01361 !strcasecmp(s, "true") ||
01362 !strcasecmp(s, "y") ||
01363 !strcasecmp(s, "t") ||
01364 !strcasecmp(s, "1") ||
01365 !strcasecmp(s, "on"))
01366 return -1;
01367
01368 return 0;
01369 }
01370
01371 int ast_false(const char *s)
01372 {
01373 if (ast_strlen_zero(s))
01374 return 0;
01375
01376
01377 if (!strcasecmp(s, "no") ||
01378 !strcasecmp(s, "false") ||
01379 !strcasecmp(s, "n") ||
01380 !strcasecmp(s, "f") ||
01381 !strcasecmp(s, "0") ||
01382 !strcasecmp(s, "off"))
01383 return -1;
01384
01385 return 0;
01386 }
01387
01388 #define ONE_MILLION 1000000
01389
01390
01391
01392
01393 static struct timeval tvfix(struct timeval a)
01394 {
01395 if (a.tv_usec >= ONE_MILLION) {
01396 ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
01397 (long)a.tv_sec, (long int) a.tv_usec);
01398 a.tv_sec += a.tv_usec / ONE_MILLION;
01399 a.tv_usec %= ONE_MILLION;
01400 } else if (a.tv_usec < 0) {
01401 ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
01402 (long)a.tv_sec, (long int) a.tv_usec);
01403 a.tv_usec = 0;
01404 }
01405 return a;
01406 }
01407
01408 struct timeval ast_tvadd(struct timeval a, struct timeval b)
01409 {
01410
01411 a = tvfix(a);
01412 b = tvfix(b);
01413 a.tv_sec += b.tv_sec;
01414 a.tv_usec += b.tv_usec;
01415 if (a.tv_usec >= ONE_MILLION) {
01416 a.tv_sec++;
01417 a.tv_usec -= ONE_MILLION;
01418 }
01419 return a;
01420 }
01421
01422 struct timeval ast_tvsub(struct timeval a, struct timeval b)
01423 {
01424
01425 a = tvfix(a);
01426 b = tvfix(b);
01427 a.tv_sec -= b.tv_sec;
01428 a.tv_usec -= b.tv_usec;
01429 if (a.tv_usec < 0) {
01430 a.tv_sec-- ;
01431 a.tv_usec += ONE_MILLION;
01432 }
01433 return a;
01434 }
01435 #undef ONE_MILLION
01436
01437
01438
01439
01440 #ifndef linux
01441 AST_MUTEX_DEFINE_STATIC(randomlock);
01442 #endif
01443
01444 long int ast_random(void)
01445 {
01446 long int res;
01447 #ifdef HAVE_DEV_URANDOM
01448 if (dev_urandom_fd >= 0) {
01449 int read_res = read(dev_urandom_fd, &res, sizeof(res));
01450 if (read_res > 0) {
01451 long int rm = RAND_MAX;
01452 res = res < 0 ? ~res : res;
01453 rm++;
01454 return res % rm;
01455 }
01456 }
01457 #endif
01458 #ifdef linux
01459 res = random();
01460 #else
01461 ast_mutex_lock(&randomlock);
01462 res = random();
01463 ast_mutex_unlock(&randomlock);
01464 #endif
01465 return res;
01466 }
01467
01468 char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
01469 {
01470 char *dataPut = start;
01471 int inEscape = 0;
01472 int inQuotes = 0;
01473
01474 for (; *start; start++) {
01475 if (inEscape) {
01476 *dataPut++ = *start;
01477 inEscape = 0;
01478 } else {
01479 if (*start == '\\') {
01480 inEscape = 1;
01481 } else if (*start == '\'') {
01482 inQuotes = 1 - inQuotes;
01483 } else {
01484
01485 *dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
01486 }
01487 }
01488 }
01489 if (start != dataPut)
01490 *dataPut = 0;
01491 return dataPut;
01492 }
01493
01494 void ast_join(char *s, size_t len, const char * const w[])
01495 {
01496 int x, ofs = 0;
01497 const char *src;
01498
01499
01500 if (!s)
01501 return;
01502 for (x = 0; ofs < len && w[x]; x++) {
01503 if (x > 0)
01504 s[ofs++] = ' ';
01505 for (src = w[x]; *src && ofs < len; src++)
01506 s[ofs++] = *src;
01507 }
01508 if (ofs == len)
01509 ofs--;
01510 s[ofs] = '\0';
01511 }
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524 static const struct {
01525 ast_string_field_allocation allocation;
01526 char string[1];
01527 } __ast_string_field_empty_buffer;
01528
01529 ast_string_field __ast_string_field_empty = __ast_string_field_empty_buffer.string;
01530
01531 #define ALLOCATOR_OVERHEAD 48
01532
01533 static size_t optimal_alloc_size(size_t size)
01534 {
01535 unsigned int count;
01536
01537 size += ALLOCATOR_OVERHEAD;
01538
01539 for (count = 1; size; size >>= 1, count++);
01540
01541 return (1 << count) - ALLOCATOR_OVERHEAD;
01542 }
01543
01544
01545
01546
01547
01548 static int add_string_pool(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
01549 size_t size, const char *file, int lineno, const char *func)
01550 {
01551 struct ast_string_field_pool *pool;
01552 size_t alloc_size = optimal_alloc_size(sizeof(*pool) + size);
01553
01554 #if defined(__AST_DEBUG_MALLOC)
01555 if (!(pool = __ast_calloc(1, alloc_size, file, lineno, func))) {
01556 return -1;
01557 }
01558 #else
01559 if (!(pool = ast_calloc(1, alloc_size))) {
01560 return -1;
01561 }
01562 #endif
01563
01564 pool->prev = *pool_head;
01565 pool->size = alloc_size - sizeof(*pool);
01566 *pool_head = pool;
01567 mgr->last_alloc = NULL;
01568
01569 return 0;
01570 }
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584 int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head,
01585 int needed, const char *file, int lineno, const char *func)
01586 {
01587 const char **p = (const char **) pool_head + 1;
01588 struct ast_string_field_pool *cur = NULL;
01589 struct ast_string_field_pool *preserve = NULL;
01590
01591
01592 while ((struct ast_string_field_mgr *) p != mgr) {
01593 *p++ = __ast_string_field_empty;
01594 }
01595
01596 mgr->last_alloc = NULL;
01597 #if defined(__AST_DEBUG_MALLOC)
01598 mgr->owner_file = file;
01599 mgr->owner_func = func;
01600 mgr->owner_line = lineno;
01601 #endif
01602 if (needed > 0) {
01603 *pool_head = NULL;
01604 mgr->embedded_pool = NULL;
01605 return add_string_pool(mgr, pool_head, needed, file, lineno, func);
01606 }
01607
01608
01609
01610
01611
01612
01613
01614 if ((needed < 0) && mgr->embedded_pool) {
01615 needed = 0;
01616 }
01617
01618 if (needed < 0) {
01619 cur = *pool_head;
01620 } else if (mgr->embedded_pool) {
01621 preserve = mgr->embedded_pool;
01622 cur = *pool_head;
01623 } else {
01624 if (*pool_head == NULL) {
01625 ast_log(LOG_WARNING, "trying to reset empty pool\n");
01626 return -1;
01627 }
01628 preserve = *pool_head;
01629 cur = preserve->prev;
01630 }
01631
01632 if (preserve) {
01633 preserve->prev = NULL;
01634 preserve->used = preserve->active = 0;
01635 }
01636
01637 while (cur) {
01638 struct ast_string_field_pool *prev = cur->prev;
01639
01640 if (cur != preserve) {
01641 ast_free(cur);
01642 }
01643 cur = prev;
01644 }
01645
01646 *pool_head = preserve;
01647
01648 return 0;
01649 }
01650
01651 ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr,
01652 struct ast_string_field_pool **pool_head, size_t needed)
01653 {
01654 char *result = NULL;
01655 size_t space = (*pool_head)->size - (*pool_head)->used;
01656 size_t to_alloc;
01657
01658
01659 to_alloc = ast_make_room_for(needed, ast_string_field_allocation);
01660 ast_assert(to_alloc % ast_alignof(ast_string_field_allocation) == 0);
01661
01662 if (__builtin_expect(to_alloc > space, 0)) {
01663 size_t new_size = (*pool_head)->size;
01664
01665 while (new_size < to_alloc) {
01666 new_size *= 2;
01667 }
01668
01669 #if defined(__AST_DEBUG_MALLOC)
01670 if (add_string_pool(mgr, pool_head, new_size, mgr->owner_file, mgr->owner_line, mgr->owner_func))
01671 return NULL;
01672 #else
01673 if (add_string_pool(mgr, pool_head, new_size, __FILE__, __LINE__, __FUNCTION__))
01674 return NULL;
01675 #endif
01676 }
01677
01678
01679
01680
01681
01682 result = (*pool_head)->base + (*pool_head)->used;
01683 (*pool_head)->used += to_alloc;
01684 (*pool_head)->active += needed;
01685 result += ast_alignof(ast_string_field_allocation);
01686 AST_STRING_FIELD_ALLOCATION(result) = needed;
01687 mgr->last_alloc = result;
01688
01689 return result;
01690 }
01691
01692 int __ast_string_field_ptr_grow(struct ast_string_field_mgr *mgr,
01693 struct ast_string_field_pool **pool_head, size_t needed,
01694 const ast_string_field *ptr)
01695 {
01696 ssize_t grow = needed - AST_STRING_FIELD_ALLOCATION(*ptr);
01697 size_t space = (*pool_head)->size - (*pool_head)->used;
01698
01699 if (*ptr != mgr->last_alloc) {
01700 return 1;
01701 }
01702
01703 if (space < grow) {
01704 return 1;
01705 }
01706
01707 (*pool_head)->used += grow;
01708 (*pool_head)->active += grow;
01709 AST_STRING_FIELD_ALLOCATION(*ptr) += grow;
01710
01711 return 0;
01712 }
01713
01714 void __ast_string_field_release_active(struct ast_string_field_pool *pool_head,
01715 const ast_string_field ptr)
01716 {
01717 struct ast_string_field_pool *pool, *prev;
01718
01719 if (ptr == __ast_string_field_empty) {
01720 return;
01721 }
01722
01723 for (pool = pool_head, prev = NULL; pool; prev = pool, pool = pool->prev) {
01724 if ((ptr >= pool->base) && (ptr <= (pool->base + pool->size))) {
01725 pool->active -= AST_STRING_FIELD_ALLOCATION(ptr);
01726 if ((pool->active == 0) && prev) {
01727 prev->prev = pool->prev;
01728 ast_free(pool);
01729 }
01730 break;
01731 }
01732 }
01733 }
01734
01735 void __ast_string_field_ptr_build_va(struct ast_string_field_mgr *mgr,
01736 struct ast_string_field_pool **pool_head,
01737 ast_string_field *ptr, const char *format, va_list ap1, va_list ap2)
01738 {
01739 size_t needed;
01740 size_t available;
01741 size_t space = (*pool_head)->size - (*pool_head)->used;
01742 ssize_t grow;
01743 char *target;
01744
01745
01746
01747
01748
01749 if (*ptr != __ast_string_field_empty) {
01750 target = (char *) *ptr;
01751 available = AST_STRING_FIELD_ALLOCATION(*ptr);
01752 if (*ptr == mgr->last_alloc) {
01753 available += space;
01754 }
01755 } else {
01756
01757
01758
01759 target = (*pool_head)->base + (*pool_head)->used + ast_alignof(ast_string_field_allocation);
01760 available = space - ast_alignof(ast_string_field_allocation);
01761 }
01762
01763 needed = vsnprintf(target, available, format, ap1) + 1;
01764
01765 if (needed > available) {
01766
01767
01768
01769
01770 if (!(target = (char *) __ast_string_field_alloc_space(mgr, pool_head, needed))) {
01771 return;
01772 }
01773 vsprintf(target, format, ap2);
01774 __ast_string_field_release_active(*pool_head, *ptr);
01775 *ptr = target;
01776 } else if (*ptr != target) {
01777
01778
01779
01780 __ast_string_field_release_active(*pool_head, *ptr);
01781 mgr->last_alloc = *ptr = target;
01782 AST_STRING_FIELD_ALLOCATION(target) = needed;
01783 (*pool_head)->used += ast_make_room_for(needed, ast_string_field_allocation);
01784 (*pool_head)->active += needed;
01785 } else if ((grow = (needed - AST_STRING_FIELD_ALLOCATION(*ptr))) > 0) {
01786
01787
01788
01789 AST_STRING_FIELD_ALLOCATION(*ptr) += grow;
01790 (*pool_head)->used += ast_align_for(grow, ast_string_field_allocation);
01791 (*pool_head)->active += grow;
01792 }
01793 }
01794
01795 void __ast_string_field_ptr_build(struct ast_string_field_mgr *mgr,
01796 struct ast_string_field_pool **pool_head,
01797 ast_string_field *ptr, const char *format, ...)
01798 {
01799 va_list ap1, ap2;
01800
01801 va_start(ap1, format);
01802 va_start(ap2, format);
01803
01804 __ast_string_field_ptr_build_va(mgr, pool_head, ptr, format, ap1, ap2);
01805
01806 va_end(ap1);
01807 va_end(ap2);
01808 }
01809
01810 void *__ast_calloc_with_stringfields(unsigned int num_structs, size_t struct_size, size_t field_mgr_offset,
01811 size_t field_mgr_pool_offset, size_t pool_size, const char *file,
01812 int lineno, const char *func)
01813 {
01814 struct ast_string_field_mgr *mgr;
01815 struct ast_string_field_pool *pool;
01816 struct ast_string_field_pool **pool_head;
01817 size_t pool_size_needed = sizeof(*pool) + pool_size;
01818 size_t size_to_alloc = optimal_alloc_size(struct_size + pool_size_needed);
01819 void *allocation;
01820 unsigned int x;
01821
01822 #if defined(__AST_DEBUG_MALLOC)
01823 if (!(allocation = __ast_calloc(num_structs, size_to_alloc, file, lineno, func))) {
01824 return NULL;
01825 }
01826 #else
01827 if (!(allocation = ast_calloc(num_structs, size_to_alloc))) {
01828 return NULL;
01829 }
01830 #endif
01831
01832 for (x = 0; x < num_structs; x++) {
01833 void *base = allocation + (size_to_alloc * x);
01834 const char **p;
01835
01836 mgr = base + field_mgr_offset;
01837 pool_head = base + field_mgr_pool_offset;
01838 pool = base + struct_size;
01839
01840 p = (const char **) pool_head + 1;
01841 while ((struct ast_string_field_mgr *) p != mgr) {
01842 *p++ = __ast_string_field_empty;
01843 }
01844
01845 mgr->embedded_pool = pool;
01846 *pool_head = pool;
01847 pool->size = size_to_alloc - struct_size - sizeof(*pool);
01848 #if defined(__AST_DEBUG_MALLOC)
01849 mgr->owner_file = file;
01850 mgr->owner_func = func;
01851 mgr->owner_line = lineno;
01852 #endif
01853 }
01854
01855 return allocation;
01856 }
01857
01858
01859
01860 AST_MUTEX_DEFINE_STATIC(fetchadd_m);
01861
01862 int ast_atomic_fetchadd_int_slow(volatile int *p, int v)
01863 {
01864 int ret;
01865 ast_mutex_lock(&fetchadd_m);
01866 ret = *p;
01867 *p += v;
01868 ast_mutex_unlock(&fetchadd_m);
01869 return ret;
01870 }
01871
01872
01873
01874
01875 int ast_get_timeval(const char *src, struct timeval *dst, struct timeval _default, int *consumed)
01876 {
01877 long double dtv = 0.0;
01878 int scanned;
01879
01880 if (dst == NULL)
01881 return -1;
01882
01883 *dst = _default;
01884
01885 if (ast_strlen_zero(src))
01886 return -1;
01887
01888
01889 if (sscanf(src, "%30Lf%n", &dtv, &scanned) > 0) {
01890 dst->tv_sec = dtv;
01891 dst->tv_usec = (dtv - dst->tv_sec) * 1000000.0;
01892 if (consumed)
01893 *consumed = scanned;
01894 return 0;
01895 } else
01896 return -1;
01897 }
01898
01899
01900
01901
01902 int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
01903 {
01904 long t;
01905 int scanned;
01906
01907 if (dst == NULL)
01908 return -1;
01909
01910 *dst = _default;
01911
01912 if (ast_strlen_zero(src))
01913 return -1;
01914
01915
01916 if (sscanf(src, "%30ld%n", &t, &scanned) == 1) {
01917 *dst = t;
01918 if (consumed)
01919 *consumed = scanned;
01920 return 0;
01921 } else
01922 return -1;
01923 }
01924
01925 void ast_enable_packet_fragmentation(int sock)
01926 {
01927 #if defined(HAVE_IP_MTU_DISCOVER)
01928 int val = IP_PMTUDISC_DONT;
01929
01930 if (setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val)))
01931 ast_log(LOG_WARNING, "Unable to disable PMTU discovery. Large UDP packets may fail to be delivered when sent from this socket.\n");
01932 #endif
01933 }
01934
01935 int ast_mkdir(const char *path, int mode)
01936 {
01937 char *ptr;
01938 int len = strlen(path), count = 0, x, piececount = 0;
01939 char *tmp = ast_strdupa(path);
01940 char **pieces;
01941 char *fullpath = ast_alloca(len + 1);
01942 int res = 0;
01943
01944 for (ptr = tmp; *ptr; ptr++) {
01945 if (*ptr == '/')
01946 count++;
01947 }
01948
01949
01950 pieces = ast_alloca(count * sizeof(*pieces));
01951 for (ptr = tmp; *ptr; ptr++) {
01952 if (*ptr == '/') {
01953 *ptr = '\0';
01954 pieces[piececount++] = ptr + 1;
01955 }
01956 }
01957
01958 *fullpath = '\0';
01959 for (x = 0; x < piececount; x++) {
01960
01961 strcat(fullpath, "/");
01962 strcat(fullpath, pieces[x]);
01963 res = mkdir(fullpath, mode);
01964 if (res && errno != EEXIST)
01965 return errno;
01966 }
01967 return 0;
01968 }
01969
01970 int ast_utils_init(void)
01971 {
01972 #ifdef HAVE_DEV_URANDOM
01973 dev_urandom_fd = open("/dev/urandom", O_RDONLY);
01974 #endif
01975 base64_init();
01976 #ifdef DEBUG_THREADS
01977 #if !defined(LOW_MEMORY)
01978 ast_cli_register_multiple(utils_cli, ARRAY_LEN(utils_cli));
01979 #endif
01980 #endif
01981 return 0;
01982 }
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992 int ast_parse_digest(const char *digest, struct ast_http_digest *d, int request, int pedantic) {
01993 char *c;
01994 struct ast_str *str = ast_str_create(16);
01995
01996
01997 const struct x {
01998 const char *key;
01999 const ast_string_field *field;
02000 } *i, keys[] = {
02001 { "username=", &d->username },
02002 { "realm=", &d->realm },
02003 { "nonce=", &d->nonce },
02004 { "uri=", &d->uri },
02005 { "domain=", &d->domain },
02006 { "response=", &d->response },
02007 { "cnonce=", &d->cnonce },
02008 { "opaque=", &d->opaque },
02009
02010 { "algorithm=", NULL },
02011 { "qop=", NULL },
02012 { "nc=", NULL },
02013 { NULL, 0 },
02014 };
02015
02016 if (ast_strlen_zero(digest) || !d || !str) {
02017 ast_free(str);
02018 return -1;
02019 }
02020
02021 ast_str_set(&str, 0, "%s", digest);
02022
02023 c = ast_skip_blanks(ast_str_buffer(str));
02024
02025 if (strncasecmp(c, "Digest ", strlen("Digest "))) {
02026 ast_log(LOG_WARNING, "Missing Digest.\n");
02027 ast_free(str);
02028 return -1;
02029 }
02030 c += strlen("Digest ");
02031
02032
02033 while (c && *c && *(c = ast_skip_blanks(c))) {
02034
02035 for (i = keys; i->key != NULL; i++) {
02036 char *src, *separator;
02037 int unescape = 0;
02038 if (strncasecmp(c, i->key, strlen(i->key)) != 0) {
02039 continue;
02040 }
02041
02042
02043 c += strlen(i->key);
02044 if (*c == '"') {
02045 src = ++c;
02046 separator = "\"";
02047 unescape = 1;
02048 } else {
02049 src = c;
02050 separator = ",";
02051 }
02052 strsep(&c, separator);
02053 if (unescape) {
02054 ast_unescape_c(src);
02055 }
02056 if (i->field) {
02057 ast_string_field_ptr_set(d, i->field, src);
02058 } else {
02059
02060 if (!strcasecmp(i->key, "algorithm=")) {
02061 if (strcasecmp(src, "MD5")) {
02062 ast_log(LOG_WARNING, "Digest algorithm: \"%s\" not supported.\n", src);
02063 ast_free(str);
02064 return -1;
02065 }
02066 } else if (!strcasecmp(i->key, "qop=") && !strcasecmp(src, "auth")) {
02067 d->qop = 1;
02068 } else if (!strcasecmp(i->key, "nc=")) {
02069 unsigned long u;
02070 if (sscanf(src, "%30lx", &u) != 1) {
02071 ast_log(LOG_WARNING, "Incorrect Digest nc value: \"%s\".\n", src);
02072 ast_free(str);
02073 return -1;
02074 }
02075 ast_string_field_set(d, nc, src);
02076 }
02077 }
02078 break;
02079 }
02080 if (i->key == NULL) {
02081 strsep(&c, ",");
02082 }
02083 }
02084 ast_free(str);
02085
02086
02087 if (ast_strlen_zero(d->realm) || ast_strlen_zero(d->nonce)) {
02088
02089 return -1;
02090 }
02091
02092 if (!request) {
02093
02094 if (ast_strlen_zero(d->username) || ast_strlen_zero(d->uri) || ast_strlen_zero(d->response)) {
02095 return -1;
02096 }
02097
02098 if (pedantic && d->qop && (ast_strlen_zero(d->cnonce) || ast_strlen_zero(d->nc))) {
02099 return -1;
02100 }
02101 }
02102
02103 return 0;
02104 }
02105
02106 #ifndef __AST_DEBUG_MALLOC
02107 int _ast_asprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, ...)
02108 {
02109 int res;
02110 va_list ap;
02111
02112 va_start(ap, fmt);
02113 if ((res = vasprintf(ret, fmt, ap)) == -1) {
02114 MALLOC_FAILURE_MSG;
02115 }
02116 va_end(ap);
02117
02118 return res;
02119 }
02120 #endif
02121
02122 char *ast_utils_which(const char *binary, char *fullpath, size_t fullpath_size)
02123 {
02124 const char *envPATH = getenv("PATH");
02125 char *tpath, *path;
02126 struct stat unused;
02127 if (!envPATH) {
02128 return NULL;
02129 }
02130 tpath = ast_strdupa(envPATH);
02131 while ((path = strsep(&tpath, ":"))) {
02132 snprintf(fullpath, fullpath_size, "%s/%s", path, binary);
02133 if (!stat(fullpath, &unused)) {
02134 return fullpath;
02135 }
02136 }
02137 return NULL;
02138 }
02139