Mon May 14 04:51:49 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/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 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)
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.
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)
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 62 of file utils.c.

#define AST_API_MODULE

Definition at line 62 of file utils.c.

#define AST_API_MODULE

Definition at line 62 of file utils.c.

#define AST_API_MODULE

Definition at line 62 of file utils.c.

#define AST_API_MODULE

Definition at line 62 of file utils.c.

#define AST_API_MODULE

Definition at line 62 of file utils.c.

#define ONE_MILLION   1000000

Definition at line 732 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 874 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.

00876 {
00877    char *result = NULL;
00878 
00879    if (__builtin_expect(needed > mgr->space, 0)) {
00880       size_t new_size = mgr->size * 2;
00881 
00882       while (new_size < needed)
00883          new_size *= 2;
00884 
00885       if (add_string_pool(mgr, new_size))
00886          return NULL;
00887    }
00888 
00889    result = mgr->pool->base + mgr->used;
00890    mgr->used += needed;
00891    mgr->space -= needed;
00892    return result;
00893 }

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

References __ast_string_field_index_build_va().

00925 {
00926    va_list ap1, ap2;
00927 
00928    va_start(ap1, format);
00929    va_start(ap2, format);     /* va_copy does not exist on FreeBSD */
00930 
00931    __ast_string_field_index_build_va(mgr, fields, num_fields, index, format, ap1, ap2);
00932 
00933    va_end(ap1);
00934    va_end(ap2);
00935 }

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

00898 {
00899    size_t needed;
00900 
00901    needed = vsnprintf(mgr->pool->base + mgr->used, mgr->space, format, ap1) + 1;
00902 
00903    va_end(ap1);
00904 
00905    if (needed > mgr->space) {
00906       size_t new_size = mgr->size * 2;
00907 
00908       while (new_size < needed)
00909          new_size *= 2;
00910 
00911       if (add_string_pool(mgr, new_size))
00912          return;
00913 
00914       vsprintf(mgr->pool->base + mgr->used, format, ap2);
00915    }
00916 
00917    fields[index] = mgr->pool->base + mgr->used;
00918    mgr->used += needed;
00919    mgr->space -= needed;
00920 }

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

Definition at line 860 of file utils.c.

References add_string_pool().

00862 {
00863    int index;
00864 
00865    if (add_string_pool(mgr, size))
00866       return -1;
00867 
00868    for (index = 0; index < num_fields; index++)
00869       fields[index] = __ast_string_field_empty;
00870 
00871    return 0;
00872 }

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

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

00845 {
00846    struct ast_string_field_pool *pool;
00847 
00848    if (!(pool = ast_calloc(1, sizeof(*pool) + size)))
00849       return -1;
00850    
00851    pool->prev = mgr->pool;
00852    mgr->pool = pool;
00853    mgr->size = size;
00854    mgr->space = size;
00855    mgr->used = 0;
00856 
00857    return 0;
00858 }

int ast_atomic_fetchadd_int_slow ( volatile int *  p,
int  v 
)

Definition at line 939 of file utils.c.

References ast_mutex_lock(), and ast_mutex_unlock().

00940 {
00941         int ret;
00942         ast_mutex_lock(&fetchadd_m);
00943         ret = *p;
00944         *p += v;
00945         ast_mutex_unlock(&fetchadd_m);
00946         return ret;
00947 }

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

decode BASE64 encoded text

Definition at line 326 of file utils.c.

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

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

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

Definition at line 404 of file utils.c.

References ast_base64encode_full().

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

00405 {
00406    return ast_base64encode_full(dst, src, srclen, max, 0);
00407 }

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

encode text to BASE64 coding

Definition at line 353 of file utils.c.

Referenced by ast_base64encode().

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

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

Definition at line 686 of file utils.c.

References ast_build_string_va().

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

00687 {
00688    va_list ap;
00689    int result;
00690 
00691    va_start(ap, fmt);
00692    result = ast_build_string_va(buffer, space, fmt, ap);
00693    va_end(ap);
00694 
00695    return result;
00696 }

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

