Mercurial > hg > freeDiameter
comparison libfdproto/messages.c @ 1096:97a257c80de0
Implemented remaining flavour of message dump function
author | Sebastien Decugis <sdecugis@freediameter.net> |
---|---|
date | Mon, 06 May 2013 18:25:50 +0800 |
parents | 647c7e7015af |
children | f38d77f9cfd3 6ce5c99a40af |
comparison
equal
deleted
inserted
replaced
1095:647c7e7015af | 1096:97a257c80de0 |
---|---|
1015 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " }"), return NULL); | 1015 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " }"), return NULL); |
1016 } | 1016 } |
1017 | 1017 |
1018 return *buf; | 1018 return *buf; |
1019 } | 1019 } |
1020 | |
1020 /* one-line dump with all the contents of the message */ | 1021 /* one-line dump with all the contents of the message */ |
1021 DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_full, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse ) | 1022 DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_full, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse ) |
1022 { | 1023 { |
1023 return msg_dump_process(FD_DUMP_STD_PARAMS, msg_format_full, avp_format_full, obj, dict, force_parsing, recurse); | 1024 return msg_dump_process(FD_DUMP_STD_PARAMS, msg_format_full, avp_format_full, obj, dict, force_parsing, recurse); |
1024 } | 1025 } |
1025 | 1026 |
1026 #warning "todo" | 1027 |
1028 | |
1029 /* | |
1030 * One-line dumper for compact but complete traces | |
1031 */ | |
1032 static DECLARE_FD_DUMP_PROTOTYPE( msg_format_summary, struct msg * msg ) | |
1033 { | |
1034 if (!CHECK_MSG(msg)) { | |
1035 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{message}(@%p): INVALID", msg), return NULL); | |
1036 return *buf; | |
1037 } | |
1038 | |
1039 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{message}(@%p): ", msg), return NULL); | |
1040 if (!msg->msg_model) { | |
1041 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(no model)"), return NULL); | |
1042 } else { | |
1043 enum dict_object_type dicttype; | |
1044 struct dict_cmd_data dictdata; | |
1045 if (fd_dict_gettype(msg->msg_model, &dicttype) || (dicttype != DICT_COMMAND) || (fd_dict_getval(msg->msg_model, &dictdata))) { | |
1046 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(model error)"), return NULL); | |
1047 } else { | |
1048 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'", dictdata.cmd_name), return NULL); | |
1049 } | |
1050 } | |
1051 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%u/%u f:" DUMP_CMDFL_str " src:'%s' len:%d", | |
1052 msg->msg_public.msg_appl, msg->msg_public.msg_code, DUMP_CMDFL_val(msg->msg_public.msg_flags), msg->msg_src_id?:"(nil)", msg->msg_public.msg_length), return NULL); | |
1053 | |
1054 return *buf; | |
1055 } | |
1056 | |
1057 static DECLARE_FD_DUMP_PROTOTYPE( avp_format_summary, struct avp * avp, int level, int first, int last ) | |
1058 { | |
1059 char * name; | |
1060 struct dict_avp_data dictdata; | |
1061 struct dict_avp_data *dictinfo = NULL; | |
1062 struct dict_vendor_data vendordata; | |
1063 struct dict_vendor_data *vendorinfo = NULL; | |
1064 | |
1065 if (level) { | |
1066 if (first) { | |
1067 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {"), return NULL); | |
1068 } else { | |
1069 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "+"), return NULL); | |
1070 } | |
1071 } | |
1072 | |
1073 if (!CHECK_AVP(avp)) { | |
1074 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID"), return NULL); | |
1075 goto end; | |
1076 } | |
1077 | |
1078 if (!level) { | |
1079 /* We have been called to explicitely dump this AVP, so we parse its name if available */ | |
1080 if (!avp->avp_model) { | |
1081 name = "(no model)"; | |
1082 } else { | |
1083 enum dict_object_type dicttype; | |
1084 if (fd_dict_gettype(avp->avp_model, &dicttype) || (dicttype != DICT_AVP) || (fd_dict_getval(avp->avp_model, &dictdata))) { | |
1085 name = "(model error)"; | |
1086 } else { | |
1087 name = dictdata.avp_name; | |
1088 dictinfo = &dictdata; | |
1089 if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) { | |
1090 struct dictionary * dict; | |
1091 struct dict_object * vendor; | |
1092 if ((!fd_dict_getdict(avp->avp_model, &dict)) | |
1093 && (!fd_dict_search(dict, DICT_VENDOR, VENDOR_OF_AVP, avp->avp_model, &vendor, ENOENT)) | |
1094 && (!fd_dict_getval(vendor, &vendordata))) { | |
1095 vendorinfo = &vendordata; | |
1096 } | |
1097 } | |
1098 } | |
1099 } | |
1100 | |
1101 if (dictinfo) { | |
1102 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'(%u)", name, avp->avp_public.avp_code), return NULL); | |
1103 } else { | |
1104 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%u%s", avp->avp_public.avp_code, name), return NULL); | |
1105 } | |
1106 | |
1107 if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) { | |
1108 if (vendorinfo) { | |
1109 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " V='%s'(%u)", vendorinfo->vendor_name, avp->avp_public.avp_vendor), return NULL); | |
1110 } else { | |
1111 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " V=%u", avp->avp_public.avp_vendor), return NULL); | |
1112 } | |
1113 } | |
1114 | |
1115 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " L=%d F=" DUMP_AVPFL_str " V=", avp->avp_public.avp_len, DUMP_AVPFL_val(avp->avp_public.avp_flags)), return NULL); | |
1116 | |
1117 if ((!dictinfo) || (dictinfo->avp_basetype != AVP_TYPE_GROUPED)) { | |
1118 if (avp->avp_public.avp_value) { | |
1119 CHECK_MALLOC_DO( fd_dict_dump_avp_value(FD_DUMP_STD_PARAMS, avp->avp_public.avp_value, avp->avp_model, 0, 0), return NULL); | |
1120 } else if (avp->avp_rawdata) { | |
1121 CHECK_MALLOC_DO( fd_dump_extend_hexdump(FD_DUMP_STD_PARAMS, avp->avp_rawdata, avp->avp_rawlen, 0, 0), return NULL); | |
1122 } else { | |
1123 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(not set)"), return NULL); | |
1124 } | |
1125 } | |
1126 } else { | |
1127 /* For embedded AVPs, we only display (vendor,) code & length */ | |
1128 if (avp->avp_public.avp_flags & AVP_FLAG_VENDOR) { | |
1129 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "V=%u,", avp->avp_public.avp_vendor), return NULL); | |
1130 } | |
1131 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "C=%u,L=%d", avp->avp_public.avp_code, avp->avp_public.avp_len), return NULL); | |
1132 } | |
1133 | |
1134 end: | |
1135 if ((level) && (last)) { | |
1136 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "}"), return NULL); | |
1137 } | |
1138 | |
1139 return *buf; | |
1140 } | |
1027 | 1141 |
1028 /* This one only prints a short display, does not go into the complete tree */ | 1142 /* This one only prints a short display, does not go into the complete tree */ |
1029 DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_summary, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse ) | 1143 DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_summary, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse ) |
1030 { | 1144 { |
1031 return NULL; | 1145 return msg_dump_process(FD_DUMP_STD_PARAMS, msg_format_summary, avp_format_summary, obj, dict, force_parsing, recurse); |
1032 } | 1146 } |
1033 | 1147 |
1034 #ifndef OLD_CODE_TO_BE_REPLACED | 1148 #ifndef OLD_CODE_TO_BE_REPLACED |
1035 void fd_msg_dump_walk ( int level, msg_or_avp *obj ) | 1149 void fd_msg_dump_walk ( int level, msg_or_avp *obj ) |
1036 { | 1150 { |
1038 } | 1152 } |
1039 void fd_msg_dump_one ( int level, msg_or_avp * obj ) | 1153 void fd_msg_dump_one ( int level, msg_or_avp * obj ) |
1040 { | 1154 { |
1041 LOG_D("fd_msg_dump_one %d, %p is deprecated", level, obj); | 1155 LOG_D("fd_msg_dump_one %d, %p is deprecated", level, obj); |
1042 } | 1156 } |
1043 #else /* OLD_CODE_TO_BE_REPLACED */ | 1157 #endif |
1044 | |
1045 | |
1046 /* indent inside an object */ | |
1047 #define INOBJHDR "%*s " | |
1048 #define INOBJHDRVAL indent<0 ? 1 : indent, indent<0 ? "-" : "|" | |
1049 | |
1050 /* Write some debug data in a buffer */ | |
1051 | |
1052 /* Dump a msg_t object */ | |
1053 static int obj_dump_msg (struct msg * msg, int indent, char **outstr, size_t *offset, size_t *outlen ) | |
1054 { | |
1055 int ret = 0; | |
1056 | |
1057 CHECK_FCT( dump_add_str(outstr, offset, outlen, "%*sMSG: %p|", INOBJHDRVAL, msg) ); | |
1058 | |
1059 if (!CHECK_MSG(msg)) { | |
1060 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "INVALID!", INOBJHDRVAL) ); | |
1061 return 0; | |
1062 } | |
1063 | |
1064 if (!msg->msg_model) { | |
1065 | |
1066 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(no model)|", INOBJHDRVAL) ); | |
1067 | |
1068 } else { | |
1069 | |
1070 enum dict_object_type dicttype; | |
1071 struct dict_cmd_data dictdata; | |
1072 ret = fd_dict_gettype(msg->msg_model, &dicttype); | |
1073 if (ret || (dicttype != DICT_COMMAND)) { | |
1074 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(invalid model: %d %d)|", INOBJHDRVAL, ret, dicttype) ); | |
1075 goto public; | |
1076 } | |
1077 ret = fd_dict_getval(msg->msg_model, &dictdata); | |
1078 if (ret != 0) { | |
1079 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(error getting model data: %s)|", INOBJHDRVAL, strerror(ret)) ); | |
1080 goto public; | |
1081 } | |
1082 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "model : v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %u \"%s\"|", INOBJHDRVAL, | |
1083 DUMP_CMDFL_val(dictdata.cmd_flag_val), DUMP_CMDFL_val(dictdata.cmd_flag_mask), dictdata.cmd_code, dictdata.cmd_name) ); | |
1084 } | |
1085 public: | |
1086 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "public: V:%d L:%d fl:" DUMP_CMDFL_str " CC:%u A:%d hi:%x ei:%x|", INOBJHDRVAL, | |
1087 msg->msg_public.msg_version, | |
1088 msg->msg_public.msg_length, | |
1089 DUMP_CMDFL_val(msg->msg_public.msg_flags), | |
1090 msg->msg_public.msg_code, | |
1091 msg->msg_public.msg_appl, | |
1092 msg->msg_public.msg_hbhid, | |
1093 msg->msg_public.msg_eteid | |
1094 ) ); | |
1095 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "intern: rwb:%p rt:%d cb:%p,%p(%p) qry:%p asso:%d sess:%p src:%s(%zd)|", | |
1096 INOBJHDRVAL, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.anscb, msg->msg_cb.expirecb, msg->msg_cb.data, msg->msg_query, msg->msg_associated, msg->msg_sess, msg->msg_src_id?:"(nil)", msg->msg_src_id_len) ); | |
1097 return 0; | |
1098 } | |
1099 | |
1100 /* Dump an avp object */ | |
1101 static int obj_dump_avp ( struct avp * avp, int indent, char **outstr, size_t *offset, size_t *outlen ) | |
1102 { | |
1103 int ret = 0; | |
1104 | |
1105 if (!CHECK_AVP(avp)) { | |
1106 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "INVALID!", INOBJHDRVAL) ); | |
1107 return 0; | |
1108 } | |
1109 | |
1110 if (!avp->avp_model) { | |
1111 | |
1112 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(no model resolved)|", INOBJHDRVAL) ); | |
1113 | |
1114 } else { | |
1115 | |
1116 enum dict_object_type dicttype; | |
1117 struct dict_avp_data dictdata; | |
1118 ret = fd_dict_gettype(avp->avp_model, &dicttype); | |
1119 if (ret || (dicttype != DICT_AVP)) { | |
1120 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(invalid model: %d %d)|", INOBJHDRVAL, ret, dicttype) ); | |
1121 goto public; | |
1122 } | |
1123 ret = fd_dict_getval(avp->avp_model, &dictdata); | |
1124 if (ret != 0) { | |
1125 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(error getting model data: %s)|", INOBJHDRVAL, strerror(ret)) ); | |
1126 goto public; | |
1127 } | |
1128 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "model : v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %u \"%s\"|", INOBJHDRVAL, | |
1129 DUMP_AVPFL_val(dictdata.avp_flag_val), | |
1130 DUMP_AVPFL_val(dictdata.avp_flag_mask), | |
1131 type_base_name[dictdata.avp_basetype], | |
1132 dictdata.avp_code, | |
1133 dictdata.avp_name ) ); | |
1134 } | |
1135 public: | |
1136 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "public: C:%u fl:" DUMP_AVPFL_str " L:%d V:%u data:@%p|", INOBJHDRVAL, | |
1137 avp->avp_public.avp_code, | |
1138 DUMP_AVPFL_val(avp->avp_public.avp_flags), | |
1139 avp->avp_public.avp_len, | |
1140 avp->avp_public.avp_vendor, | |
1141 avp->avp_public.avp_value | |
1142 ) ); | |
1143 /* Dump the value if set */ | |
1144 if (avp->avp_public.avp_value) { | |
1145 if (!avp->avp_model) { | |
1146 CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(data set but no model: ERROR)|", INOBJHDRVAL) ); | |
1147 } else { | |
1148 CHECK_FCT( fd_dict_dump_avp_value(avp->avp_public.avp_value, avp->avp_model, indent, outstr, offset, outlen, 1) ); | |
1149 } | |
1150 } | |
1151 | |
1152 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) ); | |
1153 return 0; | |
1154 } | |
1155 | |
1156 /* Dump a single object content into out string, realloc if needed */ | |
1157 static int msg_dump_intern ( int level, msg_or_avp * obj, int indent, char **outstr, size_t *offset, size_t *outlen ) | |
1158 { | |
1159 /* Log only if we are at least at level */ | |
1160 if ( ! TRACE_BOOL(level) ) | |
1161 return 0; | |
1162 | |
1163 /* Check the object */ | |
1164 if (!VALIDATE_OBJ(obj)) { | |
1165 CHECK_FCT( dump_add_str(outstr, offset, outlen, ">>> invalid object (%p)!.", obj) ); | |
1166 return 0; | |
1167 } | |
1168 | |
1169 /* Dump the object */ | |
1170 switch (_C(obj)->type) { | |
1171 case MSG_AVP: | |
1172 CHECK_FCT( obj_dump_avp ( _A(obj), indent, outstr, offset, outlen )); | |
1173 break; | |
1174 | |
1175 case MSG_MSG: | |
1176 CHECK_FCT( obj_dump_msg ( _M(obj), indent, outstr, offset, outlen ) ); | |
1177 break; | |
1178 | |
1179 default: | |
1180 ASSERT(0); | |
1181 } | |
1182 return 0; | |
1183 } | |
1184 | |
1185 /* Dump a message to a specified file stream */ | |
1186 void fd_msg_dump_fstr ( struct msg * msg, FILE * fstr ) | |
1187 { | |
1188 msg_or_avp * ref = msg; | |
1189 int indent = 2; | |
1190 char *outstr; | |
1191 size_t offset, outlen; | |
1192 CHECK_FCT_DO( dump_init_str(&outstr, &offset, &outlen), { fd_log_debug_fstr(fstr, "Error initializing string for dumping %p", msg); return; } ); | |
1193 do { | |
1194 CHECK_FCT_DO( msg_dump_intern ( NONE, ref, indent, &outstr, &offset, &outlen ), | |
1195 fd_log_debug_fstr(fstr, "Error while dumping %p", ref) ); | |
1196 | |
1197 /* Now find the next object */ | |
1198 CHECK_FCT_DO( fd_msg_browse ( ref, MSG_BRW_WALK, &ref, &indent ), break ); | |
1199 | |
1200 /* dump next object */ | |
1201 } while (ref); | |
1202 | |
1203 /* now really output this in one shot, so it is not interrupted */ | |
1204 fd_log_debug_fstr(fstr, "%s", outstr); | |
1205 | |
1206 free(outstr); | |
1207 } | |
1208 void fd_msg_dump_fstr_one ( struct msg * msg, FILE * fstr ) /* just the header */ | |
1209 { | |
1210 char *outstr; | |
1211 size_t offset, outlen; | |
1212 CHECK_FCT_DO( dump_init_str(&outstr, &offset, &outlen), { fd_log_debug_fstr(fstr, "Error initializing string for dumping %p", msg); return; } ); | |
1213 CHECK_FCT_DO( msg_dump_intern ( NONE, msg, 2, &outstr, &offset, &outlen ), | |
1214 fd_log_debug_fstr(fstr, "Error while dumping %p", msg) ); | |
1215 /* now really output this in one shot, so it is not interrupted */ | |
1216 fd_log_debug_fstr(fstr, "%s", outstr); | |
1217 | |
1218 free(outstr); | |
1219 } | |
1220 | |
1221 /* Completely dump a msg_t object */ | |
1222 static int full_obj_dump_msg (struct msg * msg, struct dictionary *dict, char **outstr, size_t *offset, size_t *outlen) | |
1223 { | |
1224 int ret = 0; | |
1225 int success = 0; | |
1226 struct dict_cmd_data dictdata; | |
1227 char buf[20]; | |
1228 | |
1229 if (!CHECK_MSG(msg)) { | |
1230 CHECK_FCT( dump_add_str(outstr, offset, outlen, "INVALID MESSAGE") ); | |
1231 return 0; | |
1232 } | |
1233 | |
1234 if (!msg->msg_model) { | |
1235 fd_msg_parse_dict(msg, dict, NULL); | |
1236 } | |
1237 if (!msg->msg_model) { | |
1238 CHECK_FCT( dump_add_str(outstr, offset, outlen, "(no model) ") ); | |
1239 } else { | |
1240 enum dict_object_type dicttype; | |
1241 ret = fd_dict_gettype(msg->msg_model, &dicttype); | |
1242 if (ret || (dicttype != DICT_COMMAND)) { | |
1243 CHECK_FCT( dump_add_str(outstr, offset, outlen, "(invalid model: %d %d) ", ret, dicttype) ); | |
1244 } else { | |
1245 ret = fd_dict_getval(msg->msg_model, &dictdata); | |
1246 if (ret != 0) { | |
1247 CHECK_FCT( dump_add_str(outstr, offset, outlen, "(error getting model data: %s) ", strerror(ret)) ); | |
1248 } else { | |
1249 success = 1; | |
1250 } | |
1251 } | |
1252 } | |
1253 | |
1254 if (msg->msg_public.msg_appl) { | |
1255 snprintf(buf, sizeof(buf), "%u/", msg->msg_public.msg_appl); | |
1256 } else { | |
1257 buf[0] = '\0'; | |
1258 } | |
1259 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", | |
1260 success ? dictdata.cmd_name : "unknown", buf, msg->msg_public.msg_code, DUMP_CMDFL_val(msg->msg_public.msg_flags), | |
1261 msg->msg_public.msg_length, msg->msg_public.msg_hbhid, msg->msg_public.msg_eteid)); | |
1262 | |
1263 return 0; | |
1264 } | |
1265 | |
1266 /* Dump an avp object completely */ | |
1267 static int full_obj_dump_avp ( struct avp * avp, char **outstr, size_t *offset, size_t *outlen, int first ) | |
1268 { | |
1269 int success = 0; | |
1270 struct dict_avp_data dictdata; | |
1271 char buf[20]; | |
1272 | |
1273 CHECK_FCT( dump_add_str(outstr, offset, outlen, first ? ((*outstr)[*offset-1] == '=' ? "{ " : ", { ") : ", ") ); | |
1274 | |
1275 if (!CHECK_AVP(avp)) { | |
1276 CHECK_FCT( dump_add_str(outstr, offset, outlen, "INVALID AVP") ); | |
1277 return 0; | |
1278 } | |
1279 | |
1280 if (avp->avp_model) { | |
1281 enum dict_object_type dicttype; | |
1282 int ret; | |
1283 ret = fd_dict_gettype(avp->avp_model, &dicttype); | |
1284 if (ret || (dicttype != DICT_AVP)) { | |
1285 CHECK_FCT( dump_add_str(outstr, offset, outlen, "(invalid model: %d %d) ", ret, dicttype) ); | |
1286 } else { | |
1287 ret = fd_dict_getval(avp->avp_model, &dictdata); | |
1288 if (ret != 0) { | |
1289 CHECK_FCT( dump_add_str(outstr, offset, outlen, "(error getting model data: %s) ", strerror(ret)) ); | |
1290 } else { | |
1291 success = 1; | |
1292 } | |
1293 } | |
1294 } | |
1295 | |
1296 if (avp->avp_public.avp_vendor) { | |
1297 snprintf(buf, sizeof(buf), "%u/", avp->avp_public.avp_vendor); | |
1298 } else { | |
1299 buf[0] = '\0'; | |
1300 } | |
1301 /* \todo add full vendorname? */ | |
1302 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))); | |
1303 | |
1304 /* Dump the value if set */ | |
1305 if (avp->avp_public.avp_value) { | |
1306 if (!avp->avp_model) { | |
1307 CHECK_FCT( dump_add_str(outstr, offset, outlen, "(unknown data type)") ); | |
1308 } else { | |
1309 CHECK_FCT( fd_dict_dump_avp_value(avp->avp_public.avp_value, avp->avp_model, 1, outstr, offset, outlen, 0) ); | |
1310 } | |
1311 } | |
1312 | |
1313 return 0; | |
1314 } | |
1315 | |
1316 /* Dump full message */ | |
1317 // TODO: need align with new prototype & behavior | |
1318 void fd_msg_dump_full_TODO ( int level, struct dictionary *dict, const char *prefix, msg_or_avp *obj ) | |
1319 { | |
1320 msg_or_avp * ref = obj; | |
1321 char *outstr; | |
1322 int indent = 1; | |
1323 int first = 1; | |
1324 int previous; | |
1325 size_t offset, outlen; | |
1326 CHECK_FCT_DO( dump_init_str(&outstr, &offset, &outlen), | |
1327 { fd_log_error("Error initializing string for dumping %p", obj); return; } ); | |
1328 CHECK_FCT_DO( dump_add_str(&outstr, &offset, &outlen, "%s: ", prefix), | |
1329 { fd_log_error("Error while dumping %p", ref); return; }); | |
1330 | |
1331 do { | |
1332 /* Check the object */ | |
1333 if (!VALIDATE_OBJ(ref)) { | |
1334 CHECK_FCT_DO( dump_add_str(&outstr, &offset, &outlen, ">>> invalid object (%p)", ref), | |
1335 { fd_log_error("Error in error handling dumping %p", ref); break; }); | |
1336 } | |
1337 /* Dump the object */ | |
1338 switch (_C(ref)->type) { | |
1339 case MSG_AVP: | |
1340 CHECK_FCT_DO( full_obj_dump_avp ( _A(ref), &outstr, &offset, &outlen, first ), | |
1341 { fd_log_error("Error in error handling dumping %p", ref); }); | |
1342 break; | |
1343 case MSG_MSG: | |
1344 CHECK_FCT_DO( full_obj_dump_msg ( _M(obj), dict, &outstr, &offset, &outlen ), | |
1345 { fd_log_error("Error in error handling dumping %p", ref); }); | |
1346 break; | |
1347 default: | |
1348 ASSERT(0); | |
1349 } | |
1350 | |
1351 first = 0; | |
1352 previous = indent; | |
1353 /* Now find the next object */ | |
1354 CHECK_FCT_DO( fd_msg_browse ( ref, MSG_BRW_WALK, &ref, &indent ), break ); | |
1355 if (previous < indent) { | |
1356 first = 1; | |
1357 } else while (previous-- > indent) { | |
1358 CHECK_FCT_DO( dump_add_str(&outstr, &offset, &outlen, " }"), | |
1359 { fd_log_error("Error while dumping %p", ref); return; }); | |
1360 } | |
1361 /* dump next object */ | |
1362 } while (ref); | |
1363 | |
1364 fd_log(level, "%s", outstr); | |
1365 free(outstr); | |
1366 } | |
1367 | |
1368 /* Dump a message content -- for debug mostly */ | |
1369 void fd_msg_dump_walk ( int level, msg_or_avp *obj ) | |
1370 { | |
1371 msg_or_avp * ref = obj; | |
1372 int indent = 1; | |
1373 char *outstr; | |
1374 size_t offset, outlen; | |
1375 CHECK_FCT_DO( dump_init_str(&outstr, &offset, &outlen), | |
1376 { fd_log_debug_fstr(fd_g_debug_fstr, "Error initializing string for dumping %p", obj); return; } ); | |
1377 | |
1378 do { | |
1379 CHECK_FCT_DO( msg_dump_intern ( level, ref, indent, &outstr, &offset, &outlen ), | |
1380 fd_log_debug_fstr(fd_g_debug_fstr, "Error while dumping %p", ref) ); | |
1381 | |
1382 /* Now find the next object */ | |
1383 CHECK_FCT_DO( fd_msg_browse ( ref, MSG_BRW_WALK, &ref, &indent ), break ); | |
1384 | |
1385 /* dump next object */ | |
1386 } while (ref); | |
1387 | |
1388 /* now really output this in one shot, so it is not interrupted */ | |
1389 TRACE_DEBUG(level, "------ Dumping object %p (w)-------", obj); | |
1390 TRACE_DEBUG(level, "%s", outstr); | |
1391 TRACE_DEBUG(level, "------ /end of object %p -------", obj); | |
1392 | |
1393 free(outstr); | |
1394 } | |
1395 | |
1396 /* Dump a single object content -- for debug mostly */ | |
1397 void fd_msg_dump_one ( int level, msg_or_avp * obj ) | |
1398 { | |
1399 char *outstr; | |
1400 size_t offset, outlen; | |
1401 CHECK_FCT_DO( dump_init_str(&outstr, &offset, &outlen), | |
1402 { fd_log_debug_fstr(fd_g_debug_fstr, "Error initializing string for dumping %p", obj); return; } ); | |
1403 CHECK_FCT_DO( msg_dump_intern ( level, obj, 1, &outstr, &offset, &outlen ), | |
1404 fd_log_debug_fstr(fd_g_debug_fstr, "Error while dumping %p", obj) ); | |
1405 TRACE_DEBUG(level, "------ Dumping object %p (s)-------", obj); | |
1406 TRACE_DEBUG(level, "%s", outstr); | |
1407 TRACE_DEBUG(level, "------ /end of object %p -------", obj); | |
1408 free(outstr); | |
1409 } | |
1410 | |
1411 #endif /* OLD_CODE_TO_BE_REPLACED */ | |
1412 /***************************************************************************************************************/ | 1158 /***************************************************************************************************************/ |
1413 /* Simple meta-data management */ | 1159 /* Simple meta-data management */ |
1414 | 1160 |
1415 /* Retrieve the model of an object */ | 1161 /* Retrieve the model of an object */ |
1416 int fd_msg_model ( msg_or_avp * reference, struct dict_object ** model ) | 1162 int fd_msg_model ( msg_or_avp * reference, struct dict_object ** model ) |