changeset 804:c5b7d4a2cc77

Log message dumps in one call to the dump function to avoid fragmentation in the log files, as per Zack comment
author Sebastien Decugis <sdecugis@nict.go.jp>
date Wed, 22 Aug 2012 00:22:46 +0200
parents d5a4b5e175c2
children fb5e0fd923ff
files include/freeDiameter/libfdproto.h libfdcore/dict_base_proto.c libfdproto/dictionary.c libfdproto/fdproto-internal.h libfdproto/messages.c
diffstat 5 files changed, 196 insertions(+), 98 deletions(-) [+]
line wrap: on
line diff
--- a/include/freeDiameter/libfdproto.h	Wed Aug 22 00:18:15 2012 +0200
+++ b/include/freeDiameter/libfdproto.h	Wed Aug 22 00:22:46 2012 +0200
@@ -1114,7 +1114,7 @@
 	char *	 		 type_name;	/* The name of this type */
 	dict_avpdata_interpret	 type_interpret;/* cb to convert the AVP value in more comprehensive format (or NULL) */
 	dict_avpdata_encode	 type_encode;	/* cb to convert formatted data into an AVP value (or NULL) */
-	void			(*type_dump)(union avp_value * val, FILE * fstr);	/* cb called by fd_msg_dump_one for this type of data (if != NULL), to dump the AVP value in fstr */
+	char * 			(*type_dump)(union avp_value * val);	/* cb called by fd_msg_dump_one for this type of data (if != NULL). Returned string must be freed.  */
 };
 
 /* The criteria for searching a type object in the dictionary */
--- a/libfdcore/dict_base_proto.c	Wed Aug 22 00:18:15 2012 +0200
+++ b/libfdcore/dict_base_proto.c	Wed Aug 22 00:22:46 2012 +0200
@@ -144,8 +144,10 @@
 }
 
 /* Dump the content of an Address AVP */
