changeset 156:e2dc300819b3

Fix overwriten thread location
author Sebastien Decugis <sdecugis@nict.go.jp>
date Wed, 20 Jan 2010 16:04:25 +0900
parents 30a7252cbb55
children 2b3a1ff2ed10
files freeDiameter/cnxctx.c freeDiameter/dict_base_proto.c freeDiameter/sctps.c include/freeDiameter/libfreeDiameter.h libfreeDiameter/dictionary.c libfreeDiameter/fifo.c libfreeDiameter/libfD.h libfreeDiameter/messages.c
diffstat 8 files changed, 201 insertions(+), 181 deletions(-) [+]
line wrap: on
line diff
--- a/freeDiameter/cnxctx.c	Tue Jan 19 11:41:01 2010 +0900
+++ b/freeDiameter/cnxctx.c	Wed Jan 20 16:04:25 2010 +0900
@@ -1257,7 +1257,7 @@
 	if (conn->cc_tls) {
 #ifndef DISABLE_SCTP
 		if (conn->cc_sctp_para.pairs > 1) {
-			/* Master session */
+			/* Bye on master session */
 			CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_WR), /* Continue */ );
 			
 			/* and other stream pairs */
--- a/freeDiameter/dict_base_proto.c	Tue Jan 19 11:41:01 2010 +0900
+++ b/freeDiameter/dict_base_proto.c	Wed Jan 20 16:04:25 2010 +0900
@@ -143,6 +143,20 @@
 	return 0;
 }
 
+static void Address_dump(union avp_value * avp_value)
+{
+	fd_log_debug("*todo: dump address*");
+}
+
+static void 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("%.*s", len, avp_value->os.data);
+}
+
+
 
 
 #define CHECK_dict_new( _type, _data, _parent, _ref )				\
@@ -230,7 +244,7 @@
 				defined in [IANAADFAM].  The AddressType is used to discriminate
 				the content and format of the remaining octets.
 			*/
-			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"Address"		, Address_interpret	, Address_encode	};
+			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"Address"		, Address_interpret	, Address_encode,	Address_dump	};
 			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
 		}
 		
@@ -249,7 +263,7 @@
 				SNTP [RFC4330] describes a procedure to extend the time to 2104.
 				This procedure MUST be supported by all DIAMETER nodes.
 			*/
-			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"Time"			, NULL			, NULL			};
+			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"Time"			, NULL			, NULL		, NULL		};
 			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
 		}
 		
@@ -287,7 +301,7 @@
 				Note that the AVP Length field of an UTF8String is measured in
 				octets, not characters.
 			*/
-			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"UTF8String"		, NULL			, NULL			};
+			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"UTF8String"		, NULL			, NULL	, UTF8String_dump	};
 			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
 		}
 		
@@ -316,7 +330,7 @@
 				interactions between the Diameter protocol and Internationalized
 				Domain Name (IDNs).
 			*/
-			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"DiameterIdentity"	, NULL			, NULL			};
+			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"DiameterIdentity"	, NULL			, NULL		, UTF8String_dump	};
 			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
 		}
 		
@@ -371,7 +385,7 @@
 				aaa://host.example.com:6666;transport=tcp;protocol=diameter
 				aaa://host.example.com:1813;transport=udp;protocol=radius
 			*/
-			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"DiameterURI"		, NULL			, NULL			};
+			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"DiameterURI"		, NULL			, NULL		, UTF8String_dump	};
 			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
 		}
 		
@@ -433,7 +447,7 @@
 				supplied rules, for example to protect the access device owner's
 				infrastructure.
 			*/
-			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"IPFilterRule"		, NULL			, NULL			};
+			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"IPFilterRule"		, NULL			, NULL		, UTF8String_dump	};
 			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
 		}
 	}
@@ -603,7 +617,7 @@
 				with above result code SHOULD NOT attempt reconnection.
 			*/
 			struct dict_object 	* 	type;
