comparison libfdproto/messages.c @ 687:026802543f57

Prepare for new message log facility
author Sebastien Decugis <sdecugis@nict.go.jp>
date Wed, 19 Jan 2011 17:08:21 +0900
parents f83d9878bf66
children 8c3dc8584dab
comparison
equal deleted inserted replaced
686:f83d9878bf66 687:026802543f57
658 /* indent inside an object */ 658 /* indent inside an object */
659 #define INOBJHDR "%*s " 659 #define INOBJHDR "%*s "
660 #define INOBJHDRVAL indent<0 ? 1 : indent, indent<0 ? "-" : "|" 660 #define INOBJHDRVAL indent<0 ? 1 : indent, indent<0 ? "-" : "|"
661 661
662 /* Dump a msg_t object */ 662 /* Dump a msg_t object */
663 static void obj_dump_msg (struct msg * msg, int indent ) 663 static void obj_dump_msg (struct msg * msg, int indent, FILE * fstr )
664 { 664 {
665 int ret = 0; 665 int ret = 0;
666 666
667 fd_log_debug("%*sMSG: %p\n", INOBJHDRVAL, msg); 667 fd_log_debug_fstr(fstr, "%*sMSG: %p\n", INOBJHDRVAL, msg);
668 668
669 if (!CHECK_MSG(msg)) { 669 if (!CHECK_MSG(msg)) {
670 fd_log_debug(INOBJHDR "INVALID!\n", INOBJHDRVAL); 670 fd_log_debug_fstr(fstr, INOBJHDR "INVALID!\n", INOBJHDRVAL);
671 return; 671 return;
672 } 672 }
673 673
674 if (!msg->msg_model) { 674 if (!msg->msg_model) {
675 675
676 fd_log_debug(INOBJHDR "(no model)\n", INOBJHDRVAL); 676 fd_log_debug_fstr(fstr, INOBJHDR "(no model)\n", INOBJHDRVAL);
677 677
678 } else { 678 } else {
679 679
680 enum dict_object_type dicttype; 680 enum dict_object_type dicttype;
681 struct dict_cmd_data dictdata; 681 struct dict_cmd_data dictdata;
682 ret = fd_dict_gettype(msg->msg_model, &dicttype); 682 ret = fd_dict_gettype(msg->msg_model, &dicttype);
683 if (ret || (dicttype != DICT_COMMAND)) { 683 if (ret || (dicttype != DICT_COMMAND)) {
684 fd_log_debug(INOBJHDR "(invalid model: %d %d)\n", INOBJHDRVAL, ret, dicttype); 684 fd_log_debug_fstr(fstr, INOBJHDR "(invalid model: %d %d)\n", INOBJHDRVAL, ret, dicttype);
685 goto public; 685 goto public;
686 } 686 }
687 ret = fd_dict_getval(msg->msg_model, &dictdata); 687 ret = fd_dict_getval(msg->msg_model, &dictdata);
688 if (ret != 0) { 688 if (ret != 0) {
689 fd_log_debug(INOBJHDR "(error getting model data: %s)\n", INOBJHDRVAL, strerror(ret)); 689 fd_log_debug_fstr(fstr, INOBJHDR "(error getting model data: %s)\n", INOBJHDRVAL, strerror(ret));
690 goto public; 690 goto public;
691 } 691 }
692 fd_log_debug(INOBJHDR "model : v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %u \"%s\"\n", INOBJHDRVAL, 692 fd_log_debug_fstr(fstr, INOBJHDR "model : v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %u \"%s\"\n", INOBJHDRVAL,
693 DUMP_CMDFL_val(dictdata.cmd_flag_val), DUMP_CMDFL_val(dictdata.cmd_flag_mask), dictdata.cmd_code, dictdata.cmd_name); 693 DUMP_CMDFL_val(dictdata.cmd_flag_val), DUMP_CMDFL_val(dictdata.cmd_flag_mask), dictdata.cmd_code, dictdata.cmd_name);
694 } 694 }
695 public: 695 public:
696 fd_log_debug(INOBJHDR "public: V:%d L:%d fl:" DUMP_CMDFL_str " CC:%u A:%d hi:%x ei:%x\n", INOBJHDRVAL, 696 fd_log_debug_fstr(fstr, INOBJHDR "public: V:%d L:%d fl:" DUMP_CMDFL_str " CC:%u A:%d hi:%x ei:%x\n", INOBJHDRVAL,
697 msg->msg_public.msg_version, 697 msg->msg_public.msg_version,
698 msg->msg_public.msg_length, 698 msg->msg_public.msg_length,
699 DUMP_CMDFL_val(msg->msg_public.msg_flags), 699 DUMP_CMDFL_val(msg->msg_public.msg_flags),
700 msg->msg_public.msg_code, 700 msg->msg_public.msg_code,
701 msg->msg_public.msg_appl, 701 msg->msg_public.msg_appl,
702 msg->msg_public.msg_hbhid, 702 msg->msg_public.msg_hbhid,
703 msg->msg_public.msg_eteid 703 msg->msg_public.msg_eteid
704 ); 704 );
705 fd_log_debug(INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p asso:%d sess:%p src:%s\n", 705 fd_log_debug_fstr(fstr, INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p asso:%d sess:%p src:%s\n",
706 INOBJHDRVAL, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.fct, msg->msg_cb.data, msg->msg_query, msg->msg_associated, msg->msg_sess, msg->msg_src_id?:"(nil)"); 706 INOBJHDRVAL, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.fct, msg->msg_cb.data, msg->msg_query, msg->msg_associated, msg->msg_sess, msg->msg_src_id?:"(nil)");
707 } 707 }
708 708
709 /* Dump an avp object */ 709 /* Dump an avp object */
710 static void obj_dump_avp ( struct avp * avp, int indent ) 710 static void obj_dump_avp ( struct avp * avp, int indent, FILE * fstr )
711 { 711 {
712 int ret = 0; 712 int ret = 0;
713 enum dict_avp_basetype type = -1; 713 enum dict_avp_basetype type = -1;
714 714
715 if (!CHECK_AVP(avp)) { 715 if (!CHECK_AVP(avp)) {
716 fd_log_debug(INOBJHDR "INVALID!\n", INOBJHDRVAL); 716 fd_log_debug_fstr(fstr, INOBJHDR "INVALID!\n", INOBJHDRVAL);
717 return; 717 return;
718 } 718 }
719 719
720 if (!avp->avp_model) { 720 if (!avp->avp_model) {
721 721
722 fd_log_debug(INOBJHDR "(no model)\n", INOBJHDRVAL); 722 fd_log_debug_fstr(fstr, INOBJHDR "(no model)\n", INOBJHDRVAL);
723 723
724 } else { 724 } else {
725 725
726 enum dict_object_type dicttype; 726 enum dict_object_type dicttype;
727 struct dict_avp_data dictdata; 727 struct dict_avp_data dictdata;
728 ret = fd_dict_gettype(avp->avp_model, &dicttype); 728 ret = fd_dict_gettype(avp->avp_model, &dicttype);
729 if (ret || (dicttype != DICT_AVP)) { 729 if (ret || (dicttype != DICT_AVP)) {
730 fd_log_debug(INOBJHDR "(invalid model: %d %d)\n", INOBJHDRVAL, ret, dicttype); 730 fd_log_debug_fstr(fstr, INOBJHDR "(invalid model: %d %d)\n", INOBJHDRVAL, ret, dicttype);
731 goto public; 731 goto public;
732 } 732 }
733 ret = fd_dict_getval(avp->avp_model, &dictdata); 733 ret = fd_dict_getval(avp->avp_model, &dictdata);
734 if (ret != 0) { 734 if (ret != 0) {
735 fd_log_debug(INOBJHDR "(error getting model data: %s)\n", INOBJHDRVAL, strerror(ret)); 735 fd_log_debug_fstr(fstr, INOBJHDR "(error getting model data: %s)\n", INOBJHDRVAL, strerror(ret));
736 goto public; 736 goto public;
737 } 737 }
738 fd_log_debug(INOBJHDR "model : v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %u \"%s\"\n", INOBJHDRVAL, 738 fd_log_debug_fstr(fstr, INOBJHDR "model : v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %u \"%s\"\n", INOBJHDRVAL,
739 DUMP_AVPFL_val(dictdata.avp_flag_val), 739 DUMP_AVPFL_val(dictdata.avp_flag_val),
740 DUMP_AVPFL_val(dictdata.avp_flag_mask), 740 DUMP_AVPFL_val(dictdata.avp_flag_mask),
741 type_base_name[dictdata.avp_basetype], 741 type_base_name[dictdata.avp_basetype],
742 dictdata.avp_code, 742 dictdata.avp_code,
743 dictdata.avp_name ); 743 dictdata.avp_name );
744 type = dictdata.avp_basetype; 744 type = dictdata.avp_basetype;
745 } 745 }
746 public: 746 public:
747 fd_log_debug(INOBJHDR "public: C:%u fl:" DUMP_AVPFL_str " L:%d V:%u data:@%p\n", INOBJHDRVAL, 747 fd_log_debug_fstr(fstr, INOBJHDR "public: C:%u fl:" DUMP_AVPFL_str " L:%d V:%u data:@%p\n", INOBJHDRVAL,
748 avp->avp_public.avp_code, 748 avp->avp_public.avp_code,
749 DUMP_AVPFL_val(avp->avp_public.avp_flags), 749 DUMP_AVPFL_val(avp->avp_public.avp_flags),
750 avp->avp_public.avp_len, 750 avp->avp_public.avp_len,
751 avp->avp_public.avp_vendor, 751 avp->avp_public.avp_vendor,
752 avp->avp_public.avp_value 752 avp->avp_public.avp_value
753 ); 753 );
754 /* Dump the value if set */ 754 /* Dump the value if set */
755 if (avp->avp_public.avp_value) { 755 if (avp->avp_public.avp_value) {
756 if (!avp->avp_model) { 756 if (!avp->avp_model) {
757 fd_log_debug(INOBJHDR "(data set but no model: ERROR)\n", INOBJHDRVAL); 757 fd_log_debug_fstr(fstr, INOBJHDR "(data set but no model: ERROR)\n", INOBJHDRVAL);
758 } else { 758 } else {
759 fd_dict_dump_avp_value(avp->avp_public.avp_value, avp->avp_model, indent); 759 fd_dict_dump_avp_value(avp->avp_public.avp_value, avp->avp_model, indent, fstr);
760 } 760 }
761 } 761 }
762 762
763 fd_log_debug(INOBJHDR "intern: src:%p mf:%d raw:%p(%d)\n", INOBJHDRVAL, avp->avp_source, avp->avp_mustfreeos, avp->avp_rawdata, avp->avp_rawlen); 763 fd_log_debug_fstr(fstr, INOBJHDR "intern: src:%p mf:%d raw:%p(%d)\n", INOBJHDRVAL, avp->avp_source, avp->avp_mustfreeos, avp->avp_rawdata, avp->avp_rawlen);
764 } 764 }
765 765
766 /* Dump a single object content */ 766 /* Dump a single object content */
767 static void msg_dump_intern ( int level, msg_or_avp * obj, int indent ) 767 static void msg_dump_intern ( int level, msg_or_avp * obj, int indent, FILE * fstr )
768 { 768 {
769 /* Log only if we are at least at level */ 769 /* Log only if we are at least at level */
770 if ( ! TRACE_BOOL(level) ) 770 if ( ! TRACE_BOOL(level) )
771 return; 771 return;
772 772
773 /* Check the object */ 773 /* Check the object */
774 if (!VALIDATE_OBJ(obj)) { 774 if (!VALIDATE_OBJ(obj)) {
775 fd_log_debug( ">>> invalid object (%p)!.\n", obj); 775 fd_log_debug_fstr(fstr, ">>> invalid object (%p)!.\n", obj);
776 return; 776 return;
777 } 777 }
778 778
779 /* Dump the object */ 779 /* Dump the object */
780 switch (_C(obj)->type) { 780 switch (_C(obj)->type) {
781 case MSG_AVP: 781 case MSG_AVP:
782 obj_dump_avp ( _A(obj), indent ); 782 obj_dump_avp ( _A(obj), indent, fstr );
783 break; 783 break;
784 784
785 case MSG_MSG: 785 case MSG_MSG:
786 obj_dump_msg ( _M(obj), indent ); 786 obj_dump_msg ( _M(obj), indent, fstr );
787 break; 787 break;
788 788
789 default: 789 default:
790 ASSERT(0); 790 ASSERT(0);
791 } 791 }
792 } 792 }
793 793
794 /* Dump a message to a specified file stream */
795 static void fd_msg_dump_fstr ( struct msg * msg, FILE * fstr )
796 {
797 msg_or_avp * ref = msg;
798 int indent = 2;
799 do {
800 msg_dump_intern ( NONE, ref, indent, fstr );
801
802 /* Now find the next object */
803 CHECK_FCT_DO( fd_msg_browse ( ref, MSG_BRW_WALK, &ref, &indent ), break );
804
805 /* dump next object */
806 } while (ref);
807 }
808
794 /* Dump a message content -- for debug mostly */ 809 /* Dump a message content -- for debug mostly */
795 void fd_msg_dump_walk ( int level, msg_or_avp *obj ) 810 void fd_msg_dump_walk ( int level, msg_or_avp *obj )
796 { 811 {
797 msg_or_avp * ref = obj; 812 msg_or_avp * ref = obj;
798 int indent = 1; 813 int indent = 1;
799 814
800 TRACE_DEBUG(level, "------ Dumping object %p (w)-------", obj); 815 TRACE_DEBUG(level, "------ Dumping object %p (w)-------", obj);
801 do { 816 do {
802 msg_dump_intern ( level, ref, indent ); 817 msg_dump_intern ( level, ref, indent, fd_g_debug_fstr );
803 818
804 /* Now find the next object */ 819 /* Now find the next object */
805 CHECK_FCT_DO( fd_msg_browse ( ref, MSG_BRW_WALK, &ref, &indent ), break ); 820 CHECK_FCT_DO( fd_msg_browse ( ref, MSG_BRW_WALK, &ref, &indent ), break );
806 821
807 /* dump next object */ 822 /* dump next object */
812 827
813 /* Dump a single object content -- for debug mostly */ 828 /* Dump a single object content -- for debug mostly */
814 void fd_msg_dump_one ( int level, msg_or_avp * obj ) 829 void fd_msg_dump_one ( int level, msg_or_avp * obj )
815 { 830 {
816 TRACE_DEBUG(level, "------ Dumping object %p (s)-------", obj); 831 TRACE_DEBUG(level, "------ Dumping object %p (s)-------", obj);
817 msg_dump_intern ( level, obj, 1 ); 832 msg_dump_intern ( level, obj, 1, fd_g_debug_fstr );
818 TRACE_DEBUG(level, "------ /end of object %p -------", obj); 833 TRACE_DEBUG(level, "------ /end of object %p -------", obj);
819 } 834 }
820 835
821 836
822 /***************************************************************************************************************/ 837 /***************************************************************************************************************/
1642 /* First handle the case where we have not found this AVP in the dictionary */ 1657 /* First handle the case where we have not found this AVP in the dictionary */
1643 if (!avp->avp_model) { 1658 if (!avp->avp_model) {
1644 1659
1645 if (mandatory && (avp->avp_public.avp_flags & AVP_FLAG_MANDATORY)) { 1660 if (mandatory && (avp->avp_public.avp_flags & AVP_FLAG_MANDATORY)) {
1646 TRACE_DEBUG(INFO, "Unsupported mandatory AVP found:"); 1661 TRACE_DEBUG(INFO, "Unsupported mandatory AVP found:");
1647 msg_dump_intern(INFO, avp, 2); 1662 msg_dump_intern(INFO, avp, 2, fd_g_debug_fstr);
1648 if (error_info) { 1663 if (error_info) {
1649 error_info->pei_errcode = "DIAMETER_AVP_UNSUPPORTED"; 1664 error_info->pei_errcode = "DIAMETER_AVP_UNSUPPORTED";
1650 error_info->pei_avp = avp; 1665 error_info->pei_avp = avp;
1651 } 1666 }
1652 return ENOTSUP; 1667 return ENOTSUP;
2306 2321
2307 error: 2322 error:
2308 CHECK_POSIX_DO(pthread_rwlock_unlock(&fd_disp_lock), /* ignore */ ); 2323 CHECK_POSIX_DO(pthread_rwlock_unlock(&fd_disp_lock), /* ignore */ );
2309 return ret; 2324 return ret;
2310 } 2325 }
2326
2327
2328 /***************************************************************************************************************/
2329 /* messages logging facility */
2330 #include <stdarg.h>
2331
2332 static struct {
2333 struct {
2334 enum fd_msg_log_method meth;
2335 const char * metharg;
2336 } causes[FD_MSG_LOG_MAX + 1];
2337 pthread_mutex_t lock;
2338 int init;
2339 } ml_conf = { .lock = PTHREAD_MUTEX_INITIALIZER, .init = 0 };
2340
2341 static void ml_conf_init(void)
2342 {
2343 memset(&ml_conf.causes, 0, sizeof(ml_conf.causes));
2344 ml_conf.init = 1;
2345 }
2346
2347 /* Set a configuration property */
2348 int fd_msg_log_config(enum fd_msg_log_cause cause, enum fd_msg_log_method method, const char * arg)
2349 {
2350 /* Check the parameters are valid */
2351 TRACE_ENTRY("%d %d %p", cause, method, arg);
2352 CHECK_PARAMS( (cause >= 0) && (cause <= FD_MSG_LOG_MAX) );
2353 CHECK_PARAMS( (method >= FD_MSG_LOGTO_DEBUGONLY) && (method <= FD_MSG_LOGTO_DIR) );
2354 CHECK_PARAMS( (method == FD_MSG_LOGTO_DEBUGONLY) || (arg != NULL) );
2355
2356 /* Lock the configuration */
2357 CHECK_POSIX( pthread_mutex_lock(&ml_conf.lock) );
2358 if (!ml_conf.init) {
2359 ml_conf_init();
2360 }
2361
2362 /* Now set the parameter */
2363 ml_conf.causes[cause].meth = method;
2364 ml_conf.causes[cause].metharg = arg;
2365
2366 if (method) {
2367 TRACE_DEBUG(INFO, "Logging %s messages set to %s '%s'",
2368 (cause == FD_MSG_LOG_DROPPED) ? "DROPPED" :
2369 (cause == FD_MSG_LOG_RECEIVED) ? "RECEIVED" :
2370 (cause == FD_MSG_LOG_SENT) ? "SENT" :
2371 "???",
2372 (method == FD_MSG_LOGTO_FILE) ? "file" :
2373 (method == FD_MSG_LOGTO_DIR) ? "directory" :
2374 "???",
2375 arg);
2376 }
2377
2378 CHECK_POSIX( pthread_mutex_unlock(&ml_conf.lock) );
2379
2380 /* Done */
2381 return 0;
2382 }
2383
2384 /* Do not log anything within this one, since log lock is held */
2385 static void fd_cleanup_mutex_silent( void * mutex )
2386 {
2387 (void)pthread_mutex_unlock((pthread_mutex_t *)mutex);
2388 }
2389
2390 /* Really log the message */
2391 void fd_msg_log( enum fd_msg_log_cause cause, struct msg * msg, const char * prefix_format, ... )
2392 {
2393 va_list ap;
2394 enum fd_msg_log_method meth;
2395 const char * metharg;
2396 FILE * fstr;
2397
2398 TRACE_ENTRY("%d %p %p", cause, msg, prefix_format);
2399 CHECK_PARAMS_DO( (cause >= 0) && (cause <= FD_MSG_LOG_MAX),
2400 {
2401 TRACE_DEBUG(INFO, "Invalid cause received (%d)! Message was:", cause);
2402 fd_msg_dump_walk(INFO, msg);
2403 } );
2404
2405 /* First retrieve the config for this message */
2406 CHECK_POSIX_DO( pthread_mutex_lock(&ml_conf.lock), );
2407 if (!ml_conf.init) {
2408 ml_conf_init();
2409 }
2410 meth = ml_conf.causes[cause].meth;
2411 metharg = ml_conf.causes[cause].metharg;
2412 CHECK_POSIX_DO( pthread_mutex_unlock(&ml_conf.lock), );
2413
2414 /* Okay, now we will create the file descriptor */
2415 switch (meth) {
2416 case FD_MSG_LOGTO_DEBUGONLY:
2417 fstr = fd_g_debug_fstr;
2418 break;
2419
2420 case FD_MSG_LOGTO_FILE:
2421 TODO("Log to arg file");
2422 break;
2423 case FD_MSG_LOGTO_DIR:
2424 TODO("Log to arg directory in a new file");
2425 break;
2426 }
2427
2428 /* Then dump the prefix message to this stream */
2429 (void)pthread_mutex_lock(&fd_log_lock);
2430 pthread_cleanup_push(fd_cleanup_mutex_silent, &fd_log_lock);
2431 va_start(ap, prefix_format);
2432 vfprintf( fstr, prefix_format, ap);
2433 va_end(ap);
2434 fflush(fstr);
2435 pthread_cleanup_pop(0);
2436 (void)pthread_mutex_unlock(&fd_log_lock);
2437 fd_log_debug_fstr(fstr, "\n\n");
2438
2439 /* And now the message itself */
2440 fd_msg_dump_fstr(msg, fstr);
2441
2442 /* And finally close the stream if needed */
2443 TODO("close?");
2444 }
2445
"Welcome to our mercurial repository"