# HG changeset patch # User Sebastien Decugis # Date 1371183740 -28800 # Node ID a4cdde705f302ff9817cf9660ee74ba1d60723ce # Parent 92f33e5ecb774227337d8330b39f8eb2ed489bd9 Add options to dbg_msg_dumps.fdx to allow more control over the behavior diff -r 92f33e5ecb77 -r a4cdde705f30 doc/freediameter.conf.sample --- a/doc/freediameter.conf.sample Fri Jun 14 12:21:42 2013 +0800 +++ b/doc/freediameter.conf.sample Fri Jun 14 12:22:20 2013 +0800 @@ -203,6 +203,15 @@ # test_* : dummy extensions that are useful only in testing environments. +# The dbg_msg_dump.fdx extension allows you to tweak the way freeDiameter displays some +# information about some events. This extension does not actually use a configuration file +# but receives directly a parameter in the string passed to the extension. Here are some examples: +# LoadExtension = "dbg_msg_dump.fdx" : "0x1111"; # Removes all default hooks, very quiet even in case of errors. +# LoadExtension = "dbg_msg_dump.fdx" : "0x2222"; # Display all events with few details. +# LoadExtension = "dbg_msg_dump.fdx" : "0x80"; # Dump complete information about sent and received messages. +# See the top of extensions/dbg_msg/dump/dbg_msg.dump.c file for more details on the value. + + ############################################################## ## Peers configuration diff -r 92f33e5ecb77 -r a4cdde705f30 extensions/dbg_msg_dumps/dbg_msg_dumps.c --- a/extensions/dbg_msg_dumps/dbg_msg_dumps.c Fri Jun 14 12:21:42 2013 +0800 +++ b/extensions/dbg_msg_dumps/dbg_msg_dumps.c Fri Jun 14 12:22:20 2013 +0800 @@ -36,36 +36,296 @@ /* This extension uses the hooks mechanism to display the full content of received and sent messages, for learning & debugging purpose. Do NOT use this extension in production environment because it will slow down all operation. */ + +/* You can add a configuration parameter on the LoadExtension line, e.g. +LoadExtension="dbg_msg_dump.fdx":"0x149"; +The value is an hexadecimal value with the following bits meaning: */ +#define HK_ERRORS_QUIET 0x0001 /* errors are not dumped -- removes the default handling as well */ +#define HK_ERRORS_COMPACT 0x0002 /* errors in compact mode */ +#define HK_ERRORS_FULL 0x0004 /* errors in full mode (1 line with all the data) */ +#define HK_ERRORS_TREE 0x0008 /* errors in treeview mode (message split over multiple lines) */ + +#define HK_SNDRCV_QUIET 0x0010 /* send+rcv are not dumped -- removes the default handling as well */ +#define HK_SNDRCV_COMPACT 0x0020 /* send+rcv in compact mode */ +#define HK_SNDRCV_FULL 0x0040 /* send+rcv in full mode */ +#define HK_SNDRCV_TREE 0x0080 /* send+rcv in tree mode */ + +#define HK_ROUTING_QUIET 0x0100 /* routing decisions are not dumped -- removes the default handling as well */ +#define HK_ROUTING_COMPACT 0x0200 /* routing decisions in compact mode */ + +#define HK_PEERS_QUIET 0x1000 /* peers connections events are not dumped -- removes the default handling as well */ +#define HK_PEERS_COMPACT 0x2000 /* peers connections events in compact mode */ +/* +Default value is HK_ERRORS_DETAIL + HK_SNDRCV_DETAIL + HK_PEERS_COMPACT +*/ #include -static struct fd_hook_hdl *md_hdl = NULL; +static struct fd_hook_hdl *md_hdl[4] = {NULL,NULL,NULL,NULL}; +static uint32_t dump_level = HK_ERRORS_TREE | HK_SNDRCV_TREE | HK_PEERS_COMPACT; /* default */ +static char * buf = NULL; +static size_t len; +static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; /* The callback called when messages are received and sent */ -static void md_hook_cb(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata) +static void md_hook_cb_tree(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata) { - char * buf = NULL; - size_t len; + char * peer_name = peer ? peer->info.pi_diamid : ""; + + CHECK_POSIX_DO( pthread_mutex_lock(&mtx), ); + + if (msg) { + CHECK_MALLOC_DO( fd_msg_dump_treeview(&buf, &len, NULL, msg, fd_g_config->cnf_dict, (type == HOOK_MESSAGE_PARSING_ERROR) ? 0 : 1, 1), + { LOG_E("Error while dumping a message"); pthread_mutex_unlock(&mtx); return; } ); + } + + switch (type) { +/* errors */ + case HOOK_MESSAGE_FAILOVER: + LOG_E("FAILOVER from '%s':", peer_name); + LOG_SPLIT(FD_LOG_ERROR, " ", buf, NULL); + break; + case HOOK_MESSAGE_PARSING_ERROR: + if (msg) { + DiamId_t id = NULL; + if (!fd_msg_source_get( msg, &id, NULL )) + id = (DiamId_t)""; + if (!id) + id = (DiamId_t)""; + LOG_E("PARSING ERROR: '%s' from '%s': ", (char *)other, (char *)id); + LOG_SPLIT(FD_LOG_ERROR, " ", buf, NULL); + } else { + struct fd_cnx_rcvdata *rcv_data = other; + CHECK_MALLOC_DO(fd_dump_extend_hexdump(&buf, &len, NULL, rcv_data->buffer, rcv_data->length, 0, 0), break); + LOG_E("PARSING ERROR: %zdB msg from '%s': %s", rcv_data->length, peer_name, buf); + } + break; + case HOOK_MESSAGE_ROUTING_ERROR: + LOG_E("ROUTING ERROR '%s' for: ", (char *)other); + LOG_SPLIT(FD_LOG_ERROR, " ", buf, NULL); + break; + case HOOK_MESSAGE_DROPPED: + LOG_E("DROPPED '%s'", (char *)other); + LOG_SPLIT(FD_LOG_ERROR, " ", buf, NULL); + break; + +/* send receive */ + case HOOK_MESSAGE_RECEIVED: + LOG_N("RCV from '%s':", peer_name); + LOG_SPLIT(FD_LOG_NOTICE, " ", buf, NULL); + break; + case HOOK_MESSAGE_SENT: + LOG_N("SND to '%s':", peer_name); + LOG_SPLIT(FD_LOG_NOTICE, " ", buf, NULL); + break; + +/* The following are not received in this hook */ + case HOOK_MESSAGE_LOCAL: + case HOOK_MESSAGE_ROUTING_FORWARD: + case HOOK_MESSAGE_ROUTING_LOCAL: + + case HOOK_PEER_CONNECT_FAILED: + case HOOK_PEER_CONNECT_SUCCESS: + + case HOOK_DATA_RECEIVED: + break; + } + + CHECK_POSIX_DO( pthread_mutex_unlock(&mtx), ); +} + +static void md_hook_cb_full(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata) +{ + char * peer_name = peer ? peer->info.pi_diamid : ""; + + CHECK_POSIX_DO( pthread_mutex_lock(&mtx), ); + + if (msg) { + CHECK_MALLOC_DO( fd_msg_dump_full(&buf, &len, NULL, msg, fd_g_config->cnf_dict, (type == HOOK_MESSAGE_PARSING_ERROR) ? 0 : 1, 1), + { LOG_E("Error while dumping a message"); pthread_mutex_unlock(&mtx); return; } ); + } + + switch (type) { +/* errors */ + case HOOK_MESSAGE_FAILOVER: + LOG_E("FAILOVER from '%s': %s", peer_name, buf); + break; + case HOOK_MESSAGE_PARSING_ERROR: + if (msg) { + DiamId_t id = NULL; + if (!fd_msg_source_get( msg, &id, NULL )) + id = (DiamId_t)""; + if (!id) + id = (DiamId_t)""; + LOG_E("PARSING ERROR: '%s' from '%s': %s", (char *)other, (char *)id, buf); + } else { + struct fd_cnx_rcvdata *rcv_data = other; + CHECK_MALLOC_DO(fd_dump_extend_hexdump(&buf, &len, NULL, rcv_data->buffer, rcv_data->length, 0, 0), break); + LOG_E("PARSING ERROR: %zdB msg from '%s': %s", rcv_data->length, peer_name, buf); + } + break; + case HOOK_MESSAGE_ROUTING_ERROR: + LOG_E("ROUTING ERROR '%s' for: %s", (char *)other, buf); + break; + case HOOK_MESSAGE_DROPPED: + LOG_E("DROPPED '%s' %s", (char *)other, buf); + break; - CHECK_MALLOC_DO( fd_msg_dump_treeview(&buf, &len, NULL, msg, fd_g_config->cnf_dict, 1, 1), - { LOG_E("Error while dumping a message"); return; } ); +/* send receive */ + case HOOK_MESSAGE_RECEIVED: + LOG_N("RCV from '%s': %s", peer_name, buf); + break; + case HOOK_MESSAGE_SENT: + LOG_N("SND to '%s': %s", peer_name, buf); + break; + +/* The following are not received in this hook */ + case HOOK_MESSAGE_LOCAL: + case HOOK_MESSAGE_ROUTING_FORWARD: + case HOOK_MESSAGE_ROUTING_LOCAL: + + case HOOK_PEER_CONNECT_FAILED: + case HOOK_PEER_CONNECT_SUCCESS: + + case HOOK_DATA_RECEIVED: + break; + } + + CHECK_POSIX_DO( pthread_mutex_unlock(&mtx), ); +} + +static void md_hook_cb_compact(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata) +{ + char * peer_name = peer ? peer->info.pi_diamid : ""; + + CHECK_POSIX_DO( pthread_mutex_lock(&mtx), ); + + if (msg) { + CHECK_MALLOC_DO( fd_msg_dump_summary(&buf, &len, NULL, msg, fd_g_config->cnf_dict, 0, 0), + { LOG_E("Error while dumping a message"); pthread_mutex_unlock(&mtx); return; } ); + } - LOG_N("%s %s:", - (type == HOOK_MESSAGE_RECEIVED) ? "RCV FROM" : "SENT TO", - peer ? peer->info.pi_diamid:""); - LOG_SPLIT( FD_LOG_NOTICE, " ", buf ?:"", NULL); + switch (type) { +/* errors */ + case HOOK_MESSAGE_FAILOVER: + LOG_E("FAILOVER from '%s': %s", peer_name, buf); + break; + case HOOK_MESSAGE_PARSING_ERROR: + if (msg) { + DiamId_t id = NULL; + if (!fd_msg_source_get( msg, &id, NULL )) + id = (DiamId_t)""; + if (!id) + id = (DiamId_t)""; + LOG_E("PARSING ERROR: '%s' from '%s': %s", (char *)other, (char *)id, buf); + } else { + struct fd_cnx_rcvdata *rcv_data = other; + CHECK_MALLOC_DO(fd_dump_extend_hexdump(&buf, &len, NULL, rcv_data->buffer, rcv_data->length, 0, 0), break); + LOG_E("PARSING ERROR: %zdB msg from '%s': %s", rcv_data->length, peer_name, buf); + } + break; + case HOOK_MESSAGE_ROUTING_ERROR: + LOG_E("ROUTING ERROR '%s' for: %s", (char *)other, buf); + break; + case HOOK_MESSAGE_DROPPED: + LOG_E("DROPPED '%s' %s", (char *)other, buf); + break; + +/* send receive */ + case HOOK_MESSAGE_RECEIVED: + LOG_N("RCV from '%s': %s", peer_name, buf); + break; + case HOOK_MESSAGE_SENT: + LOG_N("SND to '%s': %s", peer_name, buf); + break; + +/* routing */ + case HOOK_MESSAGE_LOCAL: + LOG_N("ISSUED: %s", buf); + break; + case HOOK_MESSAGE_ROUTING_FORWARD: + LOG_N("FORWARDING: %s", buf); + break; + case HOOK_MESSAGE_ROUTING_LOCAL: + LOG_N("DISPATCHING: %s", buf); + break; + +/* peers */ + case HOOK_PEER_CONNECT_FAILED: + LOG_N("CONNECT FAILED to %s: %s", peer_name, (char *)other); + break; + case HOOK_PEER_CONNECT_SUCCESS: { + char protobuf[40]; + if (peer) { + CHECK_FCT_DO(fd_peer_cnx_proto_info(peer, protobuf, sizeof(protobuf)), break ); + } else { + protobuf[0] = '-'; + protobuf[1] = '\0'; + } + LOG_N("CONNECTED TO '%s' (%s): %s", peer_name, protobuf, buf); + } + break; +/* Not handled */ + case HOOK_DATA_RECEIVED: + break; + } + + CHECK_POSIX_DO( pthread_mutex_unlock(&mtx), ); +} - free(buf); +static void md_hook_cb_quiet(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd, void * regdata) +{ } /* Entry point */ static int md_main(char * conffile) { + uint32_t mask_errors, mask_sndrcv, mask_routing, mask_peers; + uint32_t mask_quiet, mask_compact, mask_full, mask_tree; TRACE_ENTRY("%p", conffile); - CHECK_FCT( fd_hook_register( HOOK_MASK( HOOK_MESSAGE_RECEIVED, HOOK_MESSAGE_SENT ), - md_hook_cb, NULL, NULL, &md_hdl) ); + if (conffile != NULL) { + char * endp; + dump_level = (uint8_t)strtoul(conffile, &endp, 16); + CHECK_PARAMS_DO( *endp == '\0', { + LOG_E("Configuration parameter must be in the form \"0xNNNN\""); + return EINVAL; }); + } + + mask_errors = HOOK_MASK( HOOK_MESSAGE_FAILOVER, HOOK_MESSAGE_PARSING_ERROR, HOOK_MESSAGE_ROUTING_ERROR, HOOK_MESSAGE_DROPPED ); + mask_sndrcv = HOOK_MASK( HOOK_MESSAGE_RECEIVED, HOOK_MESSAGE_SENT ); + mask_routing= HOOK_MASK( HOOK_MESSAGE_LOCAL, HOOK_MESSAGE_ROUTING_FORWARD, HOOK_MESSAGE_ROUTING_LOCAL ); + mask_peers = HOOK_MASK( HOOK_PEER_CONNECT_FAILED, HOOK_PEER_CONNECT_SUCCESS ); + + mask_quiet = (dump_level & HK_ERRORS_QUIET) ? mask_errors : 0; + mask_quiet |= (dump_level & HK_SNDRCV_QUIET) ? mask_sndrcv : 0; + mask_quiet |= (dump_level & HK_ROUTING_QUIET) ? mask_routing : 0; + mask_quiet |= (dump_level & HK_PEERS_QUIET) ? mask_peers : 0; + mask_compact = (dump_level & HK_ERRORS_COMPACT) ? mask_errors : 0; + mask_compact |= (dump_level & HK_SNDRCV_COMPACT) ? mask_sndrcv : 0; + mask_compact |= (dump_level & HK_ROUTING_COMPACT) ? mask_routing : 0; + mask_compact |= (dump_level & HK_PEERS_COMPACT) ? mask_peers : 0; + + mask_full = (dump_level & HK_ERRORS_FULL) ? mask_errors : 0; + mask_full |= (dump_level & HK_SNDRCV_FULL) ? mask_sndrcv : 0; + + mask_tree = (dump_level & HK_ERRORS_TREE) ? mask_errors : 0; + mask_tree |= (dump_level & HK_SNDRCV_TREE) ? mask_sndrcv : 0; + + if (mask_quiet) { + CHECK_FCT( fd_hook_register( mask_quiet, md_hook_cb_quiet, NULL, NULL, &md_hdl[0]) ); + } + if (mask_compact) { + CHECK_FCT( fd_hook_register( mask_compact, md_hook_cb_compact, NULL, NULL, &md_hdl[1]) ); + } + if (mask_full) { + CHECK_FCT( fd_hook_register( mask_full, md_hook_cb_full, NULL, NULL, &md_hdl[2]) ); + } + if (mask_tree) { + CHECK_FCT( fd_hook_register( mask_tree, md_hook_cb_tree, NULL, NULL, &md_hdl[3]) ); + } + return 0; } @@ -73,7 +333,10 @@ void fd_ext_fini(void) { TRACE_ENTRY(); - CHECK_FCT_DO( fd_hook_unregister( md_hdl ), ); + if (md_hdl[0]) { CHECK_FCT_DO( fd_hook_unregister( md_hdl[0] ), ); } + if (md_hdl[1]) { CHECK_FCT_DO( fd_hook_unregister( md_hdl[1] ), ); } + if (md_hdl[2]) { CHECK_FCT_DO( fd_hook_unregister( md_hdl[2] ), ); } + if (md_hdl[2]) { CHECK_FCT_DO( fd_hook_unregister( md_hdl[3] ), ); } return ; }