-			struct dict_type_data 		tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Disconnect-Cause)"	, NULL, NULL};
+			struct dict_type_data 		tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Disconnect-Cause)"	, NULL, NULL, NULL };
 			struct dict_enumval_data 	t_0 = { "REBOOTING", 			{ .i32 = 0 }};
 			struct dict_enumval_data 	t_1 = { "BUSY", 			{ .i32 = 1 }};
 			struct dict_enumval_data 	t_2 = { "DO_NOT_WANT_TO_TALK_TO_YOU", 	{ .i32 = 2 }};
@@ -908,7 +922,7 @@
 			 */
 			
 			struct dict_object 	* 	type;
-			struct dict_type_data	 	tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated*(Inband-Security-Id)"	, NULL, NULL};
+			struct dict_type_data	 	tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated*(Inband-Security-Id)"	, NULL, NULL, NULL };
 			struct dict_enumval_data 	t_0 = { "NO_INBAND_SECURITY", 		{ .u32 = ACV_ISI_NO_INBAND_SECURITY }};
 			struct dict_enumval_data 	t_1 = { "TLS", 			{ .u32 = ACV_ISI_TLS }};
 			struct dict_avp_data 		data = { 
@@ -1102,7 +1116,7 @@
 				6.  ALL_HOST
 			*/
 			struct dict_object 	* 	type;
-			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Redirect-Host-Usage)"	, NULL, NULL};
+			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Redirect-Host-Usage)"	, NULL, NULL, NULL };
 			struct dict_enumval_data 	t_0 = { "DONT_CACHE", 			{ .i32 = 0 }};
 			struct dict_enumval_data 	t_1 = { "ALL_SESSION", 			{ .i32 = 1 }};
 			struct dict_enumval_data 	t_2 = { "ALL_REALM", 			{ .i32 = 2 }};
@@ -1196,7 +1210,7 @@
 			 * This is the reason for the "*" in the type name
 			 */
 			struct dict_object * 	type;
-			struct dict_type_data 	tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated*(Result-Code)"	, NULL, NULL};
+			struct dict_type_data 	tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated*(Result-Code)"	, NULL, NULL, NULL };
 			struct dict_avp_data 	data = { 
 					268, 					/* Code */
 					#if AC_RESULT_CODE != 268
@@ -1795,7 +1809,7 @@
 			 * This is the reason for the "*" in the type name. Vendors will have to define their values.
 			 */
 			struct dict_object * 	type;
-			struct dict_type_data 	tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated*(Experimental-Result-Code)"	, NULL, NULL};
+			struct dict_type_data 	tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated*(Experimental-Result-Code)"	, NULL, NULL, NULL };
 			struct dict_avp_data 	data = { 
 					298, 					/* Code */
 					0, 					/* Vendor */
@@ -1842,7 +1856,7 @@
 				offered.
 			*/
 			struct dict_object 	* 	type;
-			struct dict_type_data 		tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Auth-Request-Type)"	, NULL, NULL};
+			struct dict_type_data 		tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Auth-Request-Type)"	, NULL, NULL, NULL };
 			struct dict_enumval_data 	t_1 = { "AUTHENTICATE_ONLY", 		{ .i32 = 1 }};
 			struct dict_enumval_data 	t_2 = { "AUTHORIZE_ONLY", 		{ .i32 = 2 }};
 			struct dict_enumval_data 	t_3 = { "AUTHORIZE_AUTHENTICATE", 	{ .i32 = 3 }};
@@ -1984,7 +1998,7 @@
 				Authorization-Lifetime.
 			*/
 			struct dict_object 	* 	type;
