Index: include/freeDiameter/libfdcore.h
===================================================================
--- include/freeDiameter/libfdcore.h	(revision 968)
+++ include/freeDiameter/libfdcore.h	(revision 972)
@@ -225,5 +225,5 @@
 	(((unsigned)(state)) <= STATE_MAX ? peer_state_str[((unsigned)(state)) ] : "<Invalid>")
 
-/* Constants for the peer_info structure bellow */
+/* Constants for the peer_info structure below */
 #define PI_P3_DEFAULT	0	/* Use any available protocol */
 #define PI_P3_IP	1	/* Use only IP to connect to this peer */
@@ -406,5 +406,5 @@
  *
  * PARAMETERS:
- *  peer_validate 	: Callback as defined bellow.
+ *  peer_validate 	: Callback as defined below.
  *
  * DESCRIPTION: 
@@ -589,8 +589,8 @@
  *   - The process is the same as for IN messages, until the routing-in threads makes its decision that the message is not handled locally.
  *   - If the local peer does not relay message, an error DIAMETER_APPLICATION_UNSUPPORTED is returned.
- *   - All callbacks registered with fd_rt_fwd_register are called for the message (see bellow).
+ *   - All callbacks registered with fd_rt_fwd_register are called for the message (see below).
  *     - these callbacks will typically do proxying work. Note that adding the route-record is handled by the daemon.
  *   - Once all callbacks have been called, the message is queued in the global fd_g_outgoing queue.
- *   - The remaining processing is the same as for OUT messages, as described bellow.
+ *   - The remaining processing is the same as for OUT messages, as described below.
  *
  * (*) OUT messages details:
@@ -602,5 +602,5 @@
  *   - If the list is empty, create an error UNABLE_TO_DELIVER (note: should we trig dynamic discovery here???) and reply.
  *   - Otherwise, call all callbacks registered by function fd_rt_out_register, with the list of peers and the message.
- *   - Order the resulting list of peers by score (see bellow), and sent the message to the peer with highest (positive) score.
+ *   - Order the resulting list of peers by score (see below), and sent the message to the peer with highest (positive) score.
  *    - in case the peer is no longer in the "OPEN" state, send the message to the second peer in the list.
  *      - if no peer is in OPEN state anymore, restart the process of creating the list.
@@ -626,5 +626,5 @@
  *
  * PARAMETERS:
- *  rt_fwd_cb	  : The callback function to register (see prototype bellow).
+ *  rt_fwd_cb	  : The callback function to register (see prototype below).
  *  cbdata	  : Pointer to pass to the callback when it is called. The data is opaque to the daemon.
  *  dir           : One of the RT_FWD_* directions defined above.
@@ -703,5 +703,5 @@
  *
  * PARAMETERS:
- *  rt_out_cb	  : The callback function to register (see prototype bellow).
+ *  rt_out_cb	  : The callback function to register (see prototype below).
  *  cbdata	  : Pointer to pass to the callback when it is called. The data is opaque to the daemon.
  *  priority      : Order for calling this callback. The callbacks are called in reverse priority order (higher priority = called sooner).
Index: include/freeDiameter/libfdproto.h
===================================================================
--- include/freeDiameter/libfdproto.h	(revision 961)
+++ include/freeDiameter/libfdproto.h	(revision 972)
@@ -112,4 +112,6 @@
  * FUNCTION:	fd_log
  * MACRO:	fd_log_debug
+ * MACRO:	fd_log_notice
+ * MACRO:	fd_log_error
  *
  * PARAMETERS:
@@ -127,5 +129,8 @@
  */
 void fd_log ( int, const char *, ... );
-#define fd_log_debug(format,args...) fd_log(FD_LOG_DEBUG, format, ## args)
+#define fd_log_debug(format,args...)  fd_log(FD_LOG_DEBUG, format, ## args)
+#define fd_log_notice(format,args...) fd_log(FD_LOG_NOTICE, format, ## args)
+#define fd_log_error(format,args...)  fd_log(FD_LOG_ERROR, format, ## args)
+
 void fd_log_debug_fstr( FILE *, const char *, ... );
 
@@ -211,6 +216,7 @@
 
 /* log levels definitions */