-static void Address_dump(union avp_value * avp_value, FILE * fstr)
+static char * Address_dump(union avp_value * avp_value)
 {
+	char * ret;
+	#define STR_LEN	1024
 	union {
 		sSA	sa;
 		sSS	ss;
@@ -156,10 +158,12 @@
 	
 	memset(&s, 0, sizeof(s));
 	
+	CHECK_MALLOC_DO( ret = malloc(STR_LEN), return NULL );
+	
 	/* The first two octets represent the address family, http://www.iana.org/assignments/address-family-numbers/ */
 	if (avp_value->os.len < 2) {
-		fd_log_debug_fstr(fstr, "[invalid length: %d]", avp_value->os.len);
-		return;
+		snprintf(ret, STR_LEN, "[invalid length: %d]", avp_value->os.len);
+		return ret;
 	}
 	
 	/* Following octets are the address in network byte order already */
@@ -169,8 +173,8 @@
 			/* IP */
 			s.sa.sa_family = AF_INET;
 			if (avp_value->os.len != 6) {
-				fd_log_debug_fstr(fstr, "[invalid IP length: %d]", avp_value->os.len);
-				return;
+				snprintf(ret, STR_LEN, "[invalid IP length: %d]", avp_value->os.len);
+				return ret;
 			}
 			memcpy(&s.sin.sin_addr.s_addr, avp_value->os.data + 2, 4);
 			break;
@@ -178,33 +182,28 @@
 			/* IP6 */
 			s.sa.sa_family = AF_INET6;
 			if (avp_value->os.len != 18) {
-				fd_log_debug_fstr(fstr, "[invalid IP6 length: %d]", avp_value->os.len);
-				return;
+				snprintf(ret, STR_LEN, "[invalid IP6 length: %d]", avp_value->os.len);
+				return ret;
 			}
 			memcpy(&s.sin6.sin6_addr.s6_addr, avp_value->os.data + 2, 16);
 			break;
 		default:
-			fd_log_debug_fstr(fstr, "[unsupported family: 0x%hx]", fam);
-			return;
+			snprintf(ret, STR_LEN, "[unsupported family: 0x%hx]", fam);
+			return ret;
 	}
 	
 	{
-		char addrbuf[INET6_ADDRSTRLEN];
-		int rc = getnameinfo(&s.sa, sSAlen(&s.sa), addrbuf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
+		int rc = getnameinfo(&s.sa, sSAlen(&s.sa), ret, STR_LEN, NULL, 0, NI_NUMERICHOST);
 		if (rc)
-			fd_log_debug_fstr(fstr, "%s", (char *)gai_strerror(rc));
-		else
-			fd_log_debug_fstr(fstr, "%s", addrbuf);
-		
+			snprintf(ret, STR_LEN, "%s", (char *)gai_strerror(rc));
 	}
+	
+	return ret;
 }
 
-static void UTF8String_dump(union avp_value * avp_value, FILE * fstr)
+static char * UTF8String_dump(union avp_value * avp_value)
 {
-	size_t len = avp_value->os.len;
-	if (len > 42)
-		len = 42; /* avoid very long strings */
-	fd_log_debug_fstr(fstr, "%.*s", len, avp_value->os.data);
+	return strndup((char *)avp_value->os.data, 42); /* avoid very long strings */
 }
 
 
--- a/libfdproto/dictionary.c	Wed Aug 22 00:18:15 2012 +0200
+++ b/libfdproto/dictionary.c	Wed Aug 22 00:22:46 2012 +0200
@@ -1304,50 +1304,57 @@
 /**************************** Dump AVP values ********************************/
 
 /* Default dump functions */
-static void dump_val_os(union avp_value * value, FILE * fstr)
+static int dump_val_os(union avp_value * value, char **outstr, size_t *offset, size_t *outlen)
 {
 	int i;
 	for (i = 0; i < value->os.len; i++) {
 		if (i == 24) { /* Dump only up to 24 bytes of the buffer */
-			fd_log_debug_fstr(fstr, "[...] (len=%zd)", value->os.len);
+			CHECK_FCT( dump_add_str(outstr, offset, outlen, "[...] (len=%zd)", value->os.len) );
 			break;
 		}
-		fd_log_debug_fstr(fstr, "%02.2X ", value->os.data[i]);
+		CHECK_FCT( dump_add_str(outstr, offset, outlen, "%02.2X ", value->os.data[i]) );
 	}
+	return 0;
 }
 
-static void dump_val_i32(union avp_value * value, FILE * fstr)
+static int dump_val_i32(union avp_value * value, char **outstr, size_t *offset, size_t *outlen)
 {
-	fd_log_debug_fstr(fstr, "%i (0x%x)", value->i32, value->i32);
+	CHECK_FCT( dump_add_str(outstr, offset, outlen, "%i (0x%x)", value->i32, value->i32) );
+	return 0;
 }
 
-static void dump_val_i64(union avp_value * value, FILE * fstr)
+static int dump_val_i64(union avp_value * value, char **outstr, size_t *offset, size_t *outlen)
 {
-	fd_log_debug_fstr(fstr, "%lli (0x%llx)", value->i64, value->i64);
+	CHECK_FCT( dump_add_str(outstr, offset, outlen, "%lli (0x%llx)", value->i64, value->i64) );
+	return 0;
 }
 
-static void dump_val_u32(union avp_value * value, FILE * fstr)
+static int dump_val_u32(union avp_value * value, char **outstr, size_t *offset, size_t *outlen)
 {
-	fd_log_debug_fstr(fstr, "%u (0x%x)", value->u32, value->u32);
+	CHECK_FCT( dump_add_str(outstr, offset, outlen, "%u (0x%x)", value->u32, value->u32) );
+	return 0;
 }
 
-static void dump_val_u64(union avp_value * value, FILE * fstr)
+static int dump_val_u64(union avp_value * value, char **outstr, size_t *offset, size_t *outlen)
 {
-	fd_log_debug_fstr(fstr, "%llu (0x%llx)", value->u64, value->u64);
+	CHECK_FCT( dump_add_str(outstr, offset, outlen, "%llu (0x%llx)", value->u64, value->u64) );
+	return 0;
 }
 
-static void dump_val_f32(union avp_value * value, FILE * fstr)
+static int dump_val_f32(union avp_value * value, char **outstr, size_t *offset, size_t *outlen)
 {
-	fd_log_debug_fstr(fstr, "%f", value->f32);
+	CHECK_FCT( dump_add_str(outstr, offset, outlen, "%f", value->f32) );
+	return 0;
 }
 
-static void dump_val_f64(union avp_value * value, FILE * fstr)
+static int dump_val_f64(union avp_value * value, char **outstr, size_t *offset, size_t *outlen)
 {
-	fd_log_debug_fstr(fstr, "%g", value->f64);
+	CHECK_FCT( dump_add_str(outstr, offset, outlen, "%g", value->f64) );
+	return 0;
 }
 
 /* Get the dump function for basic dict_avp_basetype */
-static void (*get_default_dump_val_cb(enum dict_avp_basetype datatype))(union avp_value *, FILE *)
+static int (*get_default_dump_val_cb(enum dict_avp_basetype datatype))(union avp_value *, char **, size_t *, size_t *)
 {
 	switch (datatype) {
 		case AVP_TYPE_OCTETSTRING:
@@ -1382,43 +1389,60 @@
 #define INOBJHDRVAL 	indent<0 ? 1 : indent, indent<0 ? "-" : "|"
 
 /* Formater for the AVP value dump line */
-static void dump_avp_val(union avp_value *avp_value, void (*dump_val_cb)(union avp_value *, FILE *), enum dict_avp_basetype datatype, char * type_name, char * const_name, int indent, FILE * fstr)
+static int dump_avp_val(union avp_value *avp_value, 
+			int (*def_dump_val_cb)(union avp_value *, char **, size_t *, size_t *), 
+			char * (*dump_val_cb)(union avp_value *), 
+			enum dict_avp_basetype datatype, 
+			char * type_name, 
+			char * const_name, 
+			int indent, 
+			char **outstr, 
+			size_t *offset, 
+			size_t *outlen)
 {
 	/* Header for all AVP values dumps: */
-	fd_log_debug_fstr(fstr, INOBJHDR "value ", INOBJHDRVAL);
+	CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "value ", INOBJHDRVAL) );
 	
 	/* If the type is provided, write it */
-	if (type_name)
-		fd_log_debug_fstr(fstr, "t: '%s' ", type_name);
+	if (type_name) {
+		CHECK_FCT( dump_add_str(outstr, offset, outlen, "t: '%s' ", type_name) );
+	}
 	
 	/* Always give the base datatype anyway */
-	fd_log_debug_fstr(fstr, "(%s) ", type_base_name[datatype]);
+	CHECK_FCT( dump_add_str(outstr, offset, outlen, "(%s) ", type_base_name[datatype]) );
 	
 	/* Now, the value */
-	fd_log_debug_fstr(fstr, "v: ");
-	if (const_name)
-		fd_log_debug_fstr(fstr, "'%s' (", const_name);
-	(*dump_val_cb)(avp_value, fstr);
-	if (const_name)
-		fd_log_debug_fstr(fstr, ")");
+	CHECK_FCT( dump_add_str(outstr, offset, outlen, "v: ") );
+	if (const_name) {
+		CHECK_FCT( dump_add_str(outstr, offset, outlen, "'%s' (", const_name) );
+	}
+	if (dump_val_cb) {
+		char * str;
+		CHECK_MALLOC_DO( str = (*dump_val_cb)(avp_value), dump_add_str(outstr, offset, outlen, "(dump failed)") );
+		CHECK_FCT( dump_add_str(outstr, offset, outlen, "%s", str) );
+		free(str);
+	} else {
+		CHECK_FCT( (*def_dump_val_cb)(avp_value, outstr, offset, outlen) );
+	}
+	if (const_name) {
+		CHECK_FCT( dump_add_str(outstr, offset, outlen, ")") );
+	}
 	
 	/* Done! */
-	fd_log_debug_fstr(fstr, "\n");
+	CHECK_FCT( dump_add_str(outstr, offset, outlen, "\n") );
+	return 0;
 }
 
-/* Dump the value of an AVP of known type */
-void fd_dict_dump_avp_value(union avp_value *avp_value, struct dict_object * model, int indent, FILE * fstr)
+/* Dump the value of an AVP of known type into the returned str */
+int fd_dict_dump_avp_value(union avp_value *avp_value, struct dict_object * model, int indent, char **outstr, size_t *offset, size_t *outlen)
 {
-	void (*dump_val_cb)(union avp_value *avp_value, FILE * fstr);
+	char * (*dump_val_cb)(union avp_value *avp_value) = NULL;
 	struct dict_object * type = NULL;
 	char * type_name = NULL;
 	char * const_name = NULL;
 	
 	/* Check the parameters are correct */
-	CHECK_PARAMS_DO( avp_value && verify_object(model) && (model->type == DICT_AVP), return );
-	
-	/* Default: display the value with the formatter for the AVP datatype */
-	CHECK_PARAMS_DO( dump_val_cb = get_default_dump_val_cb(model->data.avp.avp_basetype), return );
+	CHECK_PARAMS( avp_value && verify_object(model) && (model->type == DICT_AVP) );
 	
 	/* Get the type definition of this AVP */
 	type = model->parent;
@@ -1444,7 +1468,8 @@
 	}
 	
 	/* And finally, dump the value */
-	dump_avp_val(avp_value, dump_val_cb, model->data.avp.avp_basetype, type_name, const_name, indent, fstr);
+	CHECK_FCT( dump_avp_val(avp_value, get_default_dump_val_cb(model->data.avp.avp_basetype), dump_val_cb, model->data.avp.avp_basetype, type_name, const_name, indent, outstr, offset, outlen) );
+	return 0;
 }
 
 /*******************************************************************************************************/
