Fri Aug 24 02:28:47 2007

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"

Include dependency graph for utils.c:

Go to the source code of this file.

Data Structures

struct  thr_arg

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 ERANGE   34
#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)
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,...)
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)
int ast_false (const char *s)
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_md5_hash (char *output, char *input)
 Produce 32 char MD5 hash of value.
 AST_MUTEX_DEFINE_STATIC (fetchadd_m)
 AST_MUTEX_DEFINE_STATIC (randomlock)
 glibc puts a lock inside random(3), so that the results are thread-safe. BSD libc (and others) do not.
 AST_MUTEX_DEFINE_STATIC (test_lock2)
 AST_MUTEX_DEFINE_STATIC (test_lock)
 AST_MUTEX_DEFINE_STATIC (__mutex)
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_sha1_hash (char *output, char *input)
 Produce 40 char SHA1 hash of value.
char * ast_strip_quoted (char *s, const char *beg_quotes, const char *end_quotes)
 AST_THREADSTORAGE (inet_ntoa_buf, inet_ntoa_buf_init)
int ast_true (const char *s)
timeval ast_tvadd (struct timeval a, struct timeval 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 gethostbyname_r (const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop)
 Reentrant replacement for gethostbyname for BSD-based systems.
int test_for_thread_safety (void)
static void * test_thread_body (void *data)
 This is a regression test for recursive mutexes. test_for_thread_safety() will return 0 if recursive mutex locks are working properly, and non-zero if they are not working properly.
static struct timeval tvfix (struct timeval a)

Variables

const char __ast_string_field_empty [] = ""
static char b2a [256]
static char base64 [64]
static int lock_count = 0
static int test_errors = 0
static pthread_t test_thread


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 ERANGE   34

duh? ERANGE value copied from web...

Definition at line 74 of file utils.c.

Referenced by gethostbyname_r(), and reload_queue_members().

#define ONE_MILLION   1000000

Definition at line 978 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 1120 of file utils.c.

References add_string_pool(), ast_string_field_pool::base, ast_string_field_mgr::pool, result, ast_string_field_mgr::size, ast_string_field_mgr::space, and ast_string_field_mgr::used.

01122 {
01123    char *result = NULL;
01124 
01125    if (__builtin_expect(needed > mgr->space, 0)) {
01126       size_t new_size = mgr->size * 2;
01127 
01128       while (new_size < needed)
01129          new_size *= 2;
01130 
01131       if (add_string_pool(mgr, new_size))
01132          return NULL;
01133    }
01134 
01135    result = mgr->pool->base + mgr->used;
01136    mgr->used += needed;
01137    mgr->space -= needed;
01138    return result;
01139 }

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 1168 of file utils.c.

References __ast_string_field_index_build_va().

01171 {
01172    va_list ap1, ap2;
01173 
01174    va_start(ap1, format);
01175    va_start(ap2, format);     /* va_copy does not exist on FreeBSD */
01176 
01177    __ast_string_field_index_build_va(mgr, fields, num_fields, index, format, ap1, ap2);
01178 
01179    va_end(ap1);
01180    va_end(ap2);
01181 }

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

Referenced by __ast_string_field_index_build().

01144 {
01145    size_t needed;
01146 
01147    needed = vsnprintf(mgr->pool->base + mgr->used, mgr->space, format, ap1) + 1;
01148 
01149    va_end(ap1);
01150 
01151    if (needed > mgr->space) {
01152       size_t new_size = mgr->size * 2;
01153 
01154       while (new_size < needed)
01155          new_size *= 2;
01156 
01157       if (add_string_pool(mgr, new_size))
01158          return;
01159 
01160       vsprintf(mgr->pool->base + mgr->used, format, ap2);
01161    }
01162 
01163    fields[index] = mgr->pool->base + mgr->used;
01164    mgr->used += needed;
01165    mgr->space -= needed;
01166 }

int __ast_string_field_init ( struct ast_string_field_mgr mgr,
size_t  size,
ast_string_field fields,
int  num_fields 
)

Definition at line 1106 of file utils.c.

References add_string_pool().

01108 {
01109    int index;
01110 
01111    if (add_string_pool(mgr, size))
01112       return -1;
01113 
01114    for (index = 0; index < num_fields; index++)
01115       fields[index] = __ast_string_field_empty;
01116 
01117    return 0;
01118 }

static int add_string_pool ( struct ast_string_field_mgr mgr,
size_t  size 
) [static]

Definition at line 1090 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().

01091 {
01092    struct ast_string_field_pool *pool;
01093 
01094    if (!(pool = ast_calloc(1, sizeof(*pool) + size)))
01095       return -1;
01096    
01097    pool->prev = mgr->pool;
01098    mgr->pool = pool;
01099    mgr->size = size;
01100    mgr->space = size;
01101    mgr->used = 0;
01102 
01103    return 0;
01104 }

int ast_atomic_fetchadd_int_slow ( volatile int *  p,
int  v 
)

Definition at line 1185 of file utils.c.

References ast_mutex_lock(), and ast_mutex_unlock().

01186 {
01187         int ret;
01188         ast_mutex_lock(&fetchadd_m);
01189         ret = *p;
01190         *p += v;
01191         ast_mutex_unlock(&fetchadd_m);
01192         return ret;
01193 }

int ast_base64decode ( unsigned char *  dst,
const char *  src,
int  max 
)

decode BASE64 encoded text

Definition at line 328 of file utils.c.

Referenced by __ast_check_signature(), base64_decode(), and osp_validate_token().

00329 {
00330    int cnt = 0;
00331    unsigned int byte = 0;
00332    unsigned int bits = 0;
00333    int incnt = 0;
00334    while(*src && (cnt < max)) {
00335       /* Shift in 6 bits of input */
00336       byte <<= 6;
00337       byte |= (b2a[(int)(*src)]) & 0x3f;
00338       bits += 6;
00339       src++;
00340       incnt++;
00341       /* If we have at least 8 bits left over, take that character 
00342          off the top */
00343       if (bits >= 8)  {
00344          bits -= 8;
00345          *dst = (byte >> bits) & 0xff;
00346          dst++;
00347          cnt++;
00348       }
00349    }
00350    /* Dont worry about left over bits, they're extra anyway */
00351    return cnt;
00352 }

int ast_base64encode ( char *  dst,
const unsigned char *  src,
int  srclen,
int  max 
)

Definition at line 406 of file utils.c.

References ast_base64encode_full().

Referenced by __ast_sign(), aji_act_hook(), base64_encode(), build_secret(), and osp_check_destination().

00407 {
00408    return ast_base64encode_full(dst, src, srclen, max, 0);
00409 }

int ast_base64encode_full ( char *  dst,
const unsigned char *  src,
int  srclen,
int  max,
int  linebreaks 
)

encode text to BASE64 coding

Definition at line 355 of file utils.c.

Referenced by ast_base64encode().

00356 {
00357    int cnt = 0;
00358    int col = 0;
00359    unsigned int byte = 0;
00360    int bits = 0;
00361    int cntin = 0;
00362    /* Reserve space for null byte at end of string */
00363    max--;
00364    while ((cntin < srclen) && (cnt < max)) {
00365       byte <<= 8;
00366       byte |= *(src++);
00367       bits += 8;
00368       cntin++;
00369       if ((bits == 24) && (cnt + 4 <= max)) {
00370          *dst++ = base64[(byte >> 18) & 0x3f];
00371          *dst++ = base64[(byte >> 12) & 0x3f];
00372          *dst++ = base64[(byte >> 6) & 0x3f];
00373          *dst++ = base64[byte & 0x3f];
00374          cnt += 4;
00375          col += 4;
00376          bits = 0;
00377          byte = 0;
00378       }
00379       if (linebreaks && (cnt < max) && (col == 64)) {
00380          *dst++ = '\n';
00381          cnt++;
00382          col = 0;
00383       }
00384    }
00385    if (bits && (cnt + 4 <= max)) {
00386       /* Add one last character for the remaining bits, 
00387          padding the rest with 0 */
00388       byte <<= 24 - bits;
00389       *dst++ = base64[(byte >> 18) & 0x3f];
00390       *dst++ = base64[(byte >> 12) & 0x3f];
00391       if (bits == 16)
00392          *dst++ = base64[(byte >> 6) & 0x3f];
00393       else
00394          *dst++ = '=';
00395       *dst++ = '=';
00396       cnt += 4;
00397    }
00398    if (linebreaks && (cnt < max)) {
00399       *dst++ = '\n';
00400       cnt++;
00401    }
00402    *dst = '\0';
00403    return cnt;
00404 }

int ast_build_string ( char **  buffer,
size_t *  space,
const char *  fmt,
  ... 
)

Definition at line 932 of file utils.c.

References ast_build_string_va(), and result.

Referenced by __queues_show(), add_codec_to_sdp(), add_noncodec_to_sdp(), add_sdp(), add_t38_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().

00933 {
00934    va_list ap;
00935    int result;
00936 
00937    va_start(ap, fmt);
00938    result = ast_build_string_va(buffer, space, fmt, ap);
00939    va_end(ap);
00940 
00941    return result;
00942 }

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 913 of file utils.c.

References result.

Referenced by ast_build_string().

00914 {
00915    int result;
00916 
00917    if (!buffer || !*buffer || !space || !*space)
00918       return -1;
00919 
00920    result = vsnprintf(*buffer, *space, fmt, ap);
00921 
00922    if (result < 0)
00923       return -1;
00924    else if (result > *space)
00925       result = *space;
00926 
00927    *buffer += result;
00928    *space -= result;
00929    return 0;
00930 }

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.

Try to write string, but wait no more than ms milliseconds before timing out.

Note:
The code assumes that the file descriptor has NONBLOCK set, so 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. If the descriptor is blocking, all assumptions on the guaranteed detail do not apply anymore. Also note that in the current implementation, the delay is per-write, so you still have no guarantees, anyways. Fortunately the routine is only used in a few places (cli.c, manager.c, res_agi.c) so it is reasonably easy to check how it behaves there.
XXX We either need to fix the code, or fix the documentation.

Definition at line 853 of file utils.c.

References pollfd::events, pollfd::fd, poll(), and POLLOUT.

Referenced by agi_debug_cli(), ast_cli(), astman_append(), and process_events().

00854 {
00855    /* Try to write string, but wait no more than ms milliseconds
00856       before timing out */
00857    int res = 0;
00858    struct pollfd fds[1];
00859    while (len) {
00860       res = write(fd, s, len);
00861       if ((res < 0) && (errno != EAGAIN)) {
00862          return -1;
00863       }
00864       if (res < 0)
00865          res = 0;
00866       len -= res;
00867       s += res;
00868       res = 0;
00869       if (len) {
00870          fds[0].fd = fd;
00871          fds[0].events = POLLOUT;
00872          /* Wait until writable again */
00873          res = poll(fds, 1, timeoutms);
00874          if (res < 1)
00875             return -1;
00876       }
00877    }
00878    return res;
00879 }

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.

In the case that this function is called and the buffer was not large enough to hold the result, the partial write will be truncated, and the result AST_DYNSTR_BUILD_RETRY will be returned to indicate that the buffer size was increased, and the function should be called a second time.

A return of AST_DYNSTR_BUILD_FAILED indicates a memory allocation error.

A return value greater than or equal to zero indicates the number of characters that have been written, not including the terminating ''. In the append case, this only includes the number of characters appended.

Note:
This function should never need to be called directly. It should through calling one of the other functions or macros defined in this file.

Definition at line 1221 of file utils.c.

References ast_realloc, ast_threadstorage::key, and offset.

01223 {
01224    int res;
01225    int offset = (append && (*buf)->len) ? strlen((*buf)->str) : 0;
01226 #if defined(DEBUG_THREADLOCALS)
01227    struct ast_dynamic_str *old_buf = *buf;
01228 #endif /* defined(DEBUG_THREADLOCALS) */
01229 
01230    res = vsnprintf((*buf)->str + offset, (*buf)->len - offset, fmt, ap);
01231 
01232    /* Check to see if there was not enough space in the string buffer to prepare
01233     * the string.  Also, if a maximum length is present, make sure the current
01234     * length is less than the maximum before increasing the size. */
01235    if ((res + offset + 1) > (*buf)->len && (max_len ? ((*buf)->len < max_len) : 1)) {
01236       /* Set the new size of the string buffer to be the size needed
01237        * to hold the resulting string (res) plus one byte for the
01238        * terminating '\0'.  If this size is greater than the max, set
01239        * the new length to be the maximum allowed. */
01240       if (max_len)
01241          (*buf)->len = ((res + offset + 1) < max_len) ? (res + offset + 1) : max_len;
01242       else
01243          (*buf)->len = res + offset + 1;
01244 
01245       if (!(*buf = ast_realloc(*buf, (*buf)->len + sizeof(*(*buf)))))
01246          return AST_DYNSTR_BUILD_FAILED;
01247 
01248       if (append)
01249          (*buf)->str[offset] = '\0';
01250 
01251       if (ts) {
01252          pthread_setspecific(ts->key, *buf);
01253 #if defined(DEBUG_THREADLOCALS)
01254          __ast_threadstorage_object_replace(old_buf, *buf, (*buf)->len + sizeof(*(*buf)));
01255 #endif /* defined(DEBUG_THREADLOCALS) */
01256       }
01257 
01258       /* va_end() and va_start() must be done before calling
01259        * vsnprintf() again. */
01260       return AST_DYNSTR_BUILD_RETRY;
01261    }
01262 
01263    return res;
01264 }

void ast_enable_packet_fragmentation ( int  sock  ) 

Definition at line 1266 of file utils.c.

References ast_log(), and LOG_WARNING.

Referenced by ast_netsock_bindaddr().

01267 {
01268 #if defined(HAVE_IP_MTU_DISCOVER)
01269    int val = IP_PMTUDISC_DONT;
01270    
01271    if (setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val)))
01272       ast_log(LOG_WARNING, "Unable to disable PMTU discovery. Large UDP packets may fail to be delivered when sent from this socket.\n");
01273 #endif /* HAVE_IP_MTU_DISCOVER */
01274 }

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 961 of file utils.c.