-			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Auth-Session-State)"	, NULL, NULL};
+			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Auth-Session-State)"	, NULL, NULL, NULL };
 			struct dict_enumval_data 	t_0 = { "STATE_MAINTAINED", 		{ .i32 = 0 }};
 			struct dict_enumval_data 	t_1 = { "NO_STATE_MAINTAINED", 		{ .i32 = 1 }};
 			struct dict_avp_data	 	data = { 
@@ -2027,7 +2041,7 @@
 				expiration of the Authorization-Lifetime.
 			*/
 			struct dict_object 	* 	type;
-			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Re-Auth-Request-Type)"	, NULL, NULL};
+			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Re-Auth-Request-Type)"	, NULL, NULL, NULL };
 			struct dict_enumval_data 	t_0 = { "AUTHORIZE_ONLY", 		{ .i32 = 0 }};
 			struct dict_enumval_data 	t_1 = { "AUTHORIZE_AUTHENTICATE",	{ .i32 = 1 }};
 			struct dict_avp_data	 	data = { 
@@ -2154,7 +2168,7 @@
 				The user's session has timed out, and service has been terminated.
 			*/
 			struct dict_object 	* 	type;
-			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Termination-Cause)"	, NULL, NULL};
+			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Termination-Cause)"	, NULL, NULL, NULL };
 			struct dict_enumval_data 	t_1 = { "DIAMETER_LOGOUT",			{ .i32 = 1 }};
 			struct dict_enumval_data 	t_2 = { "DIAMETER_SERVICE_NOT_PROVIDED", 	{ .i32 = 2 }};
 			struct dict_enumval_data 	t_3 = { "DIAMETER_BAD_ANSWER",			{ .i32 = 3 }};
@@ -2266,7 +2280,7 @@
 			 */
 			
 			struct dict_object 	* 	type;
-			struct dict_type_data	 	tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated*(Session-Binding)"	, NULL, NULL};
+			struct dict_type_data	 	tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated*(Session-Binding)"	, NULL, NULL, NULL };
 			struct dict_enumval_data 	t_1 = { "RE_AUTH", 		{ .u32 = 1 }};
 			struct dict_enumval_data 	t_2 = { "STR", 			{ .u32 = 2 }};
 			struct dict_enumval_data 	t_4 = { "ACCOUNTING", 		{ .u32 = 4 }};
@@ -2328,7 +2342,7 @@
 				session.
 			*/
 			struct dict_object  	* 	type;
-			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Session-Server-Failover)"	, NULL, NULL};
+			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Session-Server-Failover)"	, NULL, NULL, NULL };
 			struct dict_enumval_data 	t_0 = { "REFUSE_SERVICE", 		{ .i32 = 0 }};
 			struct dict_enumval_data 	t_1 = { "TRY_AGAIN",			{ .i32 = 1 }};
 			struct dict_enumval_data 	t_2 = { "ALLOW_SERVICE", 		{ .i32 = 2 }};
@@ -2460,7 +2474,7 @@
 				the existing session.
 			*/
 			struct dict_object 	* 	type;
-			struct dict_type_data	  	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Accounting-Record-Type)"	, NULL, NULL};
+			struct dict_type_data	  	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Accounting-Record-Type)"	, NULL, NULL, NULL };
 			struct dict_enumval_data 	t_1 = { "EVENT_RECORD",			{ .i32 = 1 }};
 			struct dict_enumval_data 	t_2 = { "START_RECORD", 		{ .i32 = 2 }};
 			struct dict_enumval_data 	t_3 = { "INTERIM_RECORD",		{ .i32 = 3 }};
@@ -2654,7 +2668,7 @@
 				stored.
 			*/
 			struct dict_object  	* 	type;
-			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Accounting-Realtime-Required)"	, NULL, NULL};
+			struct dict_type_data	 	tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Accounting-Realtime-Required)"	, NULL, NULL, NULL };
 			struct dict_enumval_data 	t_1 = { "DELIVER_AND_GRANT",		{ .i32 = 1 }};
 			struct dict_enumval_data 	t_2 = { "GRANT_AND_STORE", 		{ .i32 = 2 }};
 			struct dict_enumval_data 	t_3 = { "GRANT_AND_LOSE",		{ .i32 = 3 }};