-#define FD_LOG_DEBUG 0
-#define FD_LOG_ERROR 5
+#define FD_LOG_DEBUG  0  /* Verbose information for developers use */
+#define FD_LOG_NOTICE 3  /* Normal execution states worth noting */
+#define FD_LOG_ERROR  5  /* Error conditions, both recoverable or not */
 
 /* print level definitions */
@@ -252,5 +258,5 @@
 
 
-#define STD_TRACE_FMT_STRING "thread %s in %s@%s:%d: "
+#define STD_TRACE_FMT_STRING "pid:%s in %s@%s:%d: "
 /*************
  The general debug macro, each call results in two lines of debug messages (change the macro for more compact output) 
@@ -258,28 +264,42 @@
 #ifdef DEBUG
 /* In DEBUG mode, we add (a lot of) meta-information along each trace. This makes multi-threading problems easier to debug. */
-#define TRACE_DEBUG(level,format,args... ) {											\
+#define TRACE(printlevel,level,format,args... ) {										\
 	if ( TRACE_BOOL(level) ) {												\
 		const char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed");					\
-		fd_log(level, STD_TRACE_FMT_STRING format, \
-					__thn, __PRETTY_FUNCTION__, __FILE__, __LINE__, ## args); 						\
+		fd_log((printlevel), STD_TRACE_FMT_STRING format, 								\
+					__thn, __PRETTY_FUNCTION__, __STRIPPED_FILE__, __LINE__, ## args); 			\
 	}															\
 }
 #else /* DEBUG */
-/* Do not print thread, function, ... only the message itself in this case, unless the debug level is set > FULL. */
-#define TRACE_DEBUG(level,format,args... ) {												\
-	if ( TRACE_BOOL(level) ) {													\
-		if (fd_g_debug_lvl > FULL) {												\
-			const char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed");					\
-                        fd_log(level, STD_TRACE_FMT_STRING format,      \
-                               __thn, __PRETTY_FUNCTION__, __FILE__, __LINE__, ## args);  \
-		} else {														\
-			fd_log(level, format, ## args);           \
-		}															\
-	}																\
+/* Do not print thread, function, ... only the message itself in this case */
+#define TRACE(printlevel,level,format,args... ) {					\
+	if ( TRACE_BOOL(level) ) {							\
+		fd_log((printlevel), format, ## args);    				\
+	}										\
 }
 #endif /* DEBUG */
 
+/* Report debug information */
+#define TRACE_DEBUG(level,format,args... ) \
+	TRACE(FD_LOG_DEBUG,(level),format,##args)
+
+/* Report a normal message that is useful for normal admin monitoring */
+#define TRACE_NOTICE(format,args... ) \
+	TRACE(FD_LOG_NOTICE,INFO,format,##args)
+
+/* Report an error */
+#define TRACE_ERROR(format,args... ) \
+	TRACE(FD_LOG_ERROR, NONE, format, ##args)
+
+/* 
+TRACE_NOTICE(...) and fd_log_notice(...) are equivalent when the code is not compiled in DEBUG mode,
+but there is more contextual information when compiled in DEBUG with the TRACE_NOTICE macro,
+hence it is recommended to use this one except for formatted output (e.g. fd_*_dump function)
+
+resp. TRACE_DEBUG and TRACE_ERROR.
+*/
+
 /*************
- Derivatives from this macro 
+ Derivatives for debug
  ************/
 /* Helper for function entry -- for very detailed trace of the execution */
@@ -292,5 +312,5 @@
 int fd_breakhere(void);
 
-/* Helper for tracing the CHECK_* macros bellow -- very very verbose code execution! */
+/* Helper for tracing the CHECK_* macros below -- very very verbose code execution! */
 #define TRACE_DEBUG_ALL( str ) 	\
 	TRACE_DEBUG(CALL, str );
@@ -306,18 +326,35 @@
 
 /* Trace a binary buffer content */
-#define TRACE_DEBUG_BUFFER(level, prefix, buf, bufsz, suffix ) {								\
+#ifdef DEBUG
+/* In DEBUG mode, we add (a lot of) meta-information along each trace. This makes multi-threading problems easier to debug. */
+#define TRACE_BUFFER(printlevel, level, prefix, buf, bufsz, suffix ) {								\
 	if ( TRACE_BOOL(level) ) {												\
 		int __i;													\
 		size_t __sz = (size_t)(bufsz);											\
 		uint8_t * __buf = (uint8_t *)(buf);										\
+		char __strbuf[1024+1];												\
 		char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed");					\
-                fd_log(level, STD_TRACE_FMT_STRING prefix,              \
-                       __thn, __PRETTY_FUNCTION__, __FILE__, __LINE__);	\
-		for (__i = 0; __i < __sz; __i++) {										\
-			fd_log(level, "%02.2hhx", __buf[__i]);         \
+		for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2)); __i++) {						\
+			sprintf(__strbuf + (2 * __i), "%2.2hhx", __buf[__i]);     						\
 		}														\
-		fd_log(level, suffix);                        \
+                fd_log(printlevel, STD_TRACE_FMT_STRING "%s%s%s",      								\
+                       __thn, __PRETTY_FUNCTION__, __STRIPPED_FILE__, __LINE__, (prefix), __strbuf, (suffix));			\
 	}															\
 }
+#else /* DEBUG */
+/* Do not print thread, function, ... only the message itself in this case */
+#define TRACE_BUFFER(printlevel, level, prefix, buf, bufsz, suffix ) {								\
+	if ( TRACE_BOOL(level) ) {												\
+		int __i;													\
+		size_t __sz = (size_t)(bufsz);											\
+		uint8_t * __buf = (uint8_t *)(buf);										\
+		char __strbuf[1024+1];												\
+		for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2)); __i++) {						\
+			sprintf(__strbuf + (2 * __i), "%2.2hhx", __buf[__i]);     						\
+		}														\
+                fd_log(printlevel, "%s%s%s", (prefix), __strbuf, (suffix));							\
+	}															\
+}
+#endif /* DEBUG */
 
 /* Some aliases to socket addresses structures */
@@ -334,22 +371,22 @@
 
 /* Dump one sockaddr Node information */
-#define sSA_DUMP_NODE( buf, bufsize, sa, flag ) {                \
-	sSA * __sa = (sSA *)(sa);				\
-	char __addrbuf[INET6_ADDRSTRLEN];			\
-	if (__sa) {						\
-	  int __rc = getnameinfo(__sa, 				\
-	  		sSAlen(__sa),				\
-			__addrbuf,				\
-			sizeof(__addrbuf),			\
-			NULL,					\
-			0,					\
-			flag);					\
-	  if (__rc)						\
+#define sSA_DUMP_NODE( buf, bufsize, sa, flag ) {                	\
+	sSA * __sa = (sSA *)(sa);					\
+	char __addrbuf[INET6_ADDRSTRLEN];				\
+	if (__sa) {							\
+	  int __rc = getnameinfo(__sa, 					\
+	  		sSAlen(__sa),					\
+			__addrbuf,					\
+			sizeof(__addrbuf),				\
+			NULL,						\
+			0,						\
+			(flag));					\
+	  if (__rc)							\
 		snprintf(buf, bufsize, "%s", gai_strerror(__rc));	\
-	  else							\
-		snprintf(buf, bufsize, "%s", &__addrbuf[0]);       \
-	} else {						\
-		snprintf(buf, bufsize, "(NULL / ANY)");             \
-	}							\
+	  else								\
+		snprintf(buf, bufsize, "%s", &__addrbuf[0]);       	\
+	} else {							\
+		snprintf(buf, bufsize, "(NULL / ANY)");             	\
+	}								\
 }
 /* Same but with the port (service) also */
@@ -365,5 +402,5 @@
 			__servbuf,					\
 			sizeof(__servbuf),				\
-			flag);						\
+			(flag));					\
 	  if (__rc)							\
 		snprintf(buf, bufsize, "%s", gai_strerror(__rc));  \
