Mercurial > hg > freeDiameter
comparison libfdcore/hooks.c @ 1215:65c6460f60f2
Ensure the hooks lock is released when a thread is canceled. Optimize the default hook behavior to avoid too many mallocs/free
author | Sebastien Decugis <sdecugis@freediameter.net> |
---|---|
date | Wed, 19 Jun 2013 10:20:47 +0800 |
parents | 40330b75c044 |
children | 4b511d9b3def |
comparison
equal
deleted
inserted
replaced
1214:c2fbaf2985f4 | 1215:65c6460f60f2 |
---|---|
278 va_end(ap); | 278 va_end(ap); |
279 | 279 |
280 return ret; | 280 return ret; |
281 } | 281 } |
282 | 282 |
283 static pthread_mutex_t hook_default_mtx = PTHREAD_MUTEX_INITIALIZER; | |
284 static char * hook_default_buf = NULL; | |
285 static size_t hook_default_len = 0; | |
286 | |
283 /* The function that does the work of calling the extension's callbacks and also managing the permessagedata structures */ | 287 /* The function that does the work of calling the extension's callbacks and also managing the permessagedata structures */ |
284 void fd_hook_call(enum fd_hook_type type, struct msg * msg, struct fd_peer * peer, void * other, struct fd_msg_pmdl * pmdl) | 288 void fd_hook_call(enum fd_hook_type type, struct msg * msg, struct fd_peer * peer, void * other, struct fd_msg_pmdl * pmdl) |
285 { | 289 { |
286 struct fd_list * li; | 290 struct fd_list * li; |
287 ASSERT(type <= HOOK_LAST); | 291 ASSERT(type <= HOOK_LAST); |
288 int call_default = 0; | 292 int call_default = 0; |
289 | 293 |
290 /* lock the list of hooks for this type */ | 294 /* lock the list of hooks for this type */ |
291 CHECK_POSIX_DO( pthread_rwlock_rdlock(&HS_array[type].rwlock), ); | 295 CHECK_POSIX_DO( pthread_rwlock_rdlock(&HS_array[type].rwlock), ); |
296 | |
297 pthread_cleanup_push( fd_cleanup_rwlock, &HS_array[type].rwlock ); | |
292 | 298 |
293 if (FD_IS_LIST_EMPTY(&HS_array[type].sentinel)) { | 299 if (FD_IS_LIST_EMPTY(&HS_array[type].sentinel)) { |
294 call_default = 1; | 300 call_default = 1; |
295 } else { | 301 } else { |
296 /* for each registered hook */ | 302 /* for each registered hook */ |
306 /* Now, call this callback */ | 312 /* Now, call this callback */ |
307 (*h->fd_hook_cb)(type, msg, &peer->p_hdr, other, pmd, h->regdata); | 313 (*h->fd_hook_cb)(type, msg, &peer->p_hdr, other, pmd, h->regdata); |
308 } | 314 } |
309 } | 315 } |
310 | 316 |
317 pthread_cleanup_pop(0); | |
318 | |
311 /* done */ | 319 /* done */ |
312 CHECK_POSIX_DO( pthread_rwlock_unlock(&HS_array[type].rwlock), ); | 320 CHECK_POSIX_DO( pthread_rwlock_unlock(&HS_array[type].rwlock), ); |
313 | 321 |
314 if (call_default) { | 322 if (call_default) { |
315 char * buf = NULL; | 323 CHECK_POSIX_DO( pthread_mutex_lock(&hook_default_mtx), ); |
316 size_t len = 0; | 324 |
325 pthread_cleanup_push( fd_cleanup_mutex, &hook_default_mtx ); | |
317 | 326 |
318 /* There was no registered handler, default behavior for this hook */ | 327 /* There was no registered handler, default behavior for this hook */ |
319 switch (type) { | 328 switch (type) { |
320 case HOOK_DATA_RECEIVED: { | 329 case HOOK_DATA_RECEIVED: { |
321 struct fd_cnx_rcvdata *rcv_data = other; | 330 struct fd_cnx_rcvdata *rcv_data = other; |
322 LOG_A("RCV: %zd bytes", rcv_data->length); | 331 LOG_A("RCV: %zd bytes", rcv_data->length); |
323 break; | 332 break; |
324 } | 333 } |
325 | 334 |
326 case HOOK_MESSAGE_RECEIVED: { | 335 case HOOK_MESSAGE_RECEIVED: { |
327 CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break); | 336 CHECK_MALLOC_DO(fd_msg_dump_summary(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break); |
328 LOG_D("RCV from '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf); | 337 LOG_D("RCV from '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", hook_default_buf); |
329 break; | 338 break; |
330 } | 339 } |
331 | 340 |
332 case HOOK_MESSAGE_LOCAL: { | 341 case HOOK_MESSAGE_LOCAL: { |
333 CHECK_MALLOC_DO(fd_msg_dump_full(&buf, &len, NULL, msg, NULL, 0, 1), break); | 342 CHECK_MALLOC_DO(fd_msg_dump_full(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break); |
334 LOG_A("Handled to framework for sending: %s", buf); | 343 LOG_A("Handled to framework for sending: %s", hook_default_buf); |
335 break; | 344 break; |
336 } | 345 } |
337 | 346 |
338 case HOOK_MESSAGE_SENT: { | 347 case HOOK_MESSAGE_SENT: { |
339 CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break); | 348 CHECK_MALLOC_DO(fd_msg_dump_summary(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break); |
340 LOG_D("SENT to '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf); | 349 LOG_D("SENT to '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", hook_default_buf); |
341 break; | 350 break; |
342 } | 351 } |
343 | 352 |
344 case HOOK_MESSAGE_FAILOVER: { | 353 case HOOK_MESSAGE_FAILOVER: { |
345 CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break); | 354 CHECK_MALLOC_DO(fd_msg_dump_summary(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break); |
346 LOG_D("Failing over message sent to '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf); | 355 LOG_D("Failing over message sent to '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", hook_default_buf); |
347 break; | 356 break; |
348 } | 357 } |
349 | 358 |
350 case HOOK_MESSAGE_PARSING_ERROR: { | 359 case HOOK_MESSAGE_PARSING_ERROR: { |
351 if (msg) { | 360 if (msg) { |
354 id = (DiamId_t)"<error getting source>"; | 363 id = (DiamId_t)"<error getting source>"; |
355 | 364 |
356 if (!id) | 365 if (!id) |
357 id = (DiamId_t)"<local>"; | 366 id = (DiamId_t)"<local>"; |
358 | 367 |
359 CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break); | 368 CHECK_MALLOC_DO(fd_msg_dump_treeview(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break); |
360 | 369 |
361 LOG_E("Parsing error: '%s' for the following message received from '%s':", (char *)other, (char *)id); | 370 LOG_E("Parsing error: '%s' for the following message received from '%s':", (char *)other, (char *)id); |
362 LOG_SPLIT(FD_LOG_ERROR, " ", buf?:"<error dumping message>", NULL); | 371 LOG_SPLIT(FD_LOG_ERROR, " ", hook_default_buf, NULL); |
363 } else { | 372 } else { |
364 struct fd_cnx_rcvdata *rcv_data = other; | 373 struct fd_cnx_rcvdata *rcv_data = other; |
365 CHECK_MALLOC_DO(fd_dump_extend_hexdump(&buf, &len, NULL, rcv_data->buffer, rcv_data->length, 0, 0), break); | 374 CHECK_MALLOC_DO(fd_dump_extend_hexdump(&hook_default_buf, &hook_default_len, NULL, rcv_data->buffer, rcv_data->length, 0, 0), break); |
366 LOG_E("Parsing error: cannot parse %zdB buffer from '%s': %s", rcv_data->length, peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf); | 375 LOG_E("Parsing error: cannot parse %zdB buffer from '%s': %s", rcv_data->length, peer ? peer->p_hdr.info.pi_diamid : "<unknown>", hook_default_buf); |
367 } | 376 } |
368 break; | 377 break; |
369 } | 378 } |
370 | 379 |
371 case HOOK_MESSAGE_ROUTING_ERROR: { | 380 case HOOK_MESSAGE_ROUTING_ERROR: { |
372 CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break); | 381 CHECK_MALLOC_DO(fd_msg_dump_treeview(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break); |
373 LOG_E("Routing error: '%s' for the following message:", (char *)other); | 382 LOG_E("Routing error: '%s' for the following message:", (char *)other); |
374 LOG_SPLIT(FD_LOG_ERROR, " ", buf?:"<error dumping message>", NULL); | 383 LOG_SPLIT(FD_LOG_ERROR, " ", hook_default_buf, NULL); |
375 break; | 384 break; |
376 } | 385 } |
377 | 386 |
378 case HOOK_MESSAGE_ROUTING_FORWARD: { | 387 case HOOK_MESSAGE_ROUTING_FORWARD: { |
379 CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break); | 388 CHECK_MALLOC_DO(fd_msg_dump_summary(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break); |
380 LOG_D("FORWARDING: %s", buf); | 389 LOG_D("FORWARDING: %s", hook_default_buf); |
381 break; | 390 break; |
382 } | 391 } |
383 | 392 |
384 case HOOK_MESSAGE_ROUTING_LOCAL: { | 393 case HOOK_MESSAGE_ROUTING_LOCAL: { |
385 CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break); | 394 CHECK_MALLOC_DO(fd_msg_dump_summary(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break); |
386 LOG_D("DISPATCHING: %s", buf); | 395 LOG_D("DISPATCHING: %s", hook_default_buf); |
387 break; | 396 break; |
388 } | 397 } |
389 | 398 |
390 case HOOK_MESSAGE_DROPPED: { | 399 case HOOK_MESSAGE_DROPPED: { |
391 CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break); | 400 CHECK_MALLOC_DO(fd_msg_dump_treeview(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break); |
392 LOG_E("Message discarded ('%s'):", (char *)other); | 401 LOG_E("Message discarded ('%s'):", (char *)other); |
393 LOG_SPLIT(FD_LOG_ERROR, " ", buf?:"<error dumping message>", NULL); | 402 LOG_SPLIT(FD_LOG_ERROR, " ", hook_default_buf, NULL); |
394 break; | 403 break; |
395 } | 404 } |
396 | 405 |
397 case HOOK_PEER_CONNECT_FAILED: { | 406 case HOOK_PEER_CONNECT_FAILED: { |
398 if (msg) { | 407 if (msg) { |
399 CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break); | 408 CHECK_MALLOC_DO(fd_msg_dump_treeview(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break); |
400 LOG_N("Connection to '%s' failed: '%s'; CER/CEA dump:", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", (char *)other); | 409 LOG_N("Connection to '%s' failed: '%s'; CER/CEA dump:", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", (char *)other); |
401 LOG_SPLIT(FD_LOG_NOTICE, " ", buf?:"<error dumping message>", NULL); | 410 LOG_SPLIT(FD_LOG_NOTICE, " ", hook_default_buf, NULL); |
402 } else { | 411 } else { |
403 LOG_D("Connection to '%s' failed: %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", (char *)other); | 412 LOG_D("Connection to '%s' failed: %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", (char *)other); |
404 } | 413 } |
405 break; | 414 break; |
406 } | 415 } |
408 case HOOK_PEER_CONNECT_SUCCESS: { | 417 case HOOK_PEER_CONNECT_SUCCESS: { |
409 DiamId_t id = NULL; | 418 DiamId_t id = NULL; |
410 if ((!fd_msg_source_get( msg, &id, NULL )) && (id == NULL)) { /* The CEA is locally issued */ | 419 if ((!fd_msg_source_get( msg, &id, NULL )) && (id == NULL)) { /* The CEA is locally issued */ |
411 fd_msg_answ_getq(msg, &msg); /* We dump the CER in that case */ | 420 fd_msg_answ_getq(msg, &msg); /* We dump the CER in that case */ |
412 } | 421 } |
413 CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break); | 422 CHECK_MALLOC_DO(fd_msg_dump_treeview(&hook_default_buf, &hook_default_len, NULL, msg, NULL, 0, 1), break); |
414 char protobuf[40]; | 423 char protobuf[40]; |
415 if (peer) { | 424 if (peer) { |
416 CHECK_FCT_DO(fd_peer_cnx_proto_info(&peer->p_hdr, protobuf, sizeof(protobuf)), break ); | 425 CHECK_FCT_DO(fd_peer_cnx_proto_info(&peer->p_hdr, protobuf, sizeof(protobuf)), break ); |
417 } else { | 426 } else { |
418 protobuf[0] = '-'; | 427 protobuf[0] = '-'; |
419 protobuf[1] = '\0'; | 428 protobuf[1] = '\0'; |
420 } | 429 } |
421 LOG_N("Connected to '%s' (%s), remote capabilities: ", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", protobuf); | 430 LOG_N("Connected to '%s' (%s), remote capabilities: ", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", protobuf); |
422 LOG_SPLIT(FD_LOG_NOTICE, " ", buf?:"<error dumping message>", NULL); | 431 LOG_SPLIT(FD_LOG_NOTICE, " ", hook_default_buf, NULL); |
423 break; | 432 break; |
424 } | 433 } |
425 | 434 |
426 } | 435 } |
427 | 436 |
428 free(buf); | 437 pthread_cleanup_pop(0); |
429 } | 438 |
430 } | 439 CHECK_POSIX_DO( pthread_mutex_unlock(&hook_default_mtx), ); |
440 } | |
441 } |