--- a/freeDiameter/sctps.c	Tue Jan 19 11:41:01 2010 +0900
+++ b/freeDiameter/sctps.c	Wed Jan 20 16:04:25 2010 +0900
@@ -90,7 +90,12 @@
 		switch (event) {
 			case FDEVP_CNX_MSG_RECV:
 				/* Demux this message in the appropriate fifo, another thread will pull, gnutls process, and send in target queue */
-				CHECK_FCT_DO(fd_event_send(conn->cc_sctps_data.array[strid].raw_recv, event, bufsz, buf), goto error );
+				if (strid < conn->cc_sctp_para.pairs) {
+					CHECK_FCT_DO(fd_event_send(conn->cc_sctps_data.array[strid].raw_recv, event, bufsz, buf), goto error );
+				} else {
+					TRACE_DEBUG(INFO, "Received packet (%d bytes) on out-of-range stream #%s from %s, discarded.", bufsz, strid, conn->cc_remid);
+					free(buf);
+				}
 				break;
 				
 			case FDEVP_CNX_EP_CHANGE:
@@ -112,6 +117,12 @@
 	if (!conn->cc_closing) {
 		CHECK_FCT_DO( fd_event_send( Target_Queue(conn), FDEVP_CNX_ERROR, 0, NULL), /* continue or destroy everything? */);
 	}
+	
+	/* Since the demux thread terminates, we must trig an error for all decipher threads. We do this by destroying all demuxed FIFO queues */
+	for (strid = 0; strid < conn->cc_sctp_para.pairs; strid++) {
+		fd_event_destroy( &conn->cc_sctps_data.array[strid].raw_recv, free );
+	}
+	
 	goto out;
 }
 
@@ -582,37 +593,16 @@
 	return 0;
 }
 
-static void * bye_th(void * arg)
-{
-	struct sctps_ctx * ctx = (struct sctps_ctx *) arg;
-	TRACE_ENTRY("%p", arg);
-	
-	/* Set the thread name */
-	{
-		char buf[48];
-		snprintf(buf, sizeof(buf), "gnutls_bye (%hu@%d)", ctx->strid, ctx->parent->cc_socket);
-		fd_log_threadname ( buf );
-	}
-	
-	CHECK_GNUTLS_DO( gnutls_bye(ctx->session, GNUTLS_SHUT_WR), /* Continue */ );
-			
-	/* Finish */
-	return NULL;
-}
-
-/* Initiate a "bye" on all stream pairs in paralel */
+/* Initiate a "bye" on all stream pairs */
 void fd_sctps_bye(struct cnxctx * conn)
 {
 	uint16_t i;
 	
 	CHECK_PARAMS_DO( conn && conn->cc_sctps_data.array, return );
 	
-	/* End all TLS sessions, in parallel */
+	/* End all TLS sessions, in series (not as efficient as paralel, but simpler) */
 	for (i = 1; i < conn->cc_sctp_para.pairs; i++) {
-		CHECK_POSIX_DO( pthread_create( &conn->cc_sctps_data.array[i].thr, NULL, bye_th, &conn->cc_sctps_data.array[i] ), break );
-	}
-	for (--i; i > 0; --i) {
-		CHECK_POSIX_DO( pthread_join( conn->cc_sctps_data.array[i].thr, NULL ), continue );
+		CHECK_GNUTLS_DO( gnutls_bye(conn->cc_sctps_data.array[i].session, GNUTLS_SHUT_WR), /* Continue */ );
 	}
 }
 
@@ -676,7 +666,8 @@
 	
 	/* Free remaining data in the array */
 	for (i = 0; i < conn->cc_sctp_para.pairs; i++) {
-		fd_event_destroy( &conn->cc_sctps_data.array[i].raw_recv, free );
+		if (conn->cc_sctps_data.array[i].raw_recv)
+			fd_event_destroy( &conn->cc_sctps_data.array[i].raw_recv, free );
 		free(conn->cc_sctps_data.array[i].partial.buf);
 		if (i > 0)
 			gnutls_deinit(conn->cc_sctps_data.array[i].session);
--- a/include/freeDiameter/libfreeDiameter.h	Tue Jan 19 11:41:01 2010 +0900
+++ b/include/freeDiameter/libfreeDiameter.h	Wed Jan 20 16:04:25 2010 +0900
@@ -665,7 +665,6 @@
 void fd_dict_dump_object(struct dict_object * obj);
 void fd_dict_dump(struct dictionary * dict);
 
-
 /*
  ***************************************************************************
  *
@@ -894,6 +893,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);	/* cb called by fd_msg_dump_one for this type of data (if != NULL) */
 };
 
 /* The criteria for searching a type object in the dictionary */
