Index: include/freeDiameter/libfreeDiameter.h
===================================================================
--- include/freeDiameter/libfreeDiameter.h	(revision 20)
+++ include/freeDiameter/libfreeDiameter.h	(revision 29)
@@ -120,14 +120,15 @@
  *
  * PARAMETERS:
+ *  ts	 	: The timestamp to log, or NULL for "now"
  *  buf 	: An array where the time must be stored
  *  len		: size of the buffer
  *
  * DESCRIPTION: 
- *  Writes the current timestamp (in human readable format) in a buffer. 
+ *  Writes the timestamp (in human readable format) in a buffer. 
  *
  * RETURN VALUE:
  *  pointer to buf.
  */
-char * fd_log_time ( char * buf, size_t len );
+char * fd_log_time ( struct timespec * ts, char * buf, size_t len );
 
 
@@ -173,5 +174,5 @@
 		fd_log_debug("\t | tid:%-20s\t%s\tin %s@%s:%d\n"								\
 			  "\t%s|%*s" format "\n",  										\
-					__thn, fd_log_time(__buf, sizeof(__buf)), __PRETTY_FUNCTION__, __FILE__, __LINE__,	\
+					__thn, fd_log_time(NULL, __buf, sizeof(__buf)), __PRETTY_FUNCTION__, __FILE__, __LINE__,	\
 					(level < FULL)?"@":" ",level, "", ## args); 						\
 	}															\
@@ -180,5 +181,5 @@
 /* Helper for function entry -- for very detailed trace of the execution */
 #define TRACE_ENTRY(_format,_args... ) \
-	TRACE_DEBUG(FCTS, "->%s (" #_args ") = (" _format ") >", __PRETTY_FUNCTION__, ##_args );
+	TRACE_DEBUG(FCTS, "[enter] %s(" _format ") {" #_args "}", __PRETTY_FUNCTION__, ##_args );
 
 /* Helper for debugging by adding traces -- for debuging a specific location of the code */
@@ -328,12 +329,46 @@
 			flag);					\
 	  if (__rc)						\
-	  	fd_log_debug((char *)gai_strerror(__rc));	\
+	  	fd_log_debug("%s", (char *)gai_strerror(__rc));	\
 	  else							\
-	  	fd_log_debug(&__addrbuf[0]);			\
+	  	fd_log_debug("%s", &__addrbuf[0]);		\
 	} else {						\
 		fd_log_debug("(NULL / ANY)");			\
 	}							\
 }
-/* if needed, add sSA_DUMP_SERVICE */
+/* Same but with the port (service) also */
+#define sSA_DUMP_NODE_SERV( sa, flag ) {				\
+	sSA * __sa = (sSA *)(sa);					\
+	char __addrbuf[INET6_ADDRSTRLEN];				\
+	char __servbuf[32];						\
+	if (__sa) {							\
+	  int __rc = getnameinfo(__sa, 					\
+	  		sizeof(sSS),					\
+			__addrbuf,					\
+			sizeof(__addrbuf),				\
+			__servbuf,					\
+			sizeof(__servbuf),				\
+			flag);						\
+	  if (__rc)							\
+	  	fd_log_debug("%s", (char *)gai_strerror(__rc));		\
+	  else								\
+	  	fd_log_debug("[%s]:%s", &__addrbuf[0],&__servbuf[0]);	\
+	} else {							\
+		fd_log_debug("(NULL / ANY)");				\
+	}								\
+}
+/* Inside a debug trace */
+#define TRACE_DEBUG_sSA(level, prefix, sa, flags, suffix ) {										\
+	if ( TRACE_BOOL(level) ) {												\
+		char __buf[25];													\
+		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, ""); 							\
+		sSA_DUMP_NODE_SERV( sa, flags );										\
+		fd_log_debug(suffix "\n");											\
+	}															\
+}
+
 
 /* A l4 protocol name (TCP / SCTP) */
@@ -390,4 +425,24 @@
 	(    ((ts1)->tv_sec  < (ts2)->tv_sec ) 	\
 	  || (((ts1)->tv_sec  == (ts2)->tv_sec ) && ((ts1)->tv_nsec < (ts2)->tv_nsec) ))
+
+
+/* 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");											\
+	}															\
+}
+
 
 
@@ -415,5 +470,5 @@
 	
 	if (th_ret != NULL) {
-		TRACE_DEBUG(FULL, "The thread returned the following value: %p (ignored)", th_ret);
+		TRACE_DEBUG(ANNOYING, "The thread returned the following value: %p (ignored)", th_ret);
 	}
 	
@@ -439,4 +494,12 @@
 	free(buffer);
 }
+static __inline__ void fd_cleanup_socket(void * sockptr)
+{
+	if (sockptr) {
+		shutdown(*(int *)sockptr, SHUT_RDWR);
+		*(int *)sockptr = 0;
+	}
+}
+
 
 /*============================================================*/
@@ -465,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 */
@@ -2342,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
  *
