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