@@ -375,18 +412,25 @@
 }
 
-/* Inside a debug trace */
-#define TRACE_DEBUG_sSA(level, prefix, sa, flags, suffix ) {										\
+#ifdef DEBUG
+/* In DEBUG mode, we add (a lot of) meta-information along each trace. This makes multi-threading problems easier to debug. */
+#define TRACE_sSA(printlevel, level, prefix, sa, flags, suffix ) {										\
 	if ( TRACE_BOOL(level) ) {												\
-		char buf[1024]; \
+		char __buf[1024]; 												\
 		char * __thn = ((char *)pthread_getspecific(fd_log_thname) ?: "unnamed");					\
-		sSA_DUMP_NODE_SERV(buf, sizeof(buf), sa, flags );       \
-		fd_log(level, STD_TRACE_FMT_STRING "%s%s%s",              \
-                       __thn, __PRETTY_FUNCTION__, __FILE__, __LINE__, prefix, buf, suffix); \
+		sSA_DUMP_NODE_SERV(__buf, sizeof(__buf), sa, flags );       							\
+		fd_log(printlevel, STD_TRACE_FMT_STRING "%s%s%s" ,     								\
+                       __thn, __PRETTY_FUNCTION__, __STRIPPED_FILE__, __LINE__, (prefix), __buf, (suffix)); 			\
 	}															\
 }