References ast_strlen_zero().

Referenced by aji_create_client(), aji_load_config(), ast_rtp_reload(), ast_udptl_reload(), handle_common_options(), init_acf_query(), load_config(), load_odbc_config(), reload(), run_agi(), set_insecure_flags(), and strings_to_mask().

00962 {
00963    if (ast_strlen_zero(s))
00964       return 0;
00965 
00966    /* Determine if this is a false value */
00967    if (!strcasecmp(s, "no") ||
00968        !strcasecmp(s, "false") ||
00969        !strcasecmp(s, "n") ||
00970        !strcasecmp(s, "f") ||
00971        !strcasecmp(s, "0") ||
00972        !strcasecmp(s, "off"))
00973       return -1;
00974 
00975    return 0;
00976 }

int ast_get_time_t ( const char *  src,
time_t *  dst,
time_t  _default,
int *  consumed 
)

get values from config variables.

Definition at line 1198 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(), and sayunixtime_exec().

01199 {
01200    long t;
01201    int scanned;
01202 
01203    if (dst == NULL)
01204       return -1;
01205 
01206    *dst = _default;
01207 
01208    if (ast_strlen_zero(src))
01209       return -1;
01210 
01211    /* only integer at the moment, but one day we could accept more formats */
01212    if (sscanf(src, "%ld%n", &t, &scanned) == 1) {
01213       *dst = t;
01214       if (consumed)
01215          *consumed = scanned;
01216       return 0;
01217    } else
01218       return -1;
01219 }

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 gethostbyname_r(), hp, result, and s.

