comparison include/freeDiameter/libfdproto.h @ 1085:7d7266115a34

Cleaning of the traces in progress
author Sebastien Decugis <sdecugis@freediameter.net>
date Fri, 03 May 2013 19:20:56 +0800
parents b380c9f3be1e
children 1c5d410788cc
comparison
equal deleted inserted replaced
1084:6b7966ea27fb 1085:7d7266115a34
130 /*============================================================*/ 130 /*============================================================*/
131 131
132 132
133 /* 133 /*
134 * FUNCTION: fd_log 134 * FUNCTION: fd_log
135 * MACRO: fd_log_debug 135 *
136 * MACRO: fd_log_notice 136 * PARAMETERS:
137 * MACRO: fd_log_error 137 * loglevel : Integer, how important the message is. Valid values are macros FD_LOG_*
138 *
139 * PARAMETERS:
140 * loglevel : Integer, how important the message is
141 * format : Same format string as in the printf function 138 * format : Same format string as in the printf function
142 * ... : Same list as printf 139 * ... : Same list as printf
143 * 140 *
144 * DESCRIPTION: 141 * DESCRIPTION:
145 * Write information to log. 142 * Write information to log.
148 * 145 *
149 * RETURN VALUE: 146 * RETURN VALUE:
150 * None. 147 * None.
151 */ 148 */
152 void fd_log ( int, const char *, ... ) _ATTRIBUTE_PRINTFLIKE_(2,3); 149 void fd_log ( int, const char *, ... ) _ATTRIBUTE_PRINTFLIKE_(2,3);
153 #define fd_log_debug(format,args...) fd_log(FD_LOG_DEBUG, format, ## args) 150 void fd_log_va( int, const char *, va_list args );
154 #define fd_log_notice(format,args...) fd_log(FD_LOG_NOTICE, format, ## args)
155 #define fd_log_error(format,args...) fd_log(FD_LOG_ERROR, format, ## args)
156
157 void fd_log_debug_fstr( FILE *, const char *, ... );
158 151
159 /* these are internal objects of the debug facility, 152 /* these are internal objects of the debug facility,
160 might be useful to control the behavior from outside */ 153 might be useful to control the behavior from outside */
161 extern pthread_mutex_t fd_log_lock; 154 extern pthread_mutex_t fd_log_lock;
162 extern char * fd_debug_one_function; 155 extern char * fd_debug_one_function;
226 * int : Success or failure 219 * int : Success or failure
227 */ 220 */
228 int fd_log_handler_unregister ( void ); 221 int fd_log_handler_unregister ( void );
229 222
230 223
224 /* Helper function for the *dump functions that add into a buffer */
225 char * fd_dump_extend(char ** buf, size_t *len, size_t *offset, const char * format, ... ) _ATTRIBUTE_PRINTFLIKE_(4,5);
226
227 /* All dump functions follow the same prototype:
228 * PARAMETERS:
229 * buf : *buf can be NULL on entry, it will be malloc'd. Otherwise it can be realloc'd if needed.
230 * len : the current size of the buffer (in/out)
231 * offset: (optional) if provided, starts writing dump at offset in the buffer, and updated upon exit. if NULL, starts at offset O.
232 *
233 * RETURN VALUE:
234 * *buf upon success, NULL upon failure.
235 * After the buffer has been used, it should be freed.
236 */
237 #define DECLARE_FD_DUMP_PROTOTYPE( function_name, args... ) \
238 char * function_name(char ** buf, size_t *len, size_t *offset, ##args)
239
240 #define FD_DUMP_STD_PARAMS buf, len, offset
241
242
231 /*============================================================*/ 243 /*============================================================*/
232 /* DEBUG MACROS */ 244 /* DEBUG MACROS */
233 /*============================================================*/ 245 /*============================================================*/
234 246
235 #ifndef ASSERT 247 #ifndef ASSERT
236 #define ASSERT(x) assert(x) 248 #define ASSERT(x) assert(x)
237 #endif /* ASSERT */ 249 #endif /* ASSERT */
238 250
239 /* log levels definitions */ 251 /* log levels definitions, that are passed to the logger */
240 #define FD_LOG_DEBUG 0 /* Verbose information for developers use */ 252 #define FD_LOG_ANNOYING 0 /* very verbose loops and such "overkill" traces. Only active when the framework is compiled in DEBUG mode. */
241 #define FD_LOG_NOTICE 3 /* Normal execution states worth noting */ 253 #define FD_LOG_DEBUG 1 /* Get a detailed sense of what is going on in the framework. Use this level for normal debug */
242 #define FD_LOG_ERROR 5 /* Error conditions, both recoverable or not */ 254 #define FD_LOG_NOTICE 3 /* Normal execution states worth noting */
243 255 #define FD_LOG_ERROR 5 /* Recoverable or expected error conditions */
244 /* print level definitions */ 256 #define FD_LOG_FATAL 6 /* Unrecoverable error, e.g. malloc fail, etc. that requires the framework to shutdown */
245 #define NONE 0 /* Display no debug message */ 257
246 #define INFO 1 /* Display errors only */ 258 /* The level used by the default logger, can be changed by command-line arguments. Ignored for other loggers. */
247 #define FULL 2 /* Display additional information to follow code execution */
248 #define ANNOYING 4 /* Very verbose, for example in loops */
249 #define FCTS 6 /* Display entry parameters of most functions */
250 #define CALL 9 /* Display calls to most functions (with CHECK macros) */
251
252 /* A global level, changed by configuration or cmd line for example. Default is INFO (in libfdproto/log.c). */
253 extern int fd_g_debug_lvl; 259 extern int fd_g_debug_lvl;
254 260
255 /* Some portability code to get nice function name in __PRETTY_FUNCTION__ */ 261 /* Some portability code to get nice function name in __PRETTY_FUNCTION__ */
256 #if (!defined( __func__)) && (__STDC_VERSION__ < 199901L) 262 #if (!defined( __func__)) && (__STDC_VERSION__ < 199901L)
257 # if __GNUC__ >= 2 263 # if __GNUC__ >= 2
262 #endif /*(!defined( __func__)) && (__STDC_VERSION__ < 199901L) */ 268 #endif /*(!defined( __func__)) && (__STDC_VERSION__ < 199901L) */
263 #ifndef __PRETTY_FUNCTION__ 269 #ifndef __PRETTY_FUNCTION__
264 #define __PRETTY_FUNCTION__ __func__ 270 #define __PRETTY_FUNCTION__ __func__
265 #endif /* __PRETTY_FUNCTION__ */ 271 #endif /* __PRETTY_FUNCTION__ */
266 272
267 #ifdef DEBUG
268 /* A version of __FILE__ without the full path */ 273 /* A version of __FILE__ without the full path */
269 static char * file_bname = NULL; 274 static char * file_bname = NULL;
270 static char * file_bname_init(char * full) { file_bname = basename(full); return file_bname; } 275 static char * file_bname_init(char * full) { file_bname = basename(full); return file_bname; }
271 #define __STRIPPED_FILE__ (file_bname ?: file_bname_init((char *)__FILE__)) 276 #define __STRIPPED_FILE__ (file_bname ?: file_bname_init((char *)__FILE__))
272 277
273 /* Boolean for tracing at a certain level */ 278
274 #define TRACE_BOOL(_level_) ( ((_level_) <= fd_g_debug_lvl) \ 279
275 || (fd_debug_one_function && !strcmp(fd_debug_one_function, __PRETTY_FUNCTION__)) \ 280 /* In DEBUG mode, we add meta-information along each trace. This makes multi-threading problems easier to debug. */
276 || (fd_debug_one_file && !strcmp(fd_debug_one_file, __STRIPPED_FILE__) ) ) 281 #ifdef DEBUG
282 # define STD_TRACE_FMT_STRING "pid:%s in %s@%s:%d: "
283 # define STD_TRACE_FMT_ARGS , ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed"), __PRETTY_FUNCTION__, __STRIPPED_FILE__, __LINE__
277 #else /* DEBUG */ 284 #else /* DEBUG */
278 #define TRACE_BOOL(_level_) ((_level_) <= fd_g_debug_lvl) 285 # define STD_TRACE_FMT_STRING ""
279 #define __STRIPPED_FILE__ __FILE__ 286 # define STD_TRACE_FMT_ARGS
280 #endif /* DEBUG */ 287 #endif /* DEBUG */
281 288
282 289 /*************************
283 #define STD_TRACE_FMT_STRING "pid:%s in %s@%s:%d: " 290 The general debug macro
291 *************************/
292 #define LOG(printlevel,format,args... ) \
293 fd_log((printlevel), STD_TRACE_FMT_STRING format STD_TRACE_FMT_ARGS, ## args)
294
295 /*
296 * Use the following macros in the code to get traces with location & pid in debug mode:
297 */
298 #ifdef DEBUG
299 # define LOG_A(format,args... ) \
300 LOG(FD_LOG_ANNOYING,format,##args)
301 #else /* DEBUG */
302 # define LOG_A(format,args... ) /* not defined in release */
303 #endif /* DEBUG */
304
305 /* Debug information useful to follow in detail what is going on */
306 #define LOG_D(format,args... ) \
307 LOG(FD_LOG_DEBUG, format, ##args)
308
309 /* Report a normal message that is useful for normal admin monitoring */
310 #define LOG_N(format,args... ) \
311 LOG(FD_LOG_NOTICE, format,##args)
312
313 /* Report an error */
314 #define LOG_E(format,args... ) \
315 LOG(FD_LOG_ERROR, format, ##args)
316
317 /* Report a fatal error */
318 #define LOG_F(format,args... ) \
319 LOG(FD_LOG_FATAL, format, ##args)
320
321
284 /************* 322 /*************
285 The general debug macro, each call results in two lines of debug messages (change the macro for more compact output) 323 Derivatives
286 *************/ 324 ************/
287 #ifdef DEBUG 325 /* Trace a binary buffer content */
288 /* In DEBUG mode, we add (a lot of) meta-information along each trace. This makes multi-threading problems easier to debug. */ 326 #define LOG_BUFFER(printlevel, prefix, buf, bufsz, suffix ) { \
289 #define TRACE(printlevel,level,format,args... ) { \ 327 int __i; \
290 if ( TRACE_BOOL(level) ) { \ 328 size_t __sz = (size_t)(bufsz); \
291 const char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed"); \ 329 uint8_t * __buf = (uint8_t *)(buf); \
292 fd_log((printlevel), STD_TRACE_FMT_STRING format, \ 330 char __strbuf[1024+1]; \
293 __thn, __PRETTY_FUNCTION__, __STRIPPED_FILE__, __LINE__, ## args); \ 331 for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2)); __i++) { \
294 } \ 332 sprintf(__strbuf + (2 * __i), "%02hhx", __buf[__i]); \
333 } \
334 fd_log(printlevel, STD_TRACE_FMT_STRING "%s%s%s" STD_TRACE_FMT_ARGS, \
335 (prefix), __strbuf, (suffix)); \
295 } 336 }
296 #else /* DEBUG */ 337
297 /* Do not print thread, function, ... only the message itself in this case */
298 #define TRACE(printlevel,level,format,args... ) { \
299 if ( TRACE_BOOL(level) ) { \
300 fd_log((printlevel), format, ## args); \
301 } \
302 }
303 #endif /* DEBUG */
304
305 /* Report debug information */
306 #define TRACE_DEBUG(level,format,args... ) \
307 TRACE(FD_LOG_DEBUG,(level),format,##args)
308
309 /* Report a normal message that is useful for normal admin monitoring */
310 #define TRACE_NOTICE(format,args... ) \
311 TRACE(FD_LOG_NOTICE,INFO,format,##args)
312
313 /* Report an error */
314 #define TRACE_ERROR(format,args... ) \
315 TRACE(FD_LOG_ERROR, NONE, format, ##args)
316
317 /*
318 TRACE_NOTICE(...) and fd_log_notice(...) are equivalent when the code is not compiled in DEBUG mode,
319 but there is more contextual information when compiled in DEBUG with the TRACE_NOTICE macro,
320 hence it is recommended to use this one except for formatted output (e.g. fd_*_dump function)
321
322 resp. TRACE_DEBUG and TRACE_ERROR.
323 */
324
325 /*************
326 Derivatives for debug
327 ************/
328 /* Helper for function entry -- for very detailed trace of the execution */ 338 /* Helper for function entry -- for very detailed trace of the execution */
329 #define TRACE_ENTRY(_format,_args... ) \ 339 #define TRACE_ENTRY(_format,_args... ) \
330 TRACE_DEBUG(FCTS, "[enter] %s(" _format ") {" #_args "}", __PRETTY_FUNCTION__, ##_args ); 340 LOG_A(FCTS, "[enter] %s(" _format ") {" #_args "}", __PRETTY_FUNCTION__, ##_args );
331 341
332 /* Helper for debugging by adding traces -- for debuging a specific location of the code */ 342 /* Helper for debugging by adding traces -- for debuging a specific location of the code */
333 #define TRACE_HERE() \ 343 #define TRACE_HERE() \
334 TRACE_DEBUG(NONE, " -- debug checkpoint %d -- ", fd_breakhere()); 344 LOG_F(" -- debug checkpoint %d -- ", fd_breakhere());
335 int fd_breakhere(void); 345 int fd_breakhere(void);
336 346
337 /* Helper for tracing the CHECK_* macros below -- very very verbose code execution! */ 347 /* Helper for tracing the CHECK_* macros below -- very very verbose code execution! */
338 #define TRACE_DEBUG_ALL( str... ) \ 348 #define TRACE_CALL( str... ) \
339 TRACE_DEBUG(CALL, str ); 349 if ((fd_debug_one_function && !strcmp(fd_debug_one_function, __PRETTY_FUNCTION__)) \
350 || (fd_debug_one_file && !strcmp(fd_debug_one_file, __STRIPPED_FILE__) ) ) { \
351 LOG_A( str ); \
352 }
340 353
341 /* For development only, to keep track of TODO locations in the code */ 354 /* For development only, to keep track of TODO locations in the code */
342 #ifndef ERRORS_ON_TODO 355 #ifndef ERRORS_ON_TODO
343 #define TODO( _msg, _args... ) \ 356 # define TODO( _msg, _args... ) \
344 TRACE_DEBUG(NONE, "TODO: " _msg , ##_args); 357 LOG_F( "TODO: " _msg , ##_args);
345 #else /* ERRORS_ON_TODO */ 358 #else /* ERRORS_ON_TODO */
346 #define TODO( _msg, _args... ) \ 359 # define TODO( _msg, _args... ) \
347 "TODO" = _msg ## _args; /* just a stupid compilation error to spot the todo */ 360 "TODO" = _msg ## _args; /* just a stupid compilation error to spot the todo */
348 #endif /* ERRORS_ON_TODO */ 361 #endif /* ERRORS_ON_TODO */
349 362
350 /* Trace a binary buffer content */ 363
351 #ifdef DEBUG 364 /*============================================================*/
352 /* In DEBUG mode, we add (a lot of) meta-information along each trace. This makes multi-threading problems easier to debug. */ 365 /* ERROR CHECKING MACRO */
353 #define TRACE_BUFFER(printlevel, level, prefix, buf, bufsz, suffix ) { \ 366 /*============================================================*/
354 if ( TRACE_BOOL(level) ) { \ 367
355 int __i; \ 368 /* Macros to check a return value and branch out in case of error.
356 size_t __sz = (size_t)(bufsz); \ 369 * These macro additionally provide the logging information.
357 uint8_t * __buf = (uint8_t *)(buf); \ 370 *
358 char __strbuf[1024+1]; \ 371 * The name "__ret__" is always available in the __fallback__ parameter and contains the error code.
359 char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed"); \ 372 */
360 for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2)); __i++) { \ 373
361 sprintf(__strbuf + (2 * __i), "%2.2hhx", __buf[__i]); \ 374 #define CHECK_PRELUDE(__call__) \
362 } \ 375 int __ret__; \
363 fd_log(printlevel, STD_TRACE_FMT_STRING "%s%s%s", \ 376 TRACE_CALL("Check: %s", #__call__ ); \
364 __thn, __PRETTY_FUNCTION__, __STRIPPED_FILE__, __LINE__, (prefix), __strbuf, (suffix)); \ 377 __ret__ = (__call__)
365 } \ 378
379 #define DEFAULT_FB return __ret__;
380
381 /* System check: error case if < 0, error value in errno */
382 #define CHECK_SYS_GEN( faillevel, __call__, __fallback__ ) { \
383 CHECK_PRELUDE(__call__); \
384 if (__ret__ < 0) { \
385 __ret__ = errno; \
386 LOG(faillevel, "ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \
387 __fallback__; \
388 } \
366 } 389 }
367 #else /* DEBUG */ 390
368 /* Do not print thread, function, ... only the message itself in this case */ 391
369 #define TRACE_BUFFER(printlevel, level, prefix, buf, bufsz, suffix ) { \ 392 /* Check the return value of a function and execute fallback in case of error or special value */
370 if ( TRACE_BOOL(level) ) { \ 393 #define CHECK_FCT_GEN2( faillevel, __call__, __speval__, __fallback1__, __fallback2__ ) { \
371 int __i; \ 394 CHECK_PRELUDE(__call__); \
372 size_t __sz = (size_t)(bufsz); \ 395 if (__ret__ != 0) { \
373 uint8_t * __buf = (uint8_t *)(buf); \ 396 if (__ret__ == (__speval__)) { \
374 char __strbuf[1024+1]; \ 397 __fallback1__; \
375 for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2)); __i++) { \ 398 } else { \
376 sprintf(__strbuf + (2 * __i), "%2.2hhx", __buf[__i]); \ 399 LOG(faillevel, "ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \
377 } \ 400 __fallback2__; \
378 fd_log(printlevel, "%s%s%s", (prefix), __strbuf, (suffix)); \ 401 } \
379 } \ 402 } \
380 } 403 }
381 #endif /* DEBUG */ 404
382 405 /* Check the return value of a function and execute fallback in case of error (return value different from 0) */
383 /* Some aliases to socket addresses structures */ 406 #define CHECK_FCT_GEN( faillevel, __call__, __fallback__) \
384 #define sSS struct sockaddr_storage 407 CHECK_FCT_GEN2( faillevel, (__call__), 0, , (__fallback__) )
385 #define sSA struct sockaddr 408
386 #define sSA4 struct sockaddr_in 409 /* Check that a memory allocator did not return NULL, otherwise log an error and execute fallback */
387 #define sSA6 struct sockaddr_in6 410 #define CHECK_MALLOC_GEN( faillevel, __call__, __fallback__ ) { \
388 411 void * __ptr__; \
389 /* The sockaddr length of a sSS structure */ 412 TRACE_CALL("Check: %s", #__call__ ); \
390 #define sSAlen( _sa_ ) \ 413 __ptr__ = (void *)(__call__); \
391 ( (socklen_t) ( (((sSA *)_sa_)->sa_family == AF_INET) ? (sizeof(sSA4)) : \ 414 if (__ptr__ == NULL) { \
392 ((((sSA *)_sa_)->sa_family == AF_INET6) ? (sizeof(sSA6)) : \ 415 int __ret__ = errno; \
393 0 ) ) ) 416 LOG(faillevel, "ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \
394 417 __fallback__; \
395 /* Dump one sockaddr Node information */ 418 } \
396 #define sSA_DUMP_NODE( buf, bufsize, sa, flag ) { \
397 sSA * __sa = (sSA *)(sa); \
398 char __addrbuf[INET6_ADDRSTRLEN]; \
399 if (__sa) { \
400 int __rc = getnameinfo(__sa, \
401 sSAlen(__sa), \
402 __addrbuf, \
403 sizeof(__addrbuf), \
404 NULL, \
405 0, \
406 (flag)); \
407 if (__rc) \
408 snprintf(buf, bufsize, "%s", gai_strerror(__rc)); \
409 else \
410 snprintf(buf, bufsize, "%s", &__addrbuf[0]); \
411 } else { \
412 snprintf(buf, bufsize, "(NULL / ANY)"); \
413 } \
414 } 419 }
415 /* Same but with the port (service) also */ 420
416 #define sSA_DUMP_NODE_SERV( buf, bufsize, sa, flag ) { \ 421 /* Check parameters at function entry, execute fallback on error */
417 sSA * __sa = (sSA *)(sa); \ 422 #define CHECK_PARAMS_GEN( faillevel, __bool__, __fallback__ ) { \
418 char __addrbuf[INET6_ADDRSTRLEN]; \ 423 TRACE_CALL("Check: %s", #__bool__ ); \
419 char __servbuf[32]; \ 424 if ( ! (__bool__) ) { \
420 if (__sa) { \ 425 int __ret__ = EINVAL; \
421 int __rc = getnameinfo(__sa, \ 426 LOG(faillevel, "ERROR: invalid parameter '%s'", #__bool__ ); \
422 sSAlen(__sa), \ 427 __fallback__; \
423 __addrbuf, \ 428 } \
424 sizeof(__addrbuf), \
425 __servbuf, \
426 sizeof(__servbuf), \
427 (flag)); \
428 if (__rc) \
429 snprintf(buf, bufsize, "%s", gai_strerror(__rc)); \
430 else \
431 snprintf(buf, bufsize, "[%s]:%s", &__addrbuf[0],&__servbuf[0]); \
432 } else { \
433 snprintf(buf, bufsize,"(NULL / ANY)"); \
434 } \
435 } 429 }
436 430
437 #ifdef DEBUG 431
438 /* In DEBUG mode, we add (a lot of) meta-information along each trace. This makes multi-threading problems easier to debug. */ 432 /*============================================================*/
439 #define TRACE_sSA(printlevel, level, prefix, sa, flags, suffix ) { \ 433 /* COMPATIBILITY MACROS, TO BE REMOVED */
440 if ( TRACE_BOOL(level) ) { \ 434 /*============================================================*/
441 char __buf[1024]; \ 435 /* Redefine the old macros for transition of the code */
442 char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed"); \ 436 #ifndef EXCLUDE_DEPRECATED
443 sSA_DUMP_NODE_SERV(__buf, sizeof(__buf), sa, flags ); \ 437
444 fd_log(printlevel, STD_TRACE_FMT_STRING "%s%s%s" , \ 438 #define MARK_DEPRECATED /* __attribute__ ((deprecated)) */
445 __thn, __PRETTY_FUNCTION__, __STRIPPED_FILE__, __LINE__, (prefix), __buf, (suffix)); \ 439
446 } \ 440 enum old_levels {
441 NONE = 0,
442 INFO = 1,
443 FULL = 2,
444 ANNOYING = 4,
445 FCTS = 6,
446 CALL = 9
447 } MARK_DEPRECATED;
448
449 static __inline__ int TRACE_BOOL( enum old_levels level ) MARK_DEPRECATED
450 {
451 return (level <= fd_g_debug_lvl)
452 || (fd_debug_one_function && !strcmp(fd_debug_one_function, __PRETTY_FUNCTION__))
453 || (fd_debug_one_file && !strcmp(fd_debug_one_file, __STRIPPED_FILE__) );
447 } 454 }
448 #else /* DEBUG */ 455
449 /* Do not print thread, function, ... only the message itself in this case */ 456 static __inline__ void fd_log_deprecated( int level, const char *format, ... ) MARK_DEPRECATED
450 #define TRACE_sSA(printlevel, level, prefix, sa, flags, suffix ) { \ 457 {
451 if ( TRACE_BOOL(level) ) { \ 458 va_list ap;
452 char __buf[1024]; \ 459 va_start(ap, format);
453 sSA_DUMP_NODE_SERV(__buf, sizeof(__buf), sa, flags ); \ 460 fd_log_va(level, format, ap);
454 fd_log(printlevel, "%s%s%s" , (prefix), __buf, (suffix)); \ 461 va_end(ap);
455 } \
456 } 462 }
457 #endif /* DEBUG */ 463 static __inline__ void replace_me() MARK_DEPRECATED { }
458 464
459 /****************** 465 #define TRACE_sSA(...) replace_me();
460 Optimized code: remove all debugging code 466 #define sSA_DUMP_NODE_SERV(...) replace_me();
461 **/ 467 #define sSA_DUMP_NODE(...) replace_me();
468 #define TRACE_BUFFER(...) replace_me();
469 #define TRACE_NOTICE(...) replace_me();
470
471
472 /* Use the LOG_* instead, or use the new *_dump functions when dumping an object */
473 #define fd_log_debug(format,args...) fd_log_deprecated(FD_LOG_DEBUG, format, ## args)
474 #define fd_log_notice(format,args...) fd_log_deprecated(FD_LOG_NOTICE, format, ## args)
475 #define fd_log_error(format,args...) fd_log_deprecated(FD_LOG_ERROR, format, ## args)
476
477 /* old macro for traces. To be replaced by appropriate LOG_* macros. */
478 # define TRACE_DEBUG(oldlevel, format,args... ) { \
479 if (TRACE_BOOL(oldlevel)) { \
480 if (oldlevel == NONE) { LOG_E(format,##args); } \
481 else if (oldlevel == INFO) { LOG_N(format,##args); } \
482 else { LOG_D(format,##args); } \
483 } }
484
485 /* the following macro must be replaced with LOG_E or LOG_F */
486 # define TRACE_ERROR fd_log_error
487
488
489 /* The following macros are missing the faillevel information, which indicates at what log level the error case should be displayed. */
490 # define CHECK_SYS_DO( __call__, __fallback__ ) { \
491 CHECK_PRELUDE(__call__); \
492 if (__ret__ < 0) { \
493 __ret__ = errno; \
494 TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \
495 __fallback__; \
496 } \
497 }
498
499 # define CHECK_SYS( __call__ ) \
500 CHECK_SYS_DO( (__call__), return __ret__ )
501
502
503 # define CHECK_POSIX_DO2( __call__, __speval__, __fallback1__, __fallback2__ ) { \
504 CHECK_PRELUDE(__call__); \
505 if (__ret__ != 0) { \
506 if (__ret__ == (__speval__)) { \
507 __fallback1__; \
508 } else { \
509 TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \
510 __fallback2__; \
511 } \
512 } \
513 }
514
515 # define CHECK_POSIX_DO( __call__, __fallback__ ) \
516 CHECK_POSIX_DO2( (__call__), 0, , __fallback__ )
517
518 # define CHECK_POSIX( __call__ ) \
519 CHECK_POSIX_DO( (__call__), return __ret__ )
520
521 # define CHECK_MALLOC_DO( __call__, __fallback__ ) { \
522 void * __ptr__; \
523 TRACE_CALL("Check: %s", #__call__ ); \
524 __ptr__ = (void *)(__call__); \
525 if (__ptr__ == NULL) { \
526 int __ret__ = errno; \
527 TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__ret__)); \
528 __fallback__; \
529 } \
530 }
531
532 # define CHECK_MALLOC( __call__ ) \
533 CHECK_MALLOC_DO( (__call__), return __ret__ )
534
535 # define CHECK_PARAMS_DO( __bool__, __fallback__ ) { \
536 TRACE_CALL("Check: %s", #__bool__ ); \
537 if ( ! (__bool__) ) { \
538 int __ret__ = EINVAL; \
539 TRACE_ERROR("ERROR: invalid parameter '%s'", #__bool__ ); \
540 __fallback__; \
541 } \
542 }
543
544 # define CHECK_PARAMS( __bool__ ) \
545 CHECK_PARAMS_DO( (__bool__), return __ret__ )
546
547 # define CHECK_FCT_DO CHECK_POSIX_DO
548 # define CHECK_FCT CHECK_POSIX
549
550 #endif /* EXCLUDE_DEPRECATED */
551
552
553 /*============================================================*/
554 /* Optimized code: remove all debugging code */
555 /*============================================================*/
462 #ifdef STRIP_DEBUG_CODE 556 #ifdef STRIP_DEBUG_CODE
463 #undef TRACE_DEBUG 557 #undef LOG_D
464 #undef TRACE_NOTICE 558 #undef LOG_N
465 #undef TRACE_ERROR 559 #undef LOG_E
466 #undef TRACE_BOOL 560 #undef LOG_F
467 #undef TRACE_BUFFER 561 #undef LOG_BUFFER
468 #undef TRACE_sSA 562
469 563 #define LOG_D(format,args... ) /* noop */
470 #define TRACE_DEBUG(level,format,args... ) /* noop */ 564 #define LOG_N(format,args...) fd_log(FD_LOG_NOTICE, format, ## args)
471 #define TRACE_BOOL(_level_) (0) /* always false */ 565 #define LOG_E(format,args...) fd_log(FD_LOG_ERROR, format, ## args)
472 #define TRACE_NOTICE fd_log_notice 566 #define LOG_F(format,args...) fd_log(FD_LOG_FATAL, format, ## args)
473 #define TRACE_ERROR fd_log_error 567 #define LOG_BUFFER(printlevel, level, prefix, buf, bufsz, suffix ) { \
474 #define TRACE_BUFFER(printlevel, level, prefix, buf, bufsz, suffix ) { \
475 if (printlevel > FD_LOG_DEBUG) { \ 568 if (printlevel > FD_LOG_DEBUG) { \
476 int __i; \ 569 int __i; \
477 size_t __sz = (size_t)(bufsz); \ 570 size_t __sz = (size_t)(bufsz); \
478 uint8_t * __buf = (uint8_t *)(buf); \ 571 uint8_t * __buf = (uint8_t *)(buf); \
479 char * __strbuf[1024+1]; \ 572 char * __strbuf[1024+1]; \
480 for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2); __i++) { \ 573 for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2); __i++) { \
481 sprintf(__strbuf + (2 * __i), "%02.2hhx", __buf[__i]); \ 574 sprintf(__strbuf + (2 * __i), "%02.2hhx", __buf[__i]); \
482 } \ 575 } \
483 fd_log(printlevel, prefix"%s"suffix, __strbuf); \ 576 fd_log(printlevel, prefix"%s"suffix, __strbuf); \
484 } 577 }
485 #define TRACE_sSA(printlevel, level, prefix, sa, flags, suffix ) { \
486 if (printlevel > FD_LOG_DEBUG) { \
487 char __buf[1024]; \
488 sSA_DUMP_NODE_SERV(__buf, sizeof(__buf), sa, flags ); \
489 fd_log(printlevel, prefix "%s" suffix, __buf); \
490 }
491 #endif /* STRIP_DEBUG_CODE */ 578 #endif /* STRIP_DEBUG_CODE */
492 579
493 580 /*============================================================*/
494 /*============================================================*/ 581 /* OTHER MACROS */
495 /* ERROR CHECKING MACRO */ 582 /*============================================================*/
496 /*============================================================*/
497
498 /* Macros to check a return value and branch out in case of error.
499 * These macro should be used only when errors are improbable, not for expected errors.
500 */
501
502 /* Check the return value of a system function and execute fallback in case of error */
503 #define CHECK_SYS_DO( __call__, __fallback__ ) { \
504 int __ret__; \
505 TRACE_DEBUG_ALL( "Check SYS: %s", #__call__ ); \
506 __ret__ = (__call__); \
507 if (__ret__ < 0) { \
508 int __err__ = errno; /* We may handle EINTR here */ \
509 TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__err__)); \
510 __fallback__; \
511 } \
512 }
513 /* Check the return value of a system function, return error code on error */
514 #define CHECK_SYS( __call__ ) { \
515 int __ret__; \
516 TRACE_DEBUG_ALL( "Check SYS: %s", #__call__ ); \
517 __ret__ = (__call__); \
518 if (__ret__ < 0) { \
519 int __err__ = errno; /* We may handle EINTR here */ \
520 TRACE_ERROR("ERROR: in '%s' :\t%s", #__call__ , strerror(__err__)); \
521 return __err__; \
522 } \
523 }
524
525 /* Check the return value of a POSIX function and execute fallback in case of error or special value */
526 #define CHECK_POSIX_DO2( __call__, __speval__, __fallback1__, __fallback2__ ) { \
527 int __ret__; \
528 TRACE_DEBUG_ALL( "Check POSIX: %s", #__call__ ); \
529 __ret__ = (__call__); \
530 if (__ret__ != 0) { \
531 if (__ret__ == (__speval__)) { \
532 __fallback1__; \
533 } else { \
534 TRACE_ERROR("ERROR: in '%s':\t%s", #__call__, strerror(__ret__)); \
535 __fallback2__; \
536 } \
537 } \
538 }
539
540 /* Check the return value of a POSIX function and execute fallback in case of error */
541 #define CHECK_POSIX_DO( __call__, __fallback__ ) \
542 CHECK_POSIX_DO2( (__call__), 0, , __fallback__ );
543
544 /* Check the return value of a POSIX function and return it if error */
545 #define CHECK_POSIX( __call__ ) { \
546 int __v__; \
547 CHECK_POSIX_DO( __v__ = (__call__), return __v__ ); \
548 }
549
550 /* Check that a memory allocator did not return NULL, otherwise log an error and execute fallback */
551 #define CHECK_MALLOC_DO( __call__, __fallback__ ) { \
552 void * __ret__; \
553 TRACE_DEBUG_ALL( "Check MALLOC: %s", #__call__ ); \
554 __ret__ = (void *)( __call__ ); \
555 if (__ret__ == NULL) { \
556 int __err__ = errno; \
557 TRACE_ERROR("ERROR: in '%s':\t%s", #__call__, strerror(__err__)); \
558 __fallback__; \
559 } \
560 }
561
562 /* Check that a memory allocator did not return NULL, otherwise return ENOMEM */
563 #define CHECK_MALLOC( __call__ ) \
564 CHECK_MALLOC_DO( __call__, return ENOMEM );
565
566
567 /* Check parameters at function entry, execute fallback on error */
568 #define CHECK_PARAMS_DO( __bool__, __fallback__ ) \
569 TRACE_DEBUG_ALL( "Check PARAMS: %s", #__bool__ ); \
570 if ( ! (__bool__) ) { \
571 TRACE_ERROR("Warning: Invalid parameter received in '%s'", #__bool__); \
572 __fallback__; \
573 }
574 /* Check parameters at function entry, return EINVAL if the boolean is false (similar to assert) */
575 #define CHECK_PARAMS( __bool__ ) \
576 CHECK_PARAMS_DO( __bool__, return EINVAL );
577
578 /* Check the return value of an internal function, log and propagate */
579 #define CHECK_FCT_DO( __call__, __fallback__ ) { \
580 int __ret__; \
581 TRACE_DEBUG_ALL( "Check FCT: %s", #__call__ ); \
582 __ret__ = (__call__); \
583 if (__ret__ != 0) { \
584 TRACE_ERROR("ERROR: in '%s':\t%s", #__call__, strerror(__ret__)); \
585 __fallback__; \
586 } \
587 }
588 /* Check the return value of a function call, return any error code */
589 #define CHECK_FCT( __call__ ) { \
590 int __v__; \
591 CHECK_FCT_DO( __v__ = (__call__), return __v__ ); \
592 }
593
594
595
596 /*============================================================*/
597 /* OTHER MACROS */
598 /*============================================================*/
599
600
601 /* helper macros (pre-processor hacks to allow macro arguments) */ 583 /* helper macros (pre-processor hacks to allow macro arguments) */
602 #define __tostr( arg ) #arg 584 #define __tostr( arg ) #arg
603 #define _stringize( arg ) __tostr( arg ) 585 #define _stringize( arg ) __tostr( arg )
604 #define __agr( arg1, arg2 ) arg1 ## arg2 586 #define __agr( arg1, arg2 ) arg1 ## arg2
605 #define _aggregate( arg1, arg2 ) __agr( arg1, arg2 ) 587 #define _aggregate( arg1, arg2 ) __agr( arg1, arg2 )
588
589 /* Some aliases to socket addresses structures */
590 #define sSS struct sockaddr_storage
591 #define sSA struct sockaddr
592 #define sSA4 struct sockaddr_in
593 #define sSA6 struct sockaddr_in6
594
595 /* The sockaddr length of a sSS structure */
596 #define sSAlen( _sa_ ) \
597 ( (socklen_t) ( (((sSA *)_sa_)->sa_family == AF_INET) ? (sizeof(sSA4)) : \
598 ((((sSA *)_sa_)->sa_family == AF_INET6) ? (sizeof(sSA6)) : \
599 0 ) ) )
600
601 DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node, sSA * sa, int flags);
602 DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node_serv, sSA * sa, int flags);
606 603
607 604
608 /* A l4 protocol name (TCP / SCTP) */ 605 /* A l4 protocol name (TCP / SCTP) */
609 #ifdef DISABLE_SCTP 606 #ifdef DISABLE_SCTP
610 #define IPPROTO_NAME( _proto ) \ 607 #define IPPROTO_NAME( _proto ) \
981 int fd_dict_getval ( struct dict_object * object, void * val); 978 int fd_dict_getval ( struct dict_object * object, void * val);
982 int fd_dict_gettype ( struct dict_object * object, enum dict_object_type * type); 979 int fd_dict_gettype ( struct dict_object * object, enum dict_object_type * type);
983 int fd_dict_getdict ( struct dict_object * object, struct dictionary ** dict); 980 int fd_dict_getdict ( struct dict_object * object, struct dictionary ** dict);
984 981
985 /* Debug functions */ 982 /* Debug functions */
986 void fd_dict_dump_object(struct dict_object * obj); 983 DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_object, struct dict_object * obj);
987 void fd_dict_dump(struct dictionary * dict); 984 DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump, struct dictionary * dict);
988 985
989 /* Function to access full contents of the dictionary, see doc in dictionary.c */ 986 /* Function to access full contents of the dictionary, see doc in dictionary.c */
990 int fd_dict_getlistof(int criteria, void * parent, struct fd_list ** sentinel); 987 int fd_dict_getlistof(int criteria, void * parent, struct fd_list ** sentinel);
991 988
992 /* Function to remove an entry from the dictionary. 989 /* Function to remove an entry from the dictionary.
1220 struct dict_type_data { 1217 struct dict_type_data {
1221 enum dict_avp_basetype type_base; /* How the data of such AVP must be interpreted */ 1218 enum dict_avp_basetype type_base; /* How the data of such AVP must be interpreted */
1222 char * type_name; /* The name of this type */ 1219 char * type_name; /* The name of this type */
1223 dict_avpdata_interpret type_interpret;/* cb to convert the AVP value in more comprehensive format (or NULL) */ 1220 dict_avpdata_interpret type_interpret;/* cb to convert the AVP value in more comprehensive format (or NULL) */
1224 dict_avpdata_encode type_encode; /* cb to convert formatted data into an AVP value (or NULL) */ 1221 dict_avpdata_encode type_encode; /* cb to convert formatted data into an AVP value (or NULL) */
1225 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. */ 1222 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. */
1226 }; 1223 };
1227 1224
1228 /* The criteria for searching a type object in the dictionary */ 1225 /* The criteria for searching a type object in the dictionary */
1229 enum { 1226 enum {
1230 TYPE_BY_NAME = 30, /* "what" points to a char * */ 1227 TYPE_BY_NAME = 30, /* "what" points to a char * */
1237 */ 1234 */
1238 1235
1239 /* Convert an Address type AVP into a struct sockaddr_storage */ 1236 /* Convert an Address type AVP into a struct sockaddr_storage */
1240 int fd_dictfct_Address_encode(void * data, union avp_value * avp_value); 1237 int fd_dictfct_Address_encode(void * data, union avp_value * avp_value);
1241 int fd_dictfct_Address_interpret(union avp_value * avp_value, void * interpreted); 1238 int fd_dictfct_Address_interpret(union avp_value * avp_value, void * interpreted);
1242 char * fd_dictfct_Address_dump(union avp_value * avp_value); 1239 DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_Address_dump, union avp_value * avp_value);
1243 1240
1244 /* Display the content of an AVP of type UTF8String in the log file */ 1241 /* Display the content of an AVP of type UTF8String in the log file */
1245 char * fd_dictfct_UTF8String_dump(union avp_value * avp_value); 1242 DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_UTF8String_dump, union avp_value * avp_value);
1246 1243
1247 /* For Time AVPs, map with time_t value directly */ 1244 /* For Time AVPs, map with time_t value directly */
1248 int fd_dictfct_Time_encode(void * data, union avp_value * avp_value); 1245 int fd_dictfct_Time_encode(void * data, union avp_value * avp_value);
1249 int fd_dictfct_Time_interpret(union avp_value * avp_value, void * interpreted); 1246 int fd_dictfct_Time_interpret(union avp_value * avp_value, void * interpreted);
1250 char * fd_dictfct_Time_dump(union avp_value * avp_value); 1247 DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_Time_dump, union avp_value * avp_value);
1251 1248
1252 1249
1253 1250
1254 /****/ 1251 /****/
1255 1252
1819 struct session; 1816 struct session;
1820 1817
1821 /* The state information that a module associate with a session -- each module defines its own data format */ 1818 /* The state information that a module associate with a session -- each module defines its own data format */
1822 typedef void session_state; 1819 typedef void session_state;
1823 1820
1821 typedef DECLARE_FD_DUMP_PROTOTYPE(session_state_dump, session_state * st);
1822
1824 /* The following function must be called to activate the session expiry mechanism */ 1823 /* The following function must be called to activate the session expiry mechanism */
1825 int fd_sess_start(void); 1824 int fd_sess_start(void);
1826 1825
1827 /* 1826 /*
1828 * FUNCTION: fd_sess_handler_create 1827 * FUNCTION: fd_sess_handler_create
1829 * 1828 *
1830 * PARAMETERS: 1829 * PARAMETERS:
1831 * handler : location where the new handler must be stored. 1830 * handler : location where the new handler must be stored.
1832 * cleanup : a callback function that must be called when the session with associated data is destroyed. 1831 * cleanup : a callback function that must be called when the session with associated data is destroyed.
1832 * dumper : if not NULL, will be called during fd_sess_dump to display the data associated with a session. NULL otherwise.
1833 * opaque : A pointer that is passed to the cleanup callback -- the content is never examined by the framework. 1833 * opaque : A pointer that is passed to the cleanup callback -- the content is never examined by the framework.
1834 * 1834 *
1835 * DESCRIPTION: 1835 * DESCRIPTION:
1836 * Create a new session handler. This is needed by a module to associate a state with a session object. 1836 * Create a new session handler. This is needed by a module to associate a state with a session object.
1837 * The cleanup handler is called when the session timeout expires, or fd_sess_destroy is called. It must free 1837 * The cleanup handler is called when the session timeout expires, or fd_sess_destroy is called. It must free
1840 * RETURN VALUE: 1840 * RETURN VALUE:
1841 * 0 : The new handler has been created. 1841 * 0 : The new handler has been created.
1842 * EINVAL : A parameter is invalid. 1842 * EINVAL : A parameter is invalid.
1843 * ENOMEM : Not enough memory to complete the operation 1843 * ENOMEM : Not enough memory to complete the operation
1844 */ 1844 */
1845 int fd_sess_handler_create_internal ( struct session_handler ** handler, void (*cleanup)(session_state * state, os0_t sid, void * opaque), void * opaque ); 1845 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 );
1846 /* Macro to avoid casting everywhere */ 1846 /* Macro to avoid casting everywhere */
1847 #define fd_sess_handler_create( _handler, _cleanup, _opaque ) \ 1847 #define fd_sess_handler_create( _handler, _cleanup, _dumper, _opaque ) \
1848 fd_sess_handler_create_internal( (_handler), (void (*)(session_state *, os0_t, void *))(_cleanup), (void *)(_opaque) ) 1848 fd_sess_handler_create_internal( (_handler), (void (*)(session_state *, os0_t, void *))(_cleanup), _dumper, (void *)(_opaque) )
1849 1849
1850 1850
1851 /* 1851 /*
1852 * FUNCTION: fd_sess_handler_destroy 1852 * FUNCTION: fd_sess_handler_destroy
1853 * 1853 *
2043 #define fd_sess_state_retrieve( _handler, _session, _state ) \ 2043 #define fd_sess_state_retrieve( _handler, _session, _state ) \
2044 fd_sess_state_retrieve_internal( (_handler), (_session), (void *)(_state) ) 2044 fd_sess_state_retrieve_internal( (_handler), (_session), (void *)(_state) )
2045 2045
2046 2046
2047 /* For debug */ 2047 /* For debug */
2048 void fd_sess_dump(int level, struct session * session); 2048 DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump, struct session * session, int with_states);
2049 void fd_sess_dump_hdl(int level, struct session_handler * handler); 2049 DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump_hdl, struct session_handler * handler);
2050 2050
2051 /* For statistics / monitoring: get the number of struct session in memory */ 2051 /* For statistics / monitoring: get the number of struct session in memory */
2052 int fd_sess_getcount(uint32_t *cnt); 2052 int fd_sess_getcount(uint32_t *cnt);
2053 2053
2054 /*============================================================*/ 2054 /*============================================================*/
2325 /***************************************/ 2325 /***************************************/
2326 /* 2326 /*
2327 * FUNCTION: fd_msg_dump_* 2327 * FUNCTION: fd_msg_dump_*
2328 * 2328 *
2329 * PARAMETERS: 2329 * PARAMETERS:
2330 * level : the log level (INFO, FULL, ...) at which the object is dumped 2330 * see definition of DECLARE_FD_DUMP_PROTOTYPE,
2331 * obj : A msg or avp object. 2331 * obj : A msg or avp object to dump.
2332 * 2332 * dict : the dictionary to use if parsing is requested (optional)
2333 * DESCRIPTION: 2333 * force_parsing: by default these functions do not parse the object but dump hexa values in that case.
2334 * These functions dump the content of a message to the debug log 2334 * use !0 to force parsing. If parsing fails, the hexa dump is still provided.
2335 * recurse : allow the function to go through the children objects if any to dump more information. might require parsing.
2336 *
2337 * DESCRIPTION:
2338 * These functions dump the content of a message or avp into a buffer
2335 * either recursively or only the object itself. 2339 * either recursively or only the object itself.
2336 * 2340 *
2337 * RETURN VALUE: 2341 * RETURN VALUE:
2338 * - 2342 * - see DECLARE_FD_DUMP_PROTOTYPE,
2339 */
2340 void fd_msg_dump_walk ( int level, msg_or_avp *obj );
2341 void fd_msg_dump_one ( int level, msg_or_avp *obj );
2342
2343 /* Helper functions to get a dump of an object in the logs. Several formats are available.
2344 * buf : a buffer that can be reallocated if needed. *buf==NULL is also accepted for first allocation
2345 * buflen: the length of the buffer buf.
2346 * dict : optional, the dictionary to use for resolving objects, if force_parsing != 0
2347 * obj : the message or AVP to dump.
2348 *
2349 * After use, the buf pointer should be freed.
2350 */ 2343 */
2351 /* one-line dump with only short information */ 2344 /* one-line dump with only short information */
2352 void fd_msg_dump_summary( char ** buf, size_t buflen, struct dictionary *dict, msg_or_avp *obj, int force_parsing); 2345 DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_summary, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse );
2353 /* one-line dump with all the contents of the message */ 2346 /* one-line dump with all the contents of the message */
2354 void fd_msg_dump_full( char ** buf, size_t buflen, struct dictionary *dict, msg_or_avp *obj, int force_parsing); 2347 DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_full, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse );
2355 /* multi-line human-readable dump similar to wireshark output */ 2348 /* multi-line human-readable dump similar to wireshark output */
2356 void fd_msg_dump_treeview( char ** buf, size_t buflen, struct dictionary *dict, msg_or_avp *obj, int force_parsing); 2349 DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_treeview, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse );
2357 2350
2358 2351
2359 /*********************************************/ 2352 /*********************************************/
2360 /* Message metadata management functions */ 2353 /* Message metadata management functions */
2361 /*********************************************/ 2354 /*********************************************/
3138 int fd_fifo_timedget_int ( struct fifo * queue, void ** item, const struct timespec *abstime ); 3131 int fd_fifo_timedget_int ( struct fifo * queue, void ** item, const struct timespec *abstime );
3139 #define fd_fifo_timedget(queue, item, abstime) \ 3132 #define fd_fifo_timedget(queue, item, abstime) \
3140 fd_fifo_timedget_int((queue), (void *)(item), (abstime)) 3133 fd_fifo_timedget_int((queue), (void *)(item), (abstime))
3141 3134
3142 /* Dump a fifo list and optionally its inner elements -- beware of deadlocks! */ 3135 /* Dump a fifo list and optionally its inner elements -- beware of deadlocks! */
3143 void fd_fifo_dump(int level, char * name, struct fifo * queue, void (*dump_item)(int level, void * item)); 3136 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' */
3137 DECLARE_FD_DUMP_PROTOTYPE(fd_fifo_dump, char * name, struct fifo * queue, fd_fifo_dump_item_cb dump_item);
3144 3138
3145 #ifdef __cplusplus 3139 #ifdef __cplusplus
3146 } 3140 }
3147 #endif 3141 #endif
3148 3142
"Welcome to our mercurial repository"