--- a/libfdproto/fdproto-internal.h	Wed Aug 22 00:18:15 2012 +0200
+++ b/libfdproto/fdproto-internal.h	Wed Aug 22 00:22:46 2012 +0200
@@ -59,7 +59,7 @@
 
 /* Dispatch / messages / dictionary API */
 int fd_dict_disp_cb(enum dict_object_type type, struct dict_object *obj, struct fd_list ** cb_list);
-void fd_dict_dump_avp_value(union avp_value *avp_value, struct dict_object * model, int indent, FILE * fstr);
+int fd_dict_dump_avp_value(union avp_value *avp_value, struct dict_object * model, int indent, char **outstr, size_t *offset, size_t *outlen);
 int fd_disp_call_cb_int( struct fd_list * cb_list, struct msg ** msg, struct avp *avp, struct session *sess, enum disp_action *action, 
 			struct dict_object * obj_app, struct dict_object * obj_cmd, struct dict_object * obj_avp, struct dict_object * obj_enu);
 extern pthread_rwlock_t fd_disp_lock;
@@ -69,4 +69,40 @@
 int fd_sess_ref_msg ( struct session * session );
 int fd_sess_reclaim_msg ( struct session ** session );
 
+/* For dump routines into string buffers */
+#include <stdarg.h>
+static __inline__ int dump_init_str(char **outstr, size_t *offset, size_t *outlen) 
+{
+	*outlen = 1<<12;
+	CHECK_MALLOC( *outstr = malloc(*outlen) );
+	*offset = 0;
+	(*outstr)[0] = 0;
+	return 0;
+}
+static __inline__ int dump_add_str(char **outstr, size_t *offset, size_t *outlen, char * fmt, ...) 
+{
+	va_list argp;
+	int len;
+	va_start(argp, fmt);
+	len = vsnprintf(*outstr + *offset, *outlen - *offset, fmt, argp);
+	va_end(argp);
+	if ((len + *offset) >= *outlen) {
+		char * newstr;
+		/* buffer was too short, extend */
+		size_t newsize = ((len + *offset) + (1<<12)) & ~((1<<12) - 1); /* next multiple of 4k */
+		CHECK_MALLOC( newstr = realloc(*outstr, newsize) );
+		
+		/* redo */
+		*outstr = newstr;
+		*outlen = newsize;
+		va_start(argp, fmt);
+		len = vsnprintf(*outstr + *offset, *outlen - *offset, fmt, argp);
+		va_end(argp);
+	}
+	*offset += len;
+	return 0;
+}
+
+
+
 #endif /* _LIBFDPROTO_INTERNAL_H */
