2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * See http://www.asterisk.org for more information about
7 * the Asterisk project. Please do not directly contact
8 * any of the maintainers of this project for assistance;
9 * the project provides a web site, mailing lists and IRC
10 * channels for your use.
12 * This program is free software, distributed under the terms of
13 * the GNU General Public License Version 2. See the LICENSE file
14 * at the top of the source tree.
19 * \brief Utility functions
21 * \note These are important for portability and security,
22 * so please use them in favour of other routines.
23 * Please consult the CODING GUIDELINES for more information.
28 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
42 #define AST_API_MODULE /* ensure that inlinable API functions will be built in lock.h if required */
43 #include "asterisk/lock.h"
44 #include "asterisk/io.h"
45 #include "asterisk/logger.h"
46 #include "asterisk/md5.h"
47 #include "asterisk/sha1.h"
48 #include "asterisk/options.h"
49 #include "asterisk/cli.h"
50 #include "asterisk/linkedlists.h"
52 #define AST_API_MODULE /* ensure that inlinable API functions will be built in this module if required */
53 #include "asterisk/strings.h"
55 #define AST_API_MODULE /* ensure that inlinable API functions will be built in this module if required */
56 #include "asterisk/time.h"
58 #define AST_API_MODULE /* ensure that inlinable API functions will be built in this module if required */
59 #include "asterisk/stringfields.h"
61 #define AST_API_MODULE /* ensure that inlinable API functions will be built in this module if required */
62 #include "asterisk/utils.h"
64 #define AST_API_MODULE
65 #include "asterisk/threadstorage.h"
67 static char base64
[64];
70 AST_THREADSTORAGE(inet_ntoa_buf
, inet_ntoa_buf_init
);
72 #if !defined(HAVE_GETHOSTBYNAME_R_5) && !defined(HAVE_GETHOSTBYNAME_R_6)
74 #define ERANGE 34 /*!< duh? ERANGE value copied from web... */
77 AST_MUTEX_DEFINE_STATIC(__mutex
);
79 /*! \brief Reentrant replacement for gethostbyname for BSD-based systems.
81 routine is derived from code originally written and placed in the public
82 domain by Enzo Michelangeli <em@em.no-ip.com> */
84 static int gethostbyname_r (const char *name
, struct hostent
*ret
, char *buf
,
85 size_t buflen
, struct hostent
**result
,
90 ast_mutex_lock(&__mutex
); /* begin critical area */
93 ph
= gethostbyname(name
);
94 *h_errnop
= h_errno
; /* copy h_errno to *h_herrnop */
101 int naddr
=0, naliases
=0;
102 /* determine if we have enough space in buf */
104 /* count how many addresses */
105 for (p
= ph
->h_addr_list
; *p
!= 0; p
++) {
106 nbytes
+= ph
->h_length
; /* addresses */
107 nbytes
+= sizeof(*p
); /* pointers */
110 nbytes
+= sizeof(*p
); /* one more for the terminating NULL */
112 /* count how many aliases, and total length of strings */
113 for (p
= ph
->h_aliases
; *p
!= 0; p
++) {
114 nbytes
+= (strlen(*p
)+1); /* aliases */
115 nbytes
+= sizeof(*p
); /* pointers */
118 nbytes
+= sizeof(*p
); /* one more for the terminating NULL */
120 /* here nbytes is the number of bytes required in buffer */
121 /* as a terminator must be there, the minimum value is ph->h_length */
122 if (nbytes
> buflen
) {
124 ast_mutex_unlock(&__mutex
); /* end critical area */
125 return ERANGE
; /* not enough space in buf!! */
128 /* There is enough space. Now we need to do a deep copy! */
129 /* Allocation in buffer:
130 from [0] to [(naddr-1) * sizeof(*p)]:
131 pointers to addresses
132 at [naddr * sizeof(*p)]:
134 from [(naddr+1) * sizeof(*p)] to [(naddr+naliases) * sizeof(*p)] :
136 at [(naddr+naliases+1) * sizeof(*p)]:
138 then naddr addresses (fixed length), and naliases aliases (asciiz).
141 *ret
= *ph
; /* copy whole structure (not its address!) */
144 q
= (char **)buf
; /* pointer to pointers area (type: char **) */
145 ret
->h_addr_list
= q
; /* update pointer to address list */
146 pbuf
= buf
+ ((naddr
+ naliases
+ 2) * sizeof(*p
)); /* skip that area */
147 for (p
= ph
->h_addr_list
; *p
!= 0; p
++) {
148 memcpy(pbuf
, *p
, ph
->h_length
); /* copy address bytes */
149 *q
++ = pbuf
; /* the pointer is the one inside buf... */
150 pbuf
+= ph
->h_length
; /* advance pbuf */
152 *q
++ = NULL
; /* address list terminator */
155 ret
->h_aliases
= q
; /* update pointer to aliases list */
156 for (p
= ph
->h_aliases
; *p
!= 0; p
++) {
157 strcpy(pbuf
, *p
); /* copy alias strings */
158 *q
++ = pbuf
; /* the pointer is the one inside buf... */
159 pbuf
+= strlen(*p
); /* advance pbuf */
160 *pbuf
++ = 0; /* string terminator */
162 *q
++ = NULL
; /* terminator */
164 strcpy(pbuf
, ph
->h_name
); /* copy alias strings */
166 pbuf
+= strlen(ph
->h_name
); /* advance pbuf */
167 *pbuf
++ = 0; /* string terminator */
169 *result
= ret
; /* and let *result point to structure */
172 h_errno
= hsave
; /* restore h_errno */
173 ast_mutex_unlock(&__mutex
); /* end critical area */
175 return (*result
== NULL
); /* return 0 on success, non-zero on error */
181 /*! \brief Re-entrant (thread safe) version of gethostbyname that replaces the
182 standard gethostbyname (which is not thread safe)
184 struct hostent
*ast_gethostbyname(const char *host
, struct ast_hostent
*hp
)
190 struct hostent
*result
= NULL
;
191 /* Although it is perfectly legitimate to lookup a pure integer, for
192 the sake of the sanity of people who like to name their peers as
193 integers, we break with tradition and refuse to look up a
200 else if (!isdigit(*s
))
205 /* Forge a reply for IP's to avoid octal IP's being interpreted as octal */
208 memset(hp
, 0, sizeof(struct ast_hostent
));
209 hp
->hp
.h_addrtype
= AF_INET
;
210 hp
->hp
.h_addr_list
= (void *) hp
->buf
;
211 hp
->hp
.h_addr
= hp
->buf
+ sizeof(void *);
212 if (inet_pton(AF_INET
, host
, hp
->hp
.h_addr
) > 0)
217 #ifdef HAVE_GETHOSTBYNAME_R_5
218 result
= gethostbyname_r(host
, &hp
->hp
, hp
->buf
, sizeof(hp
->buf
), &herrno
);
220 if (!result
|| !hp
->hp
.h_addr_list
|| !hp
->hp
.h_addr_list
[0])
223 res
= gethostbyname_r(host
, &hp
->hp
, hp
->buf
, sizeof(hp
->buf
), &result
, &herrno
);
225 if (res
|| !result
|| !hp
->hp
.h_addr_list
|| !hp
->hp
.h_addr_list
[0])
233 AST_MUTEX_DEFINE_STATIC(test_lock
);
234 AST_MUTEX_DEFINE_STATIC(test_lock2
);
235 static pthread_t test_thread
;
236 static int lock_count
= 0;
237 static int test_errors
= 0;
239 /*! \brief This is a regression test for recursive mutexes.
240 test_for_thread_safety() will return 0 if recursive mutex locks are
241 working properly, and non-zero if they are not working properly. */
242 static void *test_thread_body(void *data
)
244 ast_mutex_lock(&test_lock
);
246 if (lock_count
!= 10)
248 ast_mutex_lock(&test_lock
);
250 if (lock_count
!= 20)
252 ast_mutex_lock(&test_lock2
);
253 ast_mutex_unlock(&test_lock
);
255 if (lock_count
!= 10)
257 ast_mutex_unlock(&test_lock
);
259 ast_mutex_unlock(&test_lock2
);
265 int test_for_thread_safety(void)
267 ast_mutex_lock(&test_lock2
);
268 ast_mutex_lock(&test_lock
);
270 ast_mutex_lock(&test_lock
);
272 ast_pthread_create(&test_thread
, NULL
, test_thread_body
, NULL
);
276 ast_mutex_unlock(&test_lock
);
281 ast_mutex_unlock(&test_lock
);
285 ast_mutex_unlock(&test_lock2
);
289 pthread_join(test_thread
, NULL
);
290 return(test_errors
); /* return 0 on success. */
293 /*! \brief Produce 32 char MD5 hash of value. */
294 void ast_md5_hash(char *output
, char *input
)
296 struct MD5Context md5
;
297 unsigned char digest
[16];
302 MD5Update(&md5
, (unsigned char *)input
, strlen(input
));
303 MD5Final(digest
, &md5
);
305 for (x
= 0; x
< 16; x
++)
306 ptr
+= sprintf(ptr
, "%2.2x", digest
[x
]);
309 /*! \brief Produce 40 char SHA1 hash of value. */
310 void ast_sha1_hash(char *output
, char *input
)
312 struct SHA1Context sha
;
315 uint8_t Message_Digest
[20];
319 SHA1Input(&sha
, (const unsigned char *) input
, strlen(input
));
321 SHA1Result(&sha
, Message_Digest
);
323 for (x
= 0; x
< 20; x
++)
324 ptr
+= sprintf(ptr
, "%2.2x", Message_Digest
[x
]);
327 /*! \brief decode BASE64 encoded text */
328 int ast_base64decode(unsigned char *dst
, const char *src
, int max
)
331 unsigned int byte
= 0;
332 unsigned int bits
= 0;
334 while(*src
&& (cnt
< max
)) {
335 /* Shift in 6 bits of input */
337 byte
|= (b2a
[(int)(*src
)]) & 0x3f;
341 /* If we have at least 8 bits left over, take that character
345 *dst
= (byte
>> bits
) & 0xff;
350 /* Dont worry about left over bits, they're extra anyway */
354 /*! \brief encode text to BASE64 coding */
355 int ast_base64encode_full(char *dst
, const unsigned char *src
, int srclen
, int max
, int linebreaks
)
359 unsigned int byte
= 0;
362 /* Reserve space for null byte at end of string */
364 while ((cntin
< srclen
) && (cnt
< max
)) {
369 if ((bits
== 24) && (cnt
+ 4 <= max
)) {
370 *dst
++ = base64
[(byte
>> 18) & 0x3f];
371 *dst
++ = base64
[(byte
>> 12) & 0x3f];
372 *dst
++ = base64
[(byte
>> 6) & 0x3f];
373 *dst
++ = base64
[byte
& 0x3f];
379 if (linebreaks
&& (cnt
< max
) && (col
== 64)) {
385 if (bits
&& (cnt
+ 4 <= max
)) {
386 /* Add one last character for the remaining bits,
387 padding the rest with 0 */
389 *dst
++ = base64
[(byte
>> 18) & 0x3f];
390 *dst
++ = base64
[(byte
>> 12) & 0x3f];
392 *dst
++ = base64
[(byte
>> 6) & 0x3f];
398 if (linebreaks
&& (cnt
< max
)) {
406 int ast_base64encode(char *dst
, const unsigned char *src
, int srclen
, int max
)
408 return ast_base64encode_full(dst
, src
, srclen
, max
, 0);
411 static void base64_init(void)
414 memset(b2a
, -1, sizeof(b2a
));
415 /* Initialize base-64 Conversion table */
416 for (x
= 0; x
< 26; x
++) {
421 base64
[x
+ 26] = 'a' + x
;
422 b2a
['a' + x
] = x
+ 26;
425 base64
[x
+ 52] = '0' + x
;
426 b2a
['0' + x
] = x
+ 52;
435 /*! \brief ast_uri_encode: Turn text string to URI-encoded %XX version
436 \note At this point, we're converting from ISO-8859-x (8-bit), not UTF8
437 as in the SIP protocol spec
438 If doreserved == 1 we will convert reserved characters also.
439 RFC 2396, section 2.4
440 outbuf needs to have more memory allocated than the instring
441 to have room for the expansion. Every char that is converted
442 is replaced by three ASCII characters.
444 Note: The doreserved option is needed for replaces header in
447 char *ast_uri_encode(const char *string
, char *outbuf
, int buflen
, int doreserved
)
449 char *reserved
= ";/?:@&=+$,# "; /* Reserved chars */
451 const char *ptr
= string
; /* Start with the string */
455 ast_copy_string(outbuf
, string
, buflen
);
457 /* If there's no characters to convert, just go through and don't do anything */
459 if (((unsigned char) *ptr
) > 127 || (doreserved
&& strchr(reserved
, *ptr
)) ) {
460 /* Oops, we need to start working here */
463 out
= buf
+ (ptr
- string
) ; /* Set output ptr */
465 out
+= sprintf(out
, "%%%02x", (unsigned char) *ptr
);
467 *out
= *ptr
; /* Continue copying the string */
477 /*! \brief ast_uri_decode: Decode SIP URI, URN, URL (overwrite the string) */
478 void ast_uri_decode(char *s
)
483 for (o
= s
; *s
; s
++, o
++) {
484 if (*s
== '%' && strlen(s
) > 2 && sscanf(s
+ 1, "%2x", &tmp
) == 1) {
485 /* have '%', two chars and correct parsing */
487 s
+= 2; /* Will be incremented once more when we break out */
488 } else /* all other cases, just copy */
494 /*! \brief ast_inet_ntoa: Recursive thread safe replacement of inet_ntoa */
495 const char *ast_inet_ntoa(struct in_addr ia
)
499 if (!(buf
= ast_threadstorage_get(&inet_ntoa_buf
, INET_ADDRSTRLEN
)))
502 return inet_ntop(AF_INET
, &ia
, buf
, INET_ADDRSTRLEN
);
506 #undef pthread_create /* For ast_pthread_create function only */
507 #endif /* !__linux__ */
509 #if !defined(LOW_MEMORY)
513 /*! \brief A reasonable maximum number of locks a thread would be holding ... */
514 #define AST_MAX_LOCKS 64
516 /* Allow direct use of pthread_mutex_t and friends */
517 #undef pthread_mutex_t
518 #undef pthread_mutex_lock
519 #undef pthread_mutex_unlock
520 #undef pthread_mutex_init
521 #undef pthread_mutex_destroy
524 * \brief Keep track of which locks a thread holds
526 * There is an instance of this struct for every active thread
528 struct thr_lock_info
{
529 /*! The thread's ID */
531 /*! The thread name which includes where the thread was started */
532 const char *thread_name
;
533 /*! This is the actual container of info for what locks this thread holds */
538 const char *lock_name
;
541 enum ast_lock_type type
;
542 /*! This thread is waiting on this lock */
544 } locks
[AST_MAX_LOCKS
];
545 /*! This is the number of locks currently held by this thread.
546 * The index (num_locks - 1) has the info on the last one in the
548 unsigned int num_locks
;
549 /*! Protects the contents of the locks member
550 * Intentionally not ast_mutex_t */
551 pthread_mutex_t lock
;
552 AST_LIST_ENTRY(thr_lock_info
) entry
;
556 * \brief Locked when accessing the lock_infos list
558 AST_MUTEX_DEFINE_STATIC(lock_infos_lock
);
560 * \brief A list of each thread's lock info
562 static AST_LIST_HEAD_NOLOCK_STATIC(lock_infos
, thr_lock_info
);
565 * \brief Destroy a thread's lock info
567 * This gets called automatically when the thread stops
569 static void lock_info_destroy(void *data
)
571 struct thr_lock_info
*lock_info
= data
;
574 pthread_mutex_lock(&lock_infos_lock
.mutex
);
575 AST_LIST_REMOVE(&lock_infos
, lock_info
, entry
);
576 pthread_mutex_unlock(&lock_infos_lock
.mutex
);
579 for (i
= 0; i
< lock_info
->num_locks
; i
++) {
581 "Thread '%s' still has a lock! - '%s' (%p) from '%s' in %s:%d!\n",
582 lock_info
->thread_name
,
583 lock_info
->locks
[i
].lock_name
,
584 lock_info
->locks
[i
].lock_addr
,
585 lock_info
->locks
[i
].func
,
586 lock_info
->locks
[i
].file
,
587 lock_info
->locks
[i
].line_num
591 pthread_mutex_destroy(&lock_info
->lock
);
592 free((void *) lock_info
->thread_name
);
597 * \brief The thread storage key for per-thread lock info
599 AST_THREADSTORAGE_CUSTOM(thread_lock_info
, thread_lock_info_init
, lock_info_destroy
);
601 void ast_store_lock_info(enum ast_lock_type type
, const char *filename
,
602 int line_num
, const char *func
, const char *lock_name
, void *lock_addr
)
604 struct thr_lock_info
*lock_info
;
607 if (!(lock_info
= ast_threadstorage_get(&thread_lock_info
, sizeof(*lock_info
))))
610 pthread_mutex_lock(&lock_info
->lock
);
612 for (i
= 0; i
< lock_info
->num_locks
; i
++) {
613 if (lock_info
->locks
[i
].lock_addr
== lock_addr
) {
614 lock_info
->locks
[i
].times_locked
++;
615 pthread_mutex_unlock(&lock_info
->lock
);
620 if (lock_info
->num_locks
== AST_MAX_LOCKS
) {
621 /* Can't use ast_log here, because it will cause infinite recursion */
622 fprintf(stderr
, "XXX ERROR XXX A thread holds more locks than '%d'."
623 " Increase AST_MAX_LOCKS!\n", AST_MAX_LOCKS
);
624 pthread_mutex_unlock(&lock_info
->lock
);
628 if (i
&& lock_info
->locks
[i
- 1].pending
== -1) {
629 /* The last lock on the list was one that this thread tried to lock but
630 * failed at doing so. It has now moved on to something else, so remove
631 * the old lock from the list. */
633 lock_info
->num_locks
--;
634 memset(&lock_info
->locks
[i
], 0, sizeof(lock_info
->locks
[0]));
637 lock_info
->locks
[i
].file
= filename
;
638 lock_info
->locks
[i
].line_num
= line_num
;
639 lock_info
->locks
[i
].func
= func
;
640 lock_info
->locks
[i
].lock_name
= lock_name
;
641 lock_info
->locks
[i
].lock_addr
= lock_addr
;
642 lock_info
->locks
[i
].times_locked
= 1;
643 lock_info
->locks
[i
].type
= type
;
644 lock_info
->locks
[i
].pending
= 1;
645 lock_info
->num_locks
++;
647 pthread_mutex_unlock(&lock_info
->lock
);
650 void ast_mark_lock_acquired(void *lock_addr
)
652 struct thr_lock_info
*lock_info
;
654 if (!(lock_info
= ast_threadstorage_get(&thread_lock_info
, sizeof(*lock_info
))))
657 pthread_mutex_lock(&lock_info
->lock
);
658 if (lock_info
->locks
[lock_info
->num_locks
- 1].lock_addr
== lock_addr
) {
659 lock_info
->locks
[lock_info
->num_locks
- 1].pending
= 0;
661 pthread_mutex_unlock(&lock_info
->lock
);
664 void ast_mark_lock_failed(void *lock_addr
)
666 struct thr_lock_info
*lock_info
;
668 if (!(lock_info
= ast_threadstorage_get(&thread_lock_info
, sizeof(*lock_info
))))
671 pthread_mutex_lock(&lock_info
->lock
);
672 if (lock_info
->locks
[lock_info
->num_locks
- 1].lock_addr
== lock_addr
) {
673 lock_info
->locks
[lock_info
->num_locks
- 1].pending
= -1;
674 lock_info
->locks
[lock_info
->num_locks
- 1].times_locked
--;
676 pthread_mutex_unlock(&lock_info
->lock
);
679 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
)
681 struct thr_lock_info
*lock_info
;
684 if (!(lock_info
= ast_threadstorage_get(&thread_lock_info
, sizeof(*lock_info
))))
687 pthread_mutex_lock(&lock_info
->lock
);
689 for (i
= lock_info
->num_locks
- 1; i
>= 0; i
--) {
690 if (lock_info
->locks
[i
].lock_addr
== lock_addr
)
695 /* Lock not found :( */
696 pthread_mutex_unlock(&lock_info
->lock
);
700 ast_copy_string(filename
, lock_info
->locks
[i
].file
, filename_size
);
701 *lineno
= lock_info
->locks
[i
].line_num
;
702 ast_copy_string(func
, lock_info
->locks
[i
].func
, func_size
);
703 ast_copy_string(mutex_name
, lock_info
->locks
[i
].lock_name
, mutex_name_size
);
705 pthread_mutex_unlock(&lock_info
->lock
);
710 void ast_remove_lock_info(void *lock_addr
)
712 struct thr_lock_info
*lock_info
;
715 if (!(lock_info
= ast_threadstorage_get(&thread_lock_info
, sizeof(*lock_info
))))
718 pthread_mutex_lock(&lock_info
->lock
);
720 for (i
= lock_info
->num_locks
- 1; i
>= 0; i
--) {
721 if (lock_info
->locks
[i
].lock_addr
== lock_addr
)
726 /* Lock not found :( */
727 pthread_mutex_unlock(&lock_info
->lock
);
731 if (lock_info
->locks
[i
].times_locked
> 1) {
732 lock_info
->locks
[i
].times_locked
--;
733 pthread_mutex_unlock(&lock_info
->lock
);
737 if (i
< lock_info
->num_locks
- 1) {
738 /* Not the last one ... *should* be rare! */
739 memmove(&lock_info
->locks
[i
], &lock_info
->locks
[i
+ 1],
740 (lock_info
->num_locks
- (i
+ 1)) * sizeof(lock_info
->locks
[0]));
743 lock_info
->num_locks
--;
745 pthread_mutex_unlock(&lock_info
->lock
);
748 static const char *locktype2str(enum ast_lock_type type
)
762 static int handle_show_locks(int fd
, int argc
, char *argv
[])
764 struct thr_lock_info
*lock_info
;
765 struct ast_dynamic_str
*str
;
767 if (!(str
= ast_dynamic_str_create(4096)))
768 return RESULT_FAILURE
;
770 ast_dynamic_str_append(&str
, 0, "\n"
771 "=======================================================================\n"
772 "=== Currently Held Locks ==============================================\n"
773 "=======================================================================\n"
775 "=== <file> <line num> <function> <lock name> <lock addr> (times locked)\n"
779 return RESULT_FAILURE
;
781 pthread_mutex_lock(&lock_infos_lock
.mutex
);
782 AST_LIST_TRAVERSE(&lock_infos
, lock_info
, entry
) {
784 if (lock_info
->num_locks
) {
785 ast_dynamic_str_append(&str
, 0, "=== Thread ID: %u (%s)\n", (int) lock_info
->thread_id
,
786 lock_info
->thread_name
);
787 pthread_mutex_lock(&lock_info
->lock
);
788 for (i
= 0; str
&& i
< lock_info
->num_locks
; i
++) {
792 ast_dynamic_str_append(&str
, 0, "=== ---> %sLock #%d (%s): %s %d %s %s %p (%d)\n",
793 lock_info
->locks
[i
].pending
> 0 ? "Waiting for " :
794 lock_info
->locks
[i
].pending
< 0 ? "Tried and failed to get " : "", i
,
795 lock_info
->locks
[i
].file
,
796 locktype2str(lock_info
->locks
[i
].type
),
797 lock_info
->locks
[i
].line_num
,
798 lock_info
->locks
[i
].func
, lock_info
->locks
[i
].lock_name
,
799 lock_info
->locks
[i
].lock_addr
,
800 lock_info
->locks
[i
].times_locked
);
802 if (!lock_info
->locks
[i
].pending
|| lock_info
->locks
[i
].pending
== -1)
805 /* We only have further details for mutexes right now */
806 if (lock_info
->locks
[i
].type
!= AST_MUTEX
)
809 lock
= lock_info
->locks
[i
].lock_addr
;
811 ast_reentrancy_lock(lock
);
812 for (j
= 0; str
&& j
< lock
->reentrancy
; j
++) {
813 ast_dynamic_str_append(&str
, 0, "=== --- ---> Locked Here: %s line %d (%s)\n",
814 lock
->file
[j
], lock
->lineno
[j
], lock
->func
[j
]);
816 ast_reentrancy_unlock(lock
);
818 pthread_mutex_unlock(&lock_info
->lock
);
821 ast_dynamic_str_append(&str
, 0, "=== -------------------------------------------------------------------\n"
827 pthread_mutex_unlock(&lock_infos_lock
.mutex
);
830 return RESULT_FAILURE
;
832 ast_dynamic_str_append(&str
, 0, "=======================================================================\n"
836 return RESULT_FAILURE
;
838 ast_cli(fd
, "%s", str
->str
);
842 return RESULT_SUCCESS
;
845 static char show_locks_help
[] =
846 "Usage: core show locks\n"
847 " This command is for lock debugging. It prints out which locks\n"
848 "are owned by each active thread.\n";
850 static struct ast_cli_entry utils_cli
[] = {
851 { { "core", "show", "locks", NULL
}, handle_show_locks
,
852 "Show which locks are locked by which thread", show_locks_help
},
855 #endif /* DEBUG_THREADS */
860 * support for 'show threads'. The start routine is wrapped by
861 * dummy_start(), so that ast_register_thread() and
862 * ast_unregister_thread() know the thread identifier.
865 void *(*start_routine
)(void *);
871 * on OS/X, pthread_cleanup_push() and pthread_cleanup_pop()
872 * are odd macros which start and end a block, so they _must_ be
873 * used in pairs (the latter with a '1' argument to call the
875 * On BSD we don't need this, but we keep it for compatibility.
877 static void *dummy_start(void *data
)
880 struct thr_arg a
= *((struct thr_arg
*) data
); /* make a local copy */
882 struct thr_lock_info
*lock_info
;
883 pthread_mutexattr_t mutex_attr
;
886 /* note that even though data->name is a pointer to allocated memory,
887 we are not freeing it here because ast_register_thread is going to
888 keep a copy of the pointer and then ast_unregister_thread will
892 ast_register_thread(a
.name
);
893 pthread_cleanup_push(ast_unregister_thread
, (void *) pthread_self());
896 if (!(lock_info
= ast_threadstorage_get(&thread_lock_info
, sizeof(*lock_info
))))
899 lock_info
->thread_id
= pthread_self();
900 lock_info
->thread_name
= strdup(a
.name
);
902 pthread_mutexattr_init(&mutex_attr
);
903 pthread_mutexattr_settype(&mutex_attr
, AST_MUTEX_KIND
);
904 pthread_mutex_init(&lock_info
->lock
, &mutex_attr
);
905 pthread_mutexattr_destroy(&mutex_attr
);
907 pthread_mutex_lock(&lock_infos_lock
.mutex
); /* Intentionally not the wrapper */
908 AST_LIST_INSERT_TAIL(&lock_infos
, lock_info
, entry
);
909 pthread_mutex_unlock(&lock_infos_lock
.mutex
); /* Intentionally not the wrapper */
910 #endif /* DEBUG_THREADS */
912 ret
= a
.start_routine(a
.data
);
914 pthread_cleanup_pop(1);
919 #endif /* !LOW_MEMORY */
921 int ast_pthread_create_stack(pthread_t
*thread
, pthread_attr_t
*attr
, void *(*start_routine
)(void *),
922 void *data
, size_t stacksize
, const char *file
, const char *caller
,
923 int line
, const char *start_fn
)
925 #if !defined(LOW_MEMORY)
930 attr
= alloca(sizeof(*attr
));
931 pthread_attr_init(attr
);
935 /* On Linux, pthread_attr_init() defaults to PTHREAD_EXPLICIT_SCHED,
936 which is kind of useless. Change this here to
937 PTHREAD_INHERIT_SCHED; that way the -p option to set realtime
938 priority will propagate down to new threads by default.
939 This does mean that callers cannot set a different priority using
940 PTHREAD_EXPLICIT_SCHED in the attr argument; instead they must set
941 the priority afterwards with pthread_setschedparam(). */
942 if ((errno
= pthread_attr_setinheritsched(attr
, PTHREAD_INHERIT_SCHED
)))
943 ast_log(LOG_WARNING
, "pthread_attr_setinheritsched: %s\n", strerror(errno
));
947 stacksize
= AST_STACKSIZE
;
949 if ((errno
= pthread_attr_setstacksize(attr
, stacksize
? stacksize
: AST_STACKSIZE
)))
950 ast_log(LOG_WARNING
, "pthread_attr_setstacksize: %s\n", strerror(errno
));
952 #if !defined(LOW_MEMORY)
953 if ((a
= ast_malloc(sizeof(*a
)))) {
954 a
->start_routine
= start_routine
;
956 start_routine
= dummy_start
;
957 asprintf(&a
->name
, "%-20s started at [%5d] %s %s()",
958 start_fn
, line
, file
, caller
);
961 #endif /* !LOW_MEMORY */
963 return pthread_create(thread
, attr
, start_routine
, data
); /* We're in ast_pthread_create, so it's okay */
966 int ast_wait_for_input(int fd
, int ms
)
968 struct pollfd pfd
[1];
969 memset(pfd
, 0, sizeof(pfd
));
971 pfd
[0].events
= POLLIN
|POLLPRI
;
972 return poll(pfd
, 1, ms
);
975 int ast_carefulwrite(int fd
, char *s
, int len
, int timeoutms
)
977 /* Try to write string, but wait no more than ms milliseconds
980 struct pollfd fds
[1];
982 res
= write(fd
, s
, len
);
983 if ((res
< 0) && (errno
!= EAGAIN
)) {
993 fds
[0].events
= POLLOUT
;
994 /* Wait until writable again */
995 res
= poll(fds
, 1, timeoutms
);
1003 char *ast_strip_quoted(char *s
, const char *beg_quotes
, const char *end_quotes
)
1009 if ((q
= strchr(beg_quotes
, *s
)) && *q
!= '\0') {
1010 e
= s
+ strlen(s
) - 1;
1011 if (*e
== *(end_quotes
+ (q
- beg_quotes
))) {
1020 char *ast_unescape_semicolon(char *s
)
1025 while ((e
= strchr(work
, ';'))) {
1026 if ((e
> work
) && (*(e
-1) == '\\')) {
1027 memmove(e
- 1, e
, strlen(e
) + 1);
1037 int ast_build_string_va(char **buffer
, size_t *space
, const char *fmt
, va_list ap
)
1041 if (!buffer
|| !*buffer
|| !space
|| !*space
)
1044 result
= vsnprintf(*buffer
, *space
, fmt
, ap
);
1048 else if (result
> *space
)
1056 int ast_build_string(char **buffer
, size_t *space
, const char *fmt
, ...)
1062 result
= ast_build_string_va(buffer
, space
, fmt
, ap
);
1068 int ast_true(const char *s
)
1070 if (ast_strlen_zero(s
))
1073 /* Determine if this is a true value */
1074 if (!strcasecmp(s
, "yes") ||
1075 !strcasecmp(s
, "true") ||
1076 !strcasecmp(s
, "y") ||
1077 !strcasecmp(s
, "t") ||
1078 !strcasecmp(s
, "1") ||
1079 !strcasecmp(s
, "on"))
1085 int ast_false(const char *s
)
1087 if (ast_strlen_zero(s
))
1090 /* Determine if this is a false value */
1091 if (!strcasecmp(s
, "no") ||
1092 !strcasecmp(s
, "false") ||
1093 !strcasecmp(s
, "n") ||
1094 !strcasecmp(s
, "f") ||
1095 !strcasecmp(s
, "0") ||
1096 !strcasecmp(s
, "off"))
1102 #define ONE_MILLION 1000000
1104 * put timeval in a valid range. usec is 0..999999
1105 * negative values are not allowed and truncated.
1107 static struct timeval
tvfix(struct timeval a
)
1109 if (a
.tv_usec
>= ONE_MILLION
) {
1110 ast_log(LOG_WARNING
, "warning too large timestamp %ld.%ld\n",
1111 a
.tv_sec
, (long int) a
.tv_usec
);
1112 a
.tv_sec
+= a
.tv_usec
/ ONE_MILLION
;
1113 a
.tv_usec
%= ONE_MILLION
;
1114 } else if (a
.tv_usec
< 0) {
1115 ast_log(LOG_WARNING
, "warning negative timestamp %ld.%ld\n",
1116 a
.tv_sec
, (long int) a
.tv_usec
);
1122 struct timeval
ast_tvadd(struct timeval a
, struct timeval b
)
1124 /* consistency checks to guarantee usec in 0..999999 */
1127 a
.tv_sec
+= b
.tv_sec
;
1128 a
.tv_usec
+= b
.tv_usec
;
1129 if (a
.tv_usec
>= ONE_MILLION
) {
1131 a
.tv_usec
-= ONE_MILLION
;
1136 struct timeval
ast_tvsub(struct timeval a
, struct timeval b
)
1138 /* consistency checks to guarantee usec in 0..999999 */
1141 a
.tv_sec
-= b
.tv_sec
;
1142 a
.tv_usec
-= b
.tv_usec
;
1143 if (a
.tv_usec
< 0) {
1145 a
.tv_usec
+= ONE_MILLION
;
1151 /*! \brief glibc puts a lock inside random(3), so that the results are thread-safe.
1152 * BSD libc (and others) do not. */
1155 AST_MUTEX_DEFINE_STATIC(randomlock
);
1157 long int ast_random(void)
1160 ast_mutex_lock(&randomlock
);
1162 ast_mutex_unlock(&randomlock
);
1167 char *ast_process_quotes_and_slashes(char *start
, char find
, char replace_with
)
1169 char *dataPut
= start
;
1173 for (; *start
; start
++) {
1175 *dataPut
++ = *start
; /* Always goes verbatim */
1178 if (*start
== '\\') {
1179 inEscape
= 1; /* Do not copy \ into the data */
1180 } else if (*start
== '\'') {
1181 inQuotes
= 1 - inQuotes
; /* Do not copy ' into the data */
1183 /* Replace , with |, unless in quotes */
1184 *dataPut
++ = inQuotes
? *start
: ((*start
== find
) ? replace_with
: *start
);
1188 if (start
!= dataPut
)
1193 void ast_join(char *s
, size_t len
, char * const w
[])
1198 /* Join words into a string */
1201 for (x
= 0; ofs
< len
&& w
[x
]; x
++) {
1204 for (src
= w
[x
]; *src
&& ofs
< len
; src
++)
1212 const char __ast_string_field_empty
[] = "";
1214 static int add_string_pool(struct ast_string_field_mgr
*mgr
, size_t size
)
1216 struct ast_string_field_pool
*pool
;
1218 if (!(pool
= ast_calloc(1, sizeof(*pool
) + size
)))
1221 pool
->prev
= mgr
->pool
;
1230 int __ast_string_field_init(struct ast_string_field_mgr
*mgr
, size_t size
,
1231 ast_string_field
*fields
, int num_fields
)
1235 if (add_string_pool(mgr
, size
))
1238 for (index
= 0; index
< num_fields
; index
++)
1239 fields
[index
] = __ast_string_field_empty
;
1244 ast_string_field
__ast_string_field_alloc_space(struct ast_string_field_mgr
*mgr
, size_t needed
,
1245 ast_string_field
*fields
, int num_fields
)
1247 char *result
= NULL
;
1249 if (__builtin_expect(needed
> mgr
->space
, 0)) {
1250 size_t new_size
= mgr
->size
* 2;
1252 while (new_size
< needed
)
1255 if (add_string_pool(mgr
, new_size
))
1259 result
= mgr
->pool
->base
+ mgr
->used
;
1260 mgr
->used
+= needed
;
1261 mgr
->space
-= needed
;
1265 void __ast_string_field_index_build_va(struct ast_string_field_mgr
*mgr
,
1266 ast_string_field
*fields
, int num_fields
,
1267 int index
, const char *format
, va_list ap1
, va_list ap2
)
1271 needed
= vsnprintf(mgr
->pool
->base
+ mgr
->used
, mgr
->space
, format
, ap1
) + 1;
1275 if (needed
> mgr
->space
) {
1276 size_t new_size
= mgr
->size
* 2;
1278 while (new_size
< needed
)
1281 if (add_string_pool(mgr
, new_size
))
1284 vsprintf(mgr
->pool
->base
+ mgr
->used
, format
, ap2
);
1287 fields
[index
] = mgr
->pool
->base
+ mgr
->used
;
1288 mgr
->used
+= needed
;
1289 mgr
->space
-= needed
;
1292 void __ast_string_field_index_build(struct ast_string_field_mgr
*mgr
,
1293 ast_string_field
*fields
, int num_fields
,
1294 int index
, const char *format
, ...)
1298 va_start(ap1
, format
);
1299 va_start(ap2
, format
); /* va_copy does not exist on FreeBSD */
1301 __ast_string_field_index_build_va(mgr
, fields
, num_fields
, index
, format
, ap1
, ap2
);
1307 AST_MUTEX_DEFINE_STATIC(fetchadd_m
); /* used for all fetc&add ops */
1309 int ast_atomic_fetchadd_int_slow(volatile int *p
, int v
)
1312 ast_mutex_lock(&fetchadd_m
);
1315 ast_mutex_unlock(&fetchadd_m
);
1320 * get values from config variables.
1322 int ast_get_time_t(const char *src
, time_t *dst
, time_t _default
, int *consumed
)
1332 if (ast_strlen_zero(src
))
1335 /* only integer at the moment, but one day we could accept more formats */
1336 if (sscanf(src
, "%ld%n", &t
, &scanned
) == 1) {
1339 *consumed
= scanned
;
1345 int ast_dynamic_str_thread_build_va(struct ast_dynamic_str
**buf
, size_t max_len
,
1346 struct ast_threadstorage
*ts
, int append
, const char *fmt
, va_list ap
)
1349 int offset
= (append
&& (*buf
)->len
) ? strlen((*buf
)->str
) : 0;
1350 #if defined(DEBUG_THREADLOCALS)
1351 struct ast_dynamic_str
*old_buf
= *buf
;
1352 #endif /* defined(DEBUG_THREADLOCALS) */
1354 res
= vsnprintf((*buf
)->str
+ offset
, (*buf
)->len
- offset
, fmt
, ap
);
1356 /* Check to see if there was not enough space in the string buffer to prepare
1357 * the string. Also, if a maximum length is present, make sure the current
1358 * length is less than the maximum before increasing the size. */
1359 if ((res
+ offset
+ 1) > (*buf
)->len
&& (max_len
? ((*buf
)->len
< max_len
) : 1)) {
1360 /* Set the new size of the string buffer to be the size needed
1361 * to hold the resulting string (res) plus one byte for the
1362 * terminating '\0'. If this size is greater than the max, set
1363 * the new length to be the maximum allowed. */
1365 (*buf
)->len
= ((res
+ offset
+ 1) < max_len
) ? (res
+ offset
+ 1) : max_len
;
1367 (*buf
)->len
= res
+ offset
+ 1;
1369 if (!(*buf
= ast_realloc(*buf
, (*buf
)->len
+ sizeof(*(*buf
)))))
1370 return AST_DYNSTR_BUILD_FAILED
;
1373 (*buf
)->str
[offset
] = '\0';
1376 pthread_setspecific(ts
->key
, *buf
);
1377 #if defined(DEBUG_THREADLOCALS)
1378 __ast_threadstorage_object_replace(old_buf
, *buf
, (*buf
)->len
+ sizeof(*(*buf
)));
1379 #endif /* defined(DEBUG_THREADLOCALS) */
1382 /* va_end() and va_start() must be done before calling
1383 * vsnprintf() again. */
1384 return AST_DYNSTR_BUILD_RETRY
;
1390 void ast_enable_packet_fragmentation(int sock
)
1392 #if defined(HAVE_IP_MTU_DISCOVER)
1393 int val
= IP_PMTUDISC_DONT
;
1395 if (setsockopt(sock
, IPPROTO_IP
, IP_MTU_DISCOVER
, &val
, sizeof(val
)))
1396 ast_log(LOG_WARNING
, "Unable to disable PMTU discovery. Large UDP packets may fail to be delivered when sent from this socket.\n");
1397 #endif /* HAVE_IP_MTU_DISCOVER */
1400 int ast_utils_init(void)
1403 #ifdef DEBUG_THREADS
1404 #if !defined(LOW_MEMORY)
1405 ast_cli_register_multiple(utils_cli
, sizeof(utils_cli
) / sizeof(utils_cli
[0]));
1411 #ifndef __AST_DEBUG_MALLOC
1412 int _ast_asprintf(char **ret
, const char *file
, int lineno
, const char *func
, const char *fmt
, ...)
1418 if ((res
= vasprintf(ret
, fmt
, ap
)) == -1) {