Referenced by __ast_http_load(), ast_dnsmgr_lookup(), ast_find_ourip(), ast_get_ip_or_srv(), ast_sip_ouraddrfor(), check_via(), create_addr(), dnsmgr_refresh(), festival_exec(), gtalk_load_config(), gtalk_update_stun(), iax_template_parse(), launch_netscript(), parse_register_contact(), process_sdp(), reload_config(), rtcp_do_debug_ip(), rtcp_do_debug_ip_deprecated(), rtp_do_debug_ip(), set_address_from_contact(), 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 495 of file utils.c.

Referenced by __attempt_transmit(), __iax2_show_peers(), __sip_show_channels(), __sip_xmit(), _sip_show_peer(), _sip_show_peers(), accept_thread(), add_sdp(), add_t38_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_reply_digest(), build_rpid(), build_via(), 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_callno(), find_command(), find_peer(), find_subchannel_and_lock(), function_iaxpeer(), function_sipchaninfo_read(), function_sippeer(), gtalk_create_candidates(), gtalk_update_stun(), 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_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(), process_message(), process_rfc3389(), process_sdp(), raw_hangup(), realtime_peer(), realtime_update_peer(), 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(), send_dtmf(), send_packet(), send_request(), send_response(), send_trunk(), session_do(), set_config(), set_destination(), 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().

