Index: include/freeDiameter/freeDiameter.h
===================================================================
--- include/freeDiameter/freeDiameter.h	(revision 24)
+++ include/freeDiameter/freeDiameter.h	(revision 25)
@@ -152,31 +152,11 @@
 struct fd_event {
 	int	 code; /* codespace depends on the queue */
+	size_t 	 size;
 	void    *data;
 };
 
-static __inline__ int fd_event_send(struct fifo *queue, int code, void * data)
-{
-	struct fd_event * ev;
-	CHECK_MALLOC( ev = malloc(sizeof(struct fd_event)) );
-	ev->code = code;
-	ev->data = data;
-	CHECK_FCT( fd_fifo_post(queue, &ev) );
-	return 0;
-}
-static __inline__ int fd_event_get(struct fifo *queue, int *code, void ** data)
-{
-	struct fd_event * ev;
-	CHECK_FCT( fd_fifo_get(queue, &ev) );
-	if (code)
-		*code = ev->code;
-	if (data)
-		*data = ev->data;
-	free(ev);
-	return 0;
-}
-
-/* Events codespace for fd_g_config->cnf_main_ev */
+/* Daemon's codespace: 1000->1999 */
 enum {
-	 FDEV_TERMINATE = 1000	/* request to terminate */
+	 FDEV_TERMINATE	= 1000	/* request to terminate */
 	,FDEV_DUMP_DICT		/* Dump the content of the dictionary */
 	,FDEV_DUMP_EXT		/* Dump state of extensions */
@@ -186,4 +166,63 @@
 	,FDEV_DUMP_PEERS	/* Dump the list of peers */
 };
+
+static __inline__ int fd_event_send(struct fifo *queue, int code, size_t datasz, void * data)
+{
+	struct fd_event * ev;
+	CHECK_MALLOC( ev = malloc(sizeof(struct fd_event)) );
+	ev->code = code;
+	ev->size = datasz;
+	ev->data = data;
+	CHECK_FCT( fd_fifo_post(queue, &ev) );
+	return 0;
+}
+static __inline__ int fd_event_get(struct fifo *queue, int *code, size_t *datasz, void ** data)
+{
+	struct fd_event * ev;
+	CHECK_FCT( fd_fifo_get(queue, &ev) );
+	if (code)
+		*code = ev->code;
+	if (datasz)
+		*datasz = ev->size;
+	if (data)
+		*data = ev->data;
+	free(ev);
+	return 0;
+}
+static __inline__ int fd_event_timedget(struct fifo *queue, struct timespec * timeout, int timeoutcode, int *code, size_t *datasz, void ** data)
+{
+	struct fd_event * ev;
+	int ret = 0;
+	ret = fd_fifo_timedget(queue, &ev, timeout);
+	if (ret == ETIMEDOUT) {
+		if (code)
+			*code = timeoutcode;
+		if (datasz)
+			*datasz = 0;
+		if (data)
+			*data = NULL;
+	} else {
+		CHECK_FCT( ret );
+		if (code)
+			*code = ev->code;
+		if (datasz)
+			*datasz = ev->size;
+		if (data)
+			*data = ev->data;
+		free(ev);
+	}
+	return 0;
+}
+static __inline__ void fd_event_destroy(struct fifo **queue, void (*free_cb)(void * data))
+{
+	struct fd_event * ev;
+	/* Purge all events, and free the associated data if any */
+	while (fd_fifo_tryget( *queue, &ev ) == 0) {
+		(*free_cb)(ev->data);
+		free(ev);
+	}
+	CHECK_FCT_DO( fd_fifo_del(queue), /* continue */ );
+	return ;
+}  
 const char * fd_ev_str(int event); /* defined in freeDiameter/main.c */
 
Index: include/freeDiameter/libfreeDiameter.h
===================================================================
--- include/freeDiameter/libfreeDiameter.h	(revision 24)
+++ include/freeDiameter/libfreeDiameter.h	(revision 25)
@@ -427,4 +427,24 @@
 
 
+/* Trace a binary buffer content */
+#define TRACE_DEBUG_BUFFER(level, prefix, buf, bufsz, suffix ) {								\
+	if ( TRACE_BOOL(level) ) {												\
+		int __i;													\
+		size_t __sz = (size_t)(bufsz);											\
+		uint8_t * __buf = (uint8_t *)(buf);										\
+		char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed");					\
+		fd_log_debug("\t | tid:%-20s\t%s\tin %s@%s:%d\n"								\
+			  "\t%s|%*s" prefix ,  											\
+					__thn, fd_log_time(NULL, __buf, sizeof(__buf)), __PRETTY_FUNCTION__, __FILE__, __LINE__,\
+					(level < FULL)?"@":" ",level, ""); 							\
+		for (__i = 0; __i < __sz; __i++) {										\
+			fd_log_debug("%02.2hhx", __buf[__i]);									\
+		}														\
+		fd_log_debug(suffix "\n");											\
+	}															\
+}
+
+
+
 /*============================================================*/
 /*                          THREADS                           */
@@ -508,4 +528,7 @@
 void fd_list_insert_after  ( struct fd_list * ref, struct fd_list * item );
 void fd_list_insert_before ( struct fd_list * ref, struct fd_list * item );
+
+/* Move a list at the end of another */
+void fd_list_move_end(struct fd_list * ref, struct fd_list * senti);
 
 /* Insert an item in an ordered list -- ordering function provided. If duplicate object found, EEXIST and it is returned in ref_duplicate */
@@ -2385,4 +2408,21 @@
 
 /*
+ * FUNCTION:	fd_fifo_move
+ *
+ * PARAMETERS:
+ *  old		: Location of a FIFO that is to be emptied and deleted.
+ *  new		: A FIFO that will receive the old data.
+ *  loc_update	: if non NULL, a place to store the pointer to new FIFO atomically with the move.
+ *
+ * DESCRIPTION: 
+ *  Delete a queue and move its content to another one atomically.
+ *
+ * RETURN VALUE:
+ *  0		: The queue has been destroyed successfully.
+ *  EINVAL 	: A parameter is invalid.
+ */
+int fd_fifo_move ( struct fifo ** old, struct fifo * new, struct fifo ** loc_update );
+
+/*
  * FUNCTION:	fd_fifo_length
  *
