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