#include "asterisk.h"
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "asterisk/lock.h"
#include "asterisk/io.h"
#include "asterisk/logger.h"
#include "asterisk/md5.h"
#include "asterisk/sha1.h"
#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/linkedlists.h"
#include "asterisk/strings.h"
#include "asterisk/time.h"
#include "asterisk/stringfields.h"
#include "asterisk/utils.h"
#include "asterisk/threadstorage.h"
Go to the source code of this file.
Data Structures | |
struct | lock_infos |
A list of each thread's lock info. More... | |
struct | thr_arg |
struct | thr_lock_info |
Keep track of which locks a thread holds. More... | |
Defines | |
#define | AST_API_MODULE |
#define | AST_API_MODULE |
#define | AST_API_MODULE |
#define | AST_API_MODULE |
#define | AST_API_MODULE |
#define | AST_API_MODULE |
#define | AST_MAX_LOCKS 64 |
A reasonable maximum number of locks a thread would be holding ... | |
#define | ONE_MILLION 1000000 |
Functions | |
ast_string_field | __ast_string_field_alloc_space (struct ast_string_field_mgr *mgr, size_t needed, ast_string_field *fields, int num_fields) |
void | __ast_string_field_index_build (struct ast_string_field_mgr *mgr, ast_string_field *fields, int num_fields, int index, const char *format,...) |
void | __ast_string_field_index_build_va (struct ast_string_field_mgr *mgr, ast_string_field *fields, int num_fields, int index, const char *format, va_list ap1, va_list ap2) |
int | __ast_string_field_init (struct ast_string_field_mgr *mgr, size_t size, ast_string_field *fields, int num_fields) |
int | _ast_asprintf (char **ret, const char *file, int lineno, const char *func, const char *fmt,...) |
static int | add_string_pool (struct ast_string_field_mgr *mgr, size_t size) |
int | ast_atomic_fetchadd_int_slow (volatile int *p, int v) |
int | ast_base64decode (unsigned char *dst, const char *src, int max) |
decode BASE64 encoded text | |
int | ast_base64encode (char *dst, const unsigned char *src, int srclen, int max) |
int | ast_base64encode_full (char *dst, const unsigned char *src, int srclen, int max, int linebreaks) |
encode text to BASE64 coding | |
int | ast_build_string (char **buffer, size_t *space, const char *fmt,...) |
Build a string in a buffer, designed to be called repeatedly. | |
int | ast_build_string_va (char **buffer, size_t *space, const char *fmt, va_list ap) |
Build a string in a buffer, designed to be called repeatedly. | |
int | ast_carefulwrite (int fd, char *s, int len, int timeoutms) |
Try to write string, but wait no more than ms milliseconds before timing out. | |
int | ast_dynamic_str_thread_build_va (struct ast_dynamic_str **buf, size_t max_len, struct ast_threadstorage *ts, int append, const char *fmt, va_list ap) |
Core functionality of ast_dynamic_str_thread_(set|append)_va. | |
void | ast_enable_packet_fragmentation (int sock) |
Disable PMTU discovery on a socket. | |
int | ast_false (const char *s) |
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) |
retrieve lock info for the specified mutex | |
int | ast_get_time_t (const char *src, time_t *dst, time_t _default, int *consumed) |
get values from config variables. | |
hostent * | ast_gethostbyname (const char *host, struct ast_hostent *hp) |
Re-entrant (thread safe) version of gethostbyname that replaces the standard gethostbyname (which is not thread safe). | |
const char * | ast_inet_ntoa (struct in_addr ia) |
thread-safe replacement for inet_ntoa(). | |
void | ast_join (char *s, size_t len, char *const w[]) |
void | ast_mark_lock_acquired (void *lock_addr) |
Mark the last lock as acquired. | |
void | ast_mark_lock_failed (void *lock_addr) |
Mark the last lock as failed (trylock). | |
void | ast_md5_hash (char *output, char *input) |
Produce 32 char MD5 hash of value. | |
char * | ast_process_quotes_and_slashes (char *start, char find, char replace_with) |
Process a string to find and replace characters. | |
int | ast_pthread_create_stack (pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *data, size_t stacksize, const char *file, const char *caller, int line, const char *start_fn) |
long int | ast_random (void) |
void | ast_remove_lock_info (void *lock_addr) |
remove lock info for the current thread | |
void | ast_sha1_hash (char *output, char *input) |
Produce 40 char SHA1 hash of value. | |
void | ast_store_lock_info (enum ast_lock_type type, const char *filename, int line_num, const char *func, const char *lock_name, void *lock_addr) |
Store lock info for the current thread. | |
char * | ast_strip_quoted (char *s, const char *beg_quotes, const char *end_quotes) |
Strip leading/trailing whitespace and quotes from a string. | |
int | ast_true (const char *s) |
timeval | ast_tvadd (struct timeval a, struct timeval b) |
Returns the sum of two timevals a + b. | |
timeval | ast_tvsub (struct timeval a, struct timeval b) |
Returns the difference of two timevals a - b. | |
char * | ast_unescape_semicolon (char *s) |
Strip backslash for "escaped" semicolons. s The string to be stripped (will be modified). | |
void | ast_uri_decode (char *s) |
Decode URI, URN, URL (overwrite string). | |
char * | ast_uri_encode (const char *string, char *outbuf, int buflen, int doreserved) |
Turn text string to URI-encoded XX version At this point, we're converting from ISO-8859-x (8-bit), not UTF8 as in the SIP protocol spec If doreserved == 1 we will convert reserved characters also. RFC 2396, section 2.4 outbuf needs to have more memory allocated than the instring to have room for the expansion. Every char that is converted is replaced by three ASCII characters. | |
int | ast_utils_init (void) |
int | ast_wait_for_input (int fd, int ms) |
static void | base64_init (void) |
static void * | dummy_start (void *data) |
static int | handle_show_locks (int fd, int argc, char *argv[]) |
static void | inet_ntoa_buf_init (void) |
static void | lock_info_destroy (void *data) |
Destroy a thread's lock info. | |
static const char * | locktype2str (enum ast_lock_type type) |
static void | thread_lock_info_init (void) |
The thread storage key for per-thread lock info. | |
static struct timeval | tvfix (struct timeval a) |
Variables | |
const char | __ast_string_field_empty [] = "" |
static char | b2a [256] |
static char | base64 [64] |
static ast_mutex_t | fetchadd_m = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } |
static struct ast_threadstorage | inet_ntoa_buf = { .once = PTHREAD_ONCE_INIT, .key_init = inet_ntoa_buf_init , } |
static ast_mutex_t | lock_infos_lock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } |
Locked when accessing the lock_infos list. | |
static ast_mutex_t | randomlock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } |
glibc puts a lock inside random(3), so that the results are thread-safe. BSD libc (and others) do not. | |
static char | show_locks_help [] |
static struct ast_threadstorage | thread_lock_info = { .once = PTHREAD_ONCE_INIT, .key_init = thread_lock_info_init , } |
static struct ast_cli_entry | utils_cli [] |
Definition in file utils.c.
#define AST_MAX_LOCKS 64 |
#define ONE_MILLION 1000000 |
ast_string_field __ast_string_field_alloc_space | ( | struct ast_string_field_mgr * | mgr, | |
size_t | needed, | |||
ast_string_field * | fields, | |||
int | num_fields | |||
) |
Definition at line 1233 of file utils.c.
References add_string_pool(), ast_string_field_pool::base, ast_string_field_mgr::pool, ast_string_field_mgr::size, ast_string_field_mgr::space, and ast_string_field_mgr::used.
01235 { 01236 char *result = NULL; 01237 01238 if (__builtin_expect(needed > mgr->space, 0)) { 01239 size_t new_size = mgr->size * 2; 01240 01241 while (new_size < needed) 01242 new_size *= 2; 01243 01244 if (add_string_pool(mgr, new_size)) 01245 return NULL; 01246 } 01247 01248 result = mgr->pool->base + mgr->used; 01249 mgr->used += needed; 01250 mgr->space -= needed; 01251 return result; 01252 }
void __ast_string_field_index_build | ( | struct ast_string_field_mgr * | mgr, | |
ast_string_field * | fields, | |||
int | num_fields, | |||
int | index, | |||
const char * | format, | |||
... | ||||
) |
Definition at line 1308 of file utils.c.
References __ast_string_field_index_build_va().
01311 { 01312 va_list ap1, ap2; 01313 01314 va_start(ap1, format); 01315 va_start(ap2, format); /* va_copy does not exist on FreeBSD */ 01316 01317 __ast_string_field_index_build_va(mgr, fields, num_fields, index, format, ap1, ap2); 01318 01319 va_end(ap1); 01320 va_end(ap2); 01321 }
void __ast_string_field_index_build_va | ( | struct ast_string_field_mgr * | mgr, | |
ast_string_field * | fields, | |||
int | num_fields, | |||
int | index, | |||
const char * | format, | |||
va_list | ap1, | |||
va_list | ap2 | |||
) |
Definition at line 1254 of file utils.c.
References add_string_pool(), available(), ast_string_field_pool::base, ast_string_field_mgr::pool, ast_string_field_mgr::size, ast_string_field_mgr::space, and ast_string_field_mgr::used.
Referenced by __ast_string_field_index_build().
01257 { 01258 size_t needed; 01259 size_t available; 01260 char *target; 01261 01262 /* if the field already has space allocated, try to reuse it; 01263 otherwise, use the empty space at the end of the current 01264 pool 01265 */ 01266 if (fields[index][0] != '\0') { 01267 target = (char *) fields[index]; 01268 available = strlen(fields[index]) + 1; 01269 } else { 01270 target = mgr->pool->base + mgr->used; 01271 available = mgr->space; 01272 } 01273 01274 needed = vsnprintf(target, available, format, ap1) + 1; 01275 01276 va_end(ap1); 01277 01278 if (needed > available) { 01279 /* if the space needed can be satisfied by using the current 01280 pool (which could only occur if we tried to use the field's 01281 allocated space and failed), then use that space; otherwise 01282 allocate a new pool 01283 */ 01284 if (needed <= mgr->space) { 01285 target = mgr->pool->base + mgr->used; 01286 } else { 01287 size_t new_size = mgr->size * 2; 01288 01289 while (new_size < needed) 01290 new_size *= 2; 01291 01292 if (add_string_pool(mgr, new_size)) 01293 return; 01294 01295 target = mgr->pool->base + mgr->used; 01296 } 01297 01298 vsprintf(target, format, ap2); 01299 } 01300 01301 if (fields[index] != target) { 01302 fields[index] = target; 01303 mgr->used += needed; 01304 mgr->space -= needed; 01305 } 01306 }
int __ast_string_field_init | ( | struct ast_string_field_mgr * | mgr, | |
size_t | size, | |||
ast_string_field * | fields, | |||
int | num_fields | |||
) |
Definition at line 1219 of file utils.c.
References add_string_pool().
01221 { 01222 int index; 01223 01224 if (add_string_pool(mgr, size)) 01225 return -1; 01226 01227 for (index = 0; index < num_fields; index++) 01228 fields[index] = __ast_string_field_empty; 01229 01230 return 0; 01231 }
int _ast_asprintf | ( | char ** | ret, | |
const char * | file, | |||
int | lineno, | |||
const char * | func, | |||
const char * | fmt, | |||
... | ||||
) |
Definition at line 1428 of file utils.c.
References MALLOC_FAILURE_MSG, and vasprintf.
01429 { 01430 int res; 01431 va_list ap; 01432 01433 va_start(ap, fmt); 01434 if ((res = vasprintf(ret, fmt, ap)) == -1) { 01435 MALLOC_FAILURE_MSG; 01436 } 01437 va_end(ap); 01438 01439 return res; 01440 }
static int add_string_pool | ( | struct ast_string_field_mgr * | mgr, | |
size_t | size | |||
) | [static] |
Definition at line 1203 of file utils.c.
References ast_calloc, ast_string_field_mgr::pool, ast_string_field_mgr::size, ast_string_field_mgr::space, and ast_string_field_mgr::used.
Referenced by __ast_string_field_alloc_space(), __ast_string_field_index_build_va(), and __ast_string_field_init().
01204 { 01205 struct ast_string_field_pool *pool; 01206 01207 if (!(pool = ast_calloc(1, sizeof(*pool) + size))) 01208 return -1; 01209 01210 pool->prev = mgr->pool; 01211 mgr->pool = pool; 01212 mgr->size = size; 01213 mgr->space = size; 01214 mgr->used = 0; 01215 01216 return 0; 01217 }
int ast_atomic_fetchadd_int_slow | ( | volatile int * | p, | |
int | v | |||
) |
Definition at line 1325 of file utils.c.
References ast_mutex_lock, ast_mutex_unlock, and fetchadd_m.
01326 { 01327 int ret; 01328 ast_mutex_lock(&fetchadd_m); 01329 ret = *p; 01330 *p += v; 01331 ast_mutex_unlock(&fetchadd_m); 01332 return ret; 01333 }
int ast_base64decode | ( | unsigned char * | dst, | |
const char * | src, | |||
int | max | |||
) |
decode BASE64 encoded text
Definition at line 266 of file utils.c.
Referenced by __ast_check_signature(), base64_decode(), and osp_validate_token().
00267 { 00268 int cnt = 0; 00269 unsigned int byte = 0; 00270 unsigned int bits = 0; 00271 int incnt = 0; 00272 while(*src && *src != '=' && (cnt < max)) { 00273 /* Shift in 6 bits of input */ 00274 byte <<= 6; 00275 byte |= (b2a[(int)(*src)]) & 0x3f; 00276 bits += 6; 00277 src++; 00278 incnt++; 00279 /* If we have at least 8 bits left over, take that character 00280 off the top */ 00281 if (bits >= 8) { 00282 bits -= 8; 00283 *dst = (byte >> bits) & 0xff; 00284 dst++; 00285 cnt++; 00286 } 00287 } 00288 /* Dont worry about left over bits, they're extra anyway */ 00289 return cnt; 00290 }
int ast_base64encode | ( | char * | dst, | |
const unsigned char * | src, | |||
int | srclen, | |||
int | max | |||
) |
Definition at line 344 of file utils.c.
References ast_base64encode_full().
Referenced by __ast_sign(), aji_act_hook(), base64_encode(), build_secret(), and osp_check_destination().
00345 { 00346 return ast_base64encode_full(dst, src, srclen, max, 0); 00347 }
int ast_base64encode_full | ( | char * | dst, | |
const unsigned char * | src, | |||
int | srclen, | |||
int | max, | |||
int | linebreaks | |||
) |
encode text to BASE64 coding
Definition at line 293 of file utils.c.
Referenced by ast_base64encode().
00294 { 00295 int cnt = 0; 00296 int col = 0; 00297 unsigned int byte = 0; 00298 int bits = 0; 00299 int cntin = 0; 00300 /* Reserve space for null byte at end of string */ 00301 max--; 00302 while ((cntin < srclen) && (cnt < max)) { 00303 byte <<= 8; 00304 byte |= *(src++); 00305 bits += 8; 00306 cntin++; 00307 if ((bits == 24) && (cnt + 4 <= max)) { 00308 *dst++ = base64[(byte >> 18) & 0x3f]; 00309 *dst++ = base64[(byte >> 12) & 0x3f]; 00310 *dst++ = base64[(byte >> 6) & 0x3f]; 00311 *dst++ = base64[byte & 0x3f]; 00312 cnt += 4; 00313 col += 4; 00314 bits = 0; 00315 byte = 0; 00316 } 00317 if (linebreaks && (cnt < max) && (col == 64)) { 00318 *dst++ = '\n'; 00319 cnt++; 00320 col = 0; 00321 } 00322 } 00323 if (bits && (cnt + 4 <= max)) { 00324 /* Add one last character for the remaining bits, 00325 padding the rest with 0 */ 00326 byte <<= 24 - bits; 00327 *dst++ = base64[(byte >> 18) & 0x3f]; 00328 *dst++ = base64[(byte >> 12) & 0x3f]; 00329 if (bits == 16) 00330 *dst++ = base64[(byte >> 6) & 0x3f]; 00331 else 00332 *dst++ = '='; 00333 *dst++ = '='; 00334 cnt += 4; 00335 } 00336 if (linebreaks && (cnt < max)) { 00337 *dst++ = '\n'; 00338 cnt++; 00339 } 00340 *dst = '\0'; 00341 return cnt; 00342 }
int ast_build_string | ( | char ** | buffer, | |
size_t * | space, | |||
const char * | fmt, | |||
... | ||||
) |
Build a string in a buffer, designed to be called repeatedly.
This is a wrapper for snprintf, that properly handles the buffer pointer and buffer space available.
buffer | current position in buffer to place string into (will be updated on return) | |
space | remaining space in buffer (will be updated on return) | |
fmt | printf-style format string |
Definition at line 1045 of file utils.c.
References ast_build_string_va().
Referenced by __queues_show(), add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), ast_cdr_serialize_variables(), ast_http_setcookie(), config_odbc(), config_pgsql(), function_realtime_read(), html_translate(), httpstatus_callback(), initreqprep(), pbx_builtin_serialize_variables(), print_uptimestr(), show_translation(), show_translation_deprecated(), transmit_notify_with_mwi(), transmit_state_notify(), and xml_translate().
01046 { 01047 va_list ap; 01048 int result; 01049 01050 va_start(ap, fmt); 01051 result = ast_build_string_va(buffer, space, fmt, ap); 01052 va_end(ap); 01053 01054 return result; 01055 }
int ast_build_string_va | ( | char ** | buffer, | |
size_t * | space, | |||
const char * | fmt, | |||
va_list | ap | |||
) |
Build a string in a buffer, designed to be called repeatedly.
This is a wrapper for snprintf, that properly handles the buffer pointer and buffer space available.
buffer | current position in buffer to place string into (will be updated on return) | |
space | remaining space in buffer (will be updated on return) | |
fmt | printf-style format string | |
ap | varargs list of arguments for format |
Definition at line 1026 of file utils.c.
Referenced by ast_build_string().
01027 { 01028 int result; 01029 01030 if (!buffer || !*buffer || !space || !*space) 01031 return -1; 01032 01033 result = vsnprintf(*buffer, *space, fmt, ap); 01034 01035 if (result < 0) 01036 return -1; 01037 else if (result > *space) 01038 result = *space; 01039 01040 *buffer += result; 01041 *space -= result; 01042 return 0; 01043 }
int ast_carefulwrite | ( | int | fd, | |
char * | s, | |||
int | len, | |||
int | timeoutms | |||
) |
Try to write string, but wait no more than ms milliseconds before timing out.
ast_carefulwrite
Definition at line 922 of file utils.c.
References ast_log(), ast_poll, ast_tvdiff_ms(), ast_tvnow(), errno, LOG_ERROR, and LOG_NOTICE.
Referenced by agi_debug_cli(), ast_cli(), astman_append(), and process_events().
00923 { 00924 struct timeval start = ast_tvnow(); 00925 int res = 0; 00926 int elapsed = 0; 00927 00928 while (len) { 00929 struct pollfd pfd = { 00930 .fd = fd, 00931 .events = POLLOUT, 00932 }; 00933 00934 /* poll() until the fd is writable without blocking */ 00935 while ((res = ast_poll(&pfd, 1, timeoutms - elapsed)) <= 0) { 00936 if (res == 0) { 00937 /* timed out. */ 00938 ast_log(LOG_NOTICE, "Timed out trying to write\n"); 00939 return -1; 00940 } else if (res == -1) { 00941 /* poll() returned an error, check to see if it was fatal */ 00942 00943 if (errno == EINTR || errno == EAGAIN) { 00944 elapsed = ast_tvdiff_ms(ast_tvnow(), start); 00945 if (elapsed > timeoutms) { 00946 /* We've taken too long to write 00947 * This is only an error condition if we haven't finished writing. */ 00948 res = len ? -1 : 0; 00949 break; 00950 } 00951 /* This was an acceptable error, go back into poll() */ 00952 continue; 00953 } 00954 00955 /* Fatal error, bail. */ 00956 ast_log(LOG_ERROR, "poll returned error: %s\n", strerror(errno)); 00957 00958 return -1; 00959 } 00960 } 00961 00962 res = write(fd, s, len); 00963 00964 if (res < 0 && errno != EAGAIN && errno != EINTR) { 00965 /* fatal error from write() */ 00966 ast_log(LOG_ERROR, "write() returned error: %s\n", strerror(errno)); 00967 return -1; 00968 } 00969 00970 if (res < 0) { 00971 /* It was an acceptable error */ 00972 res = 0; 00973 } 00974 00975 /* Update how much data we have left to write */ 00976 len -= res; 00977 s += res; 00978 res = 0; 00979 00980 elapsed = ast_tvdiff_ms(ast_tvnow(), start); 00981 if (elapsed > timeoutms) { 00982 /* We've taken too long to write 00983 * This is only an error condition if we haven't finished writing. */ 00984 res = len ? -1 : 0; 00985 break; 00986 } 00987 } 00988 00989 return res; 00990 }
int ast_dynamic_str_thread_build_va | ( | struct ast_dynamic_str ** | buf, | |
size_t | max_len, | |||
struct ast_threadstorage * | ts, | |||
int | append, | |||
const char * | fmt, | |||
va_list | ap | |||
) |
Core functionality of ast_dynamic_str_thread_(set|append)_va.
The arguments to this function are the same as those described for ast_dynamic_str_thread_set_va except for an addition argument, append. If append is non-zero, this will append to the current string instead of writing over it.
Definition at line 1361 of file utils.c.
References AST_DYNSTR_BUILD_FAILED, AST_DYNSTR_BUILD_RETRY, ast_realloc, ast_threadstorage::key, ast_dynamic_str::len, and offset.
01363 { 01364 int res; 01365 int offset = (append && (*buf)->len) ? strlen((*buf)->str) : 0; 01366 #if defined(DEBUG_THREADLOCALS) 01367 struct ast_dynamic_str *old_buf = *buf; 01368 #endif /* defined(DEBUG_THREADLOCALS) */ 01369 01370 res = vsnprintf((*buf)->str + offset, (*buf)->len - offset, fmt, ap); 01371 01372 /* Check to see if there was not enough space in the string buffer to prepare 01373 * the string. Also, if a maximum length is present, make sure the current 01374 * length is less than the maximum before increasing the size. */ 01375 if ((res + offset + 1) > (*buf)->len && (max_len ? ((*buf)->len < max_len) : 1)) { 01376 /* Set the new size of the string buffer to be the size needed 01377 * to hold the resulting string (res) plus one byte for the 01378 * terminating '\0'. If this size is greater than the max, set 01379 * the new length to be the maximum allowed. */ 01380 if (max_len) 01381 (*buf)->len = ((res + offset + 1) < max_len) ? (res + offset + 1) : max_len; 01382 else 01383 (*buf)->len = res + offset + 1; 01384 01385 if (!(*buf = ast_realloc(*buf, (*buf)->len + sizeof(*(*buf))))) 01386 return AST_DYNSTR_BUILD_FAILED; 01387 01388 if (append) 01389 (*buf)->str[offset] = '\0'; 01390 01391 if (ts) { 01392 pthread_setspecific(ts->key, *buf); 01393 #if defined(DEBUG_THREADLOCALS) 01394 __ast_threadstorage_object_replace(old_buf, *buf, (*buf)->len + sizeof(*(*buf))); 01395 #endif /* defined(DEBUG_THREADLOCALS) */ 01396 } 01397 01398 /* va_end() and va_start() must be done before calling 01399 * vsnprintf() again. */ 01400 return AST_DYNSTR_BUILD_RETRY; 01401 } 01402 01403 return res; 01404 }
void ast_enable_packet_fragmentation | ( | int | sock | ) |
Disable PMTU discovery on a socket.
sock | The socket to manipulate |
Because of this, UDP packets sent by Asterisk that are larger than the MTU of any hop in the path will be lost. This function can be called on a socket to ensure that the DF bit will not be set.
Definition at line 1406 of file utils.c.
References ast_log(), and LOG_WARNING.
Referenced by ast_netsock_bindaddr().
01407 { 01408 #if defined(HAVE_IP_MTU_DISCOVER) 01409 int val = IP_PMTUDISC_DONT; 01410 01411 if (setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val))) 01412 ast_log(LOG_WARNING, "Unable to disable PMTU discovery. Large UDP packets may fail to be delivered when sent from this socket.\n"); 01413 #endif /* HAVE_IP_MTU_DISCOVER */ 01414 }
int ast_false | ( | const char * | val | ) |
Determine if a string containing a boolean value is "false". This function checks to see whether a string passed to it is an indication of an "false" value. It checks to see if the string is "no", "false", "n", "f", "off" or "0".
Returns 0 if val is a NULL pointer, -1 if "false", and 0 otherwise.
Definition at line 1074 of file utils.c.
References ast_strlen_zero().
Referenced by aji_create_client(), aji_load_config(), ast_rtp_reload(), ast_udptl_reload(), build_peer(), build_user(), handle_common_options(), init_acf_query(), load_config(), load_odbc_config(), reload(), run_agi(), set_config(), set_insecure_flags(), and strings_to_mask().
01075 { 01076 if (ast_strlen_zero(s)) 01077 return 0; 01078 01079 /* Determine if this is a false value */ 01080 if (!strcasecmp(s, "no") || 01081 !strcasecmp(s, "false") || 01082 !strcasecmp(s, "n") || 01083 !strcasecmp(s, "f") || 01084 !strcasecmp(s, "0") || 01085 !strcasecmp(s, "off")) 01086 return -1; 01087 01088 return 0; 01089 }
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 | |||
) |
retrieve lock info for the specified mutex
this gets called during deadlock avoidance, so that the information may be preserved as to what location originally acquired the lock.
Definition at line 623 of file utils.c.
References ast_copy_string(), ast_threadstorage_get(), pthread_mutex_lock, pthread_mutex_unlock, and thread_lock_info.
00624 { 00625 struct thr_lock_info *lock_info; 00626 int i = 0; 00627 00628 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info)))) 00629 return -1; 00630 00631 pthread_mutex_lock(&lock_info->lock); 00632 00633 for (i = lock_info->num_locks - 1; i >= 0; i--) { 00634 if (lock_info->locks[i].lock_addr == lock_addr) 00635 break; 00636 } 00637 00638 if (i == -1) { 00639 /* Lock not found :( */ 00640 pthread_mutex_unlock(&lock_info->lock); 00641 return -1; 00642 } 00643 00644 ast_copy_string(filename, lock_info->locks[i].file, filename_size); 00645 *lineno = lock_info->locks[i].line_num; 00646 ast_copy_string(func, lock_info->locks[i].func, func_size); 00647 ast_copy_string(mutex_name, lock_info->locks[i].lock_name, mutex_name_size); 00648 00649 pthread_mutex_unlock(&lock_info->lock); 00650 00651 return 0; 00652 }
int ast_get_time_t | ( | const char * | src, | |
time_t * | dst, | |||
time_t | _default, | |||
int * | consumed | |||
) |
get values from config variables.
Definition at line 1338 of file utils.c.
References ast_strlen_zero(), and t.
Referenced by acf_strftime(), build_peer(), cache_lookup_internal(), handle_saydatetime(), load_password(), play_message_datetime(), process_clearcache(), and sayunixtime_exec().
01339 { 01340 long t; 01341 int scanned; 01342 01343 if (dst == NULL) 01344 return -1; 01345 01346 *dst = _default; 01347 01348 if (ast_strlen_zero(src)) 01349 return -1; 01350 01351 /* only integer at the moment, but one day we could accept more formats */ 01352 if (sscanf(src, "%30ld%n", &t, &scanned) == 1) { 01353 *dst = t; 01354 if (consumed) 01355 *consumed = scanned; 01356 return 0; 01357 } else 01358 return -1; 01359 }
struct hostent* ast_gethostbyname | ( | const char * | host, | |
struct ast_hostent * | hp | |||
) |
Re-entrant (thread safe) version of gethostbyname that replaces the standard gethostbyname (which is not thread safe).
Definition at line 184 of file utils.c.
Referenced by __ast_http_load(), __set_address_from_contact(), ast_dnsmgr_lookup(), ast_find_ourip(), ast_get_ip_or_srv(), ast_sip_ouraddrfor(), check_via(), create_addr(), dnsmgr_refresh(), festival_exec(), get_ip_and_port_from_sdp(), gtalk_load_config(), gtalk_update_stun(), iax_template_parse(), launch_netscript(), parse_register_contact(), process_sdp(), process_sdp_c(), realtime_peer(), realtime_user(), reload_config(), rtcp_do_debug_ip(), rtcp_do_debug_ip_deprecated(), rtp_do_debug_ip(), set_config(), set_destination(), sip_devicestate(), sip_do_debug_ip(), and udptl_do_debug_ip().
00185 { 00186 int res; 00187 int herrno; 00188 int dots=0; 00189 const char *s; 00190 struct hostent *result = NULL; 00191 /* Although it is perfectly legitimate to lookup a pure integer, for 00192 the sake of the sanity of people who like to name their peers as 00193 integers, we break with tradition and refuse to look up a 00194 pure integer */ 00195 s = host; 00196 res = 0; 00197 while(s && *s) { 00198 if (*s == '.') 00199 dots++; 00200 else if (!isdigit(*s)) 00201 break; 00202 s++; 00203 } 00204 if (!s || !*s) { 00205 /* Forge a reply for IP's to avoid octal IP's being interpreted as octal */ 00206 if (dots != 3) 00207 return NULL; 00208 memset(hp, 0, sizeof(struct ast_hostent)); 00209 hp->hp.h_addrtype = AF_INET; 00210 hp->hp.h_addr_list = (void *) hp->buf; 00211 hp->hp.h_addr = hp->buf + sizeof(void *); 00212 if (inet_pton(AF_INET, host, hp->hp.h_addr) > 0) 00213 return &hp->hp; 00214 return NULL; 00215 00216 } 00217 #ifdef HAVE_GETHOSTBYNAME_R_5 00218 result = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &herrno); 00219 00220 if (!result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0]) 00221 return NULL; 00222 #else 00223 res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno); 00224 00225 if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0]) 00226 return NULL; 00227 #endif 00228 return &hp->hp; 00229 }
const char* ast_inet_ntoa | ( | struct in_addr | ia | ) |
thread-safe replacement for inet_ntoa().
Definition at line 433 of file utils.c.
References ast_threadstorage_get(), and inet_ntoa_buf.
Referenced by __attempt_transmit(), __find_callno(), __iax2_show_peers(), __sip_show_channels(), __sip_xmit(), _sip_show_peer(), _sip_show_peers(), accept_thread(), add_sdp(), ast_apply_ha(), ast_netsock_bindaddr(), ast_rtcp_read(), ast_rtcp_write_rr(), ast_rtcp_write_sr(), ast_rtp_raw_write(), ast_rtp_read(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_senddigit_continuation(), ast_rtp_senddigit_end(), ast_sip_ouraddrfor(), ast_udptl_bridge(), ast_udptl_read(), ast_udptl_write(), authenticate(), bridge_native_loop(), bridge_p2p_rtp_write(), build_callid_pvt(), build_callid_registry(), build_contact(), build_peer(), build_reply_digest(), build_rpid(), build_via(), calltoken_required(), check_access(), check_user_full(), check_via(), copy_via_headers(), create_addr_from_peer(), dnsmgr_refresh(), dump_addr(), dump_ipaddr(), dundi_rexmit(), dundi_show_peer(), dundi_show_peers(), dundi_show_trans(), dundi_showframe(), dundi_xmit(), external_rtp_create(), find_command(), find_peer(), find_subchannel_and_lock(), function_iaxpeer(), function_sipchaninfo_read(), function_sippeer(), gtalk_create_candidates(), gtalk_update_stun(), handle_call_token(), handle_command_response(), handle_error(), handle_open_receive_channel_ack_message(), handle_request(), handle_request_bye(), handle_request_register(), handle_request_subscribe(), handle_response(), handle_response_refer(), handle_show_http(), handle_showmanconn(), http_server_start(), httpstatus_callback(), iax2_ack_registry(), iax2_prov_app(), iax2_show_callnumber_usage(), iax2_show_channels(), iax2_show_peer(), iax2_show_registry(), iax2_trunk_queue(), iax_server(), iax_showframe(), initreqprep(), load_module(), mgcp_show_endpoints(), mgcpsock_read(), oh323_addrcmp_str(), oh323_call(), oh323_set_rtp_peer(), parse_register_contact(), peercnt_add(), peercnt_modify(), peercnt_remove(), process_message(), process_rfc3389(), process_sdp(), raw_hangup(), realtime_peer(), realtime_update_peer(), realtime_user(), reg_source_db(), register_verify(), registry_rerequest(), reload_config(), resend_response(), retrans_pkt(), rtcp_do_debug_ip(), rtcp_do_debug_ip_deprecated(), rtp_do_debug_ip(), sched_delay_remove(), score_address(), send_dtmf(), send_packet(), send_request(), send_response(), send_trunk(), session_do(), set_config(), set_destination(), set_peercnt_limit(), setup_incoming_call(), sip_do_debug_ip(), sip_do_debug_peer(), sip_handle_t38_reinvite(), sip_poke_peer(), sip_set_rtp_peer(), sip_set_udptl_peer(), sip_show_channel(), sip_show_settings(), sipsock_read(), skinny_session(), skinny_show_devices(), socket_process(), timing_read(), transmit_notify_with_mwi(), udptl_do_debug_ip(), and update_registry().
00434 { 00435 char *buf; 00436 00437 if (!(buf = ast_threadstorage_get(&inet_ntoa_buf, INET_ADDRSTRLEN))) 00438 return ""; 00439 00440 return inet_ntop(AF_INET, &ia, buf, INET_ADDRSTRLEN); 00441 }
void ast_join | ( | char * | s, | |
size_t | len, | |||
char *const | w[] | |||
) |
Definition at line 1182 of file utils.c.
Referenced by __ast_cli_generator(), __ast_cli_register(), ast_builtins_init(), console_sendtext(), console_sendtext_deprecated(), find_best(), handle_agidumphtml(), handle_help(), handle_showagi(), help1(), and help_workhorse().
01183 { 01184 int x, ofs = 0; 01185 const char *src; 01186 01187 /* Join words into a string */ 01188 if (!s) 01189 return; 01190 for (x = 0; ofs < len && w[x]; x++) { 01191 if (x > 0) 01192 s[ofs++] = ' '; 01193 for (src = w[x]; *src && ofs < len; src++) 01194 s[ofs++] = *src; 01195 } 01196 if (ofs == len) 01197 ofs--; 01198 s[ofs] = '\0'; 01199 }
void ast_mark_lock_acquired | ( | void * | lock_addr | ) |
Mark the last lock as acquired.
Definition at line 594 of file utils.c.
References ast_threadstorage_get(), pthread_mutex_lock, pthread_mutex_unlock, and thread_lock_info.
Referenced by __ast_pthread_mutex_lock(), __ast_pthread_mutex_trylock(), _ast_rwlock_rdlock(), _ast_rwlock_timedrdlock(), _ast_rwlock_timedwrlock(), _ast_rwlock_tryrdlock(), _ast_rwlock_trywrlock(), and _ast_rwlock_wrlock().
00595 { 00596 struct thr_lock_info *lock_info; 00597 00598 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info)))) 00599 return; 00600 00601 pthread_mutex_lock(&lock_info->lock); 00602 if (lock_info->locks[lock_info->num_locks - 1].lock_addr == lock_addr) { 00603 lock_info->locks[lock_info->num_locks - 1].pending = 0; 00604 } 00605 pthread_mutex_unlock(&lock_info->lock); 00606 }
void ast_mark_lock_failed | ( | void * | lock_addr | ) |
Mark the last lock as failed (trylock).
Definition at line 608 of file utils.c.
References ast_threadstorage_get(), pthread_mutex_lock, pthread_mutex_unlock, and thread_lock_info.
Referenced by __ast_pthread_mutex_trylock().
00609 { 00610 struct thr_lock_info *lock_info; 00611 00612 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info)))) 00613 return; 00614 00615 pthread_mutex_lock(&lock_info->lock); 00616 if (lock_info->locks[lock_info->num_locks - 1].lock_addr == lock_addr) { 00617 lock_info->locks[lock_info->num_locks - 1].pending = -1; 00618 lock_info->locks[lock_info->num_locks - 1].times_locked--; 00619 } 00620 pthread_mutex_unlock(&lock_info->lock); 00621 }
void ast_md5_hash | ( | char * | output, | |
char * | input | |||
) |
Produce 32 char MD5 hash of value.
Definition at line 232 of file utils.c.
References md5(), MD5Final(), MD5Init(), and MD5Update().
Referenced by auth_exec(), build_reply_digest(), check_auth(), checkmd5(), and md5().
00233 { 00234 struct MD5Context md5; 00235 unsigned char digest[16]; 00236 char *ptr; 00237 int x; 00238 00239 MD5Init(&md5); 00240 MD5Update(&md5, (unsigned char *)input, strlen(input)); 00241 MD5Final(digest, &md5); 00242 ptr = output; 00243 for (x = 0; x < 16; x++) 00244 ptr += sprintf(ptr, "%2.2x", digest[x]); 00245 }
char* ast_process_quotes_and_slashes | ( | char * | start, | |
char | find, | |||
char | replace_with | |||
) |
Process a string to find and replace characters.
start | The string to analyze | |
find | The character to find | |
replace_with | The character that will replace the one we are looking for |
Definition at line 1156 of file utils.c.
Referenced by handle_context_add_extension(), handle_context_add_extension_deprecated(), and pbx_load_config().
01157 { 01158 char *dataPut = start; 01159 int inEscape = 0; 01160 int inQuotes = 0; 01161 01162 for (; *start; start++) { 01163 if (inEscape) { 01164 *dataPut++ = *start; /* Always goes verbatim */ 01165 inEscape = 0; 01166 } else { 01167 if (*start == '\\') { 01168 inEscape = 1; /* Do not copy \ into the data */ 01169 } else if (*start == '\'') { 01170 inQuotes = 1 - inQuotes; /* Do not copy ' into the data */ 01171 } else { 01172 /* Replace , with |, unless in quotes */ 01173 *dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start); 01174 } 01175 } 01176 } 01177 if (start != dataPut) 01178 *dataPut = 0; 01179 return dataPut; 01180 }
int ast_pthread_create_stack | ( | pthread_t * | thread, | |
pthread_attr_t * | attr, | |||
void *(*)(void *) | start_routine, | |||
void * | data, | |||
size_t | stacksize, | |||
const char * | file, | |||
const char * | caller, | |||
int | line, | |||
const char * | start_fn | |||
) |
Definition at line 865 of file utils.c.
References asprintf, ast_log(), ast_malloc, AST_STACKSIZE, dummy_start(), errno, LOG_WARNING, and pthread_create.
00868 { 00869 #if !defined(LOW_MEMORY) 00870 struct thr_arg *a; 00871 #endif 00872 00873 if (!attr) { 00874 attr = alloca(sizeof(*attr)); 00875 pthread_attr_init(attr); 00876 } 00877 00878 #ifdef __linux__ 00879 /* On Linux, pthread_attr_init() defaults to PTHREAD_EXPLICIT_SCHED, 00880 which is kind of useless. Change this here to 00881 PTHREAD_INHERIT_SCHED; that way the -p option to set realtime 00882 priority will propagate down to new threads by default. 00883 This does mean that callers cannot set a different priority using 00884 PTHREAD_EXPLICIT_SCHED in the attr argument; instead they must set 00885 the priority afterwards with pthread_setschedparam(). */ 00886 if ((errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED))) 00887 ast_log(LOG_WARNING, "pthread_attr_setinheritsched: %s\n", strerror(errno)); 00888 #endif 00889 00890 if (!stacksize) 00891 stacksize = AST_STACKSIZE; 00892 00893 if ((errno = pthread_attr_setstacksize(attr, stacksize ? stacksize : AST_STACKSIZE))) 00894 ast_log(LOG_WARNING, "pthread_attr_setstacksize: %s\n", strerror(errno)); 00895 00896 #if !defined(LOW_MEMORY) 00897 if ((a = ast_malloc(sizeof(*a)))) { 00898 a->start_routine = start_routine; 00899 a->data = data; 00900 start_routine = dummy_start; 00901 if (asprintf(&a->name, "%-20s started at [%5d] %s %s()", 00902 start_fn, line, file, caller) < 0) { 00903 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 00904 a->name = NULL; 00905 } 00906 data = a; 00907 } 00908 #endif /* !LOW_MEMORY */ 00909 00910 return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */ 00911 }
long int ast_random | ( | void | ) |
Definition at line 1146 of file utils.c.
References ast_mutex_lock, ast_mutex_unlock, and randomlock.
Referenced by acf_rand_exec(), agent_new(), ast_lock_path(), ast_moh_files_next(), ast_rtp_new_init(), ast_rtp_new_source(), ast_rtp_new_with_bindaddr(), ast_udptl_new_with_bindaddr(), authenticate_request(), build_gateway(), build_iv(), build_rand_pad(), build_reply_digest(), calc_metric(), calc_rxstamp(), callno_hash(), dahdi_new(), generate_random_string(), get_trans_id(), gtalk_alloc(), gtalk_create_candidates(), gtalk_new(), handle_response_invite(), iax2_start_transfer(), load_module(), local_new(), make_email_file(), make_our_tag(), moh_files_alloc(), ogg_vorbis_rewrite(), page_exec(), process_message(), process_weights(), random_exec(), reg_source_db(), registry_authrequest(), reqprep(), set_nonce_randdata(), sip_alloc(), socket_read(), start_rtp(), stun_req_id(), transmit_invite(), transmit_register(), transmit_response_using_temp(), and try_firmware().
01147 { 01148 long int res; 01149 ast_mutex_lock(&randomlock); 01150 res = random(); 01151 ast_mutex_unlock(&randomlock); 01152 return res; 01153 }
void ast_remove_lock_info | ( | void * | lock_addr | ) |
remove lock info for the current thread
this gets called by ast_mutex_unlock so that information on the lock can be removed from the current thread's lock info struct.
Definition at line 654 of file utils.c.
References ast_threadstorage_get(), thr_lock_info::num_locks, pthread_mutex_lock, pthread_mutex_unlock, and thread_lock_info.
Referenced by __ast_cond_timedwait(), __ast_cond_wait(), __ast_pthread_mutex_lock(), __ast_pthread_mutex_unlock(), _ast_rwlock_rdlock(), _ast_rwlock_timedrdlock(), _ast_rwlock_timedwrlock(), _ast_rwlock_tryrdlock(), _ast_rwlock_trywrlock(), _ast_rwlock_unlock(), and _ast_rwlock_wrlock().
00655 { 00656 struct thr_lock_info *lock_info; 00657 int i = 0; 00658 00659 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info)))) 00660 return; 00661 00662 pthread_mutex_lock(&lock_info->lock); 00663 00664 for (i = lock_info->num_locks - 1; i >= 0; i--) { 00665 if (lock_info->locks[i].lock_addr == lock_addr) 00666 break; 00667 } 00668 00669 if (i == -1) { 00670 /* Lock not found :( */ 00671 pthread_mutex_unlock(&lock_info->lock); 00672 return; 00673 } 00674 00675 if (lock_info->locks[i].times_locked > 1) { 00676 lock_info->locks[i].times_locked--; 00677 pthread_mutex_unlock(&lock_info->lock); 00678 return; 00679 } 00680 00681 if (i < lock_info->num_locks - 1) { 00682 /* Not the last one ... *should* be rare! */ 00683 memmove(&lock_info->locks[i], &lock_info->locks[i + 1], 00684 (lock_info->num_locks - (i + 1)) * sizeof(lock_info->locks[0])); 00685 } 00686 00687 lock_info->num_locks--; 00688 00689 pthread_mutex_unlock(&lock_info->lock); 00690 }
void ast_sha1_hash | ( | char * | output, | |
char * | input | |||
) |
Produce 40 char SHA1 hash of value.
Definition at line 248 of file utils.c.
References SHA1Input(), SHA1Reset(), and SHA1Result().
Referenced by aji_act_hook(), handle_call_token(), jabber_make_auth(), and sha1().
00249 { 00250 struct SHA1Context sha; 00251 char *ptr; 00252 int x; 00253 uint8_t Message_Digest[20]; 00254 00255 SHA1Reset(&sha); 00256 00257 SHA1Input(&sha, (const unsigned char *) input, strlen(input)); 00258 00259 SHA1Result(&sha, Message_Digest); 00260 ptr = output; 00261 for (x = 0; x < 20; x++) 00262 ptr += sprintf(ptr, "%2.2x", Message_Digest[x]); 00263 }
void ast_store_lock_info | ( | enum ast_lock_type | type, | |
const char * | filename, | |||
int | line_num, | |||
const char * | func, | |||
const char * | lock_name, | |||
void * | lock_addr | |||
) |
Store lock info for the current thread.
This function gets called in ast_mutex_lock() and ast_mutex_trylock() so that information about this lock can be stored in this thread's lock info struct. The lock is marked as pending as the thread is waiting on the lock. ast_mark_lock_acquired() will mark it as held by this thread.
Definition at line 545 of file utils.c.
References ast_threadstorage_get(), pthread_mutex_lock, pthread_mutex_unlock, and thread_lock_info.
Referenced by __ast_cond_timedwait(), __ast_cond_wait(), __ast_pthread_mutex_lock(), __ast_pthread_mutex_trylock(), _ast_rwlock_rdlock(), _ast_rwlock_timedrdlock(), _ast_rwlock_timedwrlock(), _ast_rwlock_tryrdlock(), _ast_rwlock_trywrlock(), and _ast_rwlock_wrlock().
00547 { 00548 struct thr_lock_info *lock_info; 00549 int i; 00550 00551 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info)))) 00552 return; 00553 00554 pthread_mutex_lock(&lock_info->lock); 00555 00556 for (i = 0; i < lock_info->num_locks; i++) { 00557 if (lock_info->locks[i].lock_addr == lock_addr) { 00558 lock_info->locks[i].times_locked++; 00559 pthread_mutex_unlock(&lock_info->lock); 00560 return; 00561 } 00562 } 00563 00564 if (lock_info->num_locks == AST_MAX_LOCKS) { 00565 /* Can't use ast_log here, because it will cause infinite recursion */ 00566 fprintf(stderr, "XXX ERROR XXX A thread holds more locks than '%d'." 00567 " Increase AST_MAX_LOCKS!\n", AST_MAX_LOCKS); 00568 pthread_mutex_unlock(&lock_info->lock); 00569 return; 00570 } 00571 00572 if (i && lock_info->locks[i - 1].pending == -1) { 00573 /* The last lock on the list was one that this thread tried to lock but 00574 * failed at doing so. It has now moved on to something else, so remove 00575 * the old lock from the list. */ 00576 i--; 00577 lock_info->num_locks--; 00578 memset(&lock_info->locks[i], 0, sizeof(lock_info->locks[0])); 00579 } 00580 00581 lock_info->locks[i].file = filename; 00582 lock_info->locks[i].line_num = line_num; 00583 lock_info->locks[i].func = func; 00584 lock_info->locks[i].lock_name = lock_name; 00585 lock_info->locks[i].lock_addr = lock_addr; 00586 lock_info->locks[i].times_locked = 1; 00587 lock_info->locks[i].type = type; 00588 lock_info->locks[i].pending = 1; 00589 lock_info->num_locks++; 00590 00591 pthread_mutex_unlock(&lock_info->lock); 00592 }
char* ast_strip_quoted | ( | char * | s, | |
const char * | beg_quotes, | |||
const char * | end_quotes | |||
) |
Strip leading/trailing whitespace and quotes from a string.
s | The string to be stripped (will be modified). | |
beg_quotes | The list of possible beginning quote characters. | |
end_quotes | The list of matching ending quote characters. |
It can also remove beginning and ending quote (or quote-like) characters, in matching pairs. If the first character of the string matches any character in beg_quotes, and the last character of the string is the matching character in end_quotes, then they are removed from the string.
Examples:
ast_strip_quoted(buf, "\"", "\""); ast_strip_quoted(buf, "'", "'"); ast_strip_quoted(buf, "[{(", "]})");
Definition at line 992 of file utils.c.
References ast_strip().
Referenced by ast_register_file_version(), iftime(), parse_cookies(), and parse_dial_string().
00993 { 00994 char *e; 00995 char *q; 00996 00997 s = ast_strip(s); 00998 if ((q = strchr(beg_quotes, *s)) && *q != '\0') { 00999 e = s + strlen(s) - 1; 01000 if (*e == *(end_quotes + (q - beg_quotes))) { 01001 s++; 01002 *e = '\0'; 01003 } 01004 } 01005 01006 return s; 01007 }
int ast_true | ( | const char * | val | ) |
Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Returns 0 if val is a NULL pointer, -1 if "true", and 0 otherwise.
Definition at line 1057 of file utils.c.
References ast_strlen_zero().
Referenced by __ast_http_load(), __login_exec(), _parse(), action_agent_callback_login(), action_agent_logoff(), action_originate(), action_setcdruserfield(), action_updateconfig(), aji_create_client(), aji_load_config(), apply_option(), apply_outgoing(), ast_jb_read_conf(), ast_udptl_reload(), authenticate(), build_device(), build_gateway(), build_peer(), build_user(), connect_link(), dahdi_r2_answer(), do_directory(), do_reload(), festival_exec(), func_inheritance_write(), get_encrypt_methods(), gtalk_load_config(), handle_common_options(), handle_mfcr2_call_files(), handle_save_dialplan(), init_logger_chain(), init_manager(), load_config(), load_module(), load_odbc_config(), load_rpt_vars(), loadconfigurationfile(), manager_add_queue_member(), manager_pause_queue_member(), misdn_answer(), odbc_load_module(), osp_load(), parse_config(), pbx_load_config(), pbx_load_users(), process_dahdi(), queue_set_param(), read_agent_config(), reload(), reload_config(), reload_queues(), set_config(), set_insecure_flags(), sla_load_config(), start_monitor_action(), strings_to_mask(), and update_common_options().
01058 { 01059 if (ast_strlen_zero(s)) 01060 return 0; 01061 01062 /* Determine if this is a true value */ 01063 if (!strcasecmp(s, "yes") || 01064 !strcasecmp(s, "true") || 01065 !strcasecmp(s, "y") || 01066 !strcasecmp(s, "t") || 01067 !strcasecmp(s, "1") || 01068 !strcasecmp(s, "on")) 01069 return -1; 01070 01071 return 0; 01072 }
struct timeval ast_tvadd | ( | struct timeval | a, | |
struct timeval | b | |||
) |
Returns the sum of two timevals a + b.
Definition at line 1111 of file utils.c.
References ONE_MILLION, and tvfix().
Referenced by __get_from_jb(), agent_hangup(), agent_read(), ast_audiohook_trigger_wait(), ast_channel_bridge(), ast_generic_bridge(), ast_rtp_sendcng(), ast_rtp_senddigit_begin(), ast_rtp_senddigit_end(), ast_sched_runq(), ast_smoother_read(), ast_translate(), calc_timestamp(), do_cdr(), iax2_process_thread(), jb_get_and_deliver(), monmp3thread(), mp3_exec(), mwi_monitor_handler(), NBScat_exec(), sched_settime(), sched_thread(), schedule_delivery(), sla_process_timers(), and smdi_message_wait().
01112 { 01113 /* consistency checks to guarantee usec in 0..999999 */ 01114 a = tvfix(a); 01115 b = tvfix(b); 01116 a.tv_sec += b.tv_sec; 01117 a.tv_usec += b.tv_usec; 01118 if (a.tv_usec >= ONE_MILLION) { 01119 a.tv_sec++; 01120 a.tv_usec -= ONE_MILLION; 01121 } 01122 return a; 01123 }
struct timeval ast_tvsub | ( | struct timeval | a, | |
struct timeval | b | |||
) |
Returns the difference of two timevals a - b.
Definition at line 1125 of file utils.c.
References ONE_MILLION, and tvfix().
Referenced by _ast_rwlock_timedrdlock(), _ast_rwlock_timedwrlock(), ast_channel_bridge(), ast_sched_dump(), ast_translate(), calc_rxstamp(), calc_timestamp(), and pri_dchannel().
01126 { 01127 /* consistency checks to guarantee usec in 0..999999 */ 01128 a = tvfix(a); 01129 b = tvfix(b); 01130 a.tv_sec -= b.tv_sec; 01131 a.tv_usec -= b.tv_usec; 01132 if (a.tv_usec < 0) { 01133 a.tv_sec-- ; 01134 a.tv_usec += ONE_MILLION; 01135 } 01136 return a; 01137 }
char* ast_unescape_semicolon | ( | char * | s | ) |
Strip backslash for "escaped" semicolons. s The string to be stripped (will be modified).
Definition at line 1009 of file utils.c.
Referenced by sip_notify().
01010 { 01011 char *e; 01012 char *work = s; 01013 01014 while ((e = strchr(work, ';'))) { 01015 if ((e > work) && (*(e-1) == '\\')) { 01016 memmove(e - 1, e, strlen(e) + 1); 01017 work = e; 01018 } else { 01019 work = e + 1; 01020 } 01021 } 01022 01023 return s; 01024 }
void ast_uri_decode | ( | char * | s | ) |
Decode URI, URN, URL (overwrite string).
s | String to be decoded |
Definition at line 416 of file utils.c.
Referenced by check_user_full(), get_also_info(), get_destination(), get_refer_info(), handle_request_invite(), handle_uri(), register_verify(), sip_new(), and uridecode().
00417 { 00418 char *o; 00419 unsigned int tmp; 00420 00421 for (o = s; *s; s++, o++) { 00422 if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) { 00423 /* have '%', two chars and correct parsing */ 00424 *o = tmp; 00425 s += 2; /* Will be incremented once more when we break out */ 00426 } else /* all other cases, just copy */ 00427 *o = *s; 00428 } 00429 *o = '\0'; 00430 }
char* ast_uri_encode | ( | const char * | string, | |
char * | outbuf, | |||
int | buflen, | |||
int | doreserved | |||
) |
Turn text string to URI-encoded XX version At this point, we're converting from ISO-8859-x (8-bit), not UTF8 as in the SIP protocol spec If doreserved == 1 we will convert reserved characters also. RFC 2396, section 2.4 outbuf needs to have more memory allocated than the instring to have room for the expansion. Every char that is converted is replaced by three ASCII characters.
Definition at line 385 of file utils.c.
References ast_copy_string().
Referenced by initreqprep(), and uriencode().
00386 { 00387 char *reserved = ";/?:@&=+$,# "; /* Reserved chars */ 00388 00389 const char *ptr = string; /* Start with the string */ 00390 char *out = NULL; 00391 char *buf = NULL; 00392 00393 ast_copy_string(outbuf, string, buflen); 00394 00395 /* If there's no characters to convert, just go through and don't do anything */ 00396 while (*ptr) { 00397 if (((unsigned char) *ptr) > 127 || (doreserved && strchr(reserved, *ptr)) ) { 00398 /* Oops, we need to start working here */ 00399 if (!buf) { 00400 buf = outbuf; 00401 out = buf + (ptr - string) ; /* Set output ptr */ 00402 } 00403 out += sprintf(out, "%%%02x", (unsigned char) *ptr); 00404 } else if (buf) { 00405 *out = *ptr; /* Continue copying the string */ 00406 out++; 00407 } 00408 ptr++; 00409 } 00410 if (buf) 00411 *out = '\0'; 00412 return outbuf; 00413 }
int ast_utils_init | ( | void | ) |
Definition at line 1416 of file utils.c.
References ast_cli_register_multiple(), base64_init(), and utils_cli.
Referenced by main().
01417 { 01418 base64_init(); 01419 #ifdef DEBUG_THREADS 01420 #if !defined(LOW_MEMORY) 01421 ast_cli_register_multiple(utils_cli, sizeof(utils_cli) / sizeof(utils_cli[0])); 01422 #endif 01423 #endif 01424 return 0; 01425 }
int ast_wait_for_input | ( | int | fd, | |
int | ms | |||
) |
Definition at line 913 of file utils.c.
References ast_poll.
Referenced by action_waitevent(), http_root(), main(), and moh_class_destructor().
00914 { 00915 struct pollfd pfd[1]; 00916 memset(pfd, 0, sizeof(pfd)); 00917 pfd[0].fd = fd; 00918 pfd[0].events = POLLIN|POLLPRI; 00919 return ast_poll(pfd, 1, ms); 00920 }
static void base64_init | ( | void | ) | [static] |
Definition at line 349 of file utils.c.
Referenced by ast_utils_init().
00350 { 00351 int x; 00352 memset(b2a, -1, sizeof(b2a)); 00353 /* Initialize base-64 Conversion table */ 00354 for (x = 0; x < 26; x++) { 00355 /* A-Z */ 00356 base64[x] = 'A' + x; 00357 b2a['A' + x] = x; 00358 /* a-z */ 00359 base64[x + 26] = 'a' + x; 00360 b2a['a' + x] = x + 26; 00361 /* 0-9 */ 00362 if (x < 10) { 00363 base64[x + 52] = '0' + x; 00364 b2a['0' + x] = x + 52; 00365 } 00366 } 00367 base64[62] = '+'; 00368 base64[63] = '/'; 00369 b2a[(int)'+'] = 62; 00370 b2a[(int)'/'] = 63; 00371 }
static void* dummy_start | ( | void * | data | ) | [static] |
Definition at line 821 of file utils.c.
References AST_LIST_INSERT_TAIL, AST_MUTEX_KIND, ast_register_thread(), ast_threadstorage_get(), ast_unregister_thread(), thr_arg::data, thr_lock_info::entry, free, lock_infos_lock, ast_mutex_info::mutex, thr_arg::name, pthread_mutex_init, pthread_mutex_lock, pthread_mutex_unlock, thr_arg::start_routine, strdup, and thread_lock_info.
Referenced by ast_pthread_create_stack().
00822 { 00823 void *ret; 00824 struct thr_arg a = *((struct thr_arg *) data); /* make a local copy */ 00825 #ifdef DEBUG_THREADS 00826 struct thr_lock_info *lock_info; 00827 pthread_mutexattr_t mutex_attr; 00828 #endif 00829 00830 /* note that even though data->name is a pointer to allocated memory, 00831 we are not freeing it here because ast_register_thread is going to 00832 keep a copy of the pointer and then ast_unregister_thread will 00833 free the memory 00834 */ 00835 free(data); 00836 ast_register_thread(a.name); 00837 pthread_cleanup_push(ast_unregister_thread, (void *) pthread_self()); 00838 00839 #ifdef DEBUG_THREADS 00840 if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info)))) 00841 return NULL; 00842 00843 lock_info->thread_id = pthread_self(); 00844 lock_info->thread_name = strdup(a.name); 00845 00846 pthread_mutexattr_init(&mutex_attr); 00847 pthread_mutexattr_settype(&mutex_attr, AST_MUTEX_KIND); 00848 pthread_mutex_init(&lock_info->lock, &mutex_attr); 00849 pthread_mutexattr_destroy(&mutex_attr); 00850 00851 pthread_mutex_lock(&lock_infos_lock.mutex); /* Intentionally not the wrapper */ 00852 AST_LIST_INSERT_TAIL(&lock_infos, lock_info, entry); 00853 pthread_mutex_unlock(&lock_infos_lock.mutex); /* Intentionally not the wrapper */ 00854 #endif /* DEBUG_THREADS */ 00855 00856 ret = a.start_routine(a.data); 00857 00858 pthread_cleanup_pop(1); 00859 00860 return ret; 00861 }
static int handle_show_locks | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 706 of file utils.c.
References ast_cli(), ast_dynamic_str_append(), ast_dynamic_str_create(), AST_LIST_TRAVERSE, AST_MUTEX, ast_reentrancy_lock(), ast_reentrancy_unlock(), ast_mutex_info::file, thr_lock_info::file, free, ast_mutex_info::func, thr_lock_info::func, thr_lock_info::line_num, ast_mutex_info::lineno, lock, thr_lock_info::lock, thr_lock_info::lock_addr, lock_infos_lock, thr_lock_info::lock_name, thr_lock_info::locks, locktype2str(), ast_mutex_info::mutex, thr_lock_info::num_locks, thr_lock_info::pending, pthread_mutex_lock, pthread_mutex_unlock, ast_mutex_info::reentrancy, RESULT_FAILURE, RESULT_SUCCESS, ast_dynamic_str::str, thr_lock_info::thread_id, thr_lock_info::thread_name, thr_lock_info::times_locked, and thr_lock_info::type.
00707 { 00708 struct thr_lock_info *lock_info; 00709 struct ast_dynamic_str *str; 00710 00711 if (!(str = ast_dynamic_str_create(4096))) 00712 return RESULT_FAILURE; 00713 00714 ast_dynamic_str_append(&str, 0, "\n" 00715 "=======================================================================\n" 00716 "=== Currently Held Locks ==============================================\n" 00717 "=======================================================================\n" 00718 "===\n" 00719 "=== <file> <line num> <function> <lock name> <lock addr> (times locked)\n" 00720 "===\n"); 00721 00722 if (!str) 00723 return RESULT_FAILURE; 00724 00725 pthread_mutex_lock(&lock_infos_lock.mutex); 00726 AST_LIST_TRAVERSE(&lock_infos, lock_info, entry) { 00727 int i; 00728 if (lock_info->num_locks) { 00729 ast_dynamic_str_append(&str, 0, "=== Thread ID: %ld (%s)\n", (long) lock_info->thread_id, 00730 lock_info->thread_name); 00731 pthread_mutex_lock(&lock_info->lock); 00732 for (i = 0; str && i < lock_info->num_locks; i++) { 00733 int j; 00734 ast_mutex_t *lock; 00735 00736 ast_dynamic_str_append(&str, 0, "=== ---> %sLock #%d (%s): %s %d %s %s %p (%d)\n", 00737 lock_info->locks[i].pending > 0 ? "Waiting for " : 00738 lock_info->locks[i].pending < 0 ? "Tried and failed to get " : "", i, 00739 lock_info->locks[i].file, 00740 locktype2str(lock_info->locks[i].type), 00741 lock_info->locks[i].line_num, 00742 lock_info->locks[i].func, lock_info->locks[i].lock_name, 00743 lock_info->locks[i].lock_addr, 00744 lock_info->locks[i].times_locked); 00745 00746 if (!lock_info->locks[i].pending || lock_info->locks[i].pending == -1) 00747 continue; 00748 00749 /* We only have further details for mutexes right now */ 00750 if (lock_info->locks[i].type != AST_MUTEX) 00751 continue; 00752 00753 lock = lock_info->locks[i].lock_addr; 00754 00755 ast_reentrancy_lock(lock); 00756 for (j = 0; str && j < lock->reentrancy; j++) { 00757 ast_dynamic_str_append(&str, 0, "=== --- ---> Locked Here: %s line %d (%s)\n", 00758 lock->file[j], lock->lineno[j], lock->func[j]); 00759 } 00760 ast_reentrancy_unlock(lock); 00761 } 00762 pthread_mutex_unlock(&lock_info->lock); 00763 if (!str) 00764 break; 00765 ast_dynamic_str_append(&str, 0, "=== -------------------------------------------------------------------\n" 00766 "===\n"); 00767 if (!str) 00768 break; 00769 } 00770 } 00771 pthread_mutex_unlock(&lock_infos_lock.mutex); 00772 00773 if (!str) 00774 return RESULT_FAILURE; 00775 00776 ast_dynamic_str_append(&str, 0, "=======================================================================\n" 00777 "\n"); 00778 00779 if (!str) 00780 return RESULT_FAILURE; 00781 00782 ast_cli(fd, "%s", str->str); 00783 00784 free(str); 00785 00786 return RESULT_SUCCESS; 00787 }
static void lock_info_destroy | ( | void * | data | ) | [static] |
Destroy a thread's lock info.
This gets called automatically when the thread stops
Definition at line 507 of file utils.c.
References AST_LIST_REMOVE, ast_log(), thr_lock_info::entry, thr_lock_info::file, thr_lock_info::func, thr_lock_info::line_num, thr_lock_info::lock_addr, thr_lock_info::lock_name, thr_lock_info::locks, LOG_ERROR, thr_lock_info::num_locks, thr_lock_info::pending, pthread_mutex_lock, pthread_mutex_unlock, and thr_lock_info::thread_name.
00508 { 00509 struct thr_lock_info *lock_info = data; 00510 int i; 00511 00512 pthread_mutex_lock(&lock_infos_lock.mutex); 00513 AST_LIST_REMOVE(&lock_infos, lock_info, entry); 00514 pthread_mutex_unlock(&lock_infos_lock.mutex); 00515 00516 00517 for (i = 0; i < lock_info->num_locks; i++) { 00518 if (lock_info->locks[i].pending == -1) { 00519 /* This just means that the last lock this thread went for was by 00520 * using trylock, and it failed. This is fine. */ 00521 break; 00522 } 00523 00524 ast_log(LOG_ERROR, 00525 "Thread '%s' still has a lock! - '%s' (%p) from '%s' in %s:%d!\n", 00526 lock_info->thread_name, 00527 lock_info->locks[i].lock_name, 00528 lock_info->locks[i].lock_addr, 00529 lock_info->locks[i].func, 00530 lock_info->locks[i].file, 00531 lock_info->locks[i].line_num 00532 ); 00533 } 00534 00535 pthread_mutex_destroy(&lock_info->lock); 00536 free((void *) lock_info->thread_name); 00537 free(lock_info); 00538 }
static const char* locktype2str | ( | enum ast_lock_type | type | ) | [static] |
Definition at line 692 of file utils.c.
References AST_MUTEX, AST_RDLOCK, and AST_WRLOCK.
Referenced by handle_show_locks().
00693 { 00694 switch (type) { 00695 case AST_MUTEX: 00696 return "MUTEX"; 00697 case AST_RDLOCK: 00698 return "RDLOCK"; 00699 case AST_WRLOCK: 00700 return "WRLOCK"; 00701 } 00702 00703 return "UNKNOWN"; 00704 }
static void thread_lock_info_init | ( | void | ) | [static] |
static struct timeval tvfix | ( | struct timeval | a | ) | [static] |
Definition at line 1096 of file utils.c.
References ast_log(), LOG_WARNING, and ONE_MILLION.
Referenced by ast_tvadd(), and ast_tvsub().
01097 { 01098 if (a.tv_usec >= ONE_MILLION) { 01099 ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n", 01100 a.tv_sec, (long int) a.tv_usec); 01101 a.tv_sec += a.tv_usec / ONE_MILLION; 01102 a.tv_usec %= ONE_MILLION; 01103 } else if (a.tv_usec < 0) { 01104 ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n", 01105 a.tv_sec, (long int) a.tv_usec); 01106 a.tv_usec = 0; 01107 } 01108 return a; 01109 }
const char __ast_string_field_empty[] = "" |
char base64[64] [static] |
ast_mutex_t fetchadd_m = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } [static] |
struct ast_threadstorage inet_ntoa_buf = { .once = PTHREAD_ONCE_INIT, .key_init = inet_ntoa_buf_init , } [static] |
ast_mutex_t lock_infos_lock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } [static] |
Locked when accessing the lock_infos list.
Definition at line 496 of file utils.c.
Referenced by dummy_start(), and handle_show_locks().
ast_mutex_t randomlock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } [static] |
glibc puts a lock inside random(3), so that the results are thread-safe. BSD libc (and others) do not.
Definition at line 1144 of file utils.c.
Referenced by ast_random().
char show_locks_help[] [static] |
struct ast_threadstorage thread_lock_info = { .once = PTHREAD_ONCE_INIT, .key_init = thread_lock_info_init , } [static] |
Definition at line 543 of file utils.c.
Referenced by ast_find_lock_info(), ast_mark_lock_acquired(), ast_mark_lock_failed(), ast_remove_lock_info(), ast_store_lock_info(), and dummy_start().
struct ast_cli_entry utils_cli[] [static] |
Initial value:
{ { { "core", "show", "locks", NULL }, handle_show_locks, "Show which locks are locked by which thread", show_locks_help }, }
Definition at line 794 of file utils.c.
Referenced by ast_utils_init().