--- a/libfreeDiameter/dictionary.c	Tue Jan 19 11:41:01 2010 +0900
+++ b/libfreeDiameter/dictionary.c	Wed Jan 20 16:04:25 2010 +0900
@@ -1283,6 +1283,152 @@
 	CHECK_POSIX_DO(  pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */  );
 }
 
+/**************************** Dump AVP values ********************************/
+
+/* Default dump functions */
+static void dump_val_os(union avp_value * value)
+{
+	int i;
+	for (i = 0; i < value->os.len; i++) {
+		if (i == 16) { /* Dump only up to 16 bytes of the buffer */
+			fd_log_debug("(trunc, len=%zd)", value->os.len);
+			break;
+		}
+		fd_log_debug("%02.2X ", value->os.data[i]);
+	}
+}
+
+static void dump_val_i32(union avp_value * value)
+{
+	fd_log_debug("%i", value->i32);
+}
+
+static void dump_val_i64(union avp_value * value)
+{
+	fd_log_debug("%lli (0x%llx)", value->i64, value->i64);
+}
+
+static void dump_val_u32(union avp_value * value)
+{
+	fd_log_debug("%u", value->u32);
+}
+
+static void dump_val_u64(union avp_value * value)
+{
+	fd_log_debug("%llu", value->u64);
+}
+
+static void dump_val_f32(union avp_value * value)
+{
+	fd_log_debug("%f", value->f32);
+}
+
+static void dump_val_f64(union avp_value * value)
+{
+	fd_log_debug("%g", value->f64);
+}
+
+/* Get the dump function for basic dict_avp_basetype */
+static void (*get_default_dump_val_cb(enum dict_avp_basetype datatype))(union avp_value *)
+{
+	switch (datatype) {
+		case AVP_TYPE_OCTETSTRING:
+			return &dump_val_os;
+		
+		case AVP_TYPE_INTEGER32:
+			return &dump_val_i32;
+
+		case AVP_TYPE_INTEGER64:
+			return &dump_val_i64;
+
+		case AVP_TYPE_UNSIGNED32:
+			return &dump_val_u32;
+
+		case AVP_TYPE_UNSIGNED64:
+			return &dump_val_u64;
+
+		case AVP_TYPE_FLOAT32:
+			return &dump_val_f32;
+
+		case AVP_TYPE_FLOAT64:
+			return &dump_val_f64;
+		
+		case AVP_TYPE_GROUPED:
+			TRACE_DEBUG(FULL, "error: grouped AVP with a value!");
+	}
+	return NULL;
+}
+
+/* indent inside an object (duplicate from messages.c) */
+#define INOBJHDR 	"%*s   "
+#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 *avp_value), enum dict_avp_basetype datatype, char * type_name, char * const_name, int indent)
+{
+	/* Header for all AVP values dumps: */
+	fd_log_debug(INOBJHDR "value ", INOBJHDRVAL);
+	
+	/* If the type is provided, write it */
+	if (type_name)
+		fd_log_debug("t: '%s' ", type_name);
+	
+	/* Always give the base datatype anyway */
+	fd_log_debug("(%s) ", type_base_name[datatype]);
+	
+	/* Now, the value */
+	fd_log_debug("v: ");
+	if (const_name)
+		fd_log_debug("'%s' (", const_name);
+	(*dump_val_cb)(avp_value);
+	if (const_name)
+		fd_log_debug(")");
+	
+	/* Done! */
+	fd_log_debug("\n");
+}
+
+/* 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)
+{
+	void (*dump_val_cb)(union avp_value *avp_value);
+	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 );
+	
+	/* Get the type definition of this AVP */
+	type = model->parent;
+	if (type) {
+		struct dict_enumval_request  request;
+		struct dict_object * enumval = NULL;
+		
+		type_name = type->data.type.type_name;
+		
+		/* overwrite the dump function ? */
+		if (type->data.type.type_dump)
+			dump_val_cb = type->data.type.type_dump;
+		
+		/* Now check if the AVP value matches a constant */
+		memset(&request, 0, sizeof(request));
+		request.type_obj = type;
+		memcpy(&request.search.enum_value, avp_value, sizeof(union avp_value));
+		/* bypass checks */
+		if ((search_enumval( type->dico, ENUMVAL_BY_STRUCT, &request, &enumval ) == 0) && (enumval)) {
+			/* We found a cosntant, get its name */
+			const_name = enumval->data.enumval.enum_name;
+		}
+	}
+	
+	/* And finally, dump the value */
+	dump_avp_val(avp_value, dump_val_cb, model->data.avp.avp_basetype, type_name, const_name, indent);
+}
+
 /*******************************************************************************************************/
 /*******************************************************************************************************/
 /*                                                                                                     */