Referenced by ast_build_string().

00668 {
00669    int result;
00670 
00671    if (!buffer || !*buffer || !space || !*space)
00672       return -1;
00673 
00674    result = vsnprintf(*buffer, *space, fmt, ap);
00675 
00676    if (result < 0)
00677       return -1;
00678    else if (result > *space)
00679       result = *space;
00680 
00681    *buffer += result;
00682    *space -= result;
00683    return 0;
00684 }

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

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

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

00623 {
00624    /* Try to write string, but wait no more than ms milliseconds
00625       before timing out */
00626    int res = 0;
00627    struct pollfd fds[1];
00628    while (len) {
00629       res = write(fd, s, len);
00630       if ((res < 0) && (errno != EAGAIN)) {
00631          return -1;
00632       }
00633       if (res < 0)
00634          res = 0;
00635       len -= res;
00636       s += res;
00637       res = 0;
00638       if (len) {
00639          fds[0].fd = fd;
00640          fds[0].events = POLLOUT;
00641          /* Wait until writable again */
00642          res = poll(fds, 1, timeoutms);
00643          if (res < 1)
00644             return -1;
00645       }
00646    }
00647    return res;
00648 }

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

References ast_realloc, ast_threadstorage::key, and offset.

00977 {
00978    int res;
00979    int offset = (append && (*buf)->len) ? strlen((*buf)->str) : 0;
00980 #if defined(DEBUG_THREADLOCALS)
00981    struct ast_dynamic_str *old_buf = *buf;
00982 #endif /* defined(DEBUG_THREADLOCALS) */
00983 
00984    res = vsnprintf((*buf)->str + offset, (*buf)->len - offset, fmt, ap);
00985 
00986    /* Check to see if there was not enough space in the string buffer to prepare
00987     * the string.  Also, if a maximum length is present, make sure the current
00988     * length is less than the maximum before increasing the size. */
00989    if ((res + offset + 1) > (*buf)->len && (max_len ? ((*buf)->len < max_len) : 1)) {
00990       /* Set the new size of the string buffer to be the size needed
00991        * to hold the resulting string (res) plus one byte for the
00992        * terminating '\0'.  If this size is greater than the max, set
00993        * the new length to be the maximum allowed. */
00994       if (max_len)
00995          (*buf)->len = ((res + offset + 1) < max_len) ? (res + offset + 1) : max_len;
00996       else
00997          (*buf)->len = res + offset + 1;
00998 
00999       if (!(*buf = ast_realloc(*buf, (*buf)->len + sizeof(*(*buf)))))
01000          return AST_DYNSTR_BUILD_FAILED;
01001 
01002       if (append)
01003          (*buf)->str[offset] = '\0';
01004 
01005       if (ts) {
01006          pthread_setspecific(ts->key, *buf);
01007 #if defined(DEBUG_THREADLOCALS)
01008          __ast_threadstorage_object_replace(old_buf, *buf, (*buf)->len + sizeof(*(*buf)));
01009 #endif /* defined(DEBUG_THREADLOCALS) */
01010       }
01011 
01012       /* va_end() and va_start() must be done before calling
01013        * vsnprintf() again. */
01014       return AST_DYNSTR_BUILD_RETRY;
01015    }
01016 
01017    return res;
01018 }

void ast_enable_packet_fragmentation ( int  sock  ) 

Definition at line 1020 of file utils.c.

References ast_log(), and LOG_WARNING.

Referenced by ast_netsock_bindaddr().

01021 {
01022 #if defined(HAVE_IP_MTU_DISCOVER)
01023    int val = IP_PMTUDISC_DONT;
01024    
01025    if (setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val)))
01026       ast_log(LOG_WARNING, "Unable to disable PMTU discovery. Large UDP packets may fail to be delivered when sent from this socket.\n");
01027 #endif /* HAVE_IP_MTU_DISCOVER */
01028 }

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

