/* $Id$ */ /* * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) * Copyright (C) 2003-2008 Benny Prijono * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __PJ_ERRNO_H__ #define __PJ_ERRNO_H__ /** * @file errno.h * @brief PJLIB Error Subsystem */ #include #include #include PJ_BEGIN_DECL /** * @defgroup pj_errno Error Subsystem * @{ * * The PJLIB Error Subsystem is a framework to unify all error codes * produced by all components into a single error space, and provide * uniform set of APIs to access them. With this framework, any error * codes are encoded as pj_status_t value. The framework is extensible, * application may register new error spaces to be recognized by * the framework. * * @section pj_errno_retval Return Values * * All functions that returns @a pj_status_t returns @a PJ_SUCCESS if the * operation was completed successfully, or non-zero value to indicate * error. If the error came from operating system, then the native error * code is translated/folded into PJLIB's error namespace by using * #PJ_STATUS_FROM_OS() macro. The function will do this automatically * before returning the error to caller. * * @section err_services Retrieving and Displaying Error Messages * * The framework provides the following APIs to retrieve and/or display * error messages: * * - #pj_strerror(): this is the base API to retrieve error string * description for the specified pj_status_t error code. * * - #PJ_PERROR() macro: use this macro similar to PJ_LOG to format * an error message and display them to the log * * - #pj_perror(): this function is similar to PJ_PERROR() but unlike * #PJ_PERROR(), this function will always be included in the * link process. Due to this reason, prefer to use #PJ_PERROR() * if the application is concerned about the executable size. * * Application MUST NOT pass native error codes (such as error code from * functions like GetLastError() or errno) to PJLIB functions expecting * @a pj_status_t. * * @section err_extending Extending the Error Space * * Application may register new error space to be recognized by the * framework by using #pj_register_strerror(). Use the range started * from PJ_ERRNO_START_USER to avoid conflict with existing error * spaces. * */ /** * Guidelines on error message length. */ #define PJ_ERR_MSG_SIZE 80 /** * Buffer for title string of #PJ_PERROR(). */ #ifndef PJ_PERROR_TITLE_BUF_SIZE # define PJ_PERROR_TITLE_BUF_SIZE 120 #endif /** * Get the last platform error/status, folded into pj_status_t. * @return OS dependent error code, folded into pj_status_t. * @remark This function gets errno, or calls GetLastError() function and * convert the code into pj_status_t with PJ_STATUS_FROM_OS. Do * not call this for socket functions! * @see pj_get_netos_error() */ PJ_DECL(pj_status_t) pj_get_os_error(void); /** * Set last error. * @param code pj_status_t */ PJ_DECL(void) pj_set_os_error(pj_status_t code); /** * Get the last error from socket operations. * @return Last socket error, folded into pj_status_t. */ PJ_DECL(pj_status_t) pj_get_netos_error(void); /** * Set error code. * @param code pj_status_t. */ PJ_DECL(void) pj_set_netos_error(pj_status_t code); /** * Get the error message for the specified error code. The message * string will be NULL terminated. * * @param statcode The error code. * @param buf Buffer to hold the error message string. * @param bufsize Size of the buffer. * * @return The error message as NULL terminated string, * wrapped with pj_str_t. */ PJ_DECL(pj_str_t) pj_strerror( pj_status_t statcode, char *buf, pj_size_t bufsize); /** * A utility macro to print error message pertaining to the specified error * code to the log. This macro will construct the error message title * according to the 'title_fmt' argument, and add the error string pertaining * to the error code after the title string. A colon (':') will be added * automatically between the title and the error string. * * This function is similar to pj_perror() function, but has the advantage * that the function call can be omitted from the link process if the * log level argument is below PJ_LOG_MAX_LEVEL threshold. * * Note that the title string constructed from the title_fmt will be built on * a string buffer which size is PJ_PERROR_TITLE_BUF_SIZE, which normally is * allocated from the stack. By default this buffer size is small (around * 120 characters). Application MUST ensure that the constructed title string * will not exceed this limit, since not all platforms support truncating * the string. * * @see pj_perror() * * @param level The logging verbosity level, valid values are 0-6. Lower * number indicates higher importance, with level zero * indicates fatal error. Only numeral argument is * permitted (e.g. not variable). * @param arg Enclosed 'printf' like arguments, with the following * arguments: * - the sender (NULL terminated string), * - the error code (pj_status_t) * - the format string (title_fmt), and * - optional variable number of arguments suitable for the * format string. * * Sample: * \verbatim PJ_PERROR(2, (__FILE__, PJ_EBUSY, "Error making %s", "coffee")); \endverbatim * @hideinitializer */ #define PJ_PERROR(level,arg) do { \ pj_perror_wrapper_##level(arg); \ } while (0) /** * A utility function to print error message pertaining to the specified error * code to the log. This function will construct the error message title * according to the 'title_fmt' argument, and add the error string pertaining * to the error code after the title string. A colon (':') will be added * automatically between the title and the error string. * * Unlike the PJ_PERROR() macro, this function takes the \a log_level argument * as a normal argument, unlike in PJ_PERROR() where a numeral value must be * given. However this function will always be linked to the executable, * unlike PJ_PERROR() which can be omitted when the level is below the * PJ_LOG_MAX_LEVEL. * * Note that the title string constructed from the title_fmt will be built on * a string buffer which size is PJ_PERROR_TITLE_BUF_SIZE, which normally is * allocated from the stack. By default this buffer size is small (around * 120 characters). Application MUST ensure that the constructed title string * will not exceed this limit, since not all platforms support truncating * the string. * * @see PJ_PERROR() */ PJ_DECL(void) pj_perror(int log_level, const char *sender, pj_status_t status, const char *title_fmt, ...); /** * Type of callback to be specified in #pj_register_strerror() * * @param e The error code to lookup. * @param msg Buffer to store the error message. * @param max Length of the buffer. * * @return The error string. */ typedef pj_str_t (*pj_error_callback)(pj_status_t e, char *msg, pj_size_t max); /** * Register strerror message handler for the specified error space. * Application can register its own handler to supply the error message * for the specified error code range. This handler will be called * by #pj_strerror(). * * @param start_code The starting error code where the handler should * be called to retrieve the error message. * @param err_space The size of error space. The error code range then * will fall in start_code to start_code+err_space-1 * range. * @param f The handler to be called when #pj_strerror() is * supplied with error code that falls into this range. * * @return PJ_SUCCESS or the specified error code. The * registration may fail when the error space has been * occupied by other handler, or when there are too many * handlers registered to PJLIB. */ PJ_DECL(pj_status_t) pj_register_strerror(pj_status_t start_code, pj_status_t err_space, pj_error_callback f); /** * @hideinitializer * Return platform os error code folded into pj_status_t code. This is * the macro that is used throughout the library for all PJLIB's functions * that returns error from operating system. Application may override * this macro to reduce size (e.g. by defining it to always return * #PJ_EUNKNOWN). * * Note: * This macro MUST return non-zero value regardless whether zero is * passed as the argument. The reason is to protect logic error when * the operating system doesn't report error codes properly. * * @param os_code Platform OS error code. This value may be evaluated * more than once. * @return The platform os error code folded into pj_status_t. */ #ifndef PJ_RETURN_OS_ERROR # define PJ_RETURN_OS_ERROR(os_code) (os_code ? \ PJ_STATUS_FROM_OS(os_code) : -1) #endif /** * @hideinitializer * Fold a platform specific error into an pj_status_t code. * * @param e The platform os error code. * @return pj_status_t * @warning Macro implementation; the syserr argument may be evaluated * multiple times. */ #if PJ_NATIVE_ERR_POSITIVE # define PJ_STATUS_FROM_OS(e) (e == 0 ? PJ_SUCCESS : e + PJ_ERRNO_START_SYS) #else # define PJ_STATUS_FROM_OS(e) (e == 0 ? PJ_SUCCESS : PJ_ERRNO_START_SYS - e) #endif /** * @hideinitializer * Fold an pj_status_t code back to the native platform defined error. * * @param e The pj_status_t folded platform os error code. * @return pj_os_err_type * @warning macro implementation; the statcode argument may be evaluated * multiple times. If the statcode was not created by * pj_get_os_error or PJ_STATUS_FROM_OS, the results are undefined. */ #if PJ_NATIVE_ERR_POSITIVE # define PJ_STATUS_TO_OS(e) (e == 0 ? PJ_SUCCESS : e - PJ_ERRNO_START_SYS) #else # define PJ_STATUS_TO_OS(e) (e == 0 ? PJ_SUCCESS : PJ_ERRNO_START_SYS - e) #endif /** * @defgroup pj_errnum PJLIB's Own Error Codes * @ingroup pj_errno * @{ */ /** * Use this macro to generate error message text for your error code, * so that they look uniformly as the rest of the libraries. * * @param code The error code * @param msg The error test. */ #ifndef PJ_BUILD_ERR # define PJ_BUILD_ERR(code,msg) { code, msg " (" #code ")" } #endif /** * @hideinitializer * Unknown error has been reported. */ #define PJ_EUNKNOWN (PJ_ERRNO_START_STATUS + 1) /* 70001 */ /** * @hideinitializer * The operation is pending and will be completed later. */ #define PJ_EPENDING (PJ_ERRNO_START_STATUS + 2) /* 70002 */ /** * @hideinitializer * Too many connecting sockets. */ #define PJ_ETOOMANYCONN (PJ_ERRNO_START_STATUS + 3) /* 70003 */ /** * @hideinitializer * Invalid argument. */ #define PJ_EINVAL (PJ_ERRNO_START_STATUS + 4) /* 70004 */ /** * @hideinitializer * Name too long (eg. hostname too long). */ #define PJ_ENAMETOOLONG (PJ_ERRNO_START_STATUS + 5) /* 70005 */ /** * @hideinitializer * Not found. */ #define PJ_ENOTFOUND (PJ_ERRNO_START_STATUS + 6) /* 70006 */ /** * @hideinitializer * Not enough memory. */ #define PJ_ENOMEM (PJ_ERRNO_START_STATUS + 7) /* 70007 */ /** * @hideinitializer * Bug detected! */ #define PJ_EBUG (PJ_ERRNO_START_STATUS + 8) /* 70008 */ /** * @hideinitializer * Operation timed out. */ #define PJ_ETIMEDOUT (PJ_ERRNO_START_STATUS + 9) /* 70009 */ /** * @hideinitializer * Too many objects. */ #define PJ_ETOOMANY (PJ_ERRNO_START_STATUS + 10)/* 70010 */ /** * @hideinitializer * Object is busy. */ #define PJ_EBUSY (PJ_ERRNO_START_STATUS + 11)/* 70011 */ /** * @hideinitializer * The specified option is not supported. */ #define PJ_ENOTSUP (PJ_ERRNO_START_STATUS + 12)/* 70012 */ /** * @hideinitializer * Invalid operation. */ #define PJ_EINVALIDOP (PJ_ERRNO_START_STATUS + 13)/* 70013 */ /** * @hideinitializer * Operation is cancelled. */ #define PJ_ECANCELLED (PJ_ERRNO_START_STATUS + 14)/* 70014 */ /** * @hideinitializer * Object already exists. */ #define PJ_EEXISTS (PJ_ERRNO_START_STATUS + 15)/* 70015 */ /** * @hideinitializer * End of file. */ #define PJ_EEOF (PJ_ERRNO_START_STATUS + 16)/* 70016 */ /** * @hideinitializer * Size is too big. */ #define PJ_ETOOBIG (PJ_ERRNO_START_STATUS + 17)/* 70017 */ /** * @hideinitializer * Error in gethostbyname(). This is a generic error returned when * gethostbyname() has returned an error. */ #define PJ_ERESOLVE (PJ_ERRNO_START_STATUS + 18)/* 70018 */ /** * @hideinitializer * Size is too small. */ #define PJ_ETOOSMALL (PJ_ERRNO_START_STATUS + 19)/* 70019 */ /** * @hideinitializer * Ignored */ #define PJ_EIGNORED (PJ_ERRNO_START_STATUS + 20)/* 70020 */ /** * @hideinitializer * IPv6 is not supported */ #define PJ_EIPV6NOTSUP (PJ_ERRNO_START_STATUS + 21)/* 70021 */ /** * @hideinitializer * Unsupported address family */ #define PJ_EAFNOTSUP (PJ_ERRNO_START_STATUS + 22)/* 70022 */ /** * @hideinitializer * Object no longer exists */ #define PJ_EGONE (PJ_ERRNO_START_STATUS + 23)/* 70023 */ /** * @hideinitializer * Socket is stopped */ #define PJ_ESOCKETSTOP (PJ_ERRNO_START_STATUS + 24)/* 70024 */ /** @} */ /* pj_errnum */ /** @} */ /* pj_errno */ /** * PJ_ERRNO_START is where PJLIB specific error values start. */ #define PJ_ERRNO_START 20000 /** * PJ_ERRNO_SPACE_SIZE is the maximum number of errors in one of * the error/status range below. */ #define PJ_ERRNO_SPACE_SIZE 50000 /** * PJ_ERRNO_START_STATUS is where PJLIB specific status codes start. * Effectively the error in this class would be 70000 - 119000. */ #define PJ_ERRNO_START_STATUS (PJ_ERRNO_START + PJ_ERRNO_SPACE_SIZE) /** * PJ_ERRNO_START_SYS converts platform specific error codes into * pj_status_t values. * Effectively the error in this class would be 120000 - 169000. */ #define PJ_ERRNO_START_SYS (PJ_ERRNO_START_STATUS + PJ_ERRNO_SPACE_SIZE) /** * PJ_ERRNO_START_USER are reserved for applications that use error * codes along with PJLIB codes. * Effectively the error in this class would be 170000 - 219000. */ #define PJ_ERRNO_START_USER (PJ_ERRNO_START_SYS + PJ_ERRNO_SPACE_SIZE) /* * Below are list of error spaces that have been taken so far: * - PJSIP_ERRNO_START (PJ_ERRNO_START_USER) * - PJMEDIA_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE) * - PJSIP_SIMPLE_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*2) * - PJLIB_UTIL_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*3) * - PJNATH_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*4) * - PJMEDIA_AUDIODEV_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*5) * - PJ_SSL_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*6) * - PJMEDIA_VIDEODEV_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE*7) */ /* Internal */ void pj_errno_clear_handlers(void); /****** Internal for PJ_PERROR *******/ /** * @def pj_perror_wrapper_1(arg) * Internal function to write log with verbosity 1. Will evaluate to * empty expression if PJ_LOG_MAX_LEVEL is below 1. * @param arg Log expression. */ #if PJ_LOG_MAX_LEVEL >= 1 #define pj_perror_wrapper_1(arg) pj_perror_1 arg /** Internal function. */ PJ_DECL(void) pj_perror_1(const char *sender, pj_status_t status, const char *title_fmt, ...); #else #define pj_perror_wrapper_1(arg) #endif /** * @def pj_perror_wrapper_2(arg) * Internal function to write log with verbosity 2. Will evaluate to * empty expression if PJ_LOG_MAX_LEVEL is below 2. * @param arg Log expression. */ #if PJ_LOG_MAX_LEVEL >= 2 #define pj_perror_wrapper_2(arg) pj_perror_2 arg /** Internal function. */ PJ_DECL(void) pj_perror_2(const char *sender, pj_status_t status, const char *title_fmt, ...); #else #define pj_perror_wrapper_2(arg) #endif /** * @def pj_perror_wrapper_3(arg) * Internal function to write log with verbosity 3. Will evaluate to * empty expression if PJ_LOG_MAX_LEVEL is below 3. * @param arg Log expression. */ #if PJ_LOG_MAX_LEVEL >= 3 #define pj_perror_wrapper_3(arg) pj_perror_3 arg /** Internal function. */ PJ_DECL(void) pj_perror_3(const char *sender, pj_status_t status, const char *title_fmt, ...); #else #define pj_perror_wrapper_3(arg) #endif /** * @def pj_perror_wrapper_4(arg) * Internal function to write log with verbosity 4. Will evaluate to * empty expression if PJ_LOG_MAX_LEVEL is below 4. * @param arg Log expression. */ #if PJ_LOG_MAX_LEVEL >= 4 #define pj_perror_wrapper_4(arg) pj_perror_4 arg /** Internal function. */ PJ_DECL(void) pj_perror_4(const char *sender, pj_status_t status, const char *title_fmt, ...); #else #define pj_perror_wrapper_4(arg) #endif /** * @def pj_perror_wrapper_5(arg) * Internal function to write log with verbosity 5. Will evaluate to * empty expression if PJ_LOG_MAX_LEVEL is below 5. * @param arg Log expression. */ #if PJ_LOG_MAX_LEVEL >= 5 #define pj_perror_wrapper_5(arg) pj_perror_5 arg /** Internal function. */ PJ_DECL(void) pj_perror_5(const char *sender, pj_status_t status, const char *title_fmt, ...); #else #define pj_perror_wrapper_5(arg) #endif /** * @def pj_perror_wrapper_6(arg) * Internal function to write log with verbosity 6. Will evaluate to * empty expression if PJ_LOG_MAX_LEVEL is below 6. * @param arg Log expression. */ #if PJ_LOG_MAX_LEVEL >= 6 #define pj_perror_wrapper_6(arg) pj_perror_6 arg /** Internal function. */ PJ_DECL(void) pj_perror_6(const char *sender, pj_status_t status, const char *title_fmt, ...); #else #define pj_perror_wrapper_6(arg) #endif PJ_END_DECL #endif /* __PJ_ERRNO_H__ */