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