00496 {
00497    char *buf;
00498 
00499    if (!(buf = ast_threadstorage_get(&inet_ntoa_buf, INET_ADDRSTRLEN)))
00500       return "";
00501 
00502    return inet_ntop(AF_INET, &ia, buf, INET_ADDRSTRLEN);
00503 }

void ast_join ( char *  s,
size_t  len,
char *const   w[] 
)

Definition at line 1069 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().

01070 {
01071    int x, ofs = 0;
01072    const char *src;
01073 
01074    /* Join words into a string */
01075    if (!s)
01076       return;
01077    for (x = 0; ofs < len && w[x]; x++) {
01078       if (x > 0)
01079          s[ofs++] = ' ';
01080       for (src = w[x]; *src && ofs < len; src++)
01081          s[ofs++] = *src;
01082    }
01083    if (ofs == len)
01084       ofs--;
01085    s[ofs] = '\0';
01086 }

void ast_md5_hash ( char *  output,
char *  input 
)

Produce 32 char MD5 hash of value.

Definition at line 294 of file utils.c.

References md5(), MD5Final(), MD5Init(), and MD5Update().

Referenced by auth_exec(), build_reply_digest(), check_auth(), checkmd5(), and md5().

00295 {
00296    struct MD5Context md5;
00297    unsigned char digest[16];
00298    char *ptr;
00299    int x;
00300 
00301    MD5Init(&md5);
00302    MD5Update(&md5, (unsigned char *)input, strlen(input));
00303    MD5Final(digest, &md5);
00304    ptr = output;
00305    for (x = 0; x < 16; x++)
00306       ptr += sprintf(ptr, "%2.2x", digest[x]);
00307 }

AST_MUTEX_DEFINE_STATIC ( fetchadd_m   ) 

AST_MUTEX_DEFINE_STATIC ( randomlock   ) 

glibc puts a lock inside random(3), so that the results are thread-safe. BSD libc (and others) do not.

AST_MUTEX_DEFINE_STATIC ( test_lock2   ) 

AST_MUTEX_DEFINE_STATIC ( test_lock   ) 

AST_MUTEX_DEFINE_STATIC ( __mutex   ) 

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 1043 of file utils.c.

Referenced by handle_context_add_extension(), handle_context_add_extension_deprecated(), and pbx_load_config().

01044 {
01045    char *dataPut = start;
01046    int inEscape = 0;
01047    int inQuotes = 0;
01048 
01049    for (; *start; start++) {
01050       if (inEscape) {
01051          *dataPut++ = *start;       /* Always goes verbatim */
01052          inEscape = 0;
01053       } else {
01054          if (*start == '\\') {
01055             inEscape = 1;      /* Do not copy \ into the data */
01056          } else if (*start == '\'') {
01057             inQuotes = 1 - inQuotes;   /* Do not copy ' into the data */
01058          } else {
01059             /* Replace , with |, unless in quotes */
01060             *dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
01061          }
01062       }
01063    }
01064    if (start != dataPut)
01065       *dataPut = 0;
01066    return dataPut;
01067 }

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 784 of file utils.c.

References asprintf, ast_log(), ast_malloc, AST_STACKSIZE, dummy_start(), LOG_WARNING, and pthread_create.

