Thu Oct 8 00:59:53 2009

Asterisk developer's documentation


utils.c File Reference

Utility functions. More...

#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 []


Detailed Description

Utility functions.

Note:
These are important for portability and security, so please use them in favour of other routines. Please consult the CODING GUIDELINES for more information.

Definition in file utils.c.


Define Documentation

#define AST_API_MODULE

Definition at line 64 of file utils.c.

#define AST_API_MODULE

Definition at line 64 of file utils.c.

#define AST_API_MODULE

Definition at line 64 of file utils.c.

#define AST_API_MODULE

Definition at line 64 of file utils.c.

#define AST_API_MODULE

Definition at line 64 of file utils.c.

#define AST_API_MODULE

Definition at line 64 of file utils.c.

#define AST_MAX_LOCKS   64

A reasonable maximum number of locks a thread would be holding ...

Definition at line 452 of file utils.c.

#define ONE_MILLION   1000000

Definition at line 1091 of file utils.c.

Referenced by ast_tvadd(), ast_tvsub(), and tvfix().


Function Documentation

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 && (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.

Parameters:
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
Returns:
0 on success, non-zero on failure.

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.

Returns:
0 on success, non-zero on failure.
Parameters:
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

Note:
If you are calling ast_carefulwrite, it is assumed that you are calling it on a file descriptor that _DOES_ have NONBLOCK set. This way, there is only one system call made to do a write, unless we actually have a need to wait. This way, we get better performance.

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.

Parameters:
sock The socket to manipulate
Returns:
Nothing
On Linux, UDP sockets default to sending packets with the Dont Fragment (DF) bit set. This is supposedly done to allow the application to do PMTU discovery, but Asterisk does not do this.

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_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.

References hp, and s.

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(), 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().

Note:
It is very important to note that even though this is a thread-safe replacement for inet_ntoa(), it is *not* reentrant. In a single thread, the result from a previous call to this function is no longer valid once it is called again. If the result from multiple calls to this function need to be kept or used at once, then the result must be copied to a local buffer before calling this function again.

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_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.

Parameters:
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_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_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.

Parameters:
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.
Returns:
The stripped string.
This functions strips all leading and trailing whitespace characters from the input string, and returns a pointer to the resulting string. The string is modified in place.

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(), authenticate(), build_device(), build_gateway(), build_peer(), build_user(), connect_link(), do_directory(), do_reload(), festival_exec(), func_inheritance_write(), get_encrypt_methods(), gtalk_load_config(), handle_common_options(), 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).

Returns:
The stripped string.

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).

Parameters:
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.

Note:
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.
Note: The doreserved option is needed for replaces header in SIP transfers.

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: %u (%s)\n", (int) 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 inet_ntoa_buf_init ( void   )  [static]

Definition at line 70 of file utils.c.

00087 {

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]

The thread storage key for per-thread lock info.

Definition at line 543 of file utils.c.

00547 {

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 }


Variable Documentation

const char __ast_string_field_empty[] = ""

Definition at line 1201 of file utils.c.

char b2a[256] [static]

Definition at line 68 of file utils.c.

char base64[64] [static]

Definition at line 67 of file utils.c.

Referenced by aji_act_hook().

ast_mutex_t fetchadd_m = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } [static]

Definition at line 1323 of file utils.c.

Referenced by ast_atomic_fetchadd_int_slow().

struct ast_threadstorage inet_ntoa_buf = { .once = PTHREAD_ONCE_INIT, .key_init = inet_ntoa_buf_init , } [static]

Definition at line 70 of file utils.c.

Referenced by ast_inet_ntoa().

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]

Initial value:

"Usage: core show locks\n"
"       This command is for lock debugging.  It prints out which locks\n"
"are owned by each active thread.\n"

Definition at line 789 of file utils.c.

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().


Generated on Thu Oct 8 00:59:53 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7