# HG changeset patch # User Sebastien Decugis # Date 1367580056 -28800 # Node ID 7d7266115a345da4a2646e1039c85387ce62249f # Parent 6b7966ea27fbff1cd676de3f2e9ef75af25bf233 Cleaning of the traces in progress diff -r 6b7966ea27fb -r 7d7266115a34 include/freeDiameter/libfdcore.h --- a/include/freeDiameter/libfdcore.h Fri May 03 15:33:57 2013 +0800 +++ b/include/freeDiameter/libfdcore.h Fri May 03 19:20:56 2013 +0800 @@ -57,23 +57,36 @@ /* Check the return value of a GNUTLS function, log and propagate */ -#define CHECK_GNUTLS_DO( __call__, __fallback__ ) { \ - int __ret__; \ - TRACE_DEBUG(GNUTLS_DBG_LEVEL, "GNUTLS call: %s", #__call__ ); \ - __ret__ = (__call__); \ - if (__ret__ < 0) { \ - TRACE_DEBUG(INFO, "Error in '%s':\t%s", #__call__ , gnutls_strerror(__ret__)); \ - __fallback__; \ - } \ +#define CHECK_GNUTLS_GEN( faillevel, __call__, __fallback__ ) { \ + CHECK_PRELUDE(__call__); \ + if (__ret__ < 0) { \ + __ret__ = errno; \ + LOG(faillevel, "ERROR: in '%s' :\t%s", #__call__ , gnutls_strerror(__ret__)); \ + __fallback__; \ + } \ } -/* For GNUTLS routines that do not return a value */ +/* we use this macro to help debugging gnutls usage issues -- just change the content to display what you need */ #define GNUTLS_TRACE( __call__) { \ - TRACE_DEBUG(GNUTLS_DBG_LEVEL, "GNUTLS call: " #__call__ ); \ + TRACE_CALL("Check: %s", #__call__ ); \ (__call__); \ } +#ifndef EXCLUDE_DEPRECATED +/* Macro for transition, replace with CHECK_GNUTLS_GEN */ +#define CHECK_GNUTLS_DO( __call__, __fallback__ ) { \ + CHECK_PRELUDE(__call__); \ + if (__ret__ < 0) { \ + __ret__ = errno; \ + TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , gnutls_strerror(__ret__)); \ + __fallback__; \ + } \ +} + +#endif /* EXCLUDE_DEPRECATED */ + + /*============================================================*/ /* INITIALIZATION */ /*============================================================*/ @@ -777,12 +790,6 @@ /* Daemon's codespace: 1000->1999 (1500->1999 defined in fdcore-internal.h) */ enum { FDEV_TERMINATE = 1000 /* request to terminate */ - ,FDEV_DUMP_DICT /* Dump the content of the dictionary */ - ,FDEV_DUMP_EXT /* Dump state of extensions */ - ,FDEV_DUMP_SERV /* Dump the server socket status */ - ,FDEV_DUMP_QUEUES /* Dump the message queues */ - ,FDEV_DUMP_CONFIG /* Dump the configuration */ - ,FDEV_DUMP_PEERS /* Dump the list of peers */ ,FDEV_TRIGGER /* Trigger available for extensions. size is sizeof(int), data is int * */ }; @@ -794,8 +801,15 @@ /* for extensions */ int fd_event_trig_regcb(int trigger_val, const char * module, void (*cb)(void)); -void fd_event_trig_dump(); + +DECLARE_FD_DUMP_PROTOTYPE(fd_event_trig_dump); +/* The "old" FD_EV_DUMP_* events are replaced with direct calls to the following dump functions */ +DECLARE_FD_DUMP_PROTOTYPE(fd_conf_dump); +DECLARE_FD_DUMP_PROTOTYPE(fd_ext_dump); +DECLARE_FD_DUMP_PROTOTYPE(fd_peer_dump_list, int details); +DECLARE_FD_DUMP_PROTOTYPE(fd_peer_dump, struct peer_hdr * p, int details); +DECLARE_FD_DUMP_PROTOTYPE(fd_servers_dump); /*============================================================*/ /* ENDPOINTS */ @@ -831,8 +845,8 @@ int fd_ep_filter_family( struct fd_list * list, int af ); int fd_ep_filter_list( struct fd_list * list, struct fd_list * exclude_list ); int fd_ep_clearflags( struct fd_list * list, uint32_t flags ); -void fd_ep_dump_one( char * prefix, struct fd_endpoint * ep ); -void fd_ep_dump( int indent, struct fd_list * eps ); +DECLARE_FD_DUMP_PROTOTYPE(fd_ep_dump_one, struct fd_endpoint * ep ); +DECLARE_FD_DUMP_PROTOTYPE(fd_ep_dump, int indent, struct fd_list * eps ); /*============================================================*/ diff -r 6b7966ea27fb -r 7d7266115a34 include/freeDiameter/libfdproto.h --- a/include/freeDiameter/libfdproto.h Fri May 03 15:33:57 2013 +0800 +++ b/include/freeDiameter/libfdproto.h Fri May 03 19:20:56 2013 +0800 @@ -132,12 +132,9 @@ /* * FUNCTION: fd_log - * MACRO: fd_log_debug - * MACRO: fd_log_notice - * MACRO: fd_log_error * * PARAMETERS: - * loglevel : Integer, how important the message is + * loglevel : Integer, how important the message is. Valid values are macros FD_LOG_* * format : Same format string as in the printf function * ... : Same list as printf * @@ -150,11 +147,7 @@ * None. */ void fd_log ( int, const char *, ... ) _ATTRIBUTE_PRINTFLIKE_(2,3); -#define fd_log_debug(format,args...) fd_log(FD_LOG_DEBUG, format, ## args) -#define fd_log_notice(format,args...) fd_log(FD_LOG_NOTICE, format, ## args) -#define fd_log_error(format,args...) fd_log(FD_LOG_ERROR, format, ## args) - -void fd_log_debug_fstr( FILE *, const char *, ... ); +void fd_log_va( int, const char *, va_list args ); /* these are internal objects of the debug facility, might be useful to control the behavior from outside */ @@ -228,6 +221,25 @@ int fd_log_handler_unregister ( void ); +/* Helper function for the *dump functions that add into a buffer */ +char * fd_dump_extend(char ** buf, size_t *len, size_t *offset, const char * format, ... ) _ATTRIBUTE_PRINTFLIKE_(4,5); + +/* All dump functions follow the same prototype: + * PARAMETERS: + * buf : *buf can be NULL on entry, it will be malloc'd. Otherwise it can be realloc'd if needed. + * len : the current size of the buffer (in/out) + * offset: (optional) if provided, starts writing dump at offset in the buffer, and updated upon exit. if NULL, starts at offset O. + * + * RETURN VALUE: + * *buf upon success, NULL upon failure. + * After the buffer has been used, it should be freed. + */ +#define DECLARE_FD_DUMP_PROTOTYPE( function_name, args... ) \ + char * function_name(char ** buf, size_t *len, size_t *offset, ##args) + +#define FD_DUMP_STD_PARAMS buf, len, offset + + /*============================================================*/ /* DEBUG MACROS */ /*============================================================*/ @@ -236,20 +248,14 @@ #define ASSERT(x) assert(x) #endif /* ASSERT */ -/* log levels definitions */ -#define FD_LOG_DEBUG 0 /* Verbose information for developers use */ -#define FD_LOG_NOTICE 3 /* Normal execution states worth noting */ -#define FD_LOG_ERROR 5 /* Error conditions, both recoverable or not */ - -/* print level definitions */ -#define NONE 0 /* Display no debug message */ -#define INFO 1 /* Display errors only */ -#define FULL 2 /* Display additional information to follow code execution */ -#define ANNOYING 4 /* Very verbose, for example in loops */ -#define FCTS 6 /* Display entry parameters of most functions */ -#define CALL 9 /* Display calls to most functions (with CHECK macros) */ - -/* A global level, changed by configuration or cmd line for example. Default is INFO (in libfdproto/log.c). */ +/* log levels definitions, that are passed to the logger */ +#define FD_LOG_ANNOYING 0 /* very verbose loops and such "overkill" traces. Only active when the framework is compiled in DEBUG mode. */ +#define FD_LOG_DEBUG 1 /* Get a detailed sense of what is going on in the framework. Use this level for normal debug */ +#define FD_LOG_NOTICE 3 /* Normal execution states worth noting */ +#define FD_LOG_ERROR 5 /* Recoverable or expected error conditions */ +#define FD_LOG_FATAL 6 /* Unrecoverable error, e.g. malloc fail, etc. that requires the framework to shutdown */ + +/* The level used by the default logger, can be changed by command-line arguments. Ignored for other loggers. */ extern int fd_g_debug_lvl; /* Some portability code to get nice function name in __PRETTY_FUNCTION__ */ @@ -264,121 +270,321 @@ #define __PRETTY_FUNCTION__ __func__ #endif /* __PRETTY_FUNCTION__ */ -#ifdef DEBUG /* A version of __FILE__ without the full path */ static char * file_bname = NULL; static char * file_bname_init(char * full) { file_bname = basename(full); return file_bname; } #define __STRIPPED_FILE__ (file_bname ?: file_bname_init((char *)__FILE__)) -/* Boolean for tracing at a certain level */ -#define TRACE_BOOL(_level_) ( ((_level_) <= fd_g_debug_lvl) \ - || (fd_debug_one_function && !strcmp(fd_debug_one_function, __PRETTY_FUNCTION__)) \ - || (fd_debug_one_file && !strcmp(fd_debug_one_file, __STRIPPED_FILE__) ) ) -#else /* DEBUG */ -#define TRACE_BOOL(_level_) ((_level_) <= fd_g_debug_lvl) -#define __STRIPPED_FILE__ __FILE__ -#endif /* DEBUG */ - - -#define STD_TRACE_FMT_STRING "pid:%s in %s@%s:%d: " -/************* - The general debug macro, each call results in two lines of debug messages (change the macro for more compact output) - *************/ + + +/* In DEBUG mode, we add meta-information along each trace. This makes multi-threading problems easier to debug. */ #ifdef DEBUG -/* In DEBUG mode, we add (a lot of) meta-information along each trace. This makes multi-threading problems easier to debug. */ -#define TRACE(printlevel,level,format,args... ) { \ - if ( TRACE_BOOL(level) ) { \ - const char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed"); \ - fd_log((printlevel), STD_TRACE_FMT_STRING format, \ - __thn, __PRETTY_FUNCTION__, __STRIPPED_FILE__, __LINE__, ## args); \ - } \ -} +# define STD_TRACE_FMT_STRING "pid:%s in %s@%s:%d: " +# define STD_TRACE_FMT_ARGS , ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed"), __PRETTY_FUNCTION__, __STRIPPED_FILE__, __LINE__ #else /* DEBUG */ -/* Do not print thread, function, ... only the message itself in this case */ -#define TRACE(printlevel,level,format,args... ) { \ - if ( TRACE_BOOL(level) ) { \ - fd_log((printlevel), format, ## args); \ - } \ -} +# define STD_TRACE_FMT_STRING "" +# define STD_TRACE_FMT_ARGS #endif /* DEBUG */ -/* Report debug information */ -#define TRACE_DEBUG(level,format,args... ) \ - TRACE(FD_LOG_DEBUG,(level),format,##args) +/************************* + The general debug macro + *************************/ +#define LOG(printlevel,format,args... ) \ + fd_log((printlevel), STD_TRACE_FMT_STRING format STD_TRACE_FMT_ARGS, ## args) + +/* + * Use the following macros in the code to get traces with location & pid in debug mode: + */ +#ifdef DEBUG +# define LOG_A(format,args... ) \ + LOG(FD_LOG_ANNOYING,format,##args) +#else /* DEBUG */ +# define LOG_A(format,args... ) /* not defined in release */ +#endif /* DEBUG */ + +/* Debug information useful to follow in detail what is going on */ +#define LOG_D(format,args... ) \ + LOG(FD_LOG_DEBUG, format, ##args) /* Report a normal message that is useful for normal admin monitoring */ -#define TRACE_NOTICE(format,args... ) \ - TRACE(FD_LOG_NOTICE,INFO,format,##args) +#define LOG_N(format,args... ) \ + LOG(FD_LOG_NOTICE, format,##args) /* Report an error */ -#define TRACE_ERROR(format,args... ) \ - TRACE(FD_LOG_ERROR, NONE, format, ##args) - -/* -TRACE_NOTICE(...) and fd_log_notice(...) are equivalent when the code is not compiled in DEBUG mode, -but there is more contextual information when compiled in DEBUG with the TRACE_NOTICE macro, -hence it is recommended to use this one except for formatted output (e.g. fd_*_dump function) - -resp. TRACE_DEBUG and TRACE_ERROR. -*/ +#define LOG_E(format,args... ) \ + LOG(FD_LOG_ERROR, format, ##args) + +/* Report a fatal error */ +#define LOG_F(format,args... ) \ + LOG(FD_LOG_FATAL, format, ##args) + /************* - Derivatives for debug + Derivatives ************/ +/* Trace a binary buffer content */ +#define LOG_BUFFER(printlevel, prefix, buf, bufsz, suffix ) { \ + int __i; \ + size_t __sz = (size_t)(bufsz); \ + uint8_t * __buf = (uint8_t *)(buf); \ + char __strbuf[1024+1]; \ + for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2)); __i++) { \ + sprintf(__strbuf + (2 * __i), "%02hhx", __buf[__i]); \ + } \ + fd_log(printlevel, STD_TRACE_FMT_STRING "%s%s%s" STD_TRACE_FMT_ARGS, \ + (prefix), __strbuf, (suffix)); \ +} + /* Helper for function entry -- for very detailed trace of the execution */ #define TRACE_ENTRY(_format,_args... ) \ - TRACE_DEBUG(FCTS, "[enter] %s(" _format ") {" #_args "}", __PRETTY_FUNCTION__, ##_args ); + LOG_A(FCTS, "[enter] %s(" _format ") {" #_args "}", __PRETTY_FUNCTION__, ##_args ); /* Helper for debugging by adding traces -- for debuging a specific location of the code */ #define TRACE_HERE() \ - TRACE_DEBUG(NONE, " -- debug checkpoint %d -- ", fd_breakhere()); + LOG_F(" -- debug checkpoint %d -- ", fd_breakhere()); int fd_breakhere(void); /* Helper for tracing the CHECK_* macros below -- very very verbose code execution! */ -#define TRACE_DEBUG_ALL( str... ) \ - TRACE_DEBUG(CALL, str ); +#define TRACE_CALL( str... ) \ + if ((fd_debug_one_function && !strcmp(fd_debug_one_function, __PRETTY_FUNCTION__)) \ + || (fd_debug_one_file && !strcmp(fd_debug_one_file, __STRIPPED_FILE__) ) ) { \ + LOG_A( str ); \ + } /* For development only, to keep track of TODO locations in the code */ #ifndef ERRORS_ON_TODO -#define TODO( _msg, _args... ) \ - TRACE_DEBUG(NONE, "TODO: " _msg , ##_args); +# define TODO( _msg, _args... ) \ + LOG_F( "TODO: " _msg , ##_args); #else /* ERRORS_ON_TODO */ -#define TODO( _msg, _args... ) \ - "TODO" = _msg ## _args; /* just a stupid compilation error to spot the todo */ +# define TODO( _msg, _args... ) \ + "TODO" = _msg ## _args; /* just a stupid compilation error to spot the todo */ #endif /* ERRORS_ON_TODO */ -/* Trace a binary buffer content */ -#ifdef DEBUG -/* In DEBUG mode, we add (a lot of) meta-information along each trace. This makes multi-threading problems easier to debug. */ -#define TRACE_BUFFER(printlevel, level, prefix, buf, bufsz, suffix ) { \ - if ( TRACE_BOOL(level) ) { \ + +/*============================================================*/ +/* ERROR CHECKING MACRO */ +/*============================================================*/ + +/* Macros to check a return value and branch out in case of error. + * These macro additionally provide the logging information. + * + * The name "__ret__" is always available in the __fallback__ parameter and contains the error code. + */ + +#define CHECK_PRELUDE(__call__) \ + int __ret__; \ + TRACE_CALL("Check: %s", #__call__ ); \ + __ret__ = (__call__) + +#define DEFAULT_FB return __ret__; + +/* System check: error case if < 0, error value in errno */ +#define CHECK_SYS_GEN( faillevel, __call__, __fallback__ ) { \ + CHECK_PRELUDE(__call__); \ + if (__ret__ < 0) { \ + __ret__ = errno; \ + LOG(faillevel, "ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \ + __fallback__; \ + } \ +} + + +/* Check the return value of a function and execute fallback in case of error or special value */ +#define CHECK_FCT_GEN2( faillevel, __call__, __speval__, __fallback1__, __fallback2__ ) { \ + CHECK_PRELUDE(__call__); \ + if (__ret__ != 0) { \ + if (__ret__ == (__speval__)) { \ + __fallback1__; \ + } else { \ + LOG(faillevel, "ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \ + __fallback2__; \ + } \ + } \ +} + +/* Check the return value of a function and execute fallback in case of error (return value different from 0) */ +#define CHECK_FCT_GEN( faillevel, __call__, __fallback__) \ + CHECK_FCT_GEN2( faillevel, (__call__), 0, , (__fallback__) ) + +/* Check that a memory allocator did not return NULL, otherwise log an error and execute fallback */ +#define CHECK_MALLOC_GEN( faillevel, __call__, __fallback__ ) { \ + void * __ptr__; \ + TRACE_CALL("Check: %s", #__call__ ); \ + __ptr__ = (void *)(__call__); \ + if (__ptr__ == NULL) { \ + int __ret__ = errno; \ + LOG(faillevel, "ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \ + __fallback__; \ + } \ +} + +/* Check parameters at function entry, execute fallback on error */ +#define CHECK_PARAMS_GEN( faillevel, __bool__, __fallback__ ) { \ + TRACE_CALL("Check: %s", #__bool__ ); \ + if ( ! (__bool__) ) { \ + int __ret__ = EINVAL; \ + LOG(faillevel, "ERROR: invalid parameter '%s'", #__bool__ ); \ + __fallback__; \ + } \ +} + + +/*============================================================*/ +/* COMPATIBILITY MACROS, TO BE REMOVED */ +/*============================================================*/ +/* Redefine the old macros for transition of the code */ +#ifndef EXCLUDE_DEPRECATED + +#define MARK_DEPRECATED /* __attribute__ ((deprecated)) */ + +enum old_levels { + NONE = 0, + INFO = 1, + FULL = 2, + ANNOYING = 4, + FCTS = 6, + CALL = 9 +} MARK_DEPRECATED; + +static __inline__ int TRACE_BOOL( enum old_levels level ) MARK_DEPRECATED +{ + return (level <= fd_g_debug_lvl) + || (fd_debug_one_function && !strcmp(fd_debug_one_function, __PRETTY_FUNCTION__)) + || (fd_debug_one_file && !strcmp(fd_debug_one_file, __STRIPPED_FILE__) ); +} + +static __inline__ void fd_log_deprecated( int level, const char *format, ... ) MARK_DEPRECATED +{ + va_list ap; + va_start(ap, format); + fd_log_va(level, format, ap); + va_end(ap); +} +static __inline__ void replace_me() MARK_DEPRECATED { } + +#define TRACE_sSA(...) replace_me(); +#define sSA_DUMP_NODE_SERV(...) replace_me(); +#define sSA_DUMP_NODE(...) replace_me(); +#define TRACE_BUFFER(...) replace_me(); +#define TRACE_NOTICE(...) replace_me(); + + +/* Use the LOG_* instead, or use the new *_dump functions when dumping an object */ +#define fd_log_debug(format,args...) fd_log_deprecated(FD_LOG_DEBUG, format, ## args) +#define fd_log_notice(format,args...) fd_log_deprecated(FD_LOG_NOTICE, format, ## args) +#define fd_log_error(format,args...) fd_log_deprecated(FD_LOG_ERROR, format, ## args) + +/* old macro for traces. To be replaced by appropriate LOG_* macros. */ +# define TRACE_DEBUG(oldlevel, format,args... ) { \ + if (TRACE_BOOL(oldlevel)) { \ + if (oldlevel == NONE) { LOG_E(format,##args); } \ + else if (oldlevel == INFO) { LOG_N(format,##args); } \ + else { LOG_D(format,##args); } \ +} } + +/* the following macro must be replaced with LOG_E or LOG_F */ +# define TRACE_ERROR fd_log_error + + +/* The following macros are missing the faillevel information, which indicates at what log level the error case should be displayed. */ +# define CHECK_SYS_DO( __call__, __fallback__ ) { \ + CHECK_PRELUDE(__call__); \ + if (__ret__ < 0) { \ + __ret__ = errno; \ + TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \ + __fallback__; \ + } \ +} + +# define CHECK_SYS( __call__ ) \ + CHECK_SYS_DO( (__call__), return __ret__ ) + + +# define CHECK_POSIX_DO2( __call__, __speval__, __fallback1__, __fallback2__ ) { \ + CHECK_PRELUDE(__call__); \ + if (__ret__ != 0) { \ + if (__ret__ == (__speval__)) { \ + __fallback1__; \ + } else { \ + TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \ + __fallback2__; \ + } \ + } \ +} + +# define CHECK_POSIX_DO( __call__, __fallback__ ) \ + CHECK_POSIX_DO2( (__call__), 0, , __fallback__ ) + +# define CHECK_POSIX( __call__ ) \ + CHECK_POSIX_DO( (__call__), return __ret__ ) + +# define CHECK_MALLOC_DO( __call__, __fallback__ ) { \ + void * __ptr__; \ + TRACE_CALL("Check: %s", #__call__ ); \ + __ptr__ = (void *)(__call__); \ + if (__ptr__ == NULL) { \ + int __ret__ = errno; \ + TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \ + __fallback__; \ + } \ +} + +# define CHECK_MALLOC( __call__ ) \ + CHECK_MALLOC_DO( (__call__), return __ret__ ) + +# define CHECK_PARAMS_DO( __bool__, __fallback__ ) { \ + TRACE_CALL("Check: %s", #__bool__ ); \ + if ( ! (__bool__) ) { \ + int __ret__ = EINVAL; \ + TRACE_ERROR("ERROR: invalid parameter '%s'", #__bool__ ); \ + __fallback__; \ + } \ +} + +# define CHECK_PARAMS( __bool__ ) \ + CHECK_PARAMS_DO( (__bool__), return __ret__ ) + +# define CHECK_FCT_DO CHECK_POSIX_DO +# define CHECK_FCT CHECK_POSIX + +#endif /* EXCLUDE_DEPRECATED */ + + +/*============================================================*/ +/* Optimized code: remove all debugging code */ +/*============================================================*/ +#ifdef STRIP_DEBUG_CODE +#undef LOG_D +#undef LOG_N +#undef LOG_E +#undef LOG_F +#undef LOG_BUFFER + +#define LOG_D(format,args... ) /* noop */ +#define LOG_N(format,args...) fd_log(FD_LOG_NOTICE, format, ## args) +#define LOG_E(format,args...) fd_log(FD_LOG_ERROR, format, ## args) +#define LOG_F(format,args...) fd_log(FD_LOG_FATAL, format, ## args) +#define LOG_BUFFER(printlevel, level, prefix, buf, bufsz, suffix ) { \ + if (printlevel > FD_LOG_DEBUG) { \ int __i; \ size_t __sz = (size_t)(bufsz); \ uint8_t * __buf = (uint8_t *)(buf); \ - char __strbuf[1024+1]; \ - char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed"); \ - for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2)); __i++) { \ - sprintf(__strbuf + (2 * __i), "%2.2hhx", __buf[__i]); \ + char * __strbuf[1024+1]; \ + for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2); __i++) { \ + sprintf(__strbuf + (2 * __i), "%02.2hhx", __buf[__i]); \ } \ - fd_log(printlevel, STD_TRACE_FMT_STRING "%s%s%s", \ - __thn, __PRETTY_FUNCTION__, __STRIPPED_FILE__, __LINE__, (prefix), __strbuf, (suffix)); \ - } \ -} -#else /* DEBUG */ -/* Do not print thread, function, ... only the message itself in this case */ -#define TRACE_BUFFER(printlevel, level, prefix, buf, bufsz, suffix ) { \ - if ( TRACE_BOOL(level) ) { \ - int __i; \ - size_t __sz = (size_t)(bufsz); \ - uint8_t * __buf = (uint8_t *)(buf); \ - char __strbuf[1024+1]; \ - for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2)); __i++) { \ - sprintf(__strbuf + (2 * __i), "%2.2hhx", __buf[__i]); \ - } \ - fd_log(printlevel, "%s%s%s", (prefix), __strbuf, (suffix)); \ - } \ -} -#endif /* DEBUG */ + fd_log(printlevel, prefix"%s"suffix, __strbuf); \ + } +#endif /* STRIP_DEBUG_CODE */ + +/*============================================================*/ +/* OTHER MACROS */ +/*============================================================*/ +/* helper macros (pre-processor hacks to allow macro arguments) */ +#define __tostr( arg ) #arg +#define _stringize( arg ) __tostr( arg ) +#define __agr( arg1, arg2 ) arg1 ## arg2 +#define _aggregate( arg1, arg2 ) __agr( arg1, arg2 ) /* Some aliases to socket addresses structures */ #define sSS struct sockaddr_storage @@ -392,217 +598,8 @@ ((((sSA *)_sa_)->sa_family == AF_INET6) ? (sizeof(sSA6)) : \ 0 ) ) ) -/* Dump one sockaddr Node information */ -#define sSA_DUMP_NODE( buf, bufsize, sa, flag ) { \ - sSA * __sa = (sSA *)(sa); \ - char __addrbuf[INET6_ADDRSTRLEN]; \ - if (__sa) { \ - int __rc = getnameinfo(__sa, \ - sSAlen(__sa), \ - __addrbuf, \ - sizeof(__addrbuf), \ - NULL, \ - 0, \ - (flag)); \ - if (__rc) \ - snprintf(buf, bufsize, "%s", gai_strerror(__rc)); \ - else \ - snprintf(buf, bufsize, "%s", &__addrbuf[0]); \ - } else { \ - snprintf(buf, bufsize, "(NULL / ANY)"); \ - } \ -} -/* Same but with the port (service) also */ -#define sSA_DUMP_NODE_SERV( buf, bufsize, sa, flag ) { \ - sSA * __sa = (sSA *)(sa); \ - char __addrbuf[INET6_ADDRSTRLEN]; \ - char __servbuf[32]; \ - if (__sa) { \ - int __rc = getnameinfo(__sa, \ - sSAlen(__sa), \ - __addrbuf, \ - sizeof(__addrbuf), \ - __servbuf, \ - sizeof(__servbuf), \ - (flag)); \ - if (__rc) \ - snprintf(buf, bufsize, "%s", gai_strerror(__rc)); \ - else \ - snprintf(buf, bufsize, "[%s]:%s", &__addrbuf[0],&__servbuf[0]); \ - } else { \ - snprintf(buf, bufsize,"(NULL / ANY)"); \ - } \ -} - -#ifdef DEBUG -/* In DEBUG mode, we add (a lot of) meta-information along each trace. This makes multi-threading problems easier to debug. */ -#define TRACE_sSA(printlevel, level, prefix, sa, flags, suffix ) { \ - if ( TRACE_BOOL(level) ) { \ - char __buf[1024]; \ - char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed"); \ - sSA_DUMP_NODE_SERV(__buf, sizeof(__buf), sa, flags ); \ - fd_log(printlevel, STD_TRACE_FMT_STRING "%s%s%s" , \ - __thn, __PRETTY_FUNCTION__, __STRIPPED_FILE__, __LINE__, (prefix), __buf, (suffix)); \ - } \ -} -#else /* DEBUG */ -/* Do not print thread, function, ... only the message itself in this case */ -#define TRACE_sSA(printlevel, level, prefix, sa, flags, suffix ) { \ - if ( TRACE_BOOL(level) ) { \ - char __buf[1024]; \ - sSA_DUMP_NODE_SERV(__buf, sizeof(__buf), sa, flags ); \ - fd_log(printlevel, "%s%s%s" , (prefix), __buf, (suffix)); \ - } \ -} -#endif /* DEBUG */ - -/****************** - Optimized code: remove all debugging code - **/ -#ifdef STRIP_DEBUG_CODE -#undef TRACE_DEBUG -#undef TRACE_NOTICE -#undef TRACE_ERROR -#undef TRACE_BOOL -#undef TRACE_BUFFER -#undef TRACE_sSA - -#define TRACE_DEBUG(level,format,args... ) /* noop */ -#define TRACE_BOOL(_level_) (0) /* always false */ -#define TRACE_NOTICE fd_log_notice -#define TRACE_ERROR fd_log_error -#define TRACE_BUFFER(printlevel, level, prefix, buf, bufsz, suffix ) { \ - if (printlevel > FD_LOG_DEBUG) { \ - int __i; \ - size_t __sz = (size_t)(bufsz); \ - uint8_t * __buf = (uint8_t *)(buf); \ - char * __strbuf[1024+1]; \ - for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2); __i++) { \ - sprintf(__strbuf + (2 * __i), "%02.2hhx", __buf[__i]); \ - } \ - fd_log(printlevel, prefix"%s"suffix, __strbuf); \ - } -#define TRACE_sSA(printlevel, level, prefix, sa, flags, suffix ) { \ - if (printlevel > FD_LOG_DEBUG) { \ - char __buf[1024]; \ - sSA_DUMP_NODE_SERV(__buf, sizeof(__buf), sa, flags ); \ - fd_log(printlevel, prefix "%s" suffix, __buf); \ - } -#endif /* STRIP_DEBUG_CODE */ - - -/*============================================================*/ -/* ERROR CHECKING MACRO */ -/*============================================================*/ - -/* Macros to check a return value and branch out in case of error. - * These macro should be used only when errors are improbable, not for expected errors. - */ - -/* Check the return value of a system function and execute fallback in case of error */ -#define CHECK_SYS_DO( __call__, __fallback__ ) { \ - int __ret__; \ - TRACE_DEBUG_ALL( "Check SYS: %s", #__call__ ); \ - __ret__ = (__call__); \ - if (__ret__ < 0) { \ - int __err__ = errno; /* We may handle EINTR here */ \ - TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__err__)); \ - __fallback__; \ - } \ -} -/* Check the return value of a system function, return error code on error */ -#define CHECK_SYS( __call__ ) { \ - int __ret__; \ - TRACE_DEBUG_ALL( "Check SYS: %s", #__call__ ); \ - __ret__ = (__call__); \ - if (__ret__ < 0) { \ - int __err__ = errno; /* We may handle EINTR here */ \ - TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__err__)); \ - return __err__; \ - } \ -} - -/* Check the return value of a POSIX function and execute fallback in case of error or special value */ -#define CHECK_POSIX_DO2( __call__, __speval__, __fallback1__, __fallback2__ ) { \ - int __ret__; \ - TRACE_DEBUG_ALL( "Check POSIX: %s", #__call__ ); \ - __ret__ = (__call__); \ - if (__ret__ != 0) { \ - if (__ret__ == (__speval__)) { \ - __fallback1__; \ - } else { \ - TRACE_ERROR("ERROR: in '%s':\t%s", #__call__, strerror(__ret__)); \ - __fallback2__; \ - } \ - } \ -} - -/* Check the return value of a POSIX function and execute fallback in case of error */ -#define CHECK_POSIX_DO( __call__, __fallback__ ) \ - CHECK_POSIX_DO2( (__call__), 0, , __fallback__ ); - -/* Check the return value of a POSIX function and return it if error */ -#define CHECK_POSIX( __call__ ) { \ - int __v__; \ - CHECK_POSIX_DO( __v__ = (__call__), return __v__ ); \ -} - -/* Check that a memory allocator did not return NULL, otherwise log an error and execute fallback */ -#define CHECK_MALLOC_DO( __call__, __fallback__ ) { \ - void * __ret__; \ - TRACE_DEBUG_ALL( "Check MALLOC: %s", #__call__ ); \ - __ret__ = (void *)( __call__ ); \ - if (__ret__ == NULL) { \ - int __err__ = errno; \ - TRACE_ERROR("ERROR: in '%s':\t%s", #__call__, strerror(__err__)); \ - __fallback__; \ - } \ -} - -/* Check that a memory allocator did not return NULL, otherwise return ENOMEM */ -#define CHECK_MALLOC( __call__ ) \ - CHECK_MALLOC_DO( __call__, return ENOMEM ); - - -/* Check parameters at function entry, execute fallback on error */ -#define CHECK_PARAMS_DO( __bool__, __fallback__ ) \ - TRACE_DEBUG_ALL( "Check PARAMS: %s", #__bool__ ); \ - if ( ! (__bool__) ) { \ - TRACE_ERROR("Warning: Invalid parameter received in '%s'", #__bool__); \ - __fallback__; \ - } -/* Check parameters at function entry, return EINVAL if the boolean is false (similar to assert) */ -#define CHECK_PARAMS( __bool__ ) \ - CHECK_PARAMS_DO( __bool__, return EINVAL ); - -/* Check the return value of an internal function, log and propagate */ -#define CHECK_FCT_DO( __call__, __fallback__ ) { \ - int __ret__; \ - TRACE_DEBUG_ALL( "Check FCT: %s", #__call__ ); \ - __ret__ = (__call__); \ - if (__ret__ != 0) { \ - TRACE_ERROR("ERROR: in '%s':\t%s", #__call__, strerror(__ret__)); \ - __fallback__; \ - } \ -} -/* Check the return value of a function call, return any error code */ -#define CHECK_FCT( __call__ ) { \ - int __v__; \ - CHECK_FCT_DO( __v__ = (__call__), return __v__ ); \ -} - - - -/*============================================================*/ -/* OTHER MACROS */ -/*============================================================*/ - - -/* helper macros (pre-processor hacks to allow macro arguments) */ -#define __tostr( arg ) #arg -#define _stringize( arg ) __tostr( arg ) -#define __agr( arg1, arg2 ) arg1 ## arg2 -#define _aggregate( arg1, arg2 ) __agr( arg1, arg2 ) +DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node, sSA * sa, int flags); +DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node_serv, sSA * sa, int flags); /* A l4 protocol name (TCP / SCTP) */ @@ -983,8 +980,8 @@ int fd_dict_getdict ( struct dict_object * object, struct dictionary ** dict); /* Debug functions */ -void fd_dict_dump_object(struct dict_object * obj); -void fd_dict_dump(struct dictionary * dict); +DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_object, struct dict_object * obj); +DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump, struct dictionary * dict); /* Function to access full contents of the dictionary, see doc in dictionary.c */ int fd_dict_getlistof(int criteria, void * parent, struct fd_list ** sentinel); @@ -1222,7 +1219,7 @@ char * type_name; /* The name of this type */ dict_avpdata_interpret type_interpret;/* cb to convert the AVP value in more comprehensive format (or NULL) */ dict_avpdata_encode type_encode; /* cb to convert formatted data into an AVP value (or NULL) */ - char * (*type_dump)(union avp_value * val); /* cb called by fd_msg_dump_one for this type of data (if != NULL). Returned string must be freed. */ + DECLARE_FD_DUMP_PROTOTYPE((*type_dump), union avp_value * val); /* cb called by fd_msg_dump_one for this type of data (if != NULL). Returned string must be freed. */ }; /* The criteria for searching a type object in the dictionary */ @@ -1239,15 +1236,15 @@ /* Convert an Address type AVP into a struct sockaddr_storage */ int fd_dictfct_Address_encode(void * data, union avp_value * avp_value); int fd_dictfct_Address_interpret(union avp_value * avp_value, void * interpreted); -char * fd_dictfct_Address_dump(union avp_value * avp_value); +DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_Address_dump, union avp_value * avp_value); /* Display the content of an AVP of type UTF8String in the log file */ -char * fd_dictfct_UTF8String_dump(union avp_value * avp_value); +DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_UTF8String_dump, union avp_value * avp_value); /* For Time AVPs, map with time_t value directly */ int fd_dictfct_Time_encode(void * data, union avp_value * avp_value); int fd_dictfct_Time_interpret(union avp_value * avp_value, void * interpreted); -char * fd_dictfct_Time_dump(union avp_value * avp_value); +DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_Time_dump, union avp_value * avp_value); @@ -1821,6 +1818,8 @@ /* The state information that a module associate with a session -- each module defines its own data format */ typedef void session_state; +typedef DECLARE_FD_DUMP_PROTOTYPE(session_state_dump, session_state * st); + /* The following function must be called to activate the session expiry mechanism */ int fd_sess_start(void); @@ -1830,6 +1829,7 @@ * PARAMETERS: * handler : location where the new handler must be stored. * cleanup : a callback function that must be called when the session with associated data is destroyed. + * dumper : if not NULL, will be called during fd_sess_dump to display the data associated with a session. NULL otherwise. * opaque : A pointer that is passed to the cleanup callback -- the content is never examined by the framework. * * DESCRIPTION: @@ -1842,10 +1842,10 @@ * EINVAL : A parameter is invalid. * ENOMEM : Not enough memory to complete the operation */ -int fd_sess_handler_create_internal ( struct session_handler ** handler, void (*cleanup)(session_state * state, os0_t sid, void * opaque), void * opaque ); +int fd_sess_handler_create_internal ( struct session_handler ** handler, void (*cleanup)(session_state * state, os0_t sid, void * opaque), session_state_dump dumper, void * opaque ); /* Macro to avoid casting everywhere */ -#define fd_sess_handler_create( _handler, _cleanup, _opaque ) \ - fd_sess_handler_create_internal( (_handler), (void (*)(session_state *, os0_t, void *))(_cleanup), (void *)(_opaque) ) +#define fd_sess_handler_create( _handler, _cleanup, _dumper, _opaque ) \ + fd_sess_handler_create_internal( (_handler), (void (*)(session_state *, os0_t, void *))(_cleanup), _dumper, (void *)(_opaque) ) /* @@ -2045,8 +2045,8 @@ /* For debug */ -void fd_sess_dump(int level, struct session * session); -void fd_sess_dump_hdl(int level, struct session_handler * handler); +DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump, struct session * session, int with_states); +DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump_hdl, struct session_handler * handler); /* For statistics / monitoring: get the number of struct session in memory */ int fd_sess_getcount(uint32_t *cnt); @@ -2327,33 +2327,26 @@ * FUNCTION: fd_msg_dump_* * * PARAMETERS: - * level : the log level (INFO, FULL, ...) at which the object is dumped - * obj : A msg or avp object. + * see definition of DECLARE_FD_DUMP_PROTOTYPE, + * obj : A msg or avp object to dump. + * dict : the dictionary to use if parsing is requested (optional) + * force_parsing: by default these functions do not parse the object but dump hexa values in that case. + * use !0 to force parsing. If parsing fails, the hexa dump is still provided. + * recurse : allow the function to go through the children objects if any to dump more information. might require parsing. * * DESCRIPTION: - * These functions dump the content of a message to the debug log + * These functions dump the content of a message or avp into a buffer * either recursively or only the object itself. * * RETURN VALUE: - * - - */ -void fd_msg_dump_walk ( int level, msg_or_avp *obj ); -void fd_msg_dump_one ( int level, msg_or_avp *obj ); - -/* Helper functions to get a dump of an object in the logs. Several formats are available. - * buf : a buffer that can be reallocated if needed. *buf==NULL is also accepted for first allocation - * buflen: the length of the buffer buf. - * dict : optional, the dictionary to use for resolving objects, if force_parsing != 0 - * obj : the message or AVP to dump. - * - * After use, the buf pointer should be freed. + * - see DECLARE_FD_DUMP_PROTOTYPE, */ /* one-line dump with only short information */ -void fd_msg_dump_summary( char ** buf, size_t buflen, struct dictionary *dict, msg_or_avp *obj, int force_parsing); +DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_summary, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse ); /* one-line dump with all the contents of the message */ -void fd_msg_dump_full( char ** buf, size_t buflen, struct dictionary *dict, msg_or_avp *obj, int force_parsing); +DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_full, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse ); /* multi-line human-readable dump similar to wireshark output */ -void fd_msg_dump_treeview( char ** buf, size_t buflen, struct dictionary *dict, msg_or_avp *obj, int force_parsing); +DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_treeview, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse ); /*********************************************/ @@ -3140,7 +3133,8 @@ fd_fifo_timedget_int((queue), (void *)(item), (abstime)) /* Dump a fifo list and optionally its inner elements -- beware of deadlocks! */ -void fd_fifo_dump(int level, char * name, struct fifo * queue, void (*dump_item)(int level, void * item)); +typedef DECLARE_FD_DUMP_PROTOTYPE((*fd_fifo_dump_item_cb), void * item); /* This function should be 1 line if possible, or use indent level. Ends with '\n' */ +DECLARE_FD_DUMP_PROTOTYPE(fd_fifo_dump, char * name, struct fifo * queue, fd_fifo_dump_item_cb dump_item); #ifdef __cplusplus } diff -r 6b7966ea27fb -r 7d7266115a34 libfdcore/config.c --- a/libfdcore/config.c Fri May 03 15:33:57 2013 +0800 +++ b/libfdcore/config.c Fri May 03 19:20:56 2013 +0800 @@ -80,68 +80,71 @@ return 0; } -void fd_conf_dump() +DECLARE_FD_DUMP_PROTOTYPE(fd_conf_dump) { - if (!TRACE_BOOL(INFO)) - return; + size_t o=0; + if (!offset) + offset = &o; - fd_log_debug("-- Configuration :"); - fd_log_debug(" Debug trace level ...... : %+d", fd_g_debug_lvl); - fd_log_debug(" Configuration file ..... : %s", fd_g_config->cnf_file); - fd_log_debug(" Diameter Identity ...... : %s (l:%Zi)", fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len); - fd_log_debug(" Diameter Realm ......... : %s (l:%Zi)", fd_g_config->cnf_diamrlm, fd_g_config->cnf_diamrlm_len); - fd_log_debug(" Tc Timer ............... : %u", fd_g_config->cnf_timer_tc); - fd_log_debug(" Tw Timer ............... : %u", fd_g_config->cnf_timer_tw); - fd_log_debug(" Local port ............. : %hu", fd_g_config->cnf_port); - fd_log_debug(" Local secure port ...... : %hu", fd_g_config->cnf_port_tls); - fd_log_debug(" Number of SCTP streams . : %hu", fd_g_config->cnf_sctp_str); - fd_log_debug(" Number of server threads : %hu", fd_g_config->cnf_dispthr); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{freeDiameter configuration}(@%p): \n", fd_g_config), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Default trace level .... : %+d\n", fd_g_debug_lvl), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Configuration file ..... : %s\n", fd_g_config->cnf_file), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Diameter Identity ...... : %s (l:%Zi)\n", fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Diameter Realm ......... : %s (l:%Zi)\n", fd_g_config->cnf_diamrlm, fd_g_config->cnf_diamrlm_len), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Tc Timer ............... : %u\n", fd_g_config->cnf_timer_tc), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Tw Timer ............... : %u\n", fd_g_config->cnf_timer_tw), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Local port ............. : %hu\n", fd_g_config->cnf_port), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Local secure port ...... : %hu\n", fd_g_config->cnf_port_tls), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Number of SCTP streams . : %hu\n", fd_g_config->cnf_sctp_str), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Number of server threads : %hu\n", fd_g_config->cnf_dispthr), return NULL); if (FD_IS_LIST_EMPTY(&fd_g_config->cnf_endpoints)) { - fd_log_debug(" Local endpoints ........ : Default (use all available)"); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Local endpoints ........ : Default (use all available)\n"), return NULL); } else { - fd_log_debug(" Local endpoints ........ : "); - fd_ep_dump( 29, &fd_g_config->cnf_endpoints ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Local endpoints ........ : \n"), return NULL); + CHECK_MALLOC_DO( fd_ep_dump( FD_DUMP_STD_PARAMS, 29, &fd_g_config->cnf_endpoints ), return NULL); } if (FD_IS_LIST_EMPTY(&fd_g_config->cnf_apps)) { - fd_log_debug(" Local applications ..... : (none)"); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Local applications ..... : (none)\n"), return NULL); } else { struct fd_list * li = fd_g_config->cnf_apps.next; - fd_log_debug(" Local applications ..... : "); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Local applications ..... : \n"), return NULL); while (li != &fd_g_config->cnf_apps) { struct fd_app * app = (struct fd_app *)li; - if (li != fd_g_config->cnf_apps.next) fd_log_debug(" "); - fd_log_debug("App: %u\t%s%s\tVnd: %u", + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " App: %u\t%s%s\tVnd: %u\n", app->appid, app->flags.auth ? "Au" : "--", app->flags.acct ? "Ac" : "--", - app->vndid); + app->vndid), return NULL); li = li->next; } } - fd_log_debug(" Flags : - IP ........... : %s", fd_g_config->cnf_flags.no_ip4 ? "DISABLED" : "Enabled"); - fd_log_debug(" - IPv6 ......... : %s", fd_g_config->cnf_flags.no_ip6 ? "DISABLED" : "Enabled"); - fd_log_debug(" - Relay app .... : %s", fd_g_config->cnf_flags.no_fwd ? "DISABLED" : "Enabled"); - fd_log_debug(" - TCP .......... : %s", fd_g_config->cnf_flags.no_tcp ? "DISABLED" : "Enabled"); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Flags : - IP ........... : %s\n", fd_g_config->cnf_flags.no_ip4 ? "DISABLED" : "Enabled"), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - IPv6 ......... : %s\n", fd_g_config->cnf_flags.no_ip6 ? "DISABLED" : "Enabled"), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - Relay app .... : %s\n", fd_g_config->cnf_flags.no_fwd ? "DISABLED" : "Enabled"), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - TCP .......... : %s\n", fd_g_config->cnf_flags.no_tcp ? "DISABLED" : "Enabled"), return NULL); #ifdef DISABLE_SCTP - fd_log_debug(" - SCTP ......... : DISABLED (at compilation)"); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - SCTP ......... : DISABLED (at compilation)\n"), return NULL); #else /* DISABLE_SCTP */ - fd_log_debug(" - SCTP ......... : %s", fd_g_config->cnf_flags.no_sctp ? "DISABLED" : "Enabled"); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - SCTP ......... : %s\n", fd_g_config->cnf_flags.no_sctp ? "DISABLED" : "Enabled"), return NULL); #endif /* DISABLE_SCTP */ - fd_log_debug(" - Pref. proto .. : %s", fd_g_config->cnf_flags.pr_tcp ? "TCP" : "SCTP"); - fd_log_debug(" - TLS method ... : %s", fd_g_config->cnf_flags.tls_alg ? "INBAND" : "Separate port"); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - Pref. proto .. : %s\n", fd_g_config->cnf_flags.pr_tcp ? "TCP" : "SCTP"), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - TLS method ... : %s\n", fd_g_config->cnf_flags.tls_alg ? "INBAND" : "Separate port"), return NULL); - fd_log_debug(" TLS : - Certificate .. : %s", fd_g_config->cnf_sec_data.cert_file ?: "(NONE)"); - fd_log_debug(" - Private key .. : %s", fd_g_config->cnf_sec_data.key_file ?: "(NONE)"); - fd_log_debug(" - CA (trust) ... : %s (%d certs)", fd_g_config->cnf_sec_data.ca_file ?: "(none)", fd_g_config->cnf_sec_data.ca_file_nr); - fd_log_debug(" - CRL .......... : %s", fd_g_config->cnf_sec_data.crl_file ?: "(none)"); - fd_log_debug(" - Priority ..... : %s", fd_g_config->cnf_sec_data.prio_string ?: "(default: '" GNUTLS_DEFAULT_PRIORITY "')"); - if (fd_g_config->cnf_sec_data.dh_file) - fd_log_debug(" - DH file ...... : %s", fd_g_config->cnf_sec_data.dh_file); - else - fd_log_debug(" - DH bits ...... : %d", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " TLS : - Certificate .. : %s\n", fd_g_config->cnf_sec_data.cert_file ?: "(NONE)"), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - Private key .. : %s\n", fd_g_config->cnf_sec_data.key_file ?: "(NONE)"), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - CA (trust) ... : %s (%d certs)\n", fd_g_config->cnf_sec_data.ca_file ?: "(none)", fd_g_config->cnf_sec_data.ca_file_nr), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - CRL .......... : %s\n", fd_g_config->cnf_sec_data.crl_file ?: "(none)"), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - Priority ..... : %s\n", fd_g_config->cnf_sec_data.prio_string ?: "(default: '" GNUTLS_DEFAULT_PRIORITY "')"), return NULL); + if (fd_g_config->cnf_sec_data.dh_file) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - DH file ...... : %s\n", fd_g_config->cnf_sec_data.dh_file), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " - DH bits ...... : %d\n", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS), return NULL); + } - fd_log_debug(" Origin-State-Id ........ : %u", fd_g_config->cnf_orstateid); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " Origin-State-Id ........ : %u", fd_g_config->cnf_orstateid), return NULL); + + return *buf; } /* read contents of a file opened in "rb" mode and alloc this data into a gnutls_datum_t (must be freed afterwards) */ diff -r 6b7966ea27fb -r 7d7266115a34 libfdcore/core.c --- a/libfdcore/core.c Fri May 03 15:33:57 2013 +0800 +++ b/libfdcore/core.c Fri May 03 19:20:56 2013 +0800 @@ -84,32 +84,6 @@ int code; size_t sz; void * data; CHECK_FCT_DO( fd_event_get(fd_g_config->cnf_main_ev, &code, &sz, &data), break ); switch (code) { - case FDEV_DUMP_DICT: - fd_dict_dump(fd_g_config->cnf_dict); - break; - - case FDEV_DUMP_EXT: - fd_ext_dump(); - break; - - case FDEV_DUMP_SERV: - fd_servers_dump(); - break; - - case FDEV_DUMP_QUEUES: - fd_fifo_dump(0, "Incoming messages", fd_g_incoming, fd_msg_dump_walk); - fd_fifo_dump(0, "Outgoing messages", fd_g_outgoing, fd_msg_dump_walk); - fd_fifo_dump(0, "Local messages", fd_g_local, fd_msg_dump_walk); - break; - - case FDEV_DUMP_CONFIG: - fd_conf_dump(); - break; - - case FDEV_DUMP_PEERS: - fd_peer_dump_list(FULL); - break; - case FDEV_TRIGGER: { int tv, *p; @@ -181,7 +155,7 @@ return ret; } - TRACE_DEBUG(INFO, "libfdproto initialized."); + LOG_D("libfdproto initialized."); /* Name this thread */ fd_log_threadname("Main"); @@ -224,6 +198,10 @@ /* Parse the freeDiameter.conf configuration file, load the extensions */ int fd_core_parseconf(const char * conffile) { + char * buf = NULL, *b; + size_t len = 0, offset=0; + + TRACE_ENTRY("%p", conffile); /* Conf file */ @@ -239,11 +217,17 @@ CHECK_FCT( fd_ext_load() ); /* Display configuration */ - fd_conf_dump(); + b = fd_conf_dump(&buf, &len, NULL); + LOG_N("%s\n", b ?: "Error during configuration dump..."); /* Display registered triggers for FDEV_TRIGGER */ - fd_event_trig_dump(); + b = fd_event_trig_dump(&buf, &len, &offset); + if (!b || offset) { + LOG_N("%s\n", b ?: "Error during triggers dump..."); + } + free(buf); + return 0; } diff -r 6b7966ea27fb -r 7d7266115a34 libfdcore/endpoints.c --- a/libfdcore/endpoints.c Fri May 03 15:33:57 2013 +0800 +++ b/libfdcore/endpoints.c Fri May 03 19:20:56 2013 +0800 @@ -57,19 +57,6 @@ fd_list_init(list, NULL); } - if (TRACE_BOOL(ANNOYING + 1)) { - char buf[1024]; - sSA_DUMP_NODE_SERV( buf, sizeof(buf), sa, NI_NUMERICHOST | NI_NUMERICSERV ); - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge Current list:"); - fd_ep_dump( 4, list ); - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge Adding:"); - fd_log_debug(" %s {%s%s%s%s%s}", buf, - (flags & EP_FL_CONF) ? "C" : "-", - (flags & EP_FL_DISC) ? "D" : "-", - (flags & EP_FL_ADV) ? "A" : "-", - (flags & EP_FL_LL) ? "L" : "-", - (flags & EP_FL_PRIMARY) ? "P" : "-"); - } ptr.sa = sa; /* Filter out a bunch of invalid addresses */ @@ -81,9 +68,7 @@ /* the next one filters both EXPERIMENTAL, BADCLASS and MULTICAST. */ || ((ntohl(ptr.sin->sin_addr.s_addr) & 0xe0000000) == 0xe0000000) || (ptr.sin->sin_addr.s_addr == INADDR_BROADCAST)) { - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge Address was ignored, not added."); - } + LOG_A(" DEBUG:fd_ep_add_merge Address was ignored, not added."); return 0; } } @@ -97,9 +82,7 @@ || IN6_IS_ADDR_MULTICAST(&ptr.sin6->sin6_addr) || IN6_IS_ADDR_LINKLOCAL(&ptr.sin6->sin6_addr) || IN6_IS_ADDR_SITELOCAL(&ptr.sin6->sin6_addr)) { - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge Address was ignored, not added."); - } + LOG_A(" DEBUG:fd_ep_add_merge Address was ignored, not added."); return 0; } } @@ -107,9 +90,7 @@ break; default: - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge Address family was unknown, not added."); - } + LOG_A(" DEBUG:fd_ep_add_merge Address family was unknown, not added."); return 0; } @@ -174,10 +155,6 @@ /* Merge the flags */ ep->flags |= flags; - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_add_merge New list:"); - fd_ep_dump( 4, list ); - } return 0; } @@ -189,10 +166,6 @@ TRACE_ENTRY("%p %x", list, flags); CHECK_PARAMS(list); - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter Filter this list for flags %x:", flags); - fd_ep_dump( 4, list ); - } for (li = list->next; li != list; li = li->next) { struct fd_endpoint * ep = (struct fd_endpoint *)li; @@ -203,10 +176,6 @@ } } - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter Resulting list:"); - fd_ep_dump( 4, list ); - } return 0; } @@ -218,10 +187,6 @@ TRACE_ENTRY("%p %d", list, af); CHECK_PARAMS(list); - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter_family Filter this list for family %d:", af); - fd_ep_dump( 4, list ); - } for (li = list->next; li != list; li = li->next) { struct fd_endpoint * ep = (struct fd_endpoint *)li; @@ -232,10 +197,6 @@ } } - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter_family Resulting list:"); - fd_ep_dump( 4, list ); - } return 0; } @@ -252,12 +213,6 @@ li_out = list->next; li_ex = exclude_list->next; - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter_list Filter this list "); - fd_ep_dump( 4, list ); - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter_list Removing from list"); - fd_ep_dump( 6, exclude_list ); - } /* Now browse both lists in parallel */ while ((li_out != list) && (li_ex != exclude_list)) { int cmp; @@ -303,10 +258,6 @@ free(li); } - if (TRACE_BOOL(ANNOYING + 1)) { - TRACE_DEBUG(ANNOYING, " DEBUG:fd_ep_filter_list Resulting list:"); - fd_ep_dump( 4, list ); - } return 0; } @@ -333,26 +284,44 @@ return 0; } -void fd_ep_dump_one( char * prefix, struct fd_endpoint * ep ) +DECLARE_FD_DUMP_PROTOTYPE(fd_ep_dump_one, struct fd_endpoint * ep ) { - char buf[1024]; + size_t o = 0; + if (!offset) + offset=&o; + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{ep}(@%p): ", ep), return NULL); - sSA_DUMP_NODE_SERV( buf, sizeof(buf), &ep->sa, NI_NUMERICHOST | NI_NUMERICSERV ); - fd_log_debug("%s%s {%s%s%s%s}%s", prefix ?: "", buf, + if (!ep) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL\n"), return NULL); + return *buf; + } + + CHECK_MALLOC_DO( fd_sa_dump_node_serv( FD_DUMP_STD_PARAMS, &ep->sa, NI_NUMERICHOST | NI_NUMERICSERV ), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {%s%s%s%s%s}", (ep->flags & EP_FL_CONF) ? "C" : "-", (ep->flags & EP_FL_DISC) ? "D" : "-", (ep->flags & EP_FL_ADV) ? "A" : "-", (ep->flags & EP_FL_LL) ? "L" : "-", - (ep->flags & EP_FL_PRIMARY) ? "P" : "-"); + (ep->flags & EP_FL_PRIMARY) ? "P" : "-"), return NULL); + return *buf; } -void fd_ep_dump( int indent, struct fd_list * eps ) +DECLARE_FD_DUMP_PROTOTYPE(fd_ep_dump, int indent, struct fd_list * eps ) { struct fd_list * li; - for (li = eps->next; li != eps; li = li->next) { - struct fd_endpoint * ep = (struct fd_endpoint *)li; - fd_log_debug("%*s", indent, ""); - fd_ep_dump_one( NULL, ep ); + size_t o = 0; + if (!offset) + offset=&o; + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*s{eps}(@%p):\n", indent, "", eps), return NULL); + if (eps) { + for (li = eps->next; li != eps; li = li->next) { + struct fd_endpoint * ep = (struct fd_endpoint *)li; + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*s", indent+1, ""), return NULL); + CHECK_MALLOC_DO( fd_ep_dump_one( FD_DUMP_STD_PARAMS, ep ), return NULL); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL); + } } } diff -r 6b7966ea27fb -r 7d7266115a34 libfdcore/events.c --- a/libfdcore/events.c Fri May 03 15:33:57 2013 +0800 +++ b/libfdcore/events.c Fri May 03 19:20:56 2013 +0800 @@ -105,12 +105,6 @@ #define case_str( _val )\ case _val : return #_val case_str(FDEV_TERMINATE); - case_str(FDEV_DUMP_DICT); - case_str(FDEV_DUMP_EXT); - case_str(FDEV_DUMP_SERV); - case_str(FDEV_DUMP_QUEUES); - case_str(FDEV_DUMP_CONFIG); - case_str(FDEV_DUMP_PEERS); case_str(FDEV_TRIGGER); default: @@ -167,20 +161,22 @@ return 0; } -void fd_event_trig_dump() +DECLARE_FD_DUMP_PROTOTYPE(fd_event_trig_dump) { struct fd_list * li; - if (!TRACE_BOOL(FULL)) - return; + size_t o=0; + if (!offset) + offset=&o; CHECK_POSIX_DO( pthread_rwlock_rdlock(&trig_rwl), ); for (li = trig_list.next; li != &trig_list; li = li->next) { struct trig_item *t = li->o; - fd_log_debug(" Trigger %d, module '%s': %p", t->trig_value, t->trig_module, t->cb); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{trigger sig:%d}'%s'->%p ", t->trig_value, t->trig_module, t->cb), break); } CHECK_POSIX_DO( pthread_rwlock_unlock(&trig_rwl), ); + return *buf; } static void *call_cb_detached(void * arg) diff -r 6b7966ea27fb -r 7d7266115a34 libfdcore/extensions.c --- a/libfdcore/extensions.c Fri May 03 15:33:57 2013 +0800 +++ b/libfdcore/extensions.c Fri May 03 19:20:56 2013 +0800 @@ -77,17 +77,19 @@ } /* Dump the list */ -void fd_ext_dump(void) +DECLARE_FD_DUMP_PROTOTYPE(fd_ext_dump) { struct fd_list * li; - - fd_log_debug("Dumping extensions list :"); + size_t o=0; + if (!offset) + offset = &o; for (li = ext_list.next; li != &ext_list; li = li->next) { struct fd_ext_info * ext = (struct fd_ext_info *)li; - fd_log_debug(" - '%s'[%s] is %sloaded", ext->filename, ext->conffile?:"no conf", ext->handler ? "" : "not "); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{extension}(@%p): '%s'[%s], %sloaded\n", ext, ext->filename, ext->conffile?:"no conf", ext->handler ? "" : "not "), return NULL); } + return *buf; } /* Check the dependencies. The object must have been dlopened already. */ diff -r 6b7966ea27fb -r 7d7266115a34 libfdcore/fdcore-internal.h --- a/libfdcore/fdcore-internal.h Fri May 03 15:33:57 2013 +0800 +++ b/libfdcore/fdcore-internal.h Fri May 03 19:20:56 2013 +0800 @@ -85,7 +85,6 @@ /* Configuration */ int fd_conf_init(); int fd_conf_deinit(); -void fd_conf_dump(); int fd_conf_parse(); int fddparse(struct fd_config * conf); /* yacc generated */ int fd_conf_stream_to_gnutls_datum(FILE * pemfile, gnutls_datum_t *out); @@ -94,7 +93,6 @@ /* Extensions */ int fd_ext_add( char * filename, char * conffile ); int fd_ext_load(); -void fd_ext_dump(void); int fd_ext_term(void); /* Messages */ @@ -217,11 +215,8 @@ /* Events codespace for struct fd_peer->p_events */ enum { - /* Dump all info about this peer in the debug log */ - FDEVP_DUMP_ALL = 1500 - /* request to terminate this peer : disconnect, requeue all messages */ - ,FDEVP_TERMINATE + FDEVP_TERMINATE = 1500 /* A connection object has received a message. (data contains the buffer + struct timespec piggytailed -- unaligned) */ ,FDEVP_CNX_MSG_RECV @@ -249,13 +244,12 @@ }; #define CHECK_PEVENT( _e ) \ - (((int)(_e) >= FDEVP_DUMP_ALL) && ((int)(_e) <= FDEVP_PSM_TIMEOUT)) + (((int)(_e) >= FDEVP_TERMINATE) && ((int)(_e) <= FDEVP_PSM_TIMEOUT)) /* The following macro is actually called in p_psm.c -- another solution would be to declare it static inline */ #define DECLARE_PEV_STR() \ const char * fd_pev_str(int event) \ { \ switch (event) { \ - case_str(FDEVP_DUMP_ALL); \ case_str(FDEVP_TERMINATE); \ case_str(FDEVP_CNX_MSG_RECV); \ case_str(FDEVP_CNX_ERROR); \ @@ -280,8 +274,6 @@ /* Functions */ int fd_peer_fini(); -void fd_peer_dump_list(int details); -void fd_peer_dump(struct fd_peer * peer, int details); int fd_peer_alloc(struct fd_peer ** ptr); int fd_peer_free(struct fd_peer ** ptr); int fd_peer_handle_newCER( struct msg ** cer, struct cnxctx ** cnx ); @@ -338,7 +330,6 @@ /* Server sockets */ -void fd_servers_dump(); int fd_servers_start(); int fd_servers_stop(); diff -r 6b7966ea27fb -r 7d7266115a34 libfdcore/p_psm.c --- a/libfdcore/p_psm.c Fri May 03 15:33:57 2013 +0800 +++ b/libfdcore/p_psm.c Fri May 03 19:20:56 2013 +0800 @@ -453,12 +453,6 @@ goto psm_loop; } - /* Handle the (easy) debug event now */ - if (event == FDEVP_DUMP_ALL) { - fd_peer_dump(peer, ANNOYING); - goto psm_loop; - } - /* Requests to terminate the peer object */ if (event == FDEVP_TERMINATE) { switch (cur_state) { @@ -711,11 +705,12 @@ /* Get the new ones */ CHECK_FCT_DO( fd_cnx_getremoteeps(peer->p_cnxctx, &peer->p_hdr.info.pi_endpoints), /* ignore the error */); - /* We do not support local endpoints change currently, but it could be added here if needed (refresh fd_g_config->cnf_endpoints)*/ - - if (TRACE_BOOL(ANNOYING)) { - TRACE_DEBUG(ANNOYING, "New remote endpoint(s):" ); - fd_ep_dump(6, &peer->p_hdr.info.pi_endpoints); + /* We do not support local endpoints change currently, but it could be added here if needed (refresh fd_g_config->cnf_endpoints) */ + { + char * buf = NULL; + size_t len = 0; + LOG_D("New remote endpoint(s): %s", fd_ep_dump(&buf, &len, NULL, 6, &peer->p_hdr.info.pi_endpoints) ?: "error"); + free(buf); } /* Done */ diff -r 6b7966ea27fb -r 7d7266115a34 libfdcore/peers.c --- a/libfdcore/peers.c Fri May 03 15:33:57 2013 +0800 +++ b/libfdcore/peers.c Fri May 03 19:20:56 2013 +0800 @@ -409,53 +409,63 @@ } /* Dump info of one peer */ -void fd_peer_dump(struct fd_peer * peer, int details) +DECLARE_FD_DUMP_PROTOTYPE(fd_peer_dump, struct peer_hdr * p, int details) { - char buf[1024]; - if (peer->p_eyec != EYEC_PEER) { - fd_log_debug(" Invalid peer @ %p !", peer); - return; - } - - snprintf(buf, sizeof(buf), "> %s\t%s\t[%ldsr,%ldpa]", STATE_STR(fd_peer_getstate(peer)), peer->p_hdr.info.pi_diamid, peer->p_sr.cnt, peer->p_reqin_count); - if (details > INFO) { - snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "\t(rlm:%s)", peer->p_hdr.info.runtime.pir_realm ?: ""); - if (peer->p_hdr.info.runtime.pir_prodname) - snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "\t['%s' %u]", peer->p_hdr.info.runtime.pir_prodname, peer->p_hdr.info.runtime.pir_firmrev); + size_t o=0; + if (!offset) + offset = &o; + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{peer}(@%p): ", p), return NULL); + + if (!CHECK_PEER(p)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL"), return NULL); + } else { + struct fd_peer * peer = (struct fd_peer *)p; + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s [%s, cnt:%ldsr,%ldpa]", peer->p_hdr.info.pi_diamid, STATE_STR(fd_peer_getstate(peer)), peer->p_sr.cnt, peer->p_reqin_count), return NULL); + if (details > 0) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " rlm:%s", peer->p_hdr.info.runtime.pir_realm ?: ""), return NULL); + if (peer->p_hdr.info.runtime.pir_prodname) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " ['%s' %u]", peer->p_hdr.info.runtime.pir_prodname, peer->p_hdr.info.runtime.pir_firmrev), return NULL); + } + } + if (details > 1) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " [from:%s] flags:%s%s%s%s%s%s%s lft:%ds", + peer->p_dbgorig ?: "unset", + peer->p_hdr.info.config.pic_flags.pro3 == PI_P3_DEFAULT ? "-" : + (peer->p_hdr.info.config.pic_flags.pro3 == PI_P3_IP ? "4" : "6"), + peer->p_hdr.info.config.pic_flags.pro4 == PI_P4_DEFAULT ? "-" : + (peer->p_hdr.info.config.pic_flags.pro4 == PI_P4_TCP ? "T" : "S"), + peer->p_hdr.info.config.pic_flags.alg ? "P" : "-", + peer->p_hdr.info.config.pic_flags.sec & PI_SEC_NONE ? "N" :"-", + peer->p_hdr.info.config.pic_flags.sec & PI_SEC_TLS_OLD ? "O" :"-", + peer->p_hdr.info.config.pic_flags.exp ? "E" : "-", + peer->p_hdr.info.config.pic_flags.persist ? "P" : "-", + peer->p_hdr.info.config.pic_lft), return NULL); + } + } - fd_log_debug("%s", buf); - if (details > FULL) { - /* Dump all info */ - fd_log_debug("\tEntry origin : %s", peer->p_dbgorig?: "not set"); - fd_log_debug("\tConfig flags : %s%s%s - %s%s - %s%s", - peer->p_hdr.info.config.pic_flags.pro3 == PI_P3_DEFAULT ? "." : - (peer->p_hdr.info.config.pic_flags.pro3 == PI_P3_IP ? "IP" : "IPv6"), - peer->p_hdr.info.config.pic_flags.pro4 == PI_P4_DEFAULT ? "." : - (peer->p_hdr.info.config.pic_flags.pro4 == PI_P4_TCP ? "TCP" : "SCTP"), - peer->p_hdr.info.config.pic_flags.alg ? "PrefTCP" : ".", - peer->p_hdr.info.config.pic_flags.sec & PI_SEC_NONE ? "NoTLSok" :".", - peer->p_hdr.info.config.pic_flags.sec & PI_SEC_TLS_OLD ? "OldTLS" :".", - peer->p_hdr.info.config.pic_flags.exp ? "Expire" : ".", - peer->p_hdr.info.config.pic_flags.persist ? "Persist" : "." - ); - fd_log_debug("\tLifetime : %d sec", peer->p_hdr.info.config.pic_lft); - } + + return *buf; } /* Dump the list of peers */ -void fd_peer_dump_list(int details) +DECLARE_FD_DUMP_PROTOTYPE(fd_peer_dump_list, int details) { struct fd_list * li; + size_t o=0; + if (!offset) + offset = &o; - fd_log_debug("Dumping list of peers :"); CHECK_FCT_DO( pthread_rwlock_rdlock(&fd_g_peers_rw), /* continue */ ); for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) { - struct fd_peer * np = (struct fd_peer *)li->o; - fd_peer_dump(np, details); + CHECK_MALLOC_DO( fd_peer_dump(FD_DUMP_STD_PARAMS, (struct peer_hdr *)li->o, details), break); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), break); } CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ ); + return *buf; } static struct dict_object *avp_oh_model = NULL; diff -r 6b7966ea27fb -r 7d7266115a34 libfdcore/server.c --- a/libfdcore/server.c Fri May 03 15:33:57 2013 +0800 +++ b/libfdcore/server.c Fri May 03 19:20:56 2013 +0800 @@ -93,33 +93,35 @@ /* Dump all servers information */ -void fd_servers_dump() +DECLARE_FD_DUMP_PROTOTYPE(fd_servers_dump) { struct fd_list * li, *cli; + size_t o=0; + if (!offset) + offset = &o; - fd_log_debug("Dumping servers list :"); for (li = FD_SERVERS.next; li != &FD_SERVERS; li = li->next) { struct server * s = (struct server *)li; enum s_state st = get_status(s); - fd_log_debug(" Serv %p '%s': %s, %s, %s", - s, fd_cnx_getid(s->conn), + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{server}(@%p)'%s': %s, %s, %s\n", s, fd_cnx_getid(s->conn), IPPROTO_NAME( s->proto ), s->secur ? "Secur" : "NotSecur", (st == NOT_CREATED) ? "Thread not created" : ((st == RUNNING) ? "Thread running" : ((st == TERMINATED) ? "Thread terminated" : - "Thread status unknown"))); + "Thread status unknown"))), return NULL); /* Dump the client list of this server */ CHECK_POSIX_DO( pthread_mutex_lock(&s->clients_mtx), ); for (cli = s->clients.next; cli != &s->clients; cli = cli->next) { struct client * c = (struct client *)cli; char bufts[128]; - fd_log_debug(" Connected: '%s' (timeout: %s)", - fd_cnx_getid(c->conn), - fd_log_time(&c->ts, bufts, sizeof(bufts))); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {client}(@%p)'%s': to:%s\n", c, fd_cnx_getid(c->conn), fd_log_time(&c->ts, bufts, sizeof(bufts))), break); } CHECK_POSIX_DO( pthread_mutex_unlock(&s->clients_mtx), ); } + + return *buf; } @@ -392,9 +394,14 @@ return EINVAL; } } - if (TRACE_BOOL(FULL)){ - fd_log_debug(" Local server address(es) :"); - fd_ep_dump( 5, &fd_g_config->cnf_endpoints ); + + { + char * buf = NULL; + size_t len = 0, offset = 0; + CHECK_MALLOC_DO( fd_dump_extend( &buf, &len, &offset , "Local server address(es): "), ); + CHECK_MALLOC_DO( fd_ep_dump( &buf, &len, &offset, 5, &fd_g_config->cnf_endpoints ), ); + LOG_N("%s", buf ?: "Error dumping addresses"); + free(buf); } return 0; } diff -r 6b7966ea27fb -r 7d7266115a34 libfdcore/tcp.c --- a/libfdcore/tcp.c Fri May 03 15:33:57 2013 +0800 +++ b/libfdcore/tcp.c Fri May 03 19:20:56 2013 +0800 @@ -123,6 +123,7 @@ { int ret = 0; int s; + char * buf = NULL; size_t len = 0; TRACE_ENTRY("%p %p %d", sock, sa, salen); CHECK_PARAMS( sock && (*sock <= 0) && sa && salen ); @@ -136,7 +137,8 @@ /* Cleanup if we are cancelled */ pthread_cleanup_push(fd_cleanup_socket, &s); - TRACE_sSA(FD_LOG_DEBUG, FULL, "Attempting TCP connection with peer: ", sa, NI_NUMERICHOST | NI_NUMERICSERV, "..." ); + LOG_D( "Attempting TCP connection to %s...", fd_sa_dump_node(&buf, &len, NULL, sa, NI_NUMERICHOST | NI_NUMERICSERV)?:"" ); + free(buf); /* Try connecting to the remote address */ ret = connect(s, sa, salen); diff -r 6b7966ea27fb -r 7d7266115a34 libfdproto/dictionary.c --- a/libfdproto/dictionary.c Fri May 03 15:33:57 2013 +0800 +++ b/libfdproto/dictionary.c Fri May 03 19:20:56 2013 +0800 @@ -147,13 +147,13 @@ }; /* Forward declarations of dump functions */ -static void dump_vendor_data ( void * data ); -static void dump_application_data ( void * data ); -static void dump_type_data ( void * data ); +static DECLARE_FD_DUMP_PROTOTYPE(dump_vendor_data, void * data ); +static DECLARE_FD_DUMP_PROTOTYPE(dump_application_data, void * data ); +static DECLARE_FD_DUMP_PROTOTYPE(dump_type_data, void * data ); /* the dump function for enum has a different prototype since it need the datatype */ -static void dump_avp_data ( void * data ); -static void dump_command_data ( void * data ); -static void dump_rule_data ( void * data ); +static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_data, void * data ); +static DECLARE_FD_DUMP_PROTOTYPE(dump_command_data, void * data ); +static DECLARE_FD_DUMP_PROTOTYPE(dump_rule_data, void * data ); /* Forward declarations of search functions */ static int search_vendor ( struct dictionary * dict, int criteria, const void * what, struct dict_object **result ); @@ -172,7 +172,7 @@ int parent; /* 0: never; 1: may; 2: must */ enum dict_object_type parenttype; /* The type of the parent, when relevant */ int eyecatcher; /* A kind of signature for this object */ - void (*dump_data)(void * data ); /* The function to dump the data section */ + DECLARE_FD_DUMP_PROTOTYPE( (*dump_data), void * data ); /* The function to dump the data section */ int (*search_fct)(struct dictionary * dict, int criteria, const void * what, struct dict_object **result );; /* The function to search an object of this type */ int haslist[NB_LISTS_PER_OBJ]; /* Tell if this list is used */ } dict_obj_info[] = { { 0, "(error)", 0, 0, 0, 0, NULL, NULL, {0, 0, 0} } @@ -1149,29 +1149,29 @@ /*******************************************************************************************************/ /*******************************************************************************************************/ /* The following functions are used to debug the module, and allow to print out the content of the dictionary */ -static void dump_vendor_data ( void * data ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_vendor_data, void * data ) { struct dict_vendor_data * vendor = (struct dict_vendor_data *)data; - fd_log_debug("data: %-6u \"%s\"", vendor->vendor_id, vendor->vendor_name); + return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-6u \"%s\"", vendor->vendor_id, vendor->vendor_name); } -static void dump_application_data ( void * data ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_application_data, void * data ) { struct dict_application_data * appli = (struct dict_application_data *) data; - fd_log_debug("data: %-6u \"%s\"", appli->application_id, appli->application_name); + return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-6u \"%s\"", appli->application_id, appli->application_name); } -static void dump_type_data ( void * data ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_type_data, void * data ) { struct dict_type_data * type = ( struct dict_type_data * ) data; - fd_log_debug("data: %-12s \"%s\"", + return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-12s \"%s\"", type_base_name[type->type_base], type->type_name); } -static void dump_enumval_data ( struct dict_enumval_data * enumval, enum dict_avp_basetype type ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_enumval_data, struct dict_enumval_data * enumval, enum dict_avp_basetype type ) { const int LEN_MAX = 20; - fd_log_debug("data: (%-12s) \"%s\" -> ", type_base_name[type], enumval->enum_name); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "data: (%-12s) \"%s\" -> ", type_base_name[type], enumval->enum_name), return NULL); switch (type) { case AVP_TYPE_OCTETSTRING: { @@ -1179,60 +1179,61 @@ if (enumval->enum_value.os.len < LEN_MAX) n = enumval->enum_value.os.len; for (i=0; i < n; i++) - fd_log_debug("0x%2hhX/'%c' ", enumval->enum_value.os.data[i], ASCII(enumval->enum_value.os.data[i])); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "0x%2hhX/'%c' ", enumval->enum_value.os.data[i], ASCII(enumval->enum_value.os.data[i])), return NULL); if (n == LEN_MAX) - fd_log_debug("..."); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "..."), return NULL); } break; case AVP_TYPE_INTEGER32: - fd_log_debug("%i", enumval->enum_value.i32); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%i", enumval->enum_value.i32), return NULL); break; case AVP_TYPE_INTEGER64: - fd_log_debug("%"PRId64, enumval->enum_value.i64); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%"PRId64, enumval->enum_value.i64), return NULL); break; case AVP_TYPE_UNSIGNED32: - fd_log_debug("%u", enumval->enum_value.u32); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%u", enumval->enum_value.u32), return NULL); break; case AVP_TYPE_UNSIGNED64: - fd_log_debug("%"PRIu64, enumval->enum_value.u64); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%"PRIu64, enumval->enum_value.u64), return NULL); break; case AVP_TYPE_FLOAT32: - fd_log_debug("%f", enumval->enum_value.f32); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%f", enumval->enum_value.f32), return NULL); break; case AVP_TYPE_FLOAT64: - fd_log_debug("%g", enumval->enum_value.f64); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%g", enumval->enum_value.f64), return NULL); break; default: - fd_log_debug("??? (ERROR unknown type %d)", type); + CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "??? (ERROR unknown type %d)", type), return NULL); } + return *buf; } -static void dump_avp_data ( void * data ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_data, void * data ) { struct dict_avp_data * avp = (struct dict_avp_data * ) data; - fd_log_debug("data: v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %-6u \"%s\"", + return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %-6u \"%s\"", DUMP_AVPFL_val(avp->avp_flag_val), DUMP_AVPFL_val(avp->avp_flag_mask), type_base_name[avp->avp_basetype], avp->avp_code, avp->avp_name ); } -static void dump_command_data ( void * data ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_command_data, void * data ) { struct dict_cmd_data * cmd = (struct dict_cmd_data *) data; - fd_log_debug("data: v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %-6u \"%s\"", + return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %-6u \"%s\"", DUMP_CMDFL_val(cmd->cmd_flag_val), DUMP_CMDFL_val(cmd->cmd_flag_mask), cmd->cmd_code, cmd->cmd_name); } -static void dump_rule_data ( void * data ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_rule_data, void * data ) { struct dict_rule_data * rule = (struct dict_rule_data * )data; - fd_log_debug("data: pos:%d ord:%d m/M:%2d/%2d avp:\"%s\"", + return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: pos:%d ord:%d m/M:%2d/%2d avp:\"%s\"", rule->rule_position, rule->rule_order, rule->rule_min, @@ -1240,158 +1241,166 @@ rule->rule_avp->data.avp.avp_name); } -static void dump_object ( struct dict_object * obj, int parents, int depth, int indent ); +static DECLARE_FD_DUMP_PROTOTYPE(dump_object, struct dict_object * obj, int parents, int depth, int indent ); -static void dump_list ( struct fd_list * sentinel, int parents, int depth, int indent ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_list, struct fd_list * sentinel, int parents, int depth, int indent ) { struct fd_list * li = sentinel; /* We don't lock here, the caller must have taken the dictionary lock for reading already */ while (li->next != sentinel) { li = li->next; - dump_object( _O(li->o), parents, depth, indent ); + CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, _O(li->o), parents, depth, indent ), return NULL); } } -static void dump_object ( struct dict_object * obj, int parents, int depth, int indent ) +static DECLARE_FD_DUMP_PROTOTYPE(dump_object, struct dict_object * obj, int parents, int depth, int indent ) { - if (obj == NULL) - return; + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*s{dictobj}(@%p): ", indent, "", obj), return NULL); - if (parents) - dump_object (obj->parent, parents-1, 0, indent + 1 ); + if (!verify_object(obj)) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL\n"), return NULL); + return *buf; + } + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s p:%p ", + _OBINFO(obj).name, + obj->parent), return NULL); - fd_log_debug("%*s@%p: %s%s (p:%-9p) ", - indent, - "", - obj, - verify_object(obj) ? "" : "INVALID ", - _OBINFO(obj).name, - obj->parent); + if (obj->type == DICT_ENUMVAL) { + CHECK_MALLOC_DO( dump_enumval_data ( FD_DUMP_STD_PARAMS, &obj->data.enumval, obj->parent->data.type.type_base ), return NULL); + } else { + CHECK_MALLOC_DO( _OBINFO(obj).dump_data(FD_DUMP_STD_PARAMS, &obj->data), return NULL); + } - if (obj->type == DICT_ENUMVAL) - dump_enumval_data ( &obj->data.enumval, obj->parent->data.type.type_base ); - else - _OBINFO(obj).dump_data(&obj->data); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL); + + if (parents) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*sparent:", indent + 1, ""), return NULL); + CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, obj->parent, parents-1, 0, 0 ), return NULL); + } if (depth) { int i; for (i=0; ilist[i].o == NULL) && (obj->list[i].next != &obj->list[i])) { - fd_log_debug("%*s>%p: list[%d]:", indent, "", obj, i); - dump_list(&obj->list[i], parents, depth - 1, indent + 2); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*slist[%d]:\n", indent + 1, "", i), return NULL); + CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &obj->list[i], 0, depth - 1, indent + 2), return NULL); } } } + + return *buf; } -void fd_dict_dump_object(struct dict_object * obj) +DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_object, struct dict_object * obj) { - fd_log_debug("Dictionary object %p dump:", obj); - dump_object( obj, 1, 2, 2 ); + size_t o = 0; + + if (!offset) + offset = &o; + + CHECK_MALLOC_DO( dump_object(FD_DUMP_STD_PARAMS, obj, 1, 2, 0), return NULL); + + return *buf; } -void fd_dict_dump(struct dictionary * dict) +DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump, struct dictionary * dict) { int i; struct fd_list * li; + size_t o = 0; + + if (!offset) + offset = &o; + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{dictionary}(@%p): ", dict), return NULL); - CHECK_PARAMS_DO(dict && (dict->dict_eyec == DICT_EYECATCHER), return); + if ((dict == NULL) || (dict->dict_eyec != DICT_EYECATCHER)) { + return fd_dump_extend(FD_DUMP_STD_PARAMS, "INVALID/NULL\n"); + } CHECK_POSIX_DO( pthread_rwlock_rdlock( &dict->dict_lock ), /* ignore */ ); - fd_log_debug("######################################################"); - fd_log_debug("###### Dumping vendors, AVPs and related rules #######"); - - dump_object( &dict->dict_vendors, 0, 3, 0 ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict:%p > vendors, AVPs and related rules}\n", dict), goto error); + CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_vendors, 0, 3, 3 ), goto error); for (li = dict->dict_vendors.list[0].next; li != &dict->dict_vendors.list[0]; li = li->next) - dump_object( li->o, 0, 3, 0 ); + CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 3, 3 ), goto error); - fd_log_debug("###### Dumping applications #######"); - - dump_object( &dict->dict_applications, 0, 1, 0 ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {dict:%p > applications}\n", dict), goto error); + CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_applications, 0, 1, 3 ), goto error); for (li = dict->dict_applications.list[0].next; li != &dict->dict_applications.list[0]; li = li->next) - dump_object( li->o, 0, 1, 0 ); + CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 1, 3 ), goto error); - fd_log_debug("###### Dumping types #######"); - - dump_list( &dict->dict_types, 0, 2, 0 ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {dict:%p > types}\n", dict), goto error); + CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_types, 0, 2, 3 ), goto error); - fd_log_debug("###### Dumping commands per name #######"); - - dump_list( &dict->dict_cmd_name, 0, 2, 0 ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {dict:%p > commands}\n", dict), goto error); + CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_cmd_code, 0, 0, 3 ), goto error); - fd_log_debug("###### Dumping commands per code and flags #######"); - - dump_list( &dict->dict_cmd_code, 0, 0, 0 ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {dict:%p > statistics}\n", dict), goto error); + for (i=1; i<=DICT_TYPE_MAX; i++) + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " %5d: %s\n", dict->dict_count[i], dict_obj_info[i].name), goto error); - fd_log_debug("###### Statistics #######"); - - for (i=1; i<=DICT_TYPE_MAX; i++) - fd_log_debug(" %5d objects of type %s", dict->dict_count[i], dict_obj_info[i].name); - - fd_log_debug("######################################################"); - + CHECK_POSIX_DO( pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */ ); + return *buf; +error: /* Free the rwlock */ CHECK_POSIX_DO( pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */ ); + return NULL; } /**************************** Dump AVP values ********************************/ /* Default dump functions */ -static int dump_val_os(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) +static DECLARE_FD_DUMP_PROTOTYPE(dump_val_os, union avp_value * value) { int i; - CHECK_FCT( dump_add_str(outstr, offset, outlen, "<") ); + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "<"), return NULL); for (i = 0; i < value->os.len; i++) { if (i == 1024) { /* Dump only up to 1024 bytes of the buffer */ - CHECK_FCT( dump_add_str(outstr, offset, outlen, "[...] (len=%zd)", value->os.len) ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "[...] (len=%zd)", value->os.len), return NULL); break; } - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%s%02.2X", (i==0 ? "" : " "), value->os.data[i]) ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s%02hhX", (i==0 ? "" : " "), value->os.data[i]), return NULL); } - CHECK_FCT( dump_add_str(outstr, offset, outlen, ">") ); - return 0; + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, ">"), return NULL); + return *buf; } -static int dump_val_i32(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) +static DECLARE_FD_DUMP_PROTOTYPE(dump_val_i32, union avp_value * value) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%i (0x%x)", value->i32, value->i32) ); - return 0; + return fd_dump_extend( FD_DUMP_STD_PARAMS, "%i (0x%x)", value->i32, value->i32); } -static int dump_val_i64(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) +static DECLARE_FD_DUMP_PROTOTYPE(dump_val_i64, union avp_value * value) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%lli (0x%llx)", value->i64, value->i64) ); - return 0; + return fd_dump_extend( FD_DUMP_STD_PARAMS, "%" PRId64 " (0x%" PRIx64 ")", value->i64, value->i64); } -static int dump_val_u32(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) +static DECLARE_FD_DUMP_PROTOTYPE(dump_val_u32, union avp_value * value) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%u (0x%x)", value->u32, value->u32) ); - return 0; + return fd_dump_extend( FD_DUMP_STD_PARAMS, "%u (0x%x)", value->u32, value->u32); } -static int dump_val_u64(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) +static DECLARE_FD_DUMP_PROTOTYPE(dump_val_u64, union avp_value * value) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%llu (0x%llx)", value->u64, value->u64) ); - return 0; + return fd_dump_extend( FD_DUMP_STD_PARAMS, "%" PRIu64 " (0x%" PRIx64 ")", value->u64, value->u64); } -static int dump_val_f32(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) +static DECLARE_FD_DUMP_PROTOTYPE(dump_val_f32, union avp_value * value) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%f", value->f32) ); - return 0; + return fd_dump_extend( FD_DUMP_STD_PARAMS, "%f", value->f32); } -static int dump_val_f64(union avp_value * value, char **outstr, size_t *offset, size_t *outlen) +static DECLARE_FD_DUMP_PROTOTYPE(dump_val_f64, union avp_value * value) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%g", value->f64) ); - return 0; + return fd_dump_extend( FD_DUMP_STD_PARAMS, "%g", value->f64); } /* Get the dump function for basic dict_avp_basetype */ -static int (*get_default_dump_val_cb(enum dict_avp_basetype datatype))(union avp_value *, char **, size_t *, size_t *) +static DECLARE_FD_DUMP_PROTOTYPE((*get_default_dump_val_cb(enum dict_avp_basetype datatype)), union avp_value *) { switch (datatype) { case AVP_TYPE_OCTETSTRING: @@ -1425,63 +1434,63 @@ #define INOBJHDR "%*s " #define INOBJHDRVAL indent<0 ? 1 : indent, indent<0 ? "-" : "|" +typedef DECLARE_FD_DUMP_PROTOTYPE((*dump_val_cb_t), union avp_value *); + /* Formatter for the AVP value dump line */ -static int dump_avp_val(union avp_value *avp_value, - int (*def_dump_val_cb)(union avp_value *, char **, size_t *, size_t *), - char * (*dump_val_cb)(union avp_value *), +static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_val, union avp_value *avp_value, + dump_val_cb_t def_dump_val_cb, + dump_val_cb_t dump_val_cb, enum dict_avp_basetype datatype, char * type_name, char * const_name, int indent, - char **outstr, - size_t *offset, - size_t *outlen, int header) { if (header) { /* Header for all AVP values dumps: */ - CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "value ", INOBJHDRVAL) ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, INOBJHDR "value ", INOBJHDRVAL), return NULL); /* If the type is provided, write it */ if (type_name) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "t: '%s' ", type_name) ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "t: '%s' ", type_name), return NULL); } /* Always give the base datatype anyway */ - CHECK_FCT( dump_add_str(outstr, offset, outlen, "(%s) ", type_base_name[datatype]) ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(%s) ", type_base_name[datatype]), return NULL); /* Now, the value */ - CHECK_FCT( dump_add_str(outstr, offset, outlen, "v: ") ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "v: "), return NULL); } if (const_name) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, "'%s' (", const_name) ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s' (", const_name), return NULL); } if (dump_val_cb) { - char * str; - CHECK_MALLOC_DO( str = (*dump_val_cb)(avp_value), dump_add_str(outstr, offset, outlen, "(dump failed)") ); - CHECK_FCT( dump_add_str(outstr, offset, outlen, "%s", str) ); - free(str); + CHECK_MALLOC_DO( (*dump_val_cb)( FD_DUMP_STD_PARAMS, avp_value), fd_dump_extend( FD_DUMP_STD_PARAMS, "(dump failed)")); } else { - CHECK_FCT( (*def_dump_val_cb)(avp_value, outstr, offset, outlen) ); + CHECK_MALLOC_DO( (*def_dump_val_cb)( FD_DUMP_STD_PARAMS, avp_value), return NULL); } if (const_name) { - CHECK_FCT( dump_add_str(outstr, offset, outlen, ")") ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, ")"), return NULL); } /* Done! */ - return 0; + return *buf; } /* Dump the value of an AVP of known type into the returned str */ -int fd_dict_dump_avp_value(union avp_value *avp_value, struct dict_object * model, int indent, char **outstr, size_t *offset, size_t *outlen, int header) +DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_avp_value, union avp_value *avp_value, struct dict_object * model, int indent, int header) { - char * (*dump_val_cb)(union avp_value *avp_value) = NULL; + DECLARE_FD_DUMP_PROTOTYPE((*dump_val_cb), union avp_value *avp_value) = NULL; struct dict_object * type = NULL; char * type_name = NULL; char * const_name = NULL; + size_t o = 0; + + if (!offset) + offset = &o; /* Check the parameters are correct */ - CHECK_PARAMS( avp_value && verify_object(model) && (model->type == DICT_AVP) ); + CHECK_PARAMS_DO( avp_value && verify_object(model) && (model->type == DICT_AVP), return NULL ); /* Get the type definition of this AVP */ type = model->parent; @@ -1501,14 +1510,14 @@ memcpy(&request.search.enum_value, avp_value, sizeof(union avp_value)); /* bypass checks */ if ((search_enumval( type->dico, ENUMVAL_BY_STRUCT, &request, &enumval ) == 0) && (enumval)) { - /* We found a cosntant, get its name */ + /* We found a constant, get its name */ const_name = enumval->data.enumval.enum_name; } } /* And finally, dump the value */ - CHECK_FCT( dump_avp_val(avp_value, get_default_dump_val_cb(model->data.avp.avp_basetype), dump_val_cb, model->data.avp.avp_basetype, type_name, const_name, indent, outstr, offset, outlen, header) ); - return 0; + CHECK_MALLOC_DO( dump_avp_val(FD_DUMP_STD_PARAMS, avp_value, get_default_dump_val_cb(model->data.avp.avp_basetype), dump_val_cb, model->data.avp.avp_basetype, type_name, const_name, indent, header), return NULL ); + return *buf; } /*******************************************************************************************************/ @@ -1573,51 +1582,51 @@ /* Check the "parent" parameter */ switch (dict_obj_info[type].parent) { case 0: /* parent is forbidden */ - CHECK_PARAMS( parent == NULL ); + CHECK_PARAMS_DO( parent == NULL, goto error_param ); case 1: /* parent is optional */ if (parent == NULL) break; case 2: /* parent is mandatory */ - CHECK_PARAMS( verify_object(parent) ); + CHECK_PARAMS_DO( verify_object(parent), goto error_param ); if (type == DICT_RULE ) { /* Special case : grouped AVP or Command parents are allowed */ - CHECK_PARAMS( (parent->type == DICT_COMMAND ) - || ( (parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED ) ) ); + CHECK_PARAMS_DO( (parent->type == DICT_COMMAND ) + || ( (parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED ) ), goto error_param ); } else { - CHECK_PARAMS( parent->type == dict_obj_info[type].parenttype ); + CHECK_PARAMS_DO( parent->type == dict_obj_info[type].parenttype, goto error_param ); } } /* For AVP object, we must also check that the "vendor" referenced exists */ if (type == DICT_AVP) { CHECK_FCT_DO( fd_dict_search( dict, DICT_VENDOR, VENDOR_BY_ID, &(((struct dict_avp_data *)data)->avp_vendor), (void*)&vendor, ENOENT ), - { TRACE_DEBUG(INFO, "Unable to find vendor '%d' referenced in the AVP data", ((struct dict_avp_data *)data)->avp_vendor); return EINVAL; } ); + { TRACE_DEBUG(INFO, "Unable to find vendor '%d' referenced in the AVP data", ((struct dict_avp_data *)data)->avp_vendor); goto error_param; } ); /* Also check if a parent is provided, that the type are the same */ if (parent) { - CHECK_PARAMS( parent->data.type.type_base == ((struct dict_avp_data *)data)->avp_basetype ); + CHECK_PARAMS_DO( parent->data.type.type_base == ((struct dict_avp_data *)data)->avp_basetype, goto error_param ); } } /* For RULE object, we must also check that the "avp" referenced exists */ if (type == DICT_RULE) { - CHECK_PARAMS( verify_object(((struct dict_rule_data *)data)->rule_avp) ); - CHECK_PARAMS( ((struct dict_rule_data *)data)->rule_avp->type == DICT_AVP ); + CHECK_PARAMS_DO( verify_object(((struct dict_rule_data *)data)->rule_avp), goto error_param ); + CHECK_PARAMS_DO( ((struct dict_rule_data *)data)->rule_avp->type == DICT_AVP, goto error_param ); } /* For COMMAND object, check that the 'R' flag is fixed */ if (type == DICT_COMMAND) { - CHECK_PARAMS( ((struct dict_cmd_data *)data)->cmd_flag_mask & CMD_FLAG_REQUEST ); + CHECK_PARAMS_DO( ((struct dict_cmd_data *)data)->cmd_flag_mask & CMD_FLAG_REQUEST, goto error_param ); } /* We have to check that the new values are not equal to the sentinels */ if (type == DICT_VENDOR) { - CHECK_PARAMS( ((struct dict_vendor_data *)data)->vendor_id != 0 ); + CHECK_PARAMS_DO( ((struct dict_vendor_data *)data)->vendor_id != 0, goto error_param ); } if (type == DICT_APPLICATION) { - CHECK_PARAMS( ((struct dict_application_data *)data)->application_id != 0 ); + CHECK_PARAMS_DO( ((struct dict_application_data *)data)->application_id != 0, goto error_param ); } /* Parameters are valid, create the new object */ @@ -1717,6 +1726,10 @@ return 0; +error_param: + ret = EINVAL; + goto all_errors; + error_unlock: CHECK_POSIX_DO( pthread_rwlock_unlock(&dict->dict_lock), /* continue */ ); if (ret == EEXIST) { @@ -1727,7 +1740,7 @@ /* if we are here, it means the two vendors id are identical */ if (fd_os_cmp(locref->data.vendor.vendor_name, locref->datastr_len, new->data.vendor.vendor_name, new->datastr_len)) { - TRACE_DEBUG(FULL, "Conflicting vendor name"); + TRACE_DEBUG(INFO, "Conflicting vendor name: %s", new->data.vendor.vendor_name); break; } /* Otherwise (same name), we consider the function succeeded, since the (same) object is in the dictionary */ @@ -1865,23 +1878,26 @@ ret = 0; break; } - if (ret) { - TRACE_DEBUG(INFO, "An existing object with different non-key data was found: EEXIST"); - if (TRACE_BOOL(INFO)) { - fd_log_debug("New object to insert:"); - dump_object(new, 0, 0, 3); - fd_log_debug("Object already in dictionary:"); - dump_object(locref, 0, 0 , 3); - } - } else { + if (!ret) { TRACE_DEBUG(FULL, "An existing object with the same data was found, ignoring the error..."); } if (ref) *ref = locref; - } else { - CHECK_FCT_DO( ret, ); /* log the error */ } - +all_errors: + if (ret != 0) { + char * buf = NULL; + size_t len = 0; + + CHECK_MALLOC( dict_obj_info[CHECK_TYPE(type) ? type : 0].dump_data(&buf, &len, NULL, data) ); + TRACE_DEBUG(INFO, "An error occurred while adding the following data in the dictionary: %s", buf); + + if (ret == EEXIST) { + CHECK_MALLOC( dump_object(&buf, &len, NULL, locref, 0, 0, 0) ); + TRACE_DEBUG(INFO, "Conflicting entry in the dictionary: %s", buf); + } + free(buf); + } error_free: free(new); return ret; diff -r 6b7966ea27fb -r 7d7266115a34 libfdproto/dictionary_functions.c --- a/libfdproto/dictionary_functions.c Fri May 03 15:33:57 2013 +0800 +++ b/libfdproto/dictionary_functions.c Fri May 03 19:20:56 2013 +0800 @@ -152,10 +152,8 @@ } /* Dump the content of an Address AVP */ -char * fd_dictfct_Address_dump(union avp_value * avp_value) +DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_Address_dump, union avp_value * avp_value) { - char * ret; - #define STR_LEN 1024 union { sSA sa; sSS ss; @@ -163,15 +161,17 @@ sSA6 sin6; } s; uint16_t fam; + size_t o = 0; + + if (!offset) + offset = &o; memset(&s, 0, sizeof(s)); - CHECK_MALLOC_DO( ret = malloc(STR_LEN), return NULL ); - /* The first two octets represent the address family, http://www.iana.org/assignments/address-family-numbers/ */ if (avp_value->os.len < 2) { - snprintf(ret, STR_LEN, "[invalid length: %zd]", avp_value->os.len); - return ret; + CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid length: %zd]", avp_value->os.len), return NULL); + return *buf; } /* Following octets are the address in network byte order already */ @@ -181,8 +181,8 @@ /* IP */ s.sa.sa_family = AF_INET; if (avp_value->os.len != 6) { - snprintf(ret, STR_LEN, "[invalid IP length: %zd]", avp_value->os.len); - return ret; + CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid IP length: %zd]", avp_value->os.len), return NULL); + return *buf; } memcpy(&s.sin.sin_addr.s_addr, avp_value->os.data + 2, 4); break; @@ -190,23 +190,17 @@ /* IP6 */ s.sa.sa_family = AF_INET6; if (avp_value->os.len != 18) { - snprintf(ret, STR_LEN, "[invalid IP6 length: %zd]", avp_value->os.len); - return ret; + CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid IP6 length: %zd]", avp_value->os.len), return NULL); + return *buf; } memcpy(&s.sin6.sin6_addr.s6_addr, avp_value->os.data + 2, 16); break; default: - snprintf(ret, STR_LEN, "[unsupported family: 0x%hx]", fam); - return ret; + CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[unsupported family: 0x%hx]", fam), return NULL); + return *buf; } - { - int rc = getnameinfo(&s.sa, sSAlen(&s.sa), ret, STR_LEN, NULL, 0, NI_NUMERICHOST); - if (rc) - snprintf(ret, STR_LEN, "%s", (char *)gai_strerror(rc)); - } - - return ret; + return fd_sa_dump_node(FD_DUMP_STD_PARAMS, &s.sa, NI_NUMERICHOST); } @@ -215,42 +209,25 @@ /* UTF8String AVP type */ /*******************************/ -/* Dump the AVP in a natural human-readable format */ -char * fd_dictfct_UTF8String_dump(union avp_value * avp_value) +/* Dump the AVP in a natural human-readable format. This dumps the complete length of the AVP, it is up to the caller to truncate if needed */ +DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_UTF8String_dump, union avp_value * avp_value) { -#define TRUNC_LEN 1024 /* avoid very long strings */ - char * ret; - CHECK_MALLOC_DO( ret = malloc(TRUNC_LEN+2+3+1), return NULL ); - *ret = '"'; - strncpy(ret+1, (char *)avp_value->os.data, TRUNC_LEN); - /* be sure to have a nul-terminated string */ - ret[TRUNC_LEN+1] = '\0'; - if (ret[1] != '\0') { - /* We sanitize the returned string to avoid UTF8 boundary problem. - We do this whether the string is trucated at TRUNC_LEN or not, to avoid potential problem - with malformed AVP */ - - char * end = strchr(ret, '\0'); - while (end > ret) { - end--; - char b = *end; - /* after the position pointed by end, we have only \0s */ - if ((b & 0x80) == 0) { - break; /* this is a single byte char, no problem */ - } else { - /* this byte is start or cont. of multibyte sequence, as we do not know the next byte we need to delete it. */ - *end = '\0'; - if (b & 0x40) - break; /* This was a start byte, we can stop the loop */ - } - } - if (strlen((char *)avp_value->os.data) > strlen(ret+1)) - strcat(end, "..."); - strcat(end, "\""); - } else { - *ret = '\0'; + size_t o = 0, l; + if (!offset) + offset = &o; + + l = avp_value->os.len; + /* Just in case the string ends in invalid UTF-8 chars, we shorten it */ + while ((l > 0) && (avp_value->os.data[l - 1] & 0x80)) { + /* this byte is start or cont. of multibyte sequence, as we do not know the next byte we need to delete it. */ + l--; + if (avp_value->os.data[l] & 0x40) + break; /* This was a start byte, we can stop the loop */ } - return ret; + + CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "\"%.*s\"", (int)l, (char *)avp_value->os.data), return NULL); + + return *buf; } @@ -325,22 +302,26 @@ return diameter_string_to_time_t((const char *)avp_value->os.data, avp_value->os.len, interpreted); } -char * fd_dictfct_Time_dump(union avp_value * avp_value) +DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_Time_dump, union avp_value * avp_value) { - char * ret; + size_t o = 0; time_t val; struct tm conv; - CHECK_MALLOC_DO( ret = malloc(STR_LEN), return NULL ); + + if (!offset) + offset = &o; + if (avp_value->os.len != 4) { - snprintf(ret, STR_LEN, "[invalid length: %zd]", avp_value->os.len); - return ret; + CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid length: %zd]", avp_value->os.len), return NULL); + return *buf; } + if (diameter_string_to_time_t((char *)avp_value->os.data, avp_value->os.len, &val) != 0) { - snprintf(ret, STR_LEN, "[time conversion error]"); - return ret; + CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[time conversion error]"), return NULL); + return *buf; } - gmtime_r(&val, &conv); - snprintf(ret, STR_LEN, "%d%02d%02dT%02d%02d%02d+00", conv.tm_year+1900, conv.tm_mon+1, conv.tm_mday, conv.tm_hour, conv.tm_min, conv.tm_sec); - return ret; + + CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "%d%02d%02dT%02d%02d%02d+00", conv.tm_year+1900, conv.tm_mon+1, conv.tm_mday, conv.tm_hour, conv.tm_min, conv.tm_sec), return NULL); + return *buf; } diff -r 6b7966ea27fb -r 7d7266115a34 libfdproto/fdproto-internal.h --- a/libfdproto/fdproto-internal.h Fri May 03 15:33:57 2013 +0800 +++ b/libfdproto/fdproto-internal.h Fri May 03 19:20:56 2013 +0800 @@ -50,16 +50,12 @@ /* Where debug messages are sent */ extern FILE * fd_g_debug_fstr; -/* Special message dump function */ -void fd_msg_dump_fstr_one ( struct msg * msg, FILE * fstr ); -void fd_msg_dump_fstr ( struct msg * msg, FILE * fstr ); - /* Iterator on the rules of a parent object */ int fd_dict_iterate_rules ( struct dict_object *parent, void * data, int (*cb)(void *, struct dict_rule_data *) ); /* Dispatch / messages / dictionary API */ int fd_dict_disp_cb(enum dict_object_type type, struct dict_object *obj, struct fd_list ** cb_list); -int fd_dict_dump_avp_value(union avp_value *avp_value, struct dict_object * model, int indent, char **outstr, size_t *offset, size_t *outlen, int header); +DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_avp_value, union avp_value *avp_value, struct dict_object * model, int indent, int header); int fd_disp_call_cb_int( struct fd_list * cb_list, struct msg ** msg, struct avp *avp, struct session *sess, enum disp_action *action, struct dict_object * obj_app, struct dict_object * obj_cmd, struct dict_object * obj_avp, struct dict_object * obj_enu); extern pthread_rwlock_t fd_disp_lock; @@ -68,40 +64,4 @@ int fd_sess_reclaim_msg ( struct session ** session ); -/* For dump routines into string buffers */ -#include -static __inline__ int dump_init_str(char **outstr, size_t *offset, size_t *outlen) -{ - *outlen = 1<<12; - CHECK_MALLOC( *outstr = malloc(*outlen) ); - *offset = 0; - (*outstr)[0] = 0; - return 0; -} -static __inline__ int dump_add_str(char **outstr, size_t *offset, size_t *outlen, char * fmt, ...) -{ - va_list argp; - int len; - va_start(argp, fmt); - len = vsnprintf(*outstr + *offset, *outlen - *offset, fmt, argp); - va_end(argp); - if ((len + *offset) >= *outlen) { - char * newstr; - /* buffer was too short, extend */ - size_t newsize = ((len + *offset) + (1<<12)) & ~((1<<12) - 1); /* next multiple of 4k */ - CHECK_MALLOC( newstr = realloc(*outstr, newsize) ); - - /* redo */ - *outstr = newstr; - *outlen = newsize; - va_start(argp, fmt); - len = vsnprintf(*outstr + *offset, *outlen - *offset, fmt, argp); - va_end(argp); - } - *offset += len; - return 0; -} - - - #endif /* _LIBFDPROTO_INTERNAL_H */ diff -r 6b7966ea27fb -r 7d7266115a34 libfdproto/fifo.c --- a/libfdproto/fifo.c Fri May 03 15:33:57 2013 +0800 +++ b/libfdproto/fifo.c Fri May 03 19:20:56 2013 +0800 @@ -118,46 +118,46 @@ } /* Dump the content of a queue */ -void fd_fifo_dump(int level, char * name, struct fifo * queue, void (*dump_item)(int level, void * item)) +DECLARE_FD_DUMP_PROTOTYPE(fd_fifo_dump, char * name, struct fifo * queue, fd_fifo_dump_item_cb dump_item) { - TRACE_ENTRY("%i %p %p %p", level, name, queue, dump_item); - - if (!TRACE_BOOL(level)) - return; + size_t o = 0; + if (!offset) + offset = &o; - fd_log_debug("Dumping queue '%s' (%p):", name ?: "?", queue); + if (name) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'(@%p): ", name, queue), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{fifo}(@%p): ", queue), return NULL); + } + if (!CHECK_FIFO( queue )) { - fd_log_debug(" Queue invalid!"); - if (queue) - fd_log_debug(" (%x != %x)", queue->eyec, FIFO_EYEC); - return; + return fd_dump_extend(FD_DUMP_STD_PARAMS, "INVALID/NULL\n"); } CHECK_POSIX_DO( pthread_mutex_lock( &queue->mtx ), /* continue */ ); - fd_log_debug(" %d elements in queue / %d threads waiting", queue->count, queue->thrs); - fd_log_debug(" %d elements max / %d threads waiting to push", queue->max, queue->thrs_push); - fd_log_debug(" thresholds: %d / %d (h:%d), cb: %p,%p (%p), highest: %d", - queue->high, queue->low, queue->highest, - queue->h_cb, queue->l_cb, queue->data, - queue->highest_ever); - fd_log_debug(" stats: total:%lld in %ld.%06ld, blocking:%ld.%06ld, last:%ld.%06ld", - queue->total_items, - (long)queue->total_time.tv_sec,(long)(queue->total_time.tv_nsec/1000), - (long)queue->blocking_time.tv_sec,(long)(queue->blocking_time.tv_nsec/1000), - (long)queue->last_time.tv_sec,(long)(queue->last_time.tv_nsec/1000) ); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "items:%d,%d,%d threads:%d,%d stats:%lld/%ld.%06ld,%ld.%06ld,%ld.%06ld thresholds:%d,%d,%d,%p,%p,%p\n", + queue->count, queue->highest_ever, queue->max, + queue->thrs, queue->thrs_push, + queue->total_items,(long)queue->total_time.tv_sec,(long)(queue->total_time.tv_nsec/1000),(long)queue->blocking_time.tv_sec,(long)(queue->blocking_time.tv_nsec/1000),(long)queue->last_time.tv_sec,(long)(queue->last_time.tv_nsec/1000), + queue->high, queue->low, queue->highest, queue->h_cb, queue->l_cb, queue->data), + goto error); if (dump_item) { struct fd_list * li; int i = 0; for (li = queue->list.next; li != &queue->list; li = li->next) { struct fifo_item * fi = (struct fifo_item *)li; - fd_log_debug(" [%i] item %p in fifo %p, posted:%ld.%06ld", - i++, fi->item.o, queue, (long)fi->posted_on.tv_sec,(long)(fi->posted_on.tv_nsec/1000)); - (*dump_item)(level, fi->item.o); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " [#%i](@%p)@%ld.%06ld: ", + i++, fi->item.o, (long)fi->posted_on.tv_sec,(long)(fi->posted_on.tv_nsec/1000)), + goto error); + CHECK_MALLOC_DO( (*dump_item)(FD_DUMP_STD_PARAMS, fi->item.o), goto error); } } CHECK_POSIX_DO( pthread_mutex_unlock( &queue->mtx ), /* continue */ ); - + return *buf; +error: + CHECK_POSIX_DO( pthread_mutex_unlock( &queue->mtx ), /* continue */ ); + return NULL; } /* Delete a queue. It must be empty. */ diff -r 6b7966ea27fb -r 7d7266115a34 libfdproto/log.c --- a/libfdproto/log.c Fri May 03 15:33:57 2013 +0800 +++ b/libfdproto/log.c Fri May 03 19:20:56 2013 +0800 @@ -142,14 +142,16 @@ (void)pthread_mutex_unlock(&fd_log_lock); } -/* Log debug message to file. */ -void fd_log_debug_fstr( FILE * fstr, const char * format, ... ) +/* Log a debug message */ +void fd_log_va ( int loglevel, const char * format, va_list args ) { - va_list ap; + (void)pthread_mutex_lock(&fd_log_lock); - va_start(ap, format); - vfprintf(fstr, format, ap); - va_end(ap); + pthread_cleanup_push(fd_cleanup_mutex_silent, &fd_log_lock); + fd_logger(loglevel, format, args); + pthread_cleanup_pop(0); + + (void)pthread_mutex_unlock(&fd_log_lock); } /* Function to set the thread's friendly name */ @@ -207,3 +209,51 @@ return buf; } + + +/* Helper function for fd_*_dump. Prints the format string from 'offset' into '*buf', extends if needed. The location of buf can be updated by this function. */ +char * fd_dump_extend(char ** buf, size_t *len, size_t *offset, const char * format, ... ) +{ + va_list ap; + int to_write; + size_t o = 0; + static size_t mempagesz = 0; + + if (!mempagesz) { + mempagesz = sysconf(_SC_PAGESIZE); /* We alloc buffer by memory pages for efficiency */ + if (mempagesz <= 0) + mempagesz = 1024; /* default size if above call failed */ + } + + /* we do not TRACE_ENTRY this one on purpose */ + + CHECK_PARAMS_DO(buf && len, return NULL); + + if (*buf == NULL) { + CHECK_MALLOC_DO(*buf = malloc(mempagesz), return NULL); + *len = mempagesz; + } + + if (offset) + o = *offset; + + va_start(ap, format); + to_write = vsnprintf(*buf + o, *len - o, format, ap); + va_end(ap); + + if (to_write + o >= *len) { + /* There was no room in the buffer, we extend and redo */ + size_t new_len = (((to_write + o) / mempagesz) + 1) * mempagesz; + CHECK_MALLOC_DO(*buf = realloc(*buf, new_len), return NULL); + *len = new_len; + + va_start(ap, format); + to_write = vsnprintf(*buf + o, *len - o, format, ap); + va_end(ap); + } + + if (offset) + *offset += to_write; + + return *buf; +} diff -r 6b7966ea27fb -r 7d7266115a34 libfdproto/messages.c --- a/libfdproto/messages.c Fri May 03 15:33:57 2013 +0800 +++ b/libfdproto/messages.c Fri May 03 19:20:56 2013 +0800 @@ -710,6 +710,34 @@ /***************************************************************************************************************/ /* Debug functions: dumping */ +#warning "todo" +DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_summary, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse ) +{ + return NULL; +} +/* one-line dump with all the contents of the message */ +DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_full, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse ) +{ + return NULL; +} +/* multi-line human-readable dump similar to wireshark output */ +DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_treeview, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse ) +{ + return NULL; +} + +#ifndef OLD_CODE_TO_BE_REPLACED +void fd_msg_dump_walk ( int level, msg_or_avp *obj ) +{ + LOG_D("fd_msg_dump_walk %d, %p is deprecated", level, obj); +} +void fd_msg_dump_one ( int level, msg_or_avp * obj ) +{ + LOG_D("fd_msg_dump_one %d, %p is deprecated", level, obj); +} +#else /* OLD_CODE_TO_BE_REPLACED */ + + /* indent inside an object */ #define INOBJHDR "%*s " #define INOBJHDRVAL indent<0 ? 1 : indent, indent<0 ? "-" : "|" @@ -1075,7 +1103,7 @@ free(outstr); } - +#endif /* OLD_CODE_TO_BE_REPLACED */ /***************************************************************************************************************/ /* Simple meta-data management */ diff -r 6b7966ea27fb -r 7d7266115a34 libfdproto/sessions.c --- a/libfdproto/sessions.c Fri May 03 15:33:57 2013 +0800 +++ b/libfdproto/sessions.c Fri May 03 19:20:56 2013 +0800 @@ -69,6 +69,7 @@ int eyec; /* An eye catcher also used to ensure the object is valid, must be SH_EYEC */ int id; /* A unique integer to identify this handler */ void (*cleanup)(session_state *, os0_t, void *); /* The cleanup function to be called for cleaning a state */ + session_state_dump *state_dump; /* dumper function */ void *opaque; /* a value that is passed as is to the cleanup callback */ }; @@ -272,7 +273,7 @@ } /* Create a new handler */ -int fd_sess_handler_create_internal ( struct session_handler ** handler, void (*cleanup)(session_state *, os0_t, void *), void * opaque ) +int fd_sess_handler_create_internal ( struct session_handler ** handler, void (*cleanup)(session_state *, os0_t, void *), session_state_dump dumper, void * opaque ) { struct session_handler *new; @@ -289,6 +290,7 @@ new->eyec = SH_EYEC; new->cleanup = cleanup; + new->state_dump = dumper; new->opaque = opaque; *handler = new; @@ -872,49 +874,63 @@ /* Dump functions */ -void fd_sess_dump(int level, struct session * session) +DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump, struct session * session, int with_states) { - struct fd_list * li; - char buf[30]; - struct tm tm; + size_t o = 0; + if (!offset) + offset = &o; + + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{session}(@%p): ", session), return NULL); - if (!TRACE_BOOL(level)) - return; - - fd_log_debug("\t %*s -- Session @%p --", level, "", session); if (!VALIDATE_SI(session)) { - fd_log_debug("\t %*s Invalid session object", level, ""); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL\n"), return NULL); } else { + char timebuf[30]; + struct tm tm; + + strftime(timebuf, sizeof(timebuf), "%D,%T", localtime_r( &session->timeout.tv_sec , &tm )); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'(%zd) h:%x m:%d d:%d to:%s.%06ld\n", + session->sid, session->sidlen, session->hash, session->msg_cnt, session->is_destroyed, + timebuf, session->timeout.tv_nsec/1000), + return NULL); - fd_log_debug("\t %*s sid '%s'(%zd), hash %x, msg %d, destroyed %d", level, "", session->sid, session->sidlen, session->hash, session->msg_cnt, session->is_destroyed); - - strftime(buf, sizeof(buf), "%D,%T", localtime_r( &session->timeout.tv_sec , &tm )); - fd_log_debug("\t %*s timeout %s.%09ld", level, "", buf, session->timeout.tv_nsec); - - CHECK_POSIX_DO( pthread_mutex_lock(&session->stlock), /* ignore */ ); - pthread_cleanup_push( fd_cleanup_mutex, &session->stlock ); - for (li = session->states.next; li != &session->states; li = li->next) { - struct state * st = (struct state *)(li->o); - fd_log_debug("\t %*s handler %d registered data %p", level, "", st->hdl->id, st->state); + if (with_states) { + struct fd_list * li; + CHECK_POSIX_DO( pthread_mutex_lock(&session->stlock), /* ignore */ ); + pthread_cleanup_push( fd_cleanup_mutex, &session->stlock ); + + for (li = session->states.next; li != &session->states; li = li->next) { + struct state * st = (struct state *)(li->o); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {state i:%d}(@%p): \n", st->hdl->id, st), return NULL); + if (st->hdl->state_dump) { + CHECK_MALLOC_DO( (*st->hdl->state_dump)( FD_DUMP_STD_PARAMS, st->state), + fd_dump_extend( FD_DUMP_STD_PARAMS, "[dumper error]\n")); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "<%p>\n", st->state), return NULL); + } + } + + pthread_cleanup_pop(0); + CHECK_POSIX_DO( pthread_mutex_unlock(&session->stlock), /* ignore */ ); } - pthread_cleanup_pop(0); - CHECK_POSIX_DO( pthread_mutex_unlock(&session->stlock), /* ignore */ ); } - fd_log_debug("\t %*s -- end of session @%p --", level, "", session); + return *buf; } -void fd_sess_dump_hdl(int level, struct session_handler * handler) +DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump_hdl, struct session_handler * handler) { - if (!TRACE_BOOL(level)) - return; + size_t o = 0; + if (!offset) + offset = &o; - fd_log_debug("\t %*s -- Handler @%p --", level, "", handler); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{sesshdl}(@%p): ", handler), return NULL); + if (!VALIDATE_SH(handler)) { - fd_log_debug("\t %*s Invalid session handler object", level, ""); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL\n"), return NULL); } else { - fd_log_debug("\t %*s id %d, cleanup %p, opaque %p", level, "", handler->id, handler->cleanup, handler->opaque); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "i:%d cl:%p d:%p o:%p\n", handler->id, handler->cleanup, handler->state_dump, handler->opaque), return NULL); } - fd_log_debug("\t %*s -- end of handler @%p --", level, "", handler); + return *buf; } int fd_sess_getcount(uint32_t *cnt) diff -r 6b7966ea27fb -r 7d7266115a34 libfdproto/utils.c --- a/libfdproto/utils.c Fri May 03 15:33:57 2013 +0800 +++ b/libfdproto/utils.c Fri May 03 19:20:56 2013 +0800 @@ -35,33 +35,44 @@ #include "fdproto-internal.h" -char * fd_sa_dump_node(char * buf, size_t bufsize, sSA * sa, int flags) +DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node, sSA * sa, int flags) { char addrbuf[INET6_ADDRSTRLEN]; + size_t o = 0; + if (!offset) + offset = &o; + if (sa) { int rc = getnameinfo(sa, sSAlen( sa ), addrbuf, sizeof(addrbuf), NULL, 0, flags); - if (rc) - snprintf(buf, bufsize, "%s", gai_strerror(rc)); - else - snprintf(buf, bufsize, "%s", &addrbuf[0]); + if (rc) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", gai_strerror(rc)), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", &addrbuf[0]), return NULL); + } } else { - snprintf(buf, bufsize, "(NULL / ANY)"); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(NULL / ANY)"), return NULL); } - return buf; + + return *buf; } -char * fd_sa_dump_node_serv(char * buf, size_t bufsize, sSA * sa, int flags) +DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node_serv, sSA * sa, int flags) { char addrbuf[INET6_ADDRSTRLEN]; char servbuf[32]; + size_t o = 0; + if (!offset) + offset = &o; + if (sa) { int rc = getnameinfo(sa, sSAlen( sa ), addrbuf, sizeof(addrbuf), servbuf, sizeof(servbuf), flags); - if (rc) - snprintf(buf, bufsize, "%s", gai_strerror(rc)); - else - snprintf(buf, bufsize, "%s", &addrbuf[0]); + if (rc) { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", gai_strerror(rc)), return NULL); + } else { + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", &addrbuf[0]), return NULL); + } } else { - snprintf(buf, bufsize, "(NULL / ANY)"); + CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(NULL / ANY)"), return NULL); } - return buf; + return *buf; }