00787 {
00788 #if !defined(LOW_MEMORY)
00789    struct thr_arg *a;
00790 #endif
00791 
00792    if (!attr) {
00793       attr = alloca(sizeof(*attr));
00794       pthread_attr_init(attr);
00795    }
00796 
00797 #ifdef __linux__
00798    /* On Linux, pthread_attr_init() defaults to PTHREAD_EXPLICIT_SCHED,
00799       which is kind of useless. Change this here to
00800       PTHREAD_INHERIT_SCHED; that way the -p option to set realtime
00801       priority will propagate down to new threads by default.
00802       This does mean that callers cannot set a different priority using
00803       PTHREAD_EXPLICIT_SCHED in the attr argument; instead they must set
00804       the priority afterwards with pthread_setschedparam(). */
00805    if ((errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED)))
00806       ast_log(LOG_WARNING, "pthread_attr_setinheritsched: %s\n", strerror(errno));
00807 #endif
00808 
00809    if (!stacksize)
00810       stacksize = AST_STACKSIZE;
00811 
00812    if ((errno = pthread_attr_setstacksize(attr, stacksize ? stacksize : AST_STACKSIZE)))
00813       ast_log(LOG_WARNING, "pthread_attr_setstacksize: %s\n", strerror(errno));
00814 
00815 #if !defined(LOW_MEMORY)
00816    if ((a = ast_malloc(sizeof(*a)))) {
00817       a->start_routine = start_routine;
00818       a->data = data;
00819       start_routine = dummy_start;
00820       asprintf(&a->name, "%-20s started at [%5d] %s %s()",
00821           start_fn, line, file, caller);
00822       data = a;
00823    }
00824 #endif /* !LOW_MEMORY */
00825 
00826    return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
00827 }

long int ast_random ( void   ) 

Definition at line 1033 of file utils.c.

References ast_mutex_lock(), and ast_mutex_unlock().

Referenced by acf_rand_exec(), agent_new(), ast_lock_path(), ast_rtp_new_init(), ast_rtp_new_with_bindaddr(), ast_udptl_new_with_bindaddr(), authenticate_request(), build_gateway(), build_iv(), build_reply_digest(), calc_metric(), calc_rxstamp(), check_auth(), generate_random_string(), get_trans_id(), gtalk_alloc(), gtalk_create_candidates(), gtalk_new(), iax2_start_transfer(), local_new(), make_email_file(), make_our_tag(), moh_files_alloc(), ogg_vorbis_rewrite(), page_exec(), process_message(), random_exec(), reg_source_db(), registry_authrequest(), reqprep(), sip_alloc(), socket_read(), start_rtp(), stun_req_id(), transmit_fake_auth_response(), transmit_invite(), transmit_register(), transmit_response_using_temp(), try_calling(), try_firmware(), and zt_new().

01034 {
01035    long int res;
01036    ast_mutex_lock(&randomlock);
01037    res = random();
01038    ast_mutex_unlock(&randomlock);
01039    return res;
01040 }

void ast_sha1_hash ( char *  output,
char *  input 
)

Produce 40 char SHA1 hash of value.

Definition at line 310 of file utils.c.

References SHA1Input(), SHA1Reset(), and SHA1Result().

Referenced by aji_act_hook(), jabber_make_auth(), and sha1().

00311 {
00312    struct SHA1Context sha;
00313    char *ptr;
00314    int x;
00315    uint8_t Message_Digest[20];
00316 
00317    SHA1Reset(&sha);
00318    
00319    SHA1Input(&sha, (const unsigned char *) input, strlen(input));
00320 
00321    SHA1Result(&sha, Message_Digest);
00322    ptr = output;
00323    for (x = 0; x < 20; x++)
00324       ptr += sprintf(ptr, "%2.2x", Message_Digest[x]);
00325 }

char* ast_strip_quoted ( char *  s,
const char *  beg_quotes,
const char *  end_quotes 
)

Definition at line 881 of file utils.c.

Referenced by acf_if(), ast_register_file_version(), iftime(), and parse_dial_string().

00882 {
00883    char *e;
00884    char *q;
00885 
00886    s = ast_strip(s);
00887    if ((q = strchr(beg_quotes, *s)) && *q != '\0') {
00888       e = s + strlen(s) - 1;
00889       if (*e == *(end_quotes + (q - beg_quotes))) {
00890          s++;
00891          *e = '\0';
00892       }
00893    }
00894 
00895    return s;
00896 }

AST_THREADSTORAGE ( inet_ntoa_buf  ,
inet_ntoa_buf_init   
)

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 944 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(), get_encrypt_methods(), gtalk_load_config(), handle_common_options(), handle_save_dialplan(), init_logger_chain(), init_manager(), load_config(), load_module(), load_modules(), load_moh_classes(), load_odbc_config(), load_rpt_vars(), loadconfigurationfile(), manager_add_queue_member(), manager_pause_queue_member(), odbc_load_module(), osp_load(), parse_config(), pbx_load_config(), pbx_load_users(), process_zap(), 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().

00945 {
00946    if (ast_strlen_zero(s))
00947       return 0;
00948 
00949    /* Determine if this is a true value */
00950    if (!strcasecmp(s, "yes") ||
00951        !strcasecmp(s, "true") ||
00952        !strcasecmp(s, "y") ||
00953        !strcasecmp(s, "t") ||
00954        !strcasecmp(s, "1") ||
00955        !strcasecmp(s, "on"))
00956       return -1;
00957 
00958    return 0;
00959 }