00716 {
00717    if (ast_strlen_zero(s))
00718       return 0;
00719 
00720    /* Determine if this is a false value */
00721    if (!strcasecmp(s, "no") ||
00722        !strcasecmp(s, "false") ||
00723        !strcasecmp(s, "n") ||
00724        !strcasecmp(s, "f") ||
00725        !strcasecmp(s, "0") ||
00726        !strcasecmp(s, "off"))
00727       return -1;
00728 
00729    return 0;
00730 }

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

get values from config variables.

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

00953 {
00954    long t;
00955    int scanned;
00956 
00957    if (dst == NULL)
00958       return -1;
00959 
00960    *dst = _default;
00961 
00962    if (ast_strlen_zero(src))
00963       return -1;
00964 
00965    /* only integer at the moment, but one day we could accept more formats */
00966    if (sscanf(src, "%ld%n", &t, &scanned) == 1) {
00967       *dst = t;
00968       if (consumed)
00969          *consumed = scanned;
00970       return 0;
00971    } else
00972       return -1;
00973 }

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

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

00183 {
00184    int res;
00185    int herrno;
00186    int dots=0;
00187    const char *s;
00188    struct hostent *result = NULL;
00189    /* Although it is perfectly legitimate to lookup a pure integer, for
00190       the sake of the sanity of people who like to name their peers as
00191       integers, we break with tradition and refuse to look up a
00192       pure integer */
00193    s = host;
00194    res = 0;
00195    while(s && *s) {
00196       if (*s == '.')
00197          dots++;
00198       else if (!isdigit(*s))
00199          break;
00200       s++;
00201    }
00202    if (!s || !*s) {
00203       /* Forge a reply for IP's to avoid octal IP's being interpreted as octal */
00204       if (dots != 3)
00205          return NULL;
00206       memset(hp, 0, sizeof(struct ast_hostent));
00207       hp->hp.h_addrtype = AF_INET;
00208       hp->hp.h_addr_list = (void *) hp->buf;
00209       hp->hp.h_addr = hp->buf + sizeof(void *);
00210       if (inet_pton(AF_INET, host, hp->hp.h_addr) > 0)
00211          return &hp->hp;
00212       return NULL;
00213       
00214    }
00215 #ifdef SOLARIS
00216    result = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &herrno);
00217 
00218    if (!result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
00219       return NULL;
00220 #else
00221    res = gethostbyname_r(host, &hp->hp, hp->buf, sizeof(hp->buf), &result, &herrno);
00222 
00223    if (res || !result || !hp->hp.h_addr_list || !hp->hp.h_addr_list[0])
00224       return NULL;
00225 #endif
00226    return &hp->hp;
00227 }

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

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

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

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

00824 {
00825    int x, ofs = 0;
00826    const char *src;
00827 
00828    /* Join words into a string */
00829    if (!s)
00830       return;
00831    for (x = 0; ofs < len && w[x]; x++) {
00832       if (x > 0)
00833          s[ofs++] = ' ';
00834       for (src = w[x]; *src && ofs < len; src++)
00835          s[ofs++] = *src;
00836    }
00837    if (ofs == len)
00838       ofs--;
00839    s[ofs] = '\0';
00840 }

void ast_md5_hash ( char *  output,
char *  input 
)

Produce 32 char MD5 hash of value.

Definition at line 292 of file utils.c.

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

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

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

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   ) 

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

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

00798 {
00799    char *dataPut = start;
00800    int inEscape = 0;
00801    int inQuotes = 0;
00802 
00803    for (; *start; start++) {
00804       if (inEscape) {
00805          *dataPut++ = *start;       /* Always goes verbatim */
00806          inEscape = 0;
00807       } else {
00808          if (*start == '\\') {
00809             inEscape = 1;      /* Do not copy \ into the data */
00810          } else if (*start == '\'') {
00811             inQuotes = 1 - inQuotes;   /* Do not copy ' into the data */
00812          } else {
00813             /* Replace , with |, unless in quotes */
00814             *dataPut++ = inQuotes ? *start : ((*start == find) ? replace_with : *start);
00815          }
00816       }
00817    }
00818    if (start != dataPut)
00819       *dataPut = 0;
00820    return dataPut;
00821 }

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

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

