00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "asterisk.h"
00027
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
00029
00030 #include <ctype.h>
00031 #include <string.h>
00032 #include <unistd.h>
00033 #include <stdlib.h>
00034 #include <errno.h>
00035 #include <stdarg.h>
00036 #include <stdio.h>
00037 #include <sys/types.h>
00038 #include <sys/socket.h>
00039 #include <netinet/in.h>
00040 #include <arpa/inet.h>
00041
00042 #define AST_API_MODULE
00043 #include "asterisk/lock.h"
00044 #include "asterisk/io.h"
00045 #include "asterisk/logger.h"
00046 #include "asterisk/md5.h"
00047 #include "asterisk/sha1.h"
00048 #include "asterisk/options.h"
00049
00050 #define AST_API_MODULE
00051 #include "asterisk/strings.h"
00052
00053 #define AST_API_MODULE
00054 #include "asterisk/time.h"
00055
00056 #define AST_API_MODULE
00057 #include "asterisk/stringfields.h"
00058
00059 #define AST_API_MODULE
00060 #include "asterisk/utils.h"
00061
00062 #define AST_API_MODULE
00063 #include "asterisk/threadstorage.h"
00064
00065 static char base64[64];
00066 static char b2a[256];
00067
00068 AST_THREADSTORAGE(inet_ntoa_buf, inet_ntoa_buf_init);
00069
00070 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined(__APPLE__) || defined(__CYGWIN__)
00071
00072 #define ERANGE 34
00073 #undef gethostbyname
00074
00075 AST_MUTEX_DEFINE_STATIC(__mutex);
00076
00077
00078
00079
00080
00081
00082 static int gethostbyname_r (const char *name, struct hostent *ret, char *buf,
00083 size_t buflen, struct hostent **result,
00084 int *h_errnop)
00085 {
00086 int hsave;
00087 struct hostent *ph;
00088 ast_mutex_lock(&__mutex);
00089 hsave = h_errno;
00090
00091 ph = gethostbyname(name);
00092 *h_errnop = h_errno;
00093 if (ph == NULL) {
00094 *result = NULL;
00095 } else {
00096 char **p, **q;
00097 char *pbuf;
00098 int nbytes=0;
00099 int naddr=0, naliases=0;
00100
00101
00102
00103 for (p = ph->h_addr_list; *p != 0; p++) {
00104 nbytes += ph->h_length;
00105 nbytes += sizeof(*p);
00106 naddr++;
00107 }
00108 nbytes += sizeof(*p);
00109
00110
00111 for (p = ph->h_aliases; *p != 0; p++) {
00112 nbytes += (strlen(*p)+1);
00113 nbytes += sizeof(*p);
00114 naliases++;
00115 }
00116 nbytes += sizeof(*p);
00117
00118
00119
00120 if (nbytes > buflen) {
00121 *result = NULL;
00122 ast_mutex_unlock(&__mutex);
00123 return ERANGE;
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 *ret = *ph;
00140
00141
00142 q = (char **)buf;
00143 ret->h_addr_list = q;
00144 pbuf = buf + ((naddr + naliases + 2) * sizeof(*p));
00145 for (p = ph->h_addr_list; *p != 0; p++) {
00146 memcpy(pbuf, *p, ph->h_length);
00147 *q++ = pbuf;
00148 pbuf += ph->h_length;
00149 }
00150 *q++ = NULL;
00151
00152
00153 ret->h_aliases = q;
00154 for (p = ph->h_aliases; *p != 0; p++) {
00155 strcpy(pbuf, *p);
00156 *q++ = pbuf;
00157 pbuf += strlen(*p);
00158 *pbuf++ = 0;
00159 }
00160 *q++ = NULL;
00161
00162 strcpy(pbuf, ph->h_name);
00163 ret->h_name = pbuf;
00164 pbuf += strlen(ph->h_name);
00165 *pbuf++ = 0;
00166
00167 *result = ret;
00168
00169 }
00170 h_errno = hsave;
00171 ast_mutex_unlock(&__mutex);
00172
00173 return (*result == NULL);
00174 }
00175
00176
00177 #endif
00178
00179
00180
00181
00182 struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp)
00183 {
00184 int res;
00185 int herrno;
00186 int dots=0;
00187 const char *s;
00188 struct hostent *result = NULL;
00189
00190
00191
00192
00193 s = host;
00194 res = 0;
00195 while(s && *s) {
00196 if (*s == '.')
00197 dots++;
00198 else if (!isdigit(*s))
00199 break;
00200 s++;
00201 }
00202 if (!s || !*s) {
00203
00204 if (dots != 3)
00205 return NULL;
00206 memset(hp, 0, sizeof(struct ast_hostent));
00207 hp->hp.h_addrtype = AF_INET;
00208 hp->hp.h_addr_list = (void *) hp->buf;
00209 hp->hp.h_addr = hp->buf + sizeof(void *);
00210 if (inet_pton(AF_INET, host, hp->hp.h_addr) > 0)
00211 return &hp->hp;
00212 return NULL;
00213
00214 }
00215 #ifdef SOLARIS
00216 result = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &herrno);
00217
00218 if (!result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
00219 return NULL;
00220 #else
00221 res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno);
00222
00223 if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
00224 return NULL;
00225 #endif
00226 return &hp->hp;
00227 }
00228
00229
00230
00231 AST_MUTEX_DEFINE_STATIC(test_lock);
00232 AST_MUTEX_DEFINE_STATIC(test_lock2);
00233 static pthread_t test_thread;
00234 static int lock_count = 0;
00235 static int test_errors = 0;
00236
00237
00238
00239
00240 static void *test_thread_body(void *data)
00241 {
00242 ast_mutex_lock(&test_lock);
00243 lock_count += 10;
00244 if (lock_count != 10)
00245 test_errors++;
00246 ast_mutex_lock(&test_lock);
00247 lock_count += 10;
00248 if (lock_count != 20)
00249 test_errors++;
00250 ast_mutex_lock(&test_lock2);
00251 ast_mutex_unlock(&test_lock);
00252 lock_count -= 10;
00253 if (lock_count != 10)
00254 test_errors++;
00255 ast_mutex_unlock(&test_lock);
00256 lock_count -= 10;
00257 ast_mutex_unlock(&test_lock2);
00258 if (lock_count != 0)
00259 test_errors++;
00260 return NULL;
00261 }
00262
00263 int test_for_thread_safety(void)
00264 {
00265 ast_mutex_lock(&test_lock2);
00266 ast_mutex_lock(&test_lock);
00267 lock_count += 1;
00268 ast_mutex_lock(&test_lock);
00269 lock_count += 1;
00270 ast_pthread_create(&test_thread, NULL, test_thread_body, NULL);
00271 usleep(100);
00272 if (lock_count != 2)
00273 test_errors++;
00274 ast_mutex_unlock(&test_lock);
00275 lock_count -= 1;
00276 usleep(100);
00277 if (lock_count != 1)
00278 test_errors++;
00279 ast_mutex_unlock(&test_lock);
00280 lock_count -= 1;
00281 if (lock_count != 0)
00282 test_errors++;
00283 ast_mutex_unlock(&test_lock2);
00284 usleep(100);
00285 if (lock_count != 0)
00286 test_errors++;
00287 pthread_join(test_thread, NULL);
00288 return(test_errors);
00289 }
00290
00291
00292 void ast_md5_hash(char *output, char *input)
00293 {
00294 struct MD5Context md5;
00295 unsigned char digest[16];
00296 char *ptr;
00297 int x;
00298
00299 MD5Init(&md5);
00300 MD5Update(&md5, (unsigned char *)input, strlen(input));
00301 MD5Final(digest, &md5);
00302 ptr = output;
00303 for (x = 0; x < 16; x++)
00304 ptr += sprintf(ptr, "%2.2x", digest[x]);
00305 }
00306
00307
00308 void ast_sha1_hash(char *output, char *input)
00309 {
00310 struct SHA1Context sha;
00311 char *ptr;
00312 int x;
00313 uint8_t Message_Digest[20];
00314
00315 SHA1Reset(&sha);
00316
00317 SHA1Input(&sha, (const unsigned char *) input, strlen(input));
00318
00319 SHA1Result(&sha, Message_Digest);
00320 ptr = output;
00321 for (x = 0; x < 20; x++)
00322 ptr += sprintf(ptr, "%2.2x", Message_Digest[x]);
00323 }
00324
00325
00326 int ast_base64decode(unsigned char *dst, const char *src, int max)
00327 {
00328 int cnt = 0;
00329 unsigned int byte = 0;
00330 unsigned int bits = 0;
00331 int incnt = 0;
00332 while(*src && (cnt < max)) {
00333
00334 byte <<= 6;
00335 byte |= (b2a[(int)(*src)]) & 0x3f;
00336 bits += 6;
00337 src++;
00338 incnt++;
00339
00340
00341 if (bits >= 8) {
00342 bits -= 8;
00343 *dst = (byte >> bits) & 0xff;
00344 dst++;
00345 cnt++;
00346 }
00347 }
00348
00349 return cnt;
00350 }
00351
00352
00353 int ast_base64encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks)
00354 {
00355 int cnt = 0;
00356 int col = 0;
00357 unsigned int byte = 0;
00358 int bits = 0;
00359 int cntin = 0;
00360
00361 max--;
00362 while ((cntin < srclen) && (cnt < max)) {
00363 byte <<= 8;
00364 byte |= *(src++);
00365 bits += 8;
00366 cntin++;
00367 if ((bits == 24) && (cnt + 4 <= max)) {
00368 *dst++ = base64[(byte >> 18) & 0x3f];
00369 *dst++ = base64[(byte >> 12) & 0x3f];
00370 *dst++ = base64[(byte >> 6) & 0x3f];
00371 *dst++ = base64[byte & 0x3f];
00372 cnt += 4;
00373 col += 4;
00374 bits = 0;
00375 byte = 0;
00376 }
00377 if (linebreaks && (cnt < max) && (col == 64)) {
00378 *dst++ = '\n';
00379 cnt++;
00380 col = 0;
00381 }
00382 }
00383 if (bits && (cnt + 4 <= max)) {
00384
00385
00386 byte <<= 24 - bits;
00387 *dst++ = base64[(byte >> 18) & 0x3f];
00388 *dst++ = base64[(byte >> 12) & 0x3f];
00389 if (bits == 16)
00390 *dst++ = base64[(byte >> 6) & 0x3f];
00391 else
00392 *dst++ = '=';
00393 *dst++ = '=';
00394 cnt += 4;
00395 }
00396 if (linebreaks && (cnt < max)) {
00397 *dst++ = '\n';
00398 cnt++;
00399 }
00400 *dst = '\0';
00401 return cnt;
00402 }
00403
00404 int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
00405 {
00406 return ast_base64encode_full(dst, src, srclen, max, 0);
00407 }
00408
00409 static void base64_init(void)
00410 {
00411 int x;
00412 memset(b2a, -1, sizeof(b2a));
00413
00414 for (x = 0; x < 26; x++) {
00415
00416 base64[x] = 'A' + x;
00417 b2a['A' + x] = x;
00418
00419 base64[x + 26] = 'a' + x;
00420 b2a['a' + x] = x + 26;
00421
00422 if (x < 10) {
00423 base64[x + 52] = '0' + x;
00424 b2a['0' + x] = x + 52;
00425 }
00426 }
00427 base64[62] = '+';
00428 base64[63] = '/';
00429 b2a[(int)'+'] = 62;
00430 b2a[(int)'/'] = 63;
00431 }
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 char *ast_uri_encode(const char *string, char *outbuf, int buflen, int doreserved)
00446 {
00447 char *reserved = ";/?:@&=+$, ";
00448
00449 const char *ptr = string;
00450 char *out = NULL;
00451 char *buf = NULL;
00452
00453 ast_copy_string(outbuf, string, buflen);
00454
00455
00456 while (*ptr) {
00457 if (((unsigned char) *ptr) > 127 || (doreserved && strchr(reserved, *ptr)) ) {
00458
00459 if (!buf) {
00460 buf = outbuf;
00461 out = buf + (ptr - string) ;
00462 }
00463 out += sprintf(out, "%%%02x", (unsigned char) *ptr);
00464 } else if (buf) {
00465 *out = *ptr;
00466 out++;
00467 }
00468 ptr++;
00469 }
00470 if (buf)
00471 *out = '\0';
00472 return outbuf;
00473 }
00474
00475
00476 void ast_uri_decode(char *s)
00477 {
00478 char *o;
00479 unsigned int tmp;
00480
00481 for (o = s; *s; s++, o++) {
00482 if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) {
00483
00484 *o = tmp;
00485 s += 2;
00486 } else
00487 *o = *s;
00488 }
00489 *o = '\0';
00490 }
00491
00492
00493 const char *ast_inet_ntoa(struct in_addr ia)
00494 {
00495 char *buf;
00496
00497 if (!(buf = ast_threadstorage_get(&inet_ntoa_buf, INET_ADDRSTRLEN)))
00498 return "";
00499
00500 return inet_ntop(AF_INET, &ia, buf, INET_ADDRSTRLEN);
00501 }
00502
00503 int ast_utils_init(void)
00504 {
00505 base64_init();
00506 return 0;
00507 }
00508
00509 #ifndef __linux__
00510 #undef pthread_create
00511 #endif
00512
00513 #if !defined(LOW_MEMORY)
00514
00515
00516
00517
00518
00519 struct thr_arg {
00520 void *(*start_routine)(void *);
00521 void *data;
00522 char *name;
00523 };
00524
00525
00526
00527
00528
00529
00530
00531
00532 static void *dummy_start(void *data)
00533 {
00534 void *ret;
00535 struct thr_arg a = *((struct thr_arg *) data);
00536
00537
00538
00539
00540
00541
00542 free(data);
00543 ast_register_thread(a.name);
00544 pthread_cleanup_push(ast_unregister_thread, (void *) pthread_self());
00545 ret = a.start_routine(a.data);
00546 pthread_cleanup_pop(1);
00547
00548 return ret;
00549 }
00550
00551 #endif
00552
00553 int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
00554 void *data, size_t stacksize, const char *file, const char *caller,
00555 int line, const char *start_fn)
00556 {
00557 #if !defined(LOW_MEMORY)
00558 struct thr_arg *a;
00559 #endif
00560
00561 if (!attr) {
00562 attr = alloca(sizeof(*attr));
00563 pthread_attr_init(attr);
00564 }
00565
00566 #ifdef __linux__
00567
00568
00569
00570
00571
00572
00573
00574 if ((errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED)))
00575 ast_log(LOG_WARNING, "pthread_attr_setinheritsched: %s\n", strerror(errno));
00576 #endif
00577
00578 if (!stacksize)
00579 stacksize = AST_STACKSIZE;
00580
00581 if ((errno = pthread_attr_setstacksize(attr, stacksize ? stacksize : AST_STACKSIZE)))
00582 ast_log(LOG_WARNING, "pthread_attr_setstacksize: %s\n", strerror(errno));
00583
00584 #if !defined(LOW_MEMORY)
00585 if ((a = ast_malloc(sizeof(*a)))) {
00586 a->start_routine = start_routine;
00587 a->data = data;
00588 start_routine = dummy_start;
00589 asprintf(&a->name, "%-20s started at [%5d] %s %s()",
00590 start_fn, line, file, caller);
00591 data = a;
00592 }
00593 #endif
00594
00595 return pthread_create(thread, attr, start_routine, data);
00596 }
00597
00598 int ast_wait_for_input(int fd, int ms)
00599 {
00600 struct pollfd pfd[1];
00601 memset(pfd, 0, sizeof(pfd));
00602 pfd[0].fd = fd;
00603 pfd[0].events = POLLIN|POLLPRI;
00604 return poll(pfd, 1, ms);
00605 }
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622 int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
00623 {
00624
00625
00626 int res = 0;
00627 struct pollfd fds[1];
00628 while (len) {
00629 res = write(fd, s, len);
00630 if ((res < 0) && (errno != EAGAIN)) {
00631 return -1;
00632 }
00633 if (res < 0)
00634 res = 0;
00635 len -= res;
00636 s += res;
00637 res = 0;
00638 if (len) {
00639 fds[0].fd = fd;
00640 fds[0].events = POLLOUT;
00641
00642 res = poll(fds, 1, timeoutms);
00643 if (res < 1)
00644 return -1;
00645 }
00646 }
00647 return res;
00648 }
00649
00650 char *ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
00651 {
00652 char *e;
00653 char *q;
00654
00655 s = ast_strip(s);
00656 if ((q = strchr(beg_quotes, *s)) && *q != '\0') {
00657 e = s + strlen(s) - 1;
00658 if (*e == *(end_quotes + (q - beg_quotes))) {
00659 s++;
00660 *e = '\0';
00661 }
00662 }
00663
00664 return s;
00665 }
00666
00667 int ast_build_string_va(char **buffer, size_t *space, const char *fmt, va_list ap)
00668 {
00669 int result;
00670
00671 if (!buffer || !*buffer || !space || !*space)
00672 return -1;
00673
00674 result = vsnprintf(*buffer, *space, fmt, ap);
00675
00676 if (result < 0)
00677 return -1;
00678 else if (result > *space)
00679 result = *space;
00680
00681 *buffer += result;
00682 *space -= result;
00683 return 0;
00684 }
00685
00686 int ast_build_string(char **buffer, size_t *space, const char *fmt, ...)
00687 {
00688 va_list ap;
00689 int result;
00690
00691 va_start(ap, fmt);
00692 result = ast_build_string_va(buffer, space, fmt, ap);
00693 va_end(ap);
00694
00695 return result;
00696 }
00697
00698 int ast_true(const char *s)
00699 {
00700 if (ast_strlen_zero(s))
00701 return 0;
00702
00703
00704 if (!strcasecmp(s, "yes") ||
00705 !strcasecmp(s, "true") ||
00706 !strcasecmp(s, "y") ||
00707 !strcasecmp(s, "t") ||
00708 !strcasecmp(s, "1") ||
00709 !strcasecmp(s, "on"))
00710 return -1;
00711
00712 return 0;
00713 }
00714
00715 int ast_false(const char *s)
00716 {
00717 if (ast_strlen_zero(s))
00718 return 0;
00719
00720
00721 if (!strcasecmp(s, "no") ||
00722 !strcasecmp(s, "false") ||
00723 !strcasecmp(s, "n") ||
00724 !strcasecmp(s, "f") ||
00725 !strcasecmp(s, "0") ||
00726 !strcasecmp(s, "off"))
00727 return -1;
00728
00729 return 0;
00730 }
00731
00732 #define ONE_MILLION 1000000
00733
00734
00735
00736
00737 static struct timeval tvfix(struct timeval a)
00738 {
00739 if (a.tv_usec >= ONE_MILLION) {
00740 ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
00741 a.tv_sec, (long int) a.tv_usec);
00742 a.tv_sec += a.tv_usec / ONE_MILLION;
00743 a.tv_usec %= ONE_MILLION;
00744 } else if (a.tv_usec < 0) {
00745 ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
00746 a.tv_sec, (long int) a.tv_usec);
00747 a.tv_usec = 0;
00748 }
00749 return a;
00750 }
00751
00752 struct timeval ast_tvadd(struct timeval a, struct timeval b)
00753 {
00754
00755 a = tvfix(a);
00756 b = tvfix(b);
00757 a.tv_sec += b.tv_sec;
00758 a.tv_usec += b.tv_usec;
00759 if (a.tv_usec >= ONE_MILLION) {
00760 a.tv_sec++;
00761 a.tv_usec -= ONE_MILLION;
00762 }
00763 return a;
00764 }
00765
00766 struct timeval ast_tvsub(struct timeval a, struct timeval b)
00767 {
00768
00769 a = tvfix(a);
00770 b = tvfix(b);
00771 a.tv_sec -= b.tv_sec;
00772 a.tv_usec -= b.tv_usec;
00773 if (a.tv_usec < 0) {
00774 a.tv_sec-- ;
00775 a.tv_usec += ONE_MILLION;
00776 }
00777 return a;
00778 }
00779 #undef ONE_MILLION
00780
00781
00782
00783 #ifndef linux
00784
00785 AST_MUTEX_DEFINE_STATIC(randomlock);
00786
00787 long int ast_random(void)
00788 {
00789 long int res;
00790 ast_mutex_lock(&randomlock);
00791 res = random();
00792 ast_mutex_unlock(&randomlock);
00793 return res;
00794 }
00795 #endif
00796
00797 char *ast_process_quotes_and_slashes(char *start, char find, char replace_with)
00798 {
00799 char *dataPut = start;
00800 int inEscape = 0;
00801 int inQuotes = 0;
00802
00803 for (; *start; start++) {
00804 if (inEscape) {
00805 *dataPut++ = *start;
00806 inEscape = 0;
00807 } else {
00808 if (*start == '\\') {
00809 inEscape = 1;
00810 } else if (*start == '\'') {
00811 inQuotes = 1 - inQuotes;
00812 } else {
00813
00814 *dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
00815 }
00816 }
00817 }
00818 if (start != dataPut)
00819 *dataPut = 0;
00820 return dataPut;
00821 }
00822
00823 void ast_join(char *s, size_t len, char * const w[])
00824 {
00825 int x, ofs = 0;
00826 const char *src;
00827
00828
00829 if (!s)
00830 return;
00831 for (x = 0; ofs < len && w[x]; x++) {
00832 if (x > 0)
00833 s[ofs++] = ' ';
00834 for (src = w[x]; *src && ofs < len; src++)
00835 s[ofs++] = *src;
00836 }
00837 if (ofs == len)
00838 ofs--;
00839 s[ofs] = '\0';
00840 }
00841
00842 const char __ast_string_field_empty[] = "";
00843
00844 static int add_string_pool(struct ast_string_field_mgr *mgr, size_t size)
00845 {
00846 struct ast_string_field_pool *pool;
00847
00848 if (!(pool = ast_calloc(1, sizeof(*pool) + size)))
00849 return -1;
00850
00851 pool->prev = mgr->pool;
00852 mgr->pool = pool;
00853 mgr->size = size;
00854 mgr->space = size;
00855 mgr->used = 0;
00856
00857 return 0;
00858 }
00859
00860 int __ast_string_field_init(struct ast_string_field_mgr *mgr, size_t size,
00861 ast_string_field *fields, int num_fields)
00862 {
00863 int index;
00864
00865 if (add_string_pool(mgr, size))
00866 return -1;
00867
00868 for (index = 0; index < num_fields; index++)
00869 fields[index] = __ast_string_field_empty;
00870
00871 return 0;
00872 }
00873
00874 ast_string_field __ast_string_field_alloc_space(struct ast_string_field_mgr *mgr, size_t needed,
00875 ast_string_field *fields, int num_fields)
00876 {
00877 char *result = NULL;
00878
00879 if (__builtin_expect(needed > mgr->space, 0)) {
00880 size_t new_size = mgr->size * 2;
00881
00882 while (new_size < needed)
00883 new_size *= 2;
00884
00885 if (add_string_pool(mgr, new_size))
00886 return NULL;
00887 }
00888
00889 result = mgr->pool->base + mgr->used;
00890 mgr->used += needed;
00891 mgr->space -= needed;
00892 return result;
00893 }
00894
00895 void __ast_string_field_index_build_va(struct ast_string_field_mgr *mgr,
00896 ast_string_field *fields, int num_fields,
00897 int index, const char *format, va_list ap1, va_list ap2)
00898 {
00899 size_t needed;
00900
00901 needed = vsnprintf(mgr->pool->base + mgr->used, mgr->space, format, ap1) + 1;
00902
00903 va_end(ap1);
00904
00905 if (needed > mgr->space) {
00906 size_t new_size = mgr->size * 2;
00907
00908 while (new_size < needed)
00909 new_size *= 2;
00910
00911 if (add_string_pool(mgr, new_size))
00912 return;
00913
00914 vsprintf(mgr->pool->base + mgr->used, format, ap2);
00915 }
00916
00917 fields[index] = mgr->pool->base + mgr->used;
00918 mgr->used += needed;
00919 mgr->space -= needed;
00920 }
00921
00922 void __ast_string_field_index_build(struct ast_string_field_mgr *mgr,
00923 ast_string_field *fields, int num_fields,
00924 int index, const char *format, ...)
00925 {
00926 va_list ap1, ap2;
00927
00928 va_start(ap1, format);
00929 va_start(ap2, format);
00930
00931 __ast_string_field_index_build_va(mgr, fields, num_fields, index, format, ap1, ap2);
00932
00933 va_end(ap1);
00934 va_end(ap2);
00935 }
00936
00937 AST_MUTEX_DEFINE_STATIC(fetchadd_m);
00938
00939 int ast_atomic_fetchadd_int_slow(volatile int *p, int v)
00940 {
00941 int ret;
00942 ast_mutex_lock(&fetchadd_m);
00943 ret = *p;
00944 *p += v;
00945 ast_mutex_unlock(&fetchadd_m);
00946 return ret;
00947 }
00948
00949
00950
00951
00952 int ast_get_time_t(const char *src, time_t *dst, time_t _default, int *consumed)
00953 {
00954 long t;
00955 int scanned;
00956
00957 if (dst == NULL)
00958 return -1;
00959
00960 *dst = _default;
00961
00962 if (ast_strlen_zero(src))
00963 return -1;
00964
00965
00966 if (sscanf(src, "%ld%n", &t, &scanned) == 1) {
00967 *dst = t;
00968 if (consumed)
00969 *consumed = scanned;
00970 return 0;
00971 } else
00972 return -1;
00973 }
00974
00975 int ast_dynamic_str_thread_build_va(struct ast_dynamic_str **buf, size_t max_len,
00976 struct ast_threadstorage *ts, int append, const char *fmt, va_list ap)
00977 {
00978 int res;
00979 int offset = (append && (*buf)->len) ? strlen((*buf)->str) : 0;
00980 #if defined(DEBUG_THREADLOCALS)
00981 struct ast_dynamic_str *old_buf = *buf;
00982 #endif
00983
00984 res = vsnprintf((*buf)->str + offset, (*buf)->len - offset, fmt, ap);
00985
00986
00987
00988
00989 if ((res + offset + 1) > (*buf)->len && (max_len ? ((*buf)->len < max_len) : 1)) {
00990
00991
00992
00993
00994 if (max_len)
00995 (*buf)->len = ((res + offset + 1) < max_len) ? (res + offset + 1) : max_len;
00996 else
00997 (*buf)->len = res + offset + 1;
00998
00999 if (!(*buf = ast_realloc(*buf, (*buf)->len + sizeof(*(*buf)))))
01000 return AST_DYNSTR_BUILD_FAILED;
01001
01002 if (append)
01003 (*buf)->str[offset] = '\0';
01004
01005 if (ts) {
01006 pthread_setspecific(ts->key, *buf);
01007 #if defined(DEBUG_THREADLOCALS)
01008 __ast_threadstorage_object_replace(old_buf, *buf, (*buf)->len + sizeof(*(*buf)));
01009 #endif
01010 }
01011
01012
01013
01014 return AST_DYNSTR_BUILD_RETRY;
01015 }
01016
01017 return res;
01018 }
01019
01020 void ast_enable_packet_fragmentation(int sock)
01021 {
01022 #if defined(HAVE_IP_MTU_DISCOVER)
01023 int val = IP_PMTUDISC_DONT;
01024
01025 if (setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val)))
01026 ast_log(LOG_WARNING, "Unable to disable PMTU discovery. Large UDP packets may fail to be delivered when sent from this socket.\n");
01027 #endif
01028 }