--- a/libfdproto/messages.c	Wed Aug 22 00:18:15 2012 +0200
+++ b/libfdproto/messages.c	Wed Aug 22 00:22:46 2012 +0200
@@ -661,21 +661,23 @@
 #define INOBJHDR 	"%*s   "
 #define INOBJHDRVAL 	indent<0 ? 1 : indent, indent<0 ? "-" : "|"
 
+/* Write some debug data in a buffer */
+
 /* Dump a msg_t object */
-static void obj_dump_msg (struct msg * msg, int indent, FILE * fstr )
+static int obj_dump_msg (struct msg * msg, int indent, char **outstr, size_t *offset, size_t *outlen )
 {
 	int ret = 0;
 	
-	fd_log_debug_fstr(fstr, "%*sMSG: %p\n", INOBJHDRVAL, msg);
+	CHECK_FCT( dump_add_str(outstr, offset, outlen, "%*sMSG: %p\n", INOBJHDRVAL, msg) );
 	
 	if (!CHECK_MSG(msg)) {
-		fd_log_debug_fstr(fstr, INOBJHDR "INVALID!\n", INOBJHDRVAL);
-		return;
+		CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "INVALID!\n", INOBJHDRVAL) );
+		return 0;
 	}
 	
 	if (!msg->msg_model) {
 		
-		fd_log_debug_fstr(fstr, INOBJHDR "(no model)\n", INOBJHDRVAL);
+		CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(no model)\n", INOBJHDRVAL) );
 		
 	} else {
 		
@@ -683,19 +685,19 @@
 		struct dict_cmd_data  dictdata;
 		ret = fd_dict_gettype(msg->msg_model, &dicttype);
 		if (ret || (dicttype != DICT_COMMAND)) {
-			fd_log_debug_fstr(fstr, INOBJHDR "(invalid model: %d %d)\n", INOBJHDRVAL, ret, dicttype);
+			CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(invalid model: %d %d)\n", INOBJHDRVAL, ret, dicttype) );
 			goto public;
 		}
 		ret = fd_dict_getval(msg->msg_model, &dictdata);
 		if (ret != 0) {
-			fd_log_debug_fstr(fstr, INOBJHDR "(error getting model data: %s)\n", INOBJHDRVAL, strerror(ret));
+			CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(error getting model data: %s)\n", INOBJHDRVAL, strerror(ret)) );
 			goto public;
 		}
-		fd_log_debug_fstr(fstr, INOBJHDR "model : v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %u \"%s\"\n", INOBJHDRVAL, 
-			DUMP_CMDFL_val(dictdata.cmd_flag_val), DUMP_CMDFL_val(dictdata.cmd_flag_mask), dictdata.cmd_code, dictdata.cmd_name);
+		CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "model : v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %u \"%s\"\n", INOBJHDRVAL, 
+			DUMP_CMDFL_val(dictdata.cmd_flag_val), DUMP_CMDFL_val(dictdata.cmd_flag_mask), dictdata.cmd_code, dictdata.cmd_name) );
 	}
 public:	