struct timeval ast_tvadd ( struct timeval  a,
struct timeval  b 
)

Definition at line 998 of file utils.c.

References ONE_MILLION, and tvfix().

Referenced by __get_from_jb(), agent_hangup(), agent_read(), ast_channel_bridge(), ast_channel_spy_trigger_wait(), 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(), NBScat_exec(), sched_settime(), sched_thread(), schedule_delivery(), and sla_process_timers().

00999 {
01000    /* consistency checks to guarantee usec in 0..999999 */
01001    a = tvfix(a);
01002    b = tvfix(b);
01003    a.tv_sec += b.tv_sec;
01004    a.tv_usec += b.tv_usec;
01005    if (a.tv_usec >= ONE_MILLION) {
01006       a.tv_sec++;
01007       a.tv_usec -= ONE_MILLION;
01008    }
01009    return a;
01010 }

struct timeval ast_tvsub ( struct timeval  a,
struct timeval  b 
)

Returns the difference of two timevals a - b.

Definition at line 1012 of file utils.c.

References ONE_MILLION, and tvfix().

Referenced by ast_channel_bridge(), ast_sched_dump(), ast_translate(), calc_rxstamp(), and calc_timestamp().

01013 {
01014    /* consistency checks to guarantee usec in 0..999999 */
01015    a = tvfix(a);
01016    b = tvfix(b);
01017    a.tv_sec -= b.tv_sec;
01018    a.tv_usec -= b.tv_usec;
01019    if (a.tv_usec < 0) {
01020       a.tv_sec-- ;
01021       a.tv_usec += ONE_MILLION;
01022    }
01023    return a;
01024 }

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 898 of file utils.c.

Referenced by sip_notify().

00899 {
00900    char *e;
00901    char *work = s;
00902 
00903    while ((e = strchr(work, ';'))) {
00904       if ((e > work) && (*(e-1) == '\\')) {
00905          memmove(e - 1, e, strlen(e) + 1);
00906          work = e;
00907       }
00908    }
00909 
00910    return s;
00911 }

void ast_uri_decode ( char *  s  ) 

Decode URI, URN, URL (overwrite string).

Parameters:
s String to be decoded

Definition at line 478 of file utils.c.

Referenced by check_user_full(), get_also_info(), get_destination(), get_refer_info(), handle_request_invite(), handle_uri(), register_verify(), and uridecode().

00479 {
00480    char *o;
00481    unsigned int tmp;
00482 
00483    for (o = s; *s; s++, o++) {
00484       if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) {
00485          /* have '%', two chars and correct parsing */
00486          *o = tmp;
00487          s += 2;  /* Will be incremented once more when we break out */
00488       } else /* all other cases, just copy */
00489          *o = *s;
00490    }
00491    *o = '\0';
00492 }

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 447 of file utils.c.

Referenced by initreqprep(), and uriencode().

00448 {
00449    char *reserved = ";/?:@&=+$, ";  /* Reserved chars */
00450 
00451    const char *ptr  = string; /* Start with the string */
00452    char *out = NULL;
00453    char *buf = NULL;
00454 
00455    ast_copy_string(outbuf, string, buflen);
00456 
00457    /* If there's no characters to convert, just go through and don't do anything */
00458    while (*ptr) {
00459       if (((unsigned char) *ptr) > 127 || (doreserved && strchr(reserved, *ptr)) ) {
00460          /* Oops, we need to start working here */
00461          if (!buf) {
00462             buf = outbuf;
00463             out = buf + (ptr - string) ;  /* Set output ptr */
00464          }
00465          out += sprintf(out, "%%%02x", (unsigned char) *ptr);
00466       } else if (buf) {
00467          *out = *ptr;   /* Continue copying the string */
00468          out++;
00469       } 
00470       ptr++;
00471    }
00472    if (buf)
00473       *out = '\0';
00474    return outbuf;
00475 }

int ast_utils_init ( void   ) 

Definition at line 1276 of file utils.c.

References ast_cli_register_multiple(), and base64_init().

Referenced by main().

01277 {
01278    base64_init();
01279 #ifdef DEBUG_THREADS
01280    ast_cli_register_multiple(utils_cli, sizeof(utils_cli) / sizeof(utils_cli[0]));
01281 #endif
01282    return 0;
01283 }

int ast_wait_for_input ( int  fd,
int  ms 
)

Definition at line 829 of file utils.c.

References poll(), POLLIN, and POLLPRI.

Referenced by action_waitevent(), ast_moh_destroy_one(), and http_root().

00830 {
00831    struct pollfd pfd[1];
00832    memset(pfd, 0, sizeof(pfd));
00833    pfd[0].fd = fd;
00834    pfd[0].events = POLLIN|POLLPRI;
00835    return poll(pfd, 1, ms);
00836 }

static void base64_init ( void   )  [static]

Definition at line 411 of file utils.c.

Referenced by ast_utils_init().