00556 {
00557 #if !defined(LOW_MEMORY)
00558    struct thr_arg *a;
00559 #endif
00560 
00561    if (!attr) {
00562       attr = alloca(sizeof(*attr));
00563       pthread_attr_init(attr);
00564    }
00565 
00566 #ifdef __linux__
00567    /* On Linux, pthread_attr_init() defaults to PTHREAD_EXPLICIT_SCHED,
00568       which is kind of useless. Change this here to
00569       PTHREAD_INHERIT_SCHED; that way the -p option to set realtime
00570       priority will propagate down to new threads by default.
00571       This does mean that callers cannot set a different priority using
00572       PTHREAD_EXPLICIT_SCHED in the attr argument; instead they must set
00573       the priority afterwards with pthread_setschedparam(). */
00574    if ((errno = pthread_attr_setinheritsched(attr, PTHREAD_INHERIT_SCHED)))
00575       ast_log(LOG_WARNING, "pthread_attr_setinheritsched: %s\n", strerror(errno));
00576 #endif
00577 
00578    if (!stacksize)
00579       stacksize = AST_STACKSIZE;
00580 
00581    if ((errno = pthread_attr_setstacksize(attr, stacksize ? stacksize : AST_STACKSIZE)))
00582       ast_log(LOG_WARNING, "pthread_attr_setstacksize: %s\n", strerror(errno));
00583 
00584 #if !defined(LOW_MEMORY)
00585    if ((a = ast_malloc(sizeof(*a)))) {
00586       a->start_routine = start_routine;
00587       a->data = data;
00588       start_routine = dummy_start;
00589       asprintf(&a->name, "%-20s started at [%5d] %s %s()",
00590           start_fn, line, file, caller);
00591       data = a;
00592    }
00593 #endif /* !LOW_MEMORY */
00594 
00595    return pthread_create(thread, attr, start_routine, data); /* We're in ast_pthread_create, so it's okay */
00596 }

long int ast_random ( void   ) 

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

00788 {
00789    long int res;
00790    ast_mutex_lock(&randomlock);
00791    res = random();
00792    ast_mutex_unlock(&randomlock);
00793    return res;
00794 }

void ast_sha1_hash ( char *  output,
char *  input 
)

Produce 40 char SHA1 hash of value.

Definition at line 308 of file utils.c.

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

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

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

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

Definition at line 650 of file utils.c.

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

00651 {
00652    char *e;
00653    char *q;
00654 
00655    s = ast_strip(s);
00656    if ((q = strchr(beg_quotes, *s)) && *q != '\0') {
00657       e = s + strlen(s) - 1;
00658       if (*e == *(end_quotes + (q - beg_quotes))) {
00659          s++;
00660          *e = '\0';
00661       }
00662    }
00663 
00664    return s;
00665 }

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 698 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(), do_directory(), do_reload(), festival_exec(), function_ilink(), 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(), sla_load_config(), start_monitor_action(), strings_to_mask(), and update_common_options().

00699 {
00700    if (ast_strlen_zero(s))
00701       return 0;
00702 
00703    /* Determine if this is a true value */
00704    if (!strcasecmp(s, "yes") ||
00705        !strcasecmp(s, "true") ||
00706        !strcasecmp(s, "y") ||
00707        !strcasecmp(s, "t") ||
00708        !strcasecmp(s, "1") ||
00709        !strcasecmp(s, "on"))
00710       return -1;
00711 
00712    return 0;
00713 }

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

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

00753 {
00754    /* consistency checks to guarantee usec in 0..999999 */
00755    a = tvfix(a);
00756    b = tvfix(b);
00757    a.tv_sec += b.tv_sec;
00758    a.tv_usec += b.tv_usec;
00759    if (a.tv_usec >= ONE_MILLION) {
00760       a.tv_sec++;
00761       a.tv_usec -= ONE_MILLION;
00762    }
00763    return a;
00764 }

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