-	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, 
+	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\n", INOBJHDRVAL, 
 		msg->msg_public.msg_version,
 		msg->msg_public.msg_length,
 		DUMP_CMDFL_val(msg->msg_public.msg_flags),
@@ -703,24 +705,25 @@
 		msg->msg_public.msg_appl,
 		msg->msg_public.msg_hbhid,
 		msg->msg_public.msg_eteid
-		);
-	fd_log_debug_fstr(fstr, INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p asso:%d sess:%p src:%s(%zd)\n", 
-			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)", msg->msg_src_id_len);
+		) );
+	CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "intern: rwb:%p rt:%d cb:%p(%p) qry:%p asso:%d sess:%p src:%s(%zd)\n", 
+			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)", msg->msg_src_id_len) );
+	return 0;
 }
 
 /* Dump an avp object */
-static void obj_dump_avp ( struct avp * avp, int indent, FILE * fstr )
+static int obj_dump_avp ( struct avp * avp, int indent, char **outstr, size_t *offset, size_t *outlen )
 {
 	int ret = 0;
 	
 	if (!CHECK_AVP(avp)) {
-		fd_log_debug_fstr(fstr, INOBJHDR "INVALID!\n", INOBJHDRVAL);
-		return;
+		CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "INVALID!\n", INOBJHDRVAL) );
+		return 0;
 	}
 	
 	if (!avp->avp_model) {
 		
-		fd_log_debug_fstr(fstr, INOBJHDR "(no model)\n", INOBJHDRVAL);
+		CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(no model)\n", INOBJHDRVAL) );
 		
 	} else {
 		
@@ -728,67 +731,69 @@
 		struct dict_avp_data dictdata;
 		ret = fd_dict_gettype(avp->avp_model, &dicttype);
 		if (ret || (dicttype != DICT_AVP)) {
-			fd_log_debug_fstr(fstr, INOBJHDR "(invalid model: %d %d)\n", INOBJHDRVAL, ret, dicttype);
+			CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(invalid model: %d %d)\n", INOBJHDRVAL, ret, dicttype) );
 			goto public;
 		}
 		ret = fd_dict_getval(avp->avp_model, &dictdata);
 		if (ret != 0) {
-			fd_log_debug_fstr(fstr, INOBJHDR "(error getting model data: %s)\n", INOBJHDRVAL, strerror(ret));
+			CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(error getting model data: %s)\n", INOBJHDRVAL, strerror(ret)) );
 			goto public;
 		}
-		fd_log_debug_fstr(fstr, INOBJHDR "model : v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %u \"%s\"\n", INOBJHDRVAL, 
+		CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "model : v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %u \"%s\"\n", INOBJHDRVAL, 
 			DUMP_AVPFL_val(dictdata.avp_flag_val), 
 			DUMP_AVPFL_val(dictdata.avp_flag_mask), 
 			type_base_name[dictdata.avp_basetype], 
 			dictdata.avp_code, 
-			dictdata.avp_name );
+			dictdata.avp_name ) );
 	}
 public:	
