Mercurial > hg > freeDiameter
comparison libfdproto/messages.c @ 1036:aecdc2fbf222
Add fd_msg_dump_full function that dumps a message in human-readable format.
(not hooked in yet)
For this, add an argument to dump_avp_val if it should print a
header before each value or not.
author | Thomas Klausner <tk@giga.or.at> |
---|---|
date | Tue, 16 Apr 2013 18:53:51 +0200 |
parents | 0117a7746b21 |
children | 56bf0377e2ff |
comparison
equal
deleted
inserted
replaced
1035:2f989d1a21e9 | 1036:aecdc2fbf222 |
---|---|
826 /* Dump the value if set */ | 826 /* Dump the value if set */ |
827 if (avp->avp_public.avp_value) { | 827 if (avp->avp_public.avp_value) { |
828 if (!avp->avp_model) { | 828 if (!avp->avp_model) { |
829 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(data set but no model: ERROR)|", INOBJHDRVAL) ); | 829 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(data set but no model: ERROR)|", INOBJHDRVAL) ); |
830 } else { | 830 } else { |
831 CHECK_FCT( fd_dict_dump_avp_value(avp->avp_public.avp_value, avp->avp_model, indent, outstr, offset, outlen) ); | 831 CHECK_FCT( fd_dict_dump_avp_value(avp->avp_public.avp_value, avp->avp_model, indent, outstr, offset, outlen, 1) ); |
832 } | 832 } |
833 } | 833 } |
834 | 834 |
835 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "intern: src:%p mf:%d raw:%p(%d)|", INOBJHDRVAL, avp->avp_source, avp->avp_mustfreeos, avp->avp_rawdata, avp->avp_rawlen) ); | 835 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "intern: src:%p mf:%d raw:%p(%d)|", INOBJHDRVAL, avp->avp_source, avp->avp_mustfreeos, avp->avp_rawdata, avp->avp_rawlen) ); |
836 return 0; | 836 return 0; |
896 CHECK_FCT_DO( msg_dump_intern ( NONE, msg, 2, &outstr, &offset, &outlen ), | 896 CHECK_FCT_DO( msg_dump_intern ( NONE, msg, 2, &outstr, &offset, &outlen ), |
897 fd_log_debug_fstr(fstr, "Error while dumping %p", msg) ); | 897 fd_log_debug_fstr(fstr, "Error while dumping %p", msg) ); |
898 /* now really output this in one shot, so it is not interrupted */ | 898 /* now really output this in one shot, so it is not interrupted */ |
899 fd_log_debug_fstr(fstr, "%s", outstr); | 899 fd_log_debug_fstr(fstr, "%s", outstr); |
900 | 900 |
901 free(outstr); | |
902 } | |
903 | |
904 /* Completely dump a msg_t object */ | |
905 static int full_obj_dump_msg (struct msg * msg, struct dictionary *dict, char **outstr, size_t *offset, size_t *outlen) | |
906 { | |
907 int ret = 0; | |
908 int success = 0; | |
909 struct dict_cmd_data dictdata; | |
910 char buf[20]; | |
911 | |
912 if (!CHECK_MSG(msg)) { | |
913 CHECK_FCT( dump_add_str(outstr, offset, outlen, "INVALID MESSAGE") ); | |
914 return 0; | |
915 } | |
916 | |
917 if (!msg->msg_model) { | |
918 fd_msg_parse_dict(msg, dict, NULL); | |
919 } | |
920 if (!msg->msg_model) { | |
921 CHECK_FCT( dump_add_str(outstr, offset, outlen, "(no model) ") ); | |
922 } else { | |
923 enum dict_object_type dicttype; | |
924 ret = fd_dict_gettype(msg->msg_model, &dicttype); | |
925 if (ret || (dicttype != DICT_COMMAND)) { | |
926 CHECK_FCT( dump_add_str(outstr, offset, outlen, "(invalid model: %d %d) ", ret, dicttype) ); | |
927 } else { | |
928 ret = fd_dict_getval(msg->msg_model, &dictdata); | |
929 if (ret != 0) { | |
930 CHECK_FCT( dump_add_str(outstr, offset, outlen, "(error getting model data: %s) ", strerror(ret)) ); | |
931 } else { | |
932 success = 1; | |
933 } | |
934 } | |
935 } | |
936 | |
937 if (msg->msg_public.msg_appl) { | |
938 snprintf(buf, sizeof(buf), "%u/", msg->msg_public.msg_appl); | |
939 } else { | |
940 buf[0] = '\0'; | |
941 } | |
942 CHECK_FCT( dump_add_str(outstr, offset, outlen, "%s(%s%u)[" DUMP_CMDFL_str "], Length=%u, Hop-By-Hop-Id=0x%08x, End-to-End=0x%08x", | |
943 success ? dictdata.cmd_name : "unknown", buf, msg->msg_public.msg_code, DUMP_CMDFL_val(msg->msg_public.msg_flags), | |
944 msg->msg_public.msg_length, msg->msg_public.msg_hbhid, msg->msg_public.msg_eteid)); | |
945 | |
946 return 0; | |
947 } | |
948 | |
949 /* Dump an avp object completely */ | |
950 static int full_obj_dump_avp ( struct avp * avp, char **outstr, size_t *offset, size_t *outlen, int first ) | |
951 { | |
952 int success = 0; | |
953 struct dict_avp_data dictdata; | |
954 char buf[20]; | |
955 | |
956 CHECK_FCT( dump_add_str(outstr, offset, outlen, first ? ((*outstr)[*offset-1] == '=' ? "{ " : ", { ") : ", ") ); | |
957 | |
958 if (!CHECK_AVP(avp)) { | |
959 CHECK_FCT( dump_add_str(outstr, offset, outlen, "INVALID AVP") ); | |
960 return 0; | |
961 } | |
962 | |
963 if (avp->avp_model) { | |
964 enum dict_object_type dicttype; | |
965 int ret; | |
966 ret = fd_dict_gettype(avp->avp_model, &dicttype); | |
967 if (ret || (dicttype != DICT_AVP)) { | |
968 CHECK_FCT( dump_add_str(outstr, offset, outlen, "(invalid model: %d %d) ", ret, dicttype) ); | |
969 } else { | |
970 ret = fd_dict_getval(avp->avp_model, &dictdata); | |
971 if (ret != 0) { | |
972 CHECK_FCT( dump_add_str(outstr, offset, outlen, "(error getting model data: %s) ", strerror(ret)) ); | |
973 } else { | |
974 success = 1; | |
975 } | |
976 } | |
977 } | |
978 | |
979 if (avp->avp_public.avp_vendor) { | |
980 snprintf(buf, sizeof(buf), "%u/", avp->avp_public.avp_vendor); | |
981 } else { | |
982 buf[0] = '\0'; | |
983 } | |
984 /* \todo add full vendorname? */ | |
985 CHECK_FCT(dump_add_str(outstr, offset, outlen, "%s(%s%u)[" DUMP_AVPFL_str "]=", success ? dictdata.avp_name : "unknown", buf, avp->avp_public.avp_code, DUMP_AVPFL_val(avp->avp_public.avp_flags))); | |
986 | |
987 /* Dump the value if set */ | |
988 if (avp->avp_public.avp_value) { | |
989 if (!avp->avp_model) { | |
990 CHECK_FCT( dump_add_str(outstr, offset, outlen, "(unknown data type)") ); | |
991 } else { | |
992 CHECK_FCT( fd_dict_dump_avp_value(avp->avp_public.avp_value, avp->avp_model, 1, outstr, offset, outlen, 0) ); | |
993 } | |
994 } | |
995 | |
996 return 0; | |
997 } | |
998 | |
999 /* Dump full message */ | |
1000 void fd_msg_dump_full ( int level, struct dictionary *dict, const char *prefix, msg_or_avp *obj ) | |
1001 { | |
1002 msg_or_avp * ref = obj; | |
1003 char *outstr; | |
1004 int indent = 1; | |
1005 int first = 1; | |
1006 int previous; | |
1007 size_t offset, outlen; | |
1008 CHECK_FCT_DO( dump_init_str(&outstr, &offset, &outlen), | |
1009 { fd_log_error("Error initializing string for dumping %p", obj); return; } ); | |
1010 CHECK_FCT_DO( dump_add_str(&outstr, &offset, &outlen, "%s: ", prefix), | |
1011 { fd_log_error("Error while dumping %p", ref); return; }); | |
1012 | |
1013 do { | |
1014 /* Check the object */ | |
1015 if (!VALIDATE_OBJ(ref)) { | |
1016 CHECK_FCT_DO( dump_add_str(&outstr, &offset, &outlen, ">>> invalid object (%p)", ref), | |
1017 { fd_log_error("Error in error handling dumping %p", ref); break; }); | |
1018 } | |
1019 /* Dump the object */ | |
1020 switch (_C(ref)->type) { | |
1021 case MSG_AVP: | |
1022 CHECK_FCT_DO( full_obj_dump_avp ( _A(ref), &outstr, &offset, &outlen, first ), | |
1023 { fd_log_error("Error in error handling dumping %p", ref); }); | |
1024 break; | |
1025 case MSG_MSG: | |
1026 CHECK_FCT_DO( full_obj_dump_msg ( _M(obj), dict, &outstr, &offset, &outlen ), | |
1027 { fd_log_error("Error in error handling dumping %p", ref); }); | |
1028 break; | |
1029 default: | |
1030 ASSERT(0); | |
1031 } | |
1032 | |
1033 first = 0; | |
1034 previous = indent; | |
1035 /* Now find the next object */ | |
1036 CHECK_FCT_DO( fd_msg_browse ( ref, MSG_BRW_WALK, &ref, &indent ), break ); | |
1037 if (previous < indent) { | |
1038 first = 1; | |
1039 } else while (previous-- > indent) { | |
1040 CHECK_FCT_DO( dump_add_str(&outstr, &offset, &outlen, " }"), | |
1041 { fd_log_error("Error while dumping %p", ref); return; }); | |
1042 } | |
1043 /* dump next object */ | |
1044 } while (ref); | |
1045 | |
1046 fd_log(level, "%s", outstr); | |
901 free(outstr); | 1047 free(outstr); |
902 } | 1048 } |
903 | 1049 |
904 /* Dump a message content -- for debug mostly */ | 1050 /* Dump a message content -- for debug mostly */ |
905 void fd_msg_dump_walk ( int level, msg_or_avp *obj ) | 1051 void fd_msg_dump_walk ( int level, msg_or_avp *obj ) |