Returns the difference of two timevals a - b.

Definition at line 766 of file utils.c.

References ONE_MILLION, and tvfix().

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

00767 {
00768    /* consistency checks to guarantee usec in 0..999999 */
00769    a = tvfix(a);
00770    b = tvfix(b);
00771    a.tv_sec -= b.tv_sec;
00772    a.tv_usec -= b.tv_usec;
00773    if (a.tv_usec < 0) {
00774       a.tv_sec-- ;
00775       a.tv_usec += ONE_MILLION;
00776    }
00777    return a;
00778 }

void ast_uri_decode ( char *  s  ) 

Decode URI, URN, URL (overwrite string).

Parameters:
s String to be decoded

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

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

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

Referenced by initreqprep(), and uriencode().

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

int ast_utils_init ( void   ) 

Definition at line 503 of file utils.c.

References base64_init().

Referenced by main().

00504 {
00505    base64_init();
00506    return 0;
00507 }

int ast_wait_for_input ( int  fd,
int  ms 
)

Definition at line 598 of file utils.c.

References poll(), POLLIN, and POLLPRI.

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

00599 {
00600    struct pollfd pfd[1];
00601    memset(pfd, 0, sizeof(pfd));
00602    pfd[0].fd = fd;
00603    pfd[0].events = POLLIN|POLLPRI;
00604    return poll(pfd, 1, ms);
00605 }

static void base64_init ( void   )  [static]

Definition at line 409 of file utils.c.

Referenced by ast_utils_init().

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

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

Definition at line 532 of file utils.c.

References ast_register_thread(), ast_unregister_thread(), thr_arg::data, free, thr_arg::name, and thr_arg::start_routine.

Referenced by ast_pthread_create_stack().

00533 {
00534    void *ret;
00535    struct thr_arg a = *((struct thr_arg *) data);  /* make a local copy */
00536 
00537    /* note that even though data->name is a pointer to allocated memory,
00538       we are not freeing it here because ast_register_thread is going to
00539       keep a copy of the pointer and then ast_unregister_thread will
00540       free the memory
00541    */
00542    free(data);
00543    ast_register_thread(a.name);
00544    pthread_cleanup_push(ast_unregister_thread, (void *) pthread_self());
00545    ret = a.start_routine(a.data);
00546    pthread_cleanup_pop(1);
00547 
00548    return ret;
00549 }

int test_for_thread_safety ( void   ) 

Definition at line 263 of file utils.c.

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

Referenced by main().

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

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

References ast_mutex_lock(), and ast_mutex_unlock().

Referenced by test_for_thread_safety().

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

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

Definition at line 737 of file utils.c.

References ast_log(), LOG_WARNING, and ONE_MILLION.

Referenced by ast_tvadd(), and ast_tvsub().

00738 {
00739    if (a.tv_usec >= ONE_MILLION) {
00740       ast_log(LOG_WARNING, "warning too large timestamp %ld.%ld\n",
00741          a.tv_sec, (long int) a.tv_usec);
00742       a.tv_sec += a.tv_usec / ONE_MILLION;
00743       a.tv_usec %= ONE_MILLION;
00744    } else if (a.tv_usec < 0) {
00745       ast_log(LOG_WARNING, "warning negative timestamp %ld.%ld\n",
00746          a.tv_sec, (long int) a.tv_usec);
00747       a.tv_usec = 0;
00748    }
00749    return a;
00750 }


Variable Documentation

const char __ast_string_field_empty[] = ""

Definition at line 842 of file utils.c.

char b2a[256] [static]

Definition at line 66 of file utils.c.

char base64[64] [static]

Definition at line 65 of file utils.c.

Referenced by aji_act_hook().

int lock_count = 0 [static]

Definition at line 234 of file utils.c.

int test_errors = 0 [static]

Definition at line 235 of file utils.c.

pthread_t test_thread [static]

Definition at line 233 of file utils.c.


Generated on Mon May 14 04:51:50 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1