-	fd_log_debug_fstr(fstr, INOBJHDR "public: C:%u fl:" DUMP_AVPFL_str " L:%d V:%u  data:@%p\n", INOBJHDRVAL, 
+	CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "public: C:%u fl:" DUMP_AVPFL_str " L:%d V:%u  data:@%p\n", INOBJHDRVAL, 
 		avp->avp_public.avp_code,
 		DUMP_AVPFL_val(avp->avp_public.avp_flags),
 		avp->avp_public.avp_len,
 		avp->avp_public.avp_vendor,
 		avp->avp_public.avp_value
-		);
+		) );
 	/* Dump the value if set */
 	if (avp->avp_public.avp_value) {
 		if (!avp->avp_model) {
-			fd_log_debug_fstr(fstr, INOBJHDR "(data set but no model: ERROR)\n", INOBJHDRVAL);
+			CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "(data set but no model: ERROR)\n", INOBJHDRVAL) );
 		} else {
-			fd_dict_dump_avp_value(avp->avp_public.avp_value, avp->avp_model, indent, fstr);
+			CHECK_FCT( fd_dict_dump_avp_value(avp->avp_public.avp_value, avp->avp_model, indent, outstr, offset, outlen) );
 		}
 	}
 
-	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);
+	CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "intern: src:%p mf:%d raw:%p(%d)\n", INOBJHDRVAL, avp->avp_source, avp->avp_mustfreeos, avp->avp_rawdata, avp->avp_rawlen) );
+	return 0;
 }
 
-/* Dump a single object content */
-static void msg_dump_intern ( int level, msg_or_avp * obj, int indent, FILE * fstr )
+/* Dump a single object content into out string, realloc if needed */
+static int msg_dump_intern ( int level, msg_or_avp * obj, int indent, char **outstr, size_t *offset, size_t *outlen )
 {
 	/* Log only if we are at least at level */
 	if ( ! TRACE_BOOL(level) )
-		return;
+		return 0;
 	
 	/* Check the object */
 	if (!VALIDATE_OBJ(obj)) {
-		fd_log_debug_fstr(fstr, ">>> invalid object (%p)!.\n", obj);
-		return;
+		CHECK_FCT( dump_add_str(outstr, offset, outlen, ">>> invalid object (%p)!.\n", obj) );
+		return 0;
 	}
 	
 	/* Dump the object */
 	switch (_C(obj)->type) {
 		case MSG_AVP:
-			obj_dump_avp ( _A(obj), indent, fstr );
+			CHECK_FCT( obj_dump_avp ( _A(obj), indent, outstr, offset, outlen ));
 			break;
 		
 		case MSG_MSG:
-			obj_dump_msg ( _M(obj), indent, fstr );
+			CHECK_FCT( obj_dump_msg ( _M(obj), indent, outstr, offset, outlen ) );
 			break;
 		
 		default:
 			ASSERT(0);
 	}
+	return 0;
 }
 
 /* Dump a message to a specified file stream */