00412 {
00413    int x;
00414    memset(b2a, -1, sizeof(b2a));
00415    /* Initialize base-64 Conversion table */
00416    for (x = 0; x < 26; x++) {
00417       /* A-Z */
00418       base64[x] = 'A' + x;
00419       b2a['A' + x] = x;
00420       /* a-z */
00421       base64[x + 26] = 'a' + x;
00422       b2a['a' + x] = x + 26;
00423       /* 0-9 */
00424       if (x < 10) {
00425          base64[x + 52] = '0' + x;
00426          b2a['0' + x] = x + 52;
00427       }
00428    }
00429    base64[62] = '+';
00430    base64[63] = '/';
00431    b2a[(int)'+'] = 62;
00432    b2a[(int)'/'] = 63;
00433 }

static void* dummy_start ( void *  data  )  [static]

Definition at line 745 of file utils.c.

References AST_LIST_INSERT_TAIL, ast_register_thread(), ast_unregister_thread(), thr_arg::data, free, thr_arg::name, pthread_mutex_init, pthread_mutex_lock, pthread_mutex_unlock, thr_arg::start_routine, and strdup.

Referenced by ast_pthread_create_stack().

00746 {
00747    void *ret;
00748    struct thr_arg a = *((struct thr_arg *) data);  /* make a local copy */
00749 #ifdef DEBUG_THREADS
00750    struct thr_lock_info *lock_info;
00751 #endif
00752 
00753    /* note that even though data->name is a pointer to allocated memory,
00754       we are not freeing it here because ast_register_thread is going to
00755       keep a copy of the pointer and then ast_unregister_thread will
00756       free the memory
00757    */
00758    free(data);
00759    ast_register_thread(a.name);
00760    pthread_cleanup_push(ast_unregister_thread, (void *) pthread_self());
00761 
00762 #ifdef DEBUG_THREADS
00763    if (!(lock_info = ast_threadstorage_get(&thread_lock_info, sizeof(*lock_info))))
00764       return NULL;
00765 
00766    lock_info->thread_id = pthread_self();
00767    lock_info->thread_name = strdup(a.name);
00768    pthread_mutex_init(&lock_info->lock, NULL);
00769 
00770    pthread_mutex_lock(&lock_infos_lock.mutex); /* Intentionally not the wrapper */
00771    AST_LIST_INSERT_TAIL(&lock_infos, lock_info, entry);
00772    pthread_mutex_unlock(&lock_infos_lock.mutex); /* Intentionally not the wrapper */
00773 #endif /* DEBUG_THREADS */
00774 
00775    ret = a.start_routine(a.data);
00776 
00777    pthread_cleanup_pop(1);
00778 
00779    return ret;
00780 }

static int gethostbyname_r ( const char *  name,
struct hostent *  ret,
char *  buf,
size_t  buflen,
struct hostent **  result,
int *  h_errnop 
) [static]

Reentrant replacement for gethostbyname for BSD-based systems.

Note:
This routine is derived from code originally written and placed in the public domain by Enzo Michelangeli <em@em.no-ip.com>

Definition at line 84 of file utils.c.

References ast_mutex_lock(), ast_mutex_unlock(), ERANGE, and gethostbyname.

Referenced by ast_gethostbyname().

00087 {
00088    int hsave;
00089    struct hostent *ph;
00090    ast_mutex_lock(&__mutex); /* begin critical area */
00091    hsave = h_errno;
00092 
00093    ph = gethostbyname(name);
00094    *h_errnop = h_errno; /* copy h_errno to *h_herrnop */
00095    if (ph == NULL) {
00096       *result = NULL;
00097    } else {
00098       char **p, **q;
00099       char *pbuf;
00100       int nbytes=0;
00101       int naddr=0, naliases=0;
00102       /* determine if we have enough space in buf */
00103 
00104       /* count how many addresses */
00105       for (p = ph->h_addr_list; *p != 0; p++) {
00106          nbytes += ph->h_length; /* addresses */
00107          nbytes += sizeof(*p); /* pointers */
00108          naddr++;
00109       }
00110       nbytes += sizeof(*p); /* one more for the terminating NULL */
00111 
00112       /* count how many aliases, and total length of strings */
00113       for (p = ph->h_aliases; *p != 0; p++) {
00114          nbytes += (strlen(*p)+1); /* aliases */
00115          nbytes += sizeof(*p);  /* pointers */
00116          naliases++;
00117       }
00118       nbytes += sizeof(*p); /* one more for the terminating NULL */
00119 
00120       /* here nbytes is the number of bytes required in buffer */
00121       /* as a terminator must be there, the minimum value is ph->h_length */
00122       if (nbytes > buflen) {
00123          *result = NULL;
00124          ast_mutex_unlock(&__mutex); /* end critical area */
00125          return ERANGE; /* not enough space in buf!! */
00126       }
00127 
00128       /* There is enough space. Now we need to do a deep copy! */
00129       /* Allocation in buffer:
00130          from [0] to [(naddr-1) * sizeof(*p)]:
00131          pointers to addresses
00132          at [naddr * sizeof(*p)]:
00133          NULL
00134          from [(naddr+1) * sizeof(*p)] to [(naddr+naliases) * sizeof(*p)] :
00135          pointers to aliases
00136          at [(naddr+naliases+1) * sizeof(*p)]:
00137          NULL
00138          then naddr addresses (fixed length), and naliases aliases (asciiz).
00139       */
00140 
00141       *ret = *ph;   /* copy whole structure (not its address!) */
00142 
00143       /* copy addresses */
00144       q = (char **)buf; /* pointer to pointers area (type: char **) */
00145       ret->h_addr_list = q; /* update pointer to address list */
00146       pbuf = buf + ((naddr + naliases + 2) * sizeof(*p)); /* skip that area */
00147       for (p = ph->h_addr_list; *p != 0; p++) {
00148          memcpy(pbuf, *p, ph->h_length); /* copy address bytes */
00149          *q++ = pbuf; /* the pointer is the one inside buf... */
00150          pbuf += ph->h_length; /* advance pbuf */
00151       }
00152       *q++ = NULL; /* address list terminator */
00153 
00154       /* copy aliases */
00155       ret->h_aliases = q; /* update pointer to aliases list */
00156       for (p = ph->h_aliases; *p != 0; p++) {
00157          strcpy(pbuf, *p); /* copy alias strings */
00158          *q++ = pbuf; /* the pointer is the one inside buf... */
00159          pbuf += strlen(*p); /* advance pbuf */
00160          *pbuf++ = 0; /* string terminator */
00161       }
00162       *q++ = NULL; /* terminator */
00163 
00164       strcpy(pbuf, ph->h_name); /* copy alias strings */
00165       ret->h_name = pbuf;
00166       pbuf += strlen(ph->h_name); /* advance pbuf */
00167       *pbuf++ = 0; /* string terminator */
00168 
00169       *result = ret;  /* and let *result point to structure */
00170 
00171    }
00172    h_errno = hsave;  /* restore h_errno */
00173    ast_mutex_unlock(&__mutex); /* end critical area */
00174 
00175    return (*result == NULL); /* return 0 on success, non-zero on error */
00176 }