--- a/libfreeDiameter/fifo.c	Tue Jan 19 11:41:01 2010 +0900
+++ b/libfreeDiameter/fifo.c	Wed Jan 20 16:04:25 2010 +0900
@@ -158,6 +158,7 @@
 	/* Ok, now invalidate the queue */
 	q->eyec = 0xdead;
 	
+	/* Have all waiting threads return an error */
 	while (q->thrs) {
 		CHECK_POSIX(  pthread_mutex_unlock( &q->mtx ));
 		CHECK_POSIX(  pthread_cond_signal(&q->cond)  );
--- a/libfreeDiameter/libfD.h	Tue Jan 19 11:41:01 2010 +0900
+++ b/libfreeDiameter/libfD.h	Wed Jan 20 16:04:25 2010 +0900
@@ -51,6 +51,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);
 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;
--- a/libfreeDiameter/messages.c	Tue Jan 19 11:41:01 2010 +0900
+++ b/libfreeDiameter/messages.c	Wed Jan 20 16:04:25 2010 +0900
@@ -690,99 +690,6 @@
 			INOBJHDRVAL, msg->msg_rawbuffer, msg->msg_routable, msg->msg_cb.fct, msg->msg_cb.data, msg->msg_query, msg->msg_sess, msg->msg_src_id?:"(nil)");
 }
 