@@ -796,18 +801,35 @@
 {
 	msg_or_avp * ref = msg;
 	int indent = 2;
+	char *outstr;
+	size_t offset, outlen;
+	CHECK_FCT_DO( dump_init_str(&outstr, &offset, &outlen), { fd_log_debug_fstr(fstr, "Error initializing string for dumping %p\n", msg); return; } );
 	do {
-		msg_dump_intern ( NONE, ref, indent, fstr );
+		CHECK_FCT_DO(  msg_dump_intern ( NONE, ref, indent, &outstr, &offset, &outlen ),
+				fd_log_debug_fstr(fstr, "Error while dumping %p\n", ref) );
 		
 		/* Now find the next object */
 		CHECK_FCT_DO(  fd_msg_browse ( ref, MSG_BRW_WALK, &ref, &indent ), break  );
 		
 		/* dump next object */
 	} while (ref);
+	
+	/* now really output this in one shot, so it is not interrupted */
+	fd_log_debug_fstr(fstr, "%s", outstr);
+	
+	free(outstr);
 }
 void fd_msg_dump_fstr_one ( struct msg * msg, FILE * fstr ) /* just the header */
 {
-	msg_dump_intern ( NONE, msg, 2, fstr );
+	char *outstr;
+	size_t offset, outlen;
+	CHECK_FCT_DO( dump_init_str(&outstr, &offset, &outlen), { fd_log_debug_fstr(fstr, "Error initializing string for dumping %p\n", msg); return; } );
+	CHECK_FCT_DO(  msg_dump_intern ( NONE, msg, 2, &outstr, &offset, &outlen ),
+				fd_log_debug_fstr(fstr, "Error while dumping %p\n", msg) );
+	/* now really output this in one shot, so it is not interrupted */
+	fd_log_debug_fstr(fstr, "%s", outstr);
+	
+	free(outstr);
 }
 
 /* Dump a message content -- for debug mostly */
@@ -815,10 +837,14 @@
 {
 	msg_or_avp * ref = obj;
 	int indent = 1;
-	
-	TRACE_DEBUG(level, "------ Dumping object %p (w)-------", obj);
+	char *outstr;
+	size_t offset, outlen;
+	CHECK_FCT_DO( dump_init_str(&outstr, &offset, &outlen), 
+			{ fd_log_debug_fstr(fd_g_debug_fstr, "Error initializing string for dumping %p\n", obj); return; } );
+
 	do {
-		msg_dump_intern ( level, ref, indent, fd_g_debug_fstr );
+		CHECK_FCT_DO(  msg_dump_intern ( level, ref, indent, &outstr, &offset, &outlen ),
+				fd_log_debug_fstr(fd_g_debug_fstr, "Error while dumping %p\n", ref) );
 		
 		/* Now find the next object */
 		CHECK_FCT_DO(  fd_msg_browse ( ref, MSG_BRW_WALK, &ref, &indent ), break  );
@@ -826,15 +852,27 @@
 		/* dump next object */
 	} while (ref);
 	
+	/* now really output this in one shot, so it is not interrupted */
+	TRACE_DEBUG(level, "------ Dumping object %p (w)-------", obj);
+	fd_log_debug_fstr(fd_g_debug_fstr, "%s", outstr);
 	TRACE_DEBUG(level, "------ /end of object %p -------", obj);
+	
+	free(outstr);
 }
 
 /* Dump a single object content -- for debug mostly */
 void fd_msg_dump_one ( int level, msg_or_avp * obj )
 {
+	char *outstr;
+	size_t offset, outlen;
+	CHECK_FCT_DO( dump_init_str(&outstr, &offset, &outlen), 
+			{ fd_log_debug_fstr(fd_g_debug_fstr, "Error initializing string for dumping %p\n", obj); return; } );
+	CHECK_FCT_DO(  msg_dump_intern ( level, obj, 1, &outstr, &offset, &outlen ),
+			fd_log_debug_fstr(fd_g_debug_fstr, "Error while dumping %p\n", obj) );
 	TRACE_DEBUG(level, "------ Dumping object %p (s)-------", obj);
-	msg_dump_intern ( level, obj, 1, fd_g_debug_fstr );
+	fd_log_debug_fstr(fd_g_debug_fstr, "%s", outstr);
 	TRACE_DEBUG(level, "------ /end of object %p -------", obj);
+	free(outstr);
 }
 
 
@@ -1687,7 +1725,7 @@
 		
 		if (mandatory && (avp->avp_public.avp_flags & AVP_FLAG_MANDATORY)) {
 			TRACE_DEBUG(INFO, "Unsupported mandatory AVP found:");
-			msg_dump_intern(INFO, avp, 2, fd_g_debug_fstr);
+			fd_msg_dump_one(INFO, avp);
 			if (error_info) {
 				error_info->pei_errcode = "DIAMETER_AVP_UNSUPPORTED";
 				error_info->pei_avp = avp;
"Welcome to our mercurial repository"