int test_for_thread_safety ( void   ) 

Definition at line 265 of file utils.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, and test_thread_body().

Referenced by main().

00266 { 
00267    ast_mutex_lock(&test_lock2);
00268    ast_mutex_lock(&test_lock);
00269    lock_count += 1;
00270    ast_mutex_lock(&test_lock);
00271    lock_count += 1;
00272    ast_pthread_create(&test_thread, NULL, test_thread_body, NULL); 
00273    usleep(100);
00274    if (lock_count != 2) 
00275       test_errors++;
00276    ast_mutex_unlock(&test_lock);
00277    lock_count -= 1;
00278    usleep(100); 
00279    if (lock_count != 1) 
00280       test_errors++;
00281    ast_mutex_unlock(&test_lock);
00282    lock_count -= 1;
00283    if (lock_count != 0) 
00284       test_errors++;
00285    ast_mutex_unlock(&test_lock2);
00286    usleep(100);
00287    if (lock_count != 0) 
00288       test_errors++;
00289    pthread_join(test_thread, NULL);
00290    return(test_errors);          /* return 0 on success. */
00291 }

static void* test_thread_body ( void *  data  )  [static]

This is a regression test for recursive mutexes. test_for_thread_safety() will return 0 if recursive mutex locks are working properly, and non-zero if they are not working properly.

Definition at line 242 of file utils.c.

References ast_mutex_lock(), and ast_mutex_unlock().

Referenced by test_for_thread_safety().

00243 { 
00244    ast_mutex_lock(&test_lock);
00245    lock_count += 10;
00246    if (lock_count != 10) 
00247       test_errors++;
00248    ast_mutex_lock(&test_lock);
00249    lock_count += 10;
00250    if (lock_count != 20) 
00251       test_errors++;
00252    ast_mutex_lock(&test_lock2);
00253    ast_mutex_unlock(&test_lock);
00254    lock_count -= 10;
00255    if (lock_count != 10) 
00256       test_errors++;
00257    ast_mutex_unlock(&test_lock);
00258    lock_count -= 10;
00259    ast_mutex_unlock(&test_lock2);
00260    if (lock_count != 0) 
00261       test_errors++;
00262    return NULL;
00263 } 

static struct timeval tvfix ( struct timeval  a  )  [static]

Definition at line 983 of file utils.c.

References ast_log(), LOG_WARNING, and ONE_MILLION.

Referenced by ast_tvadd(), and ast_tvsub().

00984 {
00985    if (a.tv_usec >= ONE_MILLION) {
00986       ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
00987          a.tv_sec, (long int) a.tv_usec);
00988       a.tv_sec += a.tv_usec / ONE_MILLION;
00989       a.tv_usec %= ONE_MILLION;
00990    } else if (a.tv_usec < 0) {
00991       ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
00992          a.tv_sec, (long int) a.tv_usec);
00993       a.tv_usec = 0;
00994    }
00995    return a;
00996 }


Variable Documentation

const char __ast_string_field_empty[] = ""

Definition at line 1088 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().

int lock_count = 0 [static]

Definition at line 236 of file utils.c.

int test_errors = 0 [static]

Definition at line 237 of file utils.c.

pthread_t test_thread [static]

Definition at line 235 of file utils.c.


Generated on Fri Aug 24 02:28:48 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1