-
-/* Report an error */
-#define TRACE_DEBUG_ERROR(format,args... ) \
-	TRACE_DEBUG(INFO, format, ##args)
+#else /* DEBUG */
+/* Do not print thread, function, ... only the message itself in this case */
+#define TRACE_sSA(printlevel, level, prefix, sa, flags, suffix ) {										\
+	if ( TRACE_BOOL(level) ) {												\
+		char __buf[1024]; 												\
+		sSA_DUMP_NODE_SERV(__buf, sizeof(__buf), sa, flags );       							\
+		fd_log(printlevel, "%s%s%s" , (prefix), __buf, (suffix)); 							\
+	}															\
+}
+#endif /* DEBUG */
 
 /******************
@@ -395,15 +439,31 @@
 #ifdef STRIP_DEBUG_CODE
 #undef TRACE_DEBUG
+#undef TRACE_NOTICE
+#undef TRACE_ERROR
 #undef TRACE_BOOL
-#undef TRACE_DEBUG_sSA
-#undef TRACE_DEBUG_BUFFER
-#undef TRACE_DEBUG_ERROR
-#define TRACE_DEBUG(level,format,args... )
-#define TRACE_BOOL(_level_) (0)
-#define TRACE_DEBUG_BUFFER(level, prefix, buf, bufsz, suffix )
-#define TRACE_DEBUG_sSA(level, prefix, sa, flags, suffix )
-#define TRACE_DEBUG_ERROR(format,args... ) {	\
-	fd_log(FD_LOG_ERROR, format, ## args); 	\
-}
+#undef TRACE_BUFFER
+#undef TRACE_sSA
+
+#define TRACE_DEBUG(level,format,args... ) /* noop */
+#define TRACE_BOOL(_level_) (0)	/* always false */
+#define TRACE_NOTICE fd_log_notice
+#define TRACE_ERROR fd_log_error
+#define TRACE_BUFFER(printlevel, level, prefix, buf, bufsz, suffix ) {								\
+	if (printlevel > FD_LOG_DEBUG) {											\
+		int __i;													\
+		size_t __sz = (size_t)(bufsz);											\
+		uint8_t * __buf = (uint8_t *)(buf);										\
+		char * __strbuf[1024+1];											\
+		for (__i = 0; (__i < __sz) && (__i<(sizeof(__strbuf)/2); __i++) {						\
+			sprintf(__strbuf + (2 * __i), "%02.2hhx", __buf[__i]);     						\
+		}														\
+                fd_log(printlevel, prefix"%s"suffix, __strbuf);									\
+	}
+#define TRACE_sSA(printlevel, level, prefix, sa, flags, suffix )  {								\
+	if (printlevel > FD_LOG_DEBUG) {											\
+		char __buf[1024]; 												\
+		sSA_DUMP_NODE_SERV(__buf, sizeof(__buf), sa, flags );       							\
+		fd_log(printlevel, prefix "%s" suffix, __buf);				 					\
+	}
 #endif /* STRIP_DEBUG_CODE */
 
@@ -424,5 +484,5 @@
 	if (__ret__ < 0) {								\
 		int __err__ = errno;	/* We may handle EINTR here */			\
-		TRACE_DEBUG_ERROR("ERROR: in '" #__call__ "' :\t%s", strerror(__err__));\
+		TRACE_ERROR("ERROR: in '" #__call__ "' :\t%s", strerror(__err__));\
 		__fallback__;								\
 	}										\
@@ -435,5 +495,5 @@
 	if (__ret__ < 0) {								\
 		int __err__ = errno;	/* We may handle EINTR here */			\
-		TRACE_DEBUG_ERROR("ERROR: in '" #__call__ "' :\t%s", strerror(__err__));\
+		TRACE_ERROR("ERROR: in '" #__call__ "' :\t%s", strerror(__err__));\
 		return __err__;								\
 	}										\
@@ -449,5 +509,5 @@
 			__fallback1__;								\
 		} else {									\
-			TRACE_DEBUG_ERROR("ERROR: in '" #__call__ "':\t%s", strerror(__ret__));	\
+			TRACE_ERROR("ERROR: in '" #__call__ "':\t%s", strerror(__ret__));	\
 			__fallback2__;								\
 		}										\
@@ -472,5 +532,5 @@
 	if (__ret__ == NULL) {								\
 		int __err__ = errno;							\
-		TRACE_DEBUG_ERROR("ERROR: in '" #__call__ "':\t%s", strerror(__err__));	\
+		TRACE_ERROR("ERROR: in '" #__call__ "':\t%s", strerror(__err__));	\
 		__fallback__;								\
 	}										\
@@ -486,5 +546,5 @@
 	TRACE_DEBUG_ALL( "Check PARAMS: " #__bool__ );						\
 	if ( ! (__bool__) ) {									\
-		TRACE_DEBUG_ERROR("Warning: Invalid parameter received in '" #__bool__ "'");	\
+		TRACE_ERROR("Warning: Invalid parameter received in '" #__bool__ "'");	\
 		__fallback__;									\
 	}
@@ -499,5 +559,5 @@
 	__ret__ = (__call__);								\
 	if (__ret__ != 0) {								\
-		TRACE_DEBUG_ERROR("ERROR: in '" #__call__ "':\t%s", strerror(__ret__));	\
+		TRACE_ERROR("ERROR: in '" #__call__ "':\t%s", strerror(__ret__));	\
 		__fallback__;								\
 	}										\
@@ -834,5 +894,5 @@
  *  type 	: What kind of object must be created
  *  data 	: pointer to the data for the object. 
- *          	 type parameter is used to determine the type of data (see bellow for detail).
+ *          	 type parameter is used to determine the type of data (see below for detail).
  *  parent 	: a reference to a parent object, if needed.
  *  ref 	: upon successful creation, reference to new object is stored here if !null.
@@ -858,5 +918,5 @@
  *  dict	: Pointer to the dictionnary where the object is searched
  *  type 	: type of object that is being searched
- *  criteria 	: how the object must be searched. See object-related sections bellow for more information.
+ *  criteria 	: how the object must be searched. See object-related sections below for more information.
  *  what 	: depending on criteria, the data that must be searched.
  *  result 	: On successful return, pointer to the object is stored here.
@@ -865,5 +925,5 @@
  * DESCRIPTION: 
  *   Perform a search in the dictionary. 
- *   See the object-specific sections bellow to find how to look for each objects.
+ *   See the object-specific sections below to find how to look for each objects.
  *   If the "result" parameter is NULL, the function is used to check if an object is in the dictionary.
  *   Otherwise, a reference to the object is stored in result if found.
@@ -935,5 +995,5 @@
 	VENDOR_BY_ID = 10,	/* "what" points to a vendor_id_t */
 	VENDOR_BY_NAME,		/* "what" points to a char * */
-	VENDOR_OF_APPLICATION	/* "what" points to a struct dict_object containing an application (see bellow) */
+	VENDOR_OF_APPLICATION	/* "what" points to a struct dict_object containing an application (see below) */
 };
 
@@ -1005,6 +1065,6 @@
 	APPLICATION_BY_ID = 20,		/* "what" points to a application_id_t */
 	APPLICATION_BY_NAME,		/* "what" points to a char * */
-	APPLICATION_OF_TYPE,		/* "what" points to a struct dict_object containing a type object (see bellow) */
-	APPLICATION_OF_COMMAND		/* "what" points to a struct dict_object containing a command (see bellow) */
+	APPLICATION_OF_TYPE,		/* "what" points to a struct dict_object containing a type object (see below) */
+	APPLICATION_OF_COMMAND		/* "what" points to a struct dict_object containing a command (see below) */
 };
 
@@ -1146,5 +1206,5 @@
 enum {
 	TYPE_BY_NAME = 30,		/* "what" points to a char * */
-	TYPE_OF_ENUMVAL,		/* "what" points to a struct dict_object containing an enumerated constant (DICT_ENUMVAL, see bellow). */
+	TYPE_OF_ENUMVAL,		/* "what" points to a struct dict_object containing an enumerated constant (DICT_ENUMVAL, see below). */
 	TYPE_OF_AVP			/* "what" points to a struct dict_object containing an AVP object. */
 };
@@ -1220,5 +1280,5 @@
 /* The criteria for searching a constant in the dictionary */
 enum {
-	ENUMVAL_BY_STRUCT = 40,	/* "what" points to a struct dict_enumval_request as defined bellow */
+	ENUMVAL_BY_STRUCT = 40,	/* "what" points to a struct dict_enumval_request as defined below */
 	ENUMVAL_BY_NAME,	/* This cannot be used for researches */
 	ENUMVAL_BY_VALUE	/* This cannot be used for researches */
@@ -1342,9 +1402,9 @@
 	AVP_BY_NAME,		/* "what" points to a char *, vendor is always 0 */
 	AVP_BY_NAME_ALL_VENDORS,/* "what" points to a string. Might be quite slow... */
-	AVP_BY_STRUCT,		/* "what" points to a struct dict_avp_request_ex (see bellow) */
+	AVP_BY_STRUCT,		/* "what" points to a struct dict_avp_request_ex (see below) */
 			
 	/* kept for backward compatibility, better use AVP_BY_STRUCT above instead */
-	AVP_BY_CODE_AND_VENDOR,	/* "what" points to a struct dict_avp_request (see bellow), where avp_vendor and avp_code are set */
-	AVP_BY_NAME_AND_VENDOR	/* "what" points to a struct dict_avp_request (see bellow), where avp_vendor and avp_name are set */
+	AVP_BY_CODE_AND_VENDOR,	/* "what" points to a struct dict_avp_request (see below), where avp_vendor and avp_code are set */
+	AVP_BY_NAME_AND_VENDOR	/* "what" points to a struct dict_avp_request (see below), where avp_vendor and avp_name are set */
 };
 
@@ -1580,5 +1640,5 @@
 /* The criteria for searching a rule in the dictionary */
 enum {
-	RULE_BY_AVP_AND_PARENT = 70	/* "what" points to a struct dict_rule_request -- see bellow. This is used to query "what is the rule for this AVP in this group?" */
+	RULE_BY_AVP_AND_PARENT = 70	/* "what" points to a struct dict_rule_request -- see below. This is used to query "what is the rule for this AVP in this group?" */
 };
 
@@ -1793,5 +1853,5 @@
  *  diamid	  : a Diameter Identity, or NULL.
  *  diamidlen	  : if diamid is \0-terminated, this can be 0. Otherwise, the length of diamid.
- *  opt           : Additional string, or NULL. Usage is described bellow.
+ *  opt           : Additional string, or NULL. Usage is described below.
  *  optlen	  : if opt is \0-terminated, this can be 0. Otherwise, the length of opt.
  *
@@ -2076,5 +2136,5 @@
 };
 
-/* Some flags used in the functions bellow */
+/* Some flags used in the functions below */
 #define AVPFL_SET_BLANK_VALUE	   0x01	/* When creating an AVP, initialize its value to a blank area */
 #define AVPFL_SET_RAWDATA_FROM_AVP 0x02 /* When creating an AVP, initialize its rawdata area from an existing AVP -- it is only blank padding (for error reporting) */
