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 )
"Welcome to our mercurial repository"