Mercurial > hg > freeDiameter
comparison extensions/dbg_msg_dumps/dbg_msg_dumps.c @ 1204:a4cdde705f30
Add options to dbg_msg_dumps.fdx to allow more control over the behavior
author | Sebastien Decugis <sdecugis@freediameter.net> |
---|---|
date | Fri, 14 Jun 2013 12:22:20 +0800 |
parents | a4604f98adae |
children | 24a03140a6aa |
comparison
equal
deleted
inserted
replaced
1203:92f33e5ecb77 | 1204:a4cdde705f30 |
---|---|
34 *********************************************************************************************************/ | 34 *********************************************************************************************************/ |
35 | 35 |
36 /* This extension uses the hooks mechanism to display the full content of received and sent messages, for | 36 /* This extension uses the hooks mechanism to display the full content of received and sent messages, for |
37 learning & debugging purpose. | 37 learning & debugging purpose. |
38 Do NOT use this extension in production environment because it will slow down all operation. */ | 38 Do NOT use this extension in production environment because it will slow down all operation. */ |
39 | |
40 /* You can add a configuration parameter on the LoadExtension line, e.g. | |
41 LoadExtension="dbg_msg_dump.fdx":"0x149"; | |
42 The value is an hexadecimal value with the following bits meaning: */ | |
43 #define HK_ERRORS_QUIET 0x0001 /* errors are not dumped -- removes the default handling as well */ | |
44 #define HK_ERRORS_COMPACT 0x0002 /* errors in compact mode */ | |
45 #define HK_ERRORS_FULL 0x0004 /* errors in full mode (1 line with all the data) */ | |
46 #define HK_ERRORS_TREE 0x0008 /* errors in treeview mode (message split over multiple lines) */ | |
47 | |
48 #define HK_SNDRCV_QUIET 0x0010 /* send+rcv are not dumped -- removes the default handling as well */ | |
49 #define HK_SNDRCV_COMPACT 0x0020 /* send+rcv in compact mode */ | |
50 #define HK_SNDRCV_FULL 0x0040 /* send+rcv in full mode */ | |
51 #define HK_SNDRCV_TREE 0x0080 /* send+rcv in tree mode */ | |
52 | |
53 #define HK_ROUTING_QUIET 0x0100 /* routing decisions are not dumped -- removes the default handling as well */ | |
54 #define HK_ROUTING_COMPACT 0x0200 /* routing decisions in compact mode */ | |
55 | |
56 #define HK_PEERS_QUIET 0x1000 /* peers connections events are not dumped -- removes the default handling as well */ | |
57 #define HK_PEERS_COMPACT 0x2000 /* peers connections events in compact mode */ | |
58 /* | |
59 Default value is HK_ERRORS_DETAIL + HK_SNDRCV_DETAIL + HK_PEERS_COMPACT | |
60 */ | |
39 | 61 |
40 #include <freeDiameter/extension.h> | 62 #include <freeDiameter/extension.h> |
41 | 63 |
42 static struct fd_hook_hdl *md_hdl = NULL; | 64 static struct fd_hook_hdl *md_hdl[4] = {NULL,NULL,NULL,NULL}; |
65 static uint32_t dump_level = HK_ERRORS_TREE | HK_SNDRCV_TREE | HK_PEERS_COMPACT; /* default */ | |
66 static char * buf = NULL; | |
67 static size_t len; | |
68 static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; | |
43 | 69 |
44 /* The callback called when messages are received and sent */ | 70 /* The callback called when messages are received and sent */ |
45 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) | 71 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) |
46 { | 72 { |
47 char * buf = NULL; | 73 char * peer_name = peer ? peer->info.pi_diamid : "<unknown peer>"; |
48 size_t len; | 74 |
49 | 75 CHECK_POSIX_DO( pthread_mutex_lock(&mtx), ); |
50 CHECK_MALLOC_DO( fd_msg_dump_treeview(&buf, &len, NULL, msg, fd_g_config->cnf_dict, 1, 1), | 76 |
51 { LOG_E("Error while dumping a message"); return; } ); | 77 if (msg) { |
52 | 78 CHECK_MALLOC_DO( fd_msg_dump_treeview(&buf, &len, NULL, msg, fd_g_config->cnf_dict, (type == HOOK_MESSAGE_PARSING_ERROR) ? 0 : 1, 1), |
53 LOG_N("%s %s:", | 79 { LOG_E("Error while dumping a message"); pthread_mutex_unlock(&mtx); return; } ); |
54 (type == HOOK_MESSAGE_RECEIVED) ? "RCV FROM" : "SENT TO", | 80 } |
55 peer ? peer->info.pi_diamid:"<unknown>"); | 81 |
56 LOG_SPLIT( FD_LOG_NOTICE, " ", buf ?:"<error dumping message>", NULL); | 82 switch (type) { |
57 | 83 /* errors */ |
58 free(buf); | 84 case HOOK_MESSAGE_FAILOVER: |
85 LOG_E("FAILOVER from '%s':", peer_name); | |
86 LOG_SPLIT(FD_LOG_ERROR, " ", buf, NULL); | |
87 break; | |
88 case HOOK_MESSAGE_PARSING_ERROR: | |
89 if (msg) { | |
90 DiamId_t id = NULL; | |
91 if (!fd_msg_source_get( msg, &id, NULL )) | |
92 id = (DiamId_t)"<error getting source>"; | |
93 if (!id) | |
94 id = (DiamId_t)"<local>"; | |
95 LOG_E("PARSING ERROR: '%s' from '%s': ", (char *)other, (char *)id); | |
96 LOG_SPLIT(FD_LOG_ERROR, " ", buf, NULL); | |
97 } else { | |
98 struct fd_cnx_rcvdata *rcv_data = other; | |
99 CHECK_MALLOC_DO(fd_dump_extend_hexdump(&buf, &len, NULL, rcv_data->buffer, rcv_data->length, 0, 0), break); | |
100 LOG_E("PARSING ERROR: %zdB msg from '%s': %s", rcv_data->length, peer_name, buf); | |
101 } | |
102 break; | |
103 case HOOK_MESSAGE_ROUTING_ERROR: | |
104 LOG_E("ROUTING ERROR '%s' for: ", (char *)other); | |
105 LOG_SPLIT(FD_LOG_ERROR, " ", buf, NULL); | |
106 break; | |
107 case HOOK_MESSAGE_DROPPED: | |
108 LOG_E("DROPPED '%s'", (char *)other); | |
109 LOG_SPLIT(FD_LOG_ERROR, " ", buf, NULL); | |
110 break; | |
111 | |
112 /* send receive */ | |
113 case HOOK_MESSAGE_RECEIVED: | |
114 LOG_N("RCV from '%s':", peer_name); | |
115 LOG_SPLIT(FD_LOG_NOTICE, " ", buf, NULL); | |
116 break; | |
117 case HOOK_MESSAGE_SENT: | |
118 LOG_N("SND to '%s':", peer_name); | |
119 LOG_SPLIT(FD_LOG_NOTICE, " ", buf, NULL); | |
120 break; | |
121 | |
122 /* The following are not received in this hook */ | |
123 case HOOK_MESSAGE_LOCAL: | |
124 case HOOK_MESSAGE_ROUTING_FORWARD: | |
125 case HOOK_MESSAGE_ROUTING_LOCAL: | |
126 | |
127 case HOOK_PEER_CONNECT_FAILED: | |
128 case HOOK_PEER_CONNECT_SUCCESS: | |
129 | |
130 case HOOK_DATA_RECEIVED: | |
131 break; | |
132 } | |
133 | |
134 CHECK_POSIX_DO( pthread_mutex_unlock(&mtx), ); | |
135 } | |
136 | |
137 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) | |
138 { | |
139 char * peer_name = peer ? peer->info.pi_diamid : "<unknown peer>"; | |
140 | |
141 CHECK_POSIX_DO( pthread_mutex_lock(&mtx), ); | |
142 | |
143 if (msg) { | |
144 CHECK_MALLOC_DO( fd_msg_dump_full(&buf, &len, NULL, msg, fd_g_config->cnf_dict, (type == HOOK_MESSAGE_PARSING_ERROR) ? 0 : 1, 1), | |
145 { LOG_E("Error while dumping a message"); pthread_mutex_unlock(&mtx); return; } ); | |
146 } | |
147 | |
148 switch (type) { | |
149 /* errors */ | |
150 case HOOK_MESSAGE_FAILOVER: | |
151 LOG_E("FAILOVER from '%s': %s", peer_name, buf); | |
152 break; | |
153 case HOOK_MESSAGE_PARSING_ERROR: | |
154 if (msg) { | |
155 DiamId_t id = NULL; | |
156 if (!fd_msg_source_get( msg, &id, NULL )) | |
157 id = (DiamId_t)"<error getting source>"; | |
158 if (!id) | |
159 id = (DiamId_t)"<local>"; | |
160 LOG_E("PARSING ERROR: '%s' from '%s': %s", (char *)other, (char *)id, buf); | |
161 } else { | |
162 struct fd_cnx_rcvdata *rcv_data = other; | |
163 CHECK_MALLOC_DO(fd_dump_extend_hexdump(&buf, &len, NULL, rcv_data->buffer, rcv_data->length, 0, 0), break); | |
164 LOG_E("PARSING ERROR: %zdB msg from '%s': %s", rcv_data->length, peer_name, buf); | |
165 } | |
166 break; | |
167 case HOOK_MESSAGE_ROUTING_ERROR: | |
168 LOG_E("ROUTING ERROR '%s' for: %s", (char *)other, buf); | |
169 break; | |
170 case HOOK_MESSAGE_DROPPED: | |
171 LOG_E("DROPPED '%s' %s", (char *)other, buf); | |
172 break; | |
173 | |
174 /* send receive */ | |
175 case HOOK_MESSAGE_RECEIVED: | |
176 LOG_N("RCV from '%s': %s", peer_name, buf); | |
177 break; | |
178 case HOOK_MESSAGE_SENT: | |
179 LOG_N("SND to '%s': %s", peer_name, buf); | |
180 break; | |
181 | |
182 /* The following are not received in this hook */ | |
183 case HOOK_MESSAGE_LOCAL: | |
184 case HOOK_MESSAGE_ROUTING_FORWARD: | |
185 case HOOK_MESSAGE_ROUTING_LOCAL: | |
186 | |
187 case HOOK_PEER_CONNECT_FAILED: | |
188 case HOOK_PEER_CONNECT_SUCCESS: | |
189 | |
190 case HOOK_DATA_RECEIVED: | |
191 break; | |
192 } | |
193 | |
194 CHECK_POSIX_DO( pthread_mutex_unlock(&mtx), ); | |
195 } | |
196 | |
197 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) | |
198 { | |
199 char * peer_name = peer ? peer->info.pi_diamid : "<unknown peer>"; | |
200 | |
201 CHECK_POSIX_DO( pthread_mutex_lock(&mtx), ); | |
202 | |
203 if (msg) { | |
204 CHECK_MALLOC_DO( fd_msg_dump_summary(&buf, &len, NULL, msg, fd_g_config->cnf_dict, 0, 0), | |
205 { LOG_E("Error while dumping a message"); pthread_mutex_unlock(&mtx); return; } ); | |
206 } | |
207 | |
208 switch (type) { | |
209 /* errors */ | |
210 case HOOK_MESSAGE_FAILOVER: | |
211 LOG_E("FAILOVER from '%s': %s", peer_name, buf); | |
212 break; | |
213 case HOOK_MESSAGE_PARSING_ERROR: | |
214 if (msg) { | |
215 DiamId_t id = NULL; | |
216 if (!fd_msg_source_get( msg, &id, NULL )) | |
217 id = (DiamId_t)"<error getting source>"; | |
218 if (!id) | |
219 id = (DiamId_t)"<local>"; | |
220 LOG_E("PARSING ERROR: '%s' from '%s': %s", (char *)other, (char *)id, buf); | |
221 } else { | |
222 struct fd_cnx_rcvdata *rcv_data = other; | |
223 CHECK_MALLOC_DO(fd_dump_extend_hexdump(&buf, &len, NULL, rcv_data->buffer, rcv_data->length, 0, 0), break); | |
224 LOG_E("PARSING ERROR: %zdB msg from '%s': %s", rcv_data->length, peer_name, buf); | |
225 } | |
226 break; | |
227 case HOOK_MESSAGE_ROUTING_ERROR: | |
228 LOG_E("ROUTING ERROR '%s' for: %s", (char *)other, buf); | |
229 break; | |
230 case HOOK_MESSAGE_DROPPED: | |
231 LOG_E("DROPPED '%s' %s", (char *)other, buf); | |
232 break; | |
233 | |
234 /* send receive */ | |
235 case HOOK_MESSAGE_RECEIVED: | |
236 LOG_N("RCV from '%s': %s", peer_name, buf); | |
237 break; | |
238 case HOOK_MESSAGE_SENT: | |
239 LOG_N("SND to '%s': %s", peer_name, buf); | |
240 break; | |
241 | |
242 /* routing */ | |
243 case HOOK_MESSAGE_LOCAL: | |
244 LOG_N("ISSUED: %s", buf); | |
245 break; | |
246 case HOOK_MESSAGE_ROUTING_FORWARD: | |
247 LOG_N("FORWARDING: %s", buf); | |
248 break; | |
249 case HOOK_MESSAGE_ROUTING_LOCAL: | |
250 LOG_N("DISPATCHING: %s", buf); | |
251 break; | |
252 | |
253 /* peers */ | |
254 case HOOK_PEER_CONNECT_FAILED: | |
255 LOG_N("CONNECT FAILED to %s: %s", peer_name, (char *)other); | |
256 break; | |
257 case HOOK_PEER_CONNECT_SUCCESS: { | |
258 char protobuf[40]; | |
259 if (peer) { | |
260 CHECK_FCT_DO(fd_peer_cnx_proto_info(peer, protobuf, sizeof(protobuf)), break ); | |
261 } else { | |
262 protobuf[0] = '-'; | |
263 protobuf[1] = '\0'; | |
264 } | |
265 LOG_N("CONNECTED TO '%s' (%s): %s", peer_name, protobuf, buf); | |
266 } | |
267 break; | |
268 /* Not handled */ | |
269 case HOOK_DATA_RECEIVED: | |
270 break; | |
271 } | |
272 | |
273 CHECK_POSIX_DO( pthread_mutex_unlock(&mtx), ); | |
274 } | |
275 | |
276 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) | |
277 { | |
59 } | 278 } |
60 | 279 |
61 /* Entry point */ | 280 /* Entry point */ |
62 static int md_main(char * conffile) | 281 static int md_main(char * conffile) |
63 { | 282 { |
283 uint32_t mask_errors, mask_sndrcv, mask_routing, mask_peers; | |
284 uint32_t mask_quiet, mask_compact, mask_full, mask_tree; | |
64 TRACE_ENTRY("%p", conffile); | 285 TRACE_ENTRY("%p", conffile); |
65 | 286 |
66 CHECK_FCT( fd_hook_register( HOOK_MASK( HOOK_MESSAGE_RECEIVED, HOOK_MESSAGE_SENT ), | 287 if (conffile != NULL) { |
67 md_hook_cb, NULL, NULL, &md_hdl) ); | 288 char * endp; |
68 | 289 dump_level = (uint8_t)strtoul(conffile, &endp, 16); |
290 CHECK_PARAMS_DO( *endp == '\0', { | |
291 LOG_E("Configuration parameter must be in the form \"0xNNNN\""); | |
292 return EINVAL; }); | |
293 } | |
294 | |
295 mask_errors = HOOK_MASK( HOOK_MESSAGE_FAILOVER, HOOK_MESSAGE_PARSING_ERROR, HOOK_MESSAGE_ROUTING_ERROR, HOOK_MESSAGE_DROPPED ); | |
296 mask_sndrcv = HOOK_MASK( HOOK_MESSAGE_RECEIVED, HOOK_MESSAGE_SENT ); | |
297 mask_routing= HOOK_MASK( HOOK_MESSAGE_LOCAL, HOOK_MESSAGE_ROUTING_FORWARD, HOOK_MESSAGE_ROUTING_LOCAL ); | |
298 mask_peers = HOOK_MASK( HOOK_PEER_CONNECT_FAILED, HOOK_PEER_CONNECT_SUCCESS ); | |
299 | |
300 mask_quiet = (dump_level & HK_ERRORS_QUIET) ? mask_errors : 0; | |
301 mask_quiet |= (dump_level & HK_SNDRCV_QUIET) ? mask_sndrcv : 0; | |
302 mask_quiet |= (dump_level & HK_ROUTING_QUIET) ? mask_routing : 0; | |
303 mask_quiet |= (dump_level & HK_PEERS_QUIET) ? mask_peers : 0; | |
304 | |
305 mask_compact = (dump_level & HK_ERRORS_COMPACT) ? mask_errors : 0; | |
306 mask_compact |= (dump_level & HK_SNDRCV_COMPACT) ? mask_sndrcv : 0; | |
307 mask_compact |= (dump_level & HK_ROUTING_COMPACT) ? mask_routing : 0; | |
308 mask_compact |= (dump_level & HK_PEERS_COMPACT) ? mask_peers : 0; | |
309 | |
310 mask_full = (dump_level & HK_ERRORS_FULL) ? mask_errors : 0; | |
311 mask_full |= (dump_level & HK_SNDRCV_FULL) ? mask_sndrcv : 0; | |
312 | |
313 mask_tree = (dump_level & HK_ERRORS_TREE) ? mask_errors : 0; | |
314 mask_tree |= (dump_level & HK_SNDRCV_TREE) ? mask_sndrcv : 0; | |
315 | |
316 if (mask_quiet) { | |
317 CHECK_FCT( fd_hook_register( mask_quiet, md_hook_cb_quiet, NULL, NULL, &md_hdl[0]) ); | |
318 } | |
319 if (mask_compact) { | |
320 CHECK_FCT( fd_hook_register( mask_compact, md_hook_cb_compact, NULL, NULL, &md_hdl[1]) ); | |
321 } | |
322 if (mask_full) { | |
323 CHECK_FCT( fd_hook_register( mask_full, md_hook_cb_full, NULL, NULL, &md_hdl[2]) ); | |
324 } | |
325 if (mask_tree) { | |
326 CHECK_FCT( fd_hook_register( mask_tree, md_hook_cb_tree, NULL, NULL, &md_hdl[3]) ); | |
327 } | |
328 | |
69 return 0; | 329 return 0; |
70 } | 330 } |
71 | 331 |
72 /* Cleanup */ | 332 /* Cleanup */ |
73 void fd_ext_fini(void) | 333 void fd_ext_fini(void) |
74 { | 334 { |
75 TRACE_ENTRY(); | 335 TRACE_ENTRY(); |
76 CHECK_FCT_DO( fd_hook_unregister( md_hdl ), ); | 336 if (md_hdl[0]) { CHECK_FCT_DO( fd_hook_unregister( md_hdl[0] ), ); } |
337 if (md_hdl[1]) { CHECK_FCT_DO( fd_hook_unregister( md_hdl[1] ), ); } | |
338 if (md_hdl[2]) { CHECK_FCT_DO( fd_hook_unregister( md_hdl[2] ), ); } | |
339 if (md_hdl[2]) { CHECK_FCT_DO( fd_hook_unregister( md_hdl[3] ), ); } | |
77 return ; | 340 return ; |
78 } | 341 } |
79 | 342 |
80 EXTENSION_ENTRY("dbg_msg_dumps", md_main); | 343 EXTENSION_ENTRY("dbg_msg_dumps", md_main); |