-#define DUMP_VALUE(_format, _parms...)   fd_log_debug(INOBJHDR "value : t:'%s' v:'" _format "'\n", INOBJHDRVAL, typename, ## _parms);
-/* Dump an AVP value that is not a constant */
-static void dump_basic_type(union avp_value * value, enum dict_avp_basetype type, const char * typename, int indent)
-{
-	switch (type) {
-		case AVP_TYPE_GROUPED:
-			DUMP_VALUE("%s", "error: grouped AVP with a value!");
-			break;
-			
-		case AVP_TYPE_OCTETSTRING:
-			{
-				/* Dump only up to 16 bytes of the buffer */
-				unsigned char buf[8];
-				memset(buf, 0, sizeof(buf));
-				memcpy(buf, value->os.data, value->os.len < sizeof(buf) ? value->os.len : sizeof(buf) );
-				DUMP_VALUE("l:%d, v:%02.2X %02.2X %02.2X %02.2X  %02.2X %02.2X %02.2X %02.2X  ... ('%.*s')", 
-						value->os.len,
-						buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], 
-						value->os.len, value->os.data
-						);
-			}
-			break;
-		
-		case AVP_TYPE_INTEGER32:
-			DUMP_VALUE("%i",value->i32);
-			break;
-
-		case AVP_TYPE_INTEGER64:
-			DUMP_VALUE("%lli (0x%llx)",value->i64,value->i64);
-			break;
-
-		case AVP_TYPE_UNSIGNED32:
-			DUMP_VALUE("%u",value->u32);
-			break;
-
-		case AVP_TYPE_UNSIGNED64:
-			DUMP_VALUE("%llu",value->u64);
-			break;
-
-		case AVP_TYPE_FLOAT32:
-			DUMP_VALUE("%f",value->f32);
-			break;
-
-		case AVP_TYPE_FLOAT64:
-			DUMP_VALUE("%g",value->f64);
-			break;
-		
-		default:
-			DUMP_VALUE("%s %d", "error: invalid type :", type);
-	}
-}
-
-/* Dump an AVP value that is a constant */
-#define DUMP_CONST(_format, _parms...)   fd_log_debug(INOBJHDR "value : t:'%s' v:'%s' ( " _format " )\n", INOBJHDRVAL, typename, value->enum_name, ## _parms);
-static void dump_constant_type(struct dict_enumval_data * value, enum dict_avp_basetype type, char * typename, int indent)
-{
-	switch (type) {
-		case AVP_TYPE_GROUPED:
-			DUMP_CONST("%s", "error: grouped AVP with a constant value!");
-			break;
-		case AVP_TYPE_OCTETSTRING:
-			DUMP_CONST("%s", "value skipped");
-			break;
-		
-		case AVP_TYPE_INTEGER32:
-			DUMP_CONST("%i",value->enum_value.i32);
-			break;
-
-		case AVP_TYPE_INTEGER64:
-			DUMP_CONST("%li",value->enum_value.i64);
-			break;
-
-		case AVP_TYPE_UNSIGNED32:
-			DUMP_CONST("%u",value->enum_value.u32);
-			break;
-
-		case AVP_TYPE_UNSIGNED64:
-			DUMP_CONST("%lu",value->enum_value.u64);
-			break;
-
-		case AVP_TYPE_FLOAT32:
-			DUMP_CONST("%f",value->enum_value.f32);
-			break;
-
-		case AVP_TYPE_FLOAT64:
-			DUMP_CONST("%g",value->enum_value.f64);
-			break;
-		
-		default:
-			DUMP_CONST("%s %d", "error: invalid type :", type);
-	}
-}
-
 /* Dump an avp object */
 static void obj_dump_avp ( struct avp * avp, int indent )
 {
@@ -833,47 +740,7 @@
 		if (!avp->avp_model) {
 			fd_log_debug(INOBJHDR "(data set but no model: ERROR)\n", INOBJHDRVAL);
 		} else {
-			/* Try and find a constant name for this value */
-			struct dictionary * dict = NULL;
-			struct dict_object * avp_type = NULL;
-			struct dict_object * avp_constant = NULL;
-			struct dict_type_data type_data;
-			struct dict_enumval_request  request;
-			ret = fd_dict_getdict(avp->avp_model, & dict);
-			if (ret != 0) {
-				dump_basic_type(avp->avp_public.avp_value, type, type_base_name[type], indent);
-				goto end;
-			}
-			ret = fd_dict_search(dict, DICT_TYPE, TYPE_OF_AVP, avp->avp_model, &avp_type, ENOENT);
-			if (ret != 0) {
-				dump_basic_type(avp->avp_public.avp_value, type, type_base_name[type], indent);
-				goto end;
-			}
-			ret = fd_dict_getval(avp_type, &type_data);
-			if (ret != 0) {
-				dump_basic_type(avp->avp_public.avp_value, type, "(error getting type data)", indent);
-				goto end;
-			}
-			if (type_data.type_base != type) {
-				dump_basic_type(avp->avp_public.avp_value, type, "(mismatching type information!)", indent);
-				goto end;
-			}
-			/* Create a query for a constant */
-			memset(&request, 0, sizeof(request));
-			request.type_obj = avp_type;
-			memcpy(&request.search.enum_value, avp->avp_public.avp_value, sizeof(union avp_value));
-			ret = fd_dict_search(dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &avp_constant, ENOENT);
-			if (ret != 0)  {
-				dump_basic_type(avp->avp_public.avp_value, type, type_data.type_name, indent);
-				goto end;
-			}
-			/* get the constant's information; we re-use request.search field */
-			ret = fd_dict_getval(avp_constant, &request.search);
-			if (ret != 0) {
-				dump_basic_type(avp->avp_public.avp_value, type, "(error getting constant data)", indent);
-				goto end;
-			}
-			dump_constant_type(&request.search, type, type_data.type_name, indent);
+			fd_dict_dump_avp_value(avp->avp_public.avp_value, avp->avp_model, indent);
 		}
 	}
 end:	
"Welcome to our mercurial repository"