Sat Nov 1 06:26:11 2008

Asterisk developer's documentation


utils.h

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  * \brief Utility functions
00021  */
00022 
00023 #ifndef _ASTERISK_UTILS_H
00024 #define _ASTERISK_UTILS_H
00025 
00026 #include "asterisk/network.h"
00027 
00028 #include <time.h> /* we want to override localtime_r */
00029 #include <unistd.h>
00030 
00031 #include "asterisk/lock.h"
00032 #include "asterisk/time.h"
00033 #include "asterisk/logger.h"
00034 #include "asterisk/localtime.h"
00035 
00036 /*! 
00037 \note \verbatim
00038    Note:
00039    It is very important to use only unsigned variables to hold
00040    bit flags, as otherwise you can fall prey to the compiler's
00041    sign-extension antics if you try to use the top two bits in
00042    your variable.
00043 
00044    The flag macros below use a set of compiler tricks to verify
00045    that the caller is using an "unsigned int" variable to hold
00046    the flags, and nothing else. If the caller uses any other
00047    type of variable, a warning message similar to this:
00048 
00049    warning: comparison of distinct pointer types lacks cast
00050    will be generated.
00051 
00052    The "dummy" variable below is used to make these comparisons.
00053 
00054    Also note that at -O2 or above, this type-safety checking
00055    does _not_ produce any additional object code at all.
00056  \endverbatim
00057 */
00058 
00059 extern unsigned int __unsigned_int_flags_dummy;
00060 
00061 #define ast_test_flag(p,flag)       ({ \
00062                typeof ((p)->flags) __p = (p)->flags; \
00063                typeof (__unsigned_int_flags_dummy) __x = 0; \
00064                (void) (&__p == &__x); \
00065                ((p)->flags & (flag)); \
00066                })
00067 
00068 #define ast_set_flag(p,flag)     do { \
00069                typeof ((p)->flags) __p = (p)->flags; \
00070                typeof (__unsigned_int_flags_dummy) __x = 0; \
00071                (void) (&__p == &__x); \
00072                ((p)->flags |= (flag)); \
00073                } while(0)
00074 
00075 #define ast_clear_flag(p,flag)      do { \
00076                typeof ((p)->flags) __p = (p)->flags; \
00077                typeof (__unsigned_int_flags_dummy) __x = 0; \
00078                (void) (&__p == &__x); \
00079                ((p)->flags &= ~(flag)); \
00080                } while(0)
00081 
00082 #define ast_copy_flags(dest,src,flagz) do { \
00083                typeof ((dest)->flags) __d = (dest)->flags; \
00084                typeof ((src)->flags) __s = (src)->flags; \
00085                typeof (__unsigned_int_flags_dummy) __x = 0; \
00086                (void) (&__d == &__x); \
00087                (void) (&__s == &__x); \
00088                (dest)->flags &= ~(flagz); \
00089                (dest)->flags |= ((src)->flags & (flagz)); \
00090                } while (0)
00091 
00092 #define ast_set2_flag(p,value,flag) do { \
00093                typeof ((p)->flags) __p = (p)->flags; \
00094                typeof (__unsigned_int_flags_dummy) __x = 0; \
00095                (void) (&__p == &__x); \
00096                if (value) \
00097                   (p)->flags |= (flag); \
00098                else \
00099                   (p)->flags &= ~(flag); \
00100                } while (0)
00101 
00102 #define ast_set_flags_to(p,flag,value) do { \
00103                typeof ((p)->flags) __p = (p)->flags; \
00104                typeof (__unsigned_int_flags_dummy) __x = 0; \
00105                (void) (&__p == &__x); \
00106                (p)->flags &= ~(flag); \
00107                (p)->flags |= (value); \
00108                } while (0)
00109 
00110 
00111 /* The following 64-bit flag code can most likely be erased after app_dial
00112    is reorganized to either reduce the large number of options, or handle
00113    them in some other way. At the time of this writing, app_dial would be
00114    the only user of 64-bit option flags */
00115 
00116 extern uint64_t __unsigned_int_flags_dummy64;
00117 
00118 #define ast_test_flag64(p,flag)     ({ \
00119                typeof ((p)->flags) __p = (p)->flags; \
00120                typeof (__unsigned_int_flags_dummy64) __x = 0; \
00121                (void) (&__p == &__x); \
00122                ((p)->flags & (flag)); \
00123                })
00124 
00125 #define ast_set_flag64(p,flag)      do { \
00126                typeof ((p)->flags) __p = (p)->flags; \
00127                typeof (__unsigned_int_flags_dummy64) __x = 0; \
00128                (void) (&__p == &__x); \
00129                ((p)->flags |= (flag)); \
00130                } while(0)
00131 
00132 #define ast_clear_flag64(p,flag)       do { \
00133                typeof ((p)->flags) __p = (p)->flags; \
00134                typeof (__unsigned_int_flags_dummy64) __x = 0; \
00135                (void) (&__p == &__x); \
00136                ((p)->flags &= ~(flag)); \
00137                } while(0)
00138 
00139 #define ast_copy_flags64(dest,src,flagz)  do { \
00140                typeof ((dest)->flags) __d = (dest)->flags; \
00141                typeof ((src)->flags) __s = (src)->flags; \
00142                typeof (__unsigned_int_flags_dummy64) __x = 0; \
00143                (void) (&__d == &__x); \
00144                (void) (&__s == &__x); \
00145                (dest)->flags &= ~(flagz); \
00146                (dest)->flags |= ((src)->flags & (flagz)); \
00147                } while (0)
00148 
00149 #define ast_set2_flag64(p,value,flag)  do { \
00150                typeof ((p)->flags) __p = (p)->flags; \
00151                typeof (__unsigned_int_flags_dummy64) __x = 0; \
00152                (void) (&__p == &__x); \
00153                if (value) \
00154                   (p)->flags |= (flag); \
00155                else \
00156                   (p)->flags &= ~(flag); \
00157                } while (0)
00158 
00159 #define ast_set_flags_to64(p,flag,value)  do { \
00160                typeof ((p)->flags) __p = (p)->flags; \
00161                typeof (__unsigned_int_flags_dummy64) __x = 0; \
00162                (void) (&__p == &__x); \
00163                (p)->flags &= ~(flag); \
00164                (p)->flags |= (value); \
00165                } while (0)
00166 
00167 
00168 /* Non-type checking variations for non-unsigned int flags.  You
00169    should only use non-unsigned int flags where required by 
00170    protocol etc and if you know what you're doing :)  */
00171 #define ast_test_flag_nonstd(p,flag) \
00172                ((p)->flags & (flag))
00173 
00174 #define ast_set_flag_nonstd(p,flag)       do { \
00175                ((p)->flags |= (flag)); \
00176                } while(0)
00177 
00178 #define ast_clear_flag_nonstd(p,flag)     do { \
00179                ((p)->flags &= ~(flag)); \
00180                } while(0)
00181 
00182 #define ast_copy_flags_nonstd(dest,src,flagz)   do { \
00183                (dest)->flags &= ~(flagz); \
00184                (dest)->flags |= ((src)->flags & (flagz)); \
00185                } while (0)
00186 
00187 #define ast_set2_flag_nonstd(p,value,flag)   do { \
00188                if (value) \
00189                   (p)->flags |= (flag); \
00190                else \
00191                   (p)->flags &= ~(flag); \
00192                } while (0)
00193 
00194 #define AST_FLAGS_ALL UINT_MAX
00195 
00196 /*! \brief Structure used to handle boolean flags 
00197 */
00198 struct ast_flags {
00199    unsigned int flags;
00200 };
00201 
00202 /*! \brief Structure used to handle a large number of boolean flags == used only in app_dial?
00203 */
00204 struct ast_flags64 {
00205    uint64_t flags;
00206 };
00207 
00208 struct ast_hostent {
00209    struct hostent hp;
00210    char buf[1024];
00211 };
00212 
00213 /*! \brief Thread-safe gethostbyname function to use in Asterisk */
00214 struct hostent *ast_gethostbyname(const char *host, struct ast_hostent *hp);
00215 
00216 /*!  \brief Produces MD5 hash based on input string */
00217 void ast_md5_hash(char *output, char *input);
00218 /*! \brief Produces SHA1 hash based on input string */
00219 void ast_sha1_hash(char *output, char *input);
00220 
00221 int ast_base64encode_full(char *dst, const unsigned char *src, int srclen, int max, int linebreaks);
00222 
00223 /*!
00224  * \brief Encode data in base64
00225  * \param dst the destination buffer
00226  * \param src the source data to be encoded
00227  * \param srclen the number of bytes present in the source buffer
00228  * \param max the maximum number of bytes to write into the destination
00229  *        buffer, *including* the terminating NULL character.
00230  */
00231 int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max);
00232 
00233 /*!
00234  * \brief Decode data from base64
00235  * \param dst the destination buffer
00236  * \param src the source buffer
00237  * \param max The maximum number of bytes to write into the destination
00238  *            buffer.  Note that this function will not ensure that the
00239  *            destination buffer is NULL terminated.  So, in general,
00240  *            this parameter should be sizeof(dst) - 1.
00241  */
00242 int ast_base64decode(unsigned char *dst, const char *src, int max);
00243 
00244 /*!  \brief Turn text string to URI-encoded %XX version 
00245 
00246 \note    At this point, we're converting from ISO-8859-x (8-bit), not UTF8
00247    as in the SIP protocol spec 
00248    If doreserved == 1 we will convert reserved characters also.
00249    RFC 2396, section 2.4
00250    outbuf needs to have more memory allocated than the instring
00251    to have room for the expansion. Every char that is converted
00252    is replaced by three ASCII characters.
00253    \param string  String to be converted
00254    \param outbuf  Resulting encoded string
00255    \param buflen  Size of output buffer
00256    \param doreserved Convert reserved characters
00257 */
00258 
00259 char *ast_uri_encode(const char *string, char *outbuf, int buflen, int doreserved);
00260 
00261 /*!   \brief Decode URI, URN, URL (overwrite string)
00262    \param s String to be decoded 
00263  */
00264 void ast_uri_decode(char *s);
00265 
00266 static force_inline void ast_slinear_saturated_add(short *input, short *value)
00267 {
00268    int res;
00269 
00270    res = (int) *input + *value;
00271    if (res > 32767)
00272       *input = 32767;
00273    else if (res < -32767)
00274       *input = -32767;
00275    else
00276       *input = (short) res;
00277 }
00278 
00279 static force_inline void ast_slinear_saturated_subtract(short *input, short *value)
00280 {
00281    int res;
00282 
00283    res = (int) *input - *value;
00284    if (res > 32767)
00285       *input = 32767;
00286    else if (res < -32767)
00287       *input = -32767;
00288    else
00289       *input = (short) res;
00290 }
00291    
00292 static force_inline void ast_slinear_saturated_multiply(short *input, short *value)
00293 {
00294    int res;
00295 
00296    res = (int) *input * *value;
00297    if (res > 32767)
00298       *input = 32767;
00299    else if (res < -32767)
00300       *input = -32767;
00301    else
00302       *input = (short) res;
00303 }
00304 
00305 static force_inline void ast_slinear_saturated_divide(short *input, short *value)
00306 {
00307    *input /= *value;
00308 }
00309 
00310 int test_for_thread_safety(void);
00311 
00312 #ifdef localtime_r
00313 #undef localtime_r
00314 #endif
00315 #define localtime_r __dont_use_localtime_r_use_ast_localtime_instead__
00316 
00317 int ast_utils_init(void);
00318 int ast_wait_for_input(int fd, int ms);
00319 
00320 /*!
00321    \brief Try to write string, but wait no more than ms milliseconds
00322    before timing out.
00323 
00324    \note If you are calling ast_carefulwrite, it is assumed that you are calling
00325    it on a file descriptor that _DOES_ have NONBLOCK set.  This way,
00326    there is only one system call made to do a write, unless we actually
00327    have a need to wait.  This way, we get better performance.
00328 */
00329 int ast_carefulwrite(int fd, char *s, int len, int timeoutms);
00330 
00331 /*
00332  * Thread management support (should be moved to lock.h or a different header)
00333  */
00334  
00335 #define AST_STACKSIZE 240 * 1024
00336 
00337 #if defined(LOW_MEMORY)
00338 #define AST_BACKGROUND_STACKSIZE 48 * 1024
00339 #else
00340 #define AST_BACKGROUND_STACKSIZE 240 * 1024
00341 #endif
00342 
00343 void ast_register_thread(char *name);
00344 void ast_unregister_thread(void *id);
00345 
00346 int ast_pthread_create_stack(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *),
00347               void *data, size_t stacksize, const char *file, const char *caller,
00348               int line, const char *start_fn);
00349 
00350 int ast_pthread_create_detached_stack(pthread_t *thread, pthread_attr_t *attr, void*(*start_routine)(void *),
00351              void *data, size_t stacksize, const char *file, const char *caller,
00352              int line, const char *start_fn);
00353 
00354 #define ast_pthread_create(a, b, c, d)             \
00355    ast_pthread_create_stack(a, b, c, d,         \
00356       0, __FILE__, __FUNCTION__, __LINE__, #c)
00357 
00358 #define ast_pthread_create_detached(a, b, c, d)       \
00359    ast_pthread_create_detached_stack(a, b, c, d,      \
00360       0, __FILE__, __FUNCTION__, __LINE__, #c)
00361 
00362 #define ast_pthread_create_background(a, b, c, d)     \
00363    ast_pthread_create_stack(a, b, c, d,         \
00364       AST_BACKGROUND_STACKSIZE,        \
00365       __FILE__, __FUNCTION__, __LINE__, #c)
00366 
00367 #define ast_pthread_create_detached_background(a, b, c, d)  \
00368    ast_pthread_create_detached_stack(a, b, c, d,      \
00369       AST_BACKGROUND_STACKSIZE,        \
00370       __FILE__, __FUNCTION__, __LINE__, #c)
00371 
00372 /* End of thread management support */
00373 
00374 /*!
00375    \brief Process a string to find and replace characters
00376    \param start The string to analyze
00377    \param find The character to find
00378    \param replace_with The character that will replace the one we are looking for
00379 */
00380 char *ast_process_quotes_and_slashes(char *start, char find, char replace_with);
00381 
00382 long int ast_random(void);
00383 
00384 #define ast_free free
00385 
00386 /*! 
00387  * \brief free() wrapper
00388  *
00389  * ast_free_ptr should be used when a function pointer for free() needs to be passed
00390  * as the argument to a function. Otherwise, astmm will cause seg faults.
00391  */
00392 #ifdef __AST_DEBUG_MALLOC
00393 static void ast_free_ptr(void *ptr) attribute_unused;
00394 static void ast_free_ptr(void *ptr)
00395 {
00396    ast_free(ptr);
00397 }
00398 #else
00399 #define ast_free_ptr ast_free
00400 #endif
00401 
00402 #ifndef __AST_DEBUG_MALLOC
00403 
00404 #define MALLOC_FAILURE_MSG \
00405    ast_log(LOG_ERROR, "Memory Allocation Failure in function %s at line %d of %s\n", func, lineno, file);
00406 /*!
00407  * \brief A wrapper for malloc()
00408  *
00409  * ast_malloc() is a wrapper for malloc() that will generate an Asterisk log
00410  * message in the case that the allocation fails.
00411  *
00412  * The argument and return value are the same as malloc()
00413  */
00414 #define ast_malloc(len) \
00415    _ast_malloc((len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
00416 
00417 AST_INLINE_API(
00418 void * attribute_malloc _ast_malloc(size_t len, const char *file, int lineno, const char *func),
00419 {
00420    void *p;
00421 
00422    if (!(p = malloc(len)))
00423       MALLOC_FAILURE_MSG;
00424 
00425    return p;
00426 }
00427 )
00428 
00429 /*!
00430  * \brief A wrapper for calloc()
00431  *
00432  * ast_calloc() is a wrapper for calloc() that will generate an Asterisk log
00433  * message in the case that the allocation fails.
00434  *
00435  * The arguments and return value are the same as calloc()
00436  */
00437 #define ast_calloc(num, len) \
00438    _ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
00439 
00440 AST_INLINE_API(
00441 void * attribute_malloc _ast_calloc(size_t num, size_t len, const char *file, int lineno, const char *func),
00442 {
00443    void *p;
00444 
00445    if (!(p = calloc(num, len)))
00446       MALLOC_FAILURE_MSG;
00447 
00448    return p;
00449 }
00450 )
00451 
00452 /*!
00453  * \brief A wrapper for calloc() for use in cache pools
00454  *
00455  * ast_calloc_cache() is a wrapper for calloc() that will generate an Asterisk log
00456  * message in the case that the allocation fails. When memory debugging is in use,
00457  * the memory allocated by this function will be marked as 'cache' so it can be
00458  * distinguished from normal memory allocations.
00459  *
00460  * The arguments and return value are the same as calloc()
00461  */
00462 #define ast_calloc_cache(num, len) \
00463    _ast_calloc((num), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
00464 
00465 /*!
00466  * \brief A wrapper for realloc()
00467  *
00468  * ast_realloc() is a wrapper for realloc() that will generate an Asterisk log
00469  * message in the case that the allocation fails.
00470  *
00471  * The arguments and return value are the same as realloc()
00472  */
00473 #define ast_realloc(p, len) \
00474    _ast_realloc((p), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
00475 
00476 AST_INLINE_API(
00477 void * attribute_malloc _ast_realloc(void *p, size_t len, const char *file, int lineno, const char *func),
00478 {
00479    void *newp;
00480 
00481    if (!(newp = realloc(p, len)))
00482       MALLOC_FAILURE_MSG;
00483 
00484    return newp;
00485 }
00486 )
00487 
00488 /*!
00489  * \brief A wrapper for strdup()
00490  *
00491  * ast_strdup() is a wrapper for strdup() that will generate an Asterisk log
00492  * message in the case that the allocation fails.
00493  *
00494  * ast_strdup(), unlike strdup(), can safely accept a NULL argument. If a NULL
00495  * argument is provided, ast_strdup will return NULL without generating any
00496  * kind of error log message.
00497  *
00498  * The argument and return value are the same as strdup()
00499  */
00500 #define ast_strdup(str) \
00501    _ast_strdup((str), __FILE__, __LINE__, __PRETTY_FUNCTION__)
00502 
00503 AST_INLINE_API(
00504 char * attribute_malloc _ast_strdup(const char *str, const char *file, int lineno, const char *func),
00505 {
00506    char *newstr = NULL;
00507 
00508    if (str) {
00509       if (!(newstr = strdup(str)))
00510          MALLOC_FAILURE_MSG;
00511    }
00512 
00513    return newstr;
00514 }
00515 )
00516 
00517 /*!
00518  * \brief A wrapper for strndup()
00519  *
00520  * ast_strndup() is a wrapper for strndup() that will generate an Asterisk log
00521  * message in the case that the allocation fails.
00522  *
00523  * ast_strndup(), unlike strndup(), can safely accept a NULL argument for the
00524  * string to duplicate. If a NULL argument is provided, ast_strdup will return  
00525  * NULL without generating any kind of error log message.
00526  *
00527  * The arguments and return value are the same as strndup()
00528  */
00529 #define ast_strndup(str, len) \
00530    _ast_strndup((str), (len), __FILE__, __LINE__, __PRETTY_FUNCTION__)
00531 
00532 AST_INLINE_API(
00533 char * attribute_malloc _ast_strndup(const char *str, size_t len, const char *file, int lineno, const char *func),
00534 {
00535    char *newstr = NULL;
00536 
00537    if (str) {
00538       if (!(newstr = strndup(str, len)))
00539          MALLOC_FAILURE_MSG;
00540    }
00541 
00542    return newstr;
00543 }
00544 )
00545 
00546 /*!
00547  * \brief A wrapper for asprintf()
00548  *
00549  * ast_asprintf() is a wrapper for asprintf() that will generate an Asterisk log
00550  * message in the case that the allocation fails.
00551  *
00552  * The arguments and return value are the same as asprintf()
00553  */
00554 #define ast_asprintf(ret, fmt, ...) \
00555    _ast_asprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, fmt, __VA_ARGS__)
00556 
00557 int __attribute__((format (printf, 5, 6)))
00558    _ast_asprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, ...);
00559 
00560 /*!
00561  * \brief A wrapper for vasprintf()
00562  *
00563  * ast_vasprintf() is a wrapper for vasprintf() that will generate an Asterisk log
00564  * message in the case that the allocation fails.
00565  *
00566  * The arguments and return value are the same as vasprintf()
00567  */
00568 #define ast_vasprintf(ret, fmt, ap) \
00569    _ast_vasprintf((ret), __FILE__, __LINE__, __PRETTY_FUNCTION__, (fmt), (ap))
00570 
00571 AST_INLINE_API(
00572 __attribute__((format (printf, 5, 0)))
00573 int _ast_vasprintf(char **ret, const char *file, int lineno, const char *func, const char *fmt, va_list ap),
00574 {
00575    int res;
00576 
00577    if ((res = vasprintf(ret, fmt, ap)) == -1)
00578       MALLOC_FAILURE_MSG;
00579 
00580    return res;
00581 }
00582 )
00583 
00584 #else
00585 
00586 /* If astmm is in use, let it handle these.  Otherwise, it will report that
00587    all allocations are coming from this header file */
00588 
00589 #define ast_malloc(a)      malloc(a)
00590 #define ast_calloc(a,b)    calloc(a,b)
00591 #define ast_realloc(a,b)   realloc(a,b)
00592 #define ast_strdup(a)      strdup(a)
00593 #define ast_strndup(a,b)   strndup(a,b)
00594 #define ast_asprintf(a,b,...) asprintf(a,b,__VA_ARGS__)
00595 #define ast_vasprintf(a,b,c)  vasprintf(a,b,c)
00596 
00597 #endif /* AST_DEBUG_MALLOC */
00598 
00599 #if !defined(ast_strdupa) && defined(__GNUC__)
00600 /*!
00601   \brief duplicate a string in memory from the stack
00602   \param s The string to duplicate
00603 
00604   This macro will duplicate the given string.  It returns a pointer to the stack
00605   allocatted memory for the new string.
00606 */
00607 #define ast_strdupa(s)                                                    \
00608    (__extension__                                                    \
00609    ({                                                                \
00610       const char *__old = (s);                                  \
00611       size_t __len = strlen(__old) + 1;                         \
00612       char *__new = __builtin_alloca(__len);                    \
00613       memcpy (__new, __old, __len);                             \
00614       __new;                                                    \
00615    }))
00616 #endif
00617 
00618 /*!
00619   \brief Disable PMTU discovery on a socket
00620   \param sock The socket to manipulate
00621   \return Nothing
00622 
00623   On Linux, UDP sockets default to sending packets with the Dont Fragment (DF)
00624   bit set. This is supposedly done to allow the application to do PMTU
00625   discovery, but Asterisk does not do this.
00626 
00627   Because of this, UDP packets sent by Asterisk that are larger than the MTU
00628   of any hop in the path will be lost. This function can be called on a socket
00629   to ensure that the DF bit will not be set.
00630  */
00631 void ast_enable_packet_fragmentation(int sock);
00632 
00633 /*!
00634   \brief Recursively create directory path
00635   \param path The directory path to create
00636   \param mode The permissions with which to try to create the directory
00637   \return 0 on success or an error code otherwise
00638 
00639   Creates a directory path, creating parent directories as needed.
00640  */
00641 int ast_mkdir(const char *path, int mode);
00642 
00643 #define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
00644 
00645 #ifdef AST_DEVMODE
00646 #define ast_assert(a) _ast_assert(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00647 static void force_inline _ast_assert(int condition, const char *condition_str, 
00648    const char *file, int line, const char *function)
00649 {
00650    if (__builtin_expect(!condition, 1)) {
00651       /* Attempt to put it into the logger, but hope that at least someone saw the
00652        * message on stderr ... */
00653       ast_log(__LOG_ERROR, file, line, function, "FRACK!, Failed assertion %s (%d)\n",
00654          condition_str, condition);
00655       fprintf(stderr, "FRACK!, Failed assertion %s (%d) at line %d in %s of %s\n",
00656          condition_str, condition, line, function, file);
00657       /* Give the logger a chance to get the message out, just in case we abort(), or
00658        * Asterisk crashes due to whatever problem just happened after we exit ast_assert(). */
00659       usleep(1);
00660 #ifdef DO_CRASH
00661       abort();
00662       /* Just in case abort() doesn't work or something else super silly,
00663        * and for Qwell's amusement. */
00664       *((int*)0)=0;
00665 #endif
00666    }
00667 }
00668 #else
00669 #define ast_assert(a)
00670 #endif
00671 
00672 #include "asterisk/strings.h"
00673 
00674 /*!
00675  * \brief An Entity ID is essentially a MAC address, brief and unique 
00676  */
00677 struct ast_eid {
00678    unsigned char eid[6];
00679 } __attribute__ ((__packed__));
00680 
00681 /*!
00682  * \brief Global EID
00683  *
00684  * This is set in asterisk.conf, or determined automatically by taking the mac
00685  * address of an Ethernet interface on the system.
00686  */
00687 extern struct ast_eid g_eid;
00688 
00689 /*!
00690  * \brief Fill in an ast_eid with the default eid of this machine
00691  */
00692 void ast_set_default_eid(struct ast_eid *eid);
00693 
00694 /*!
00695  * /brief Convert an EID to a string
00696  */
00697 char *ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid);
00698 
00699 /*!
00700  * \brief Convert a string into an EID
00701  *
00702  * This function expects an EID in the format:
00703  *    00:11:22:33:44:55
00704  *
00705  * \return 0 success, non-zero failure
00706  */
00707 int ast_str_to_eid(struct ast_eid *eid, const char *s);
00708 
00709 /*!
00710  * \brief Compare two EIDs
00711  *
00712  * \return 0 if the two are the same, non-zero otherwise
00713  */
00714 int ast_eid_cmp(const struct ast_eid *eid1, const struct ast_eid *eid2);
00715 
00716 #endif /* _ASTERISK_UTILS_H */

Generated on Sat Nov 1 06:26:11 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1