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