changeset 1082:b380c9f3be1e

Merge
author Sebastien Decugis <sdecugis@freediameter.net>
date Thu, 02 May 2013 16:09:50 +0800
parents 758b21ae6c3e (current diff) b36c81e52e9a (diff)
children d0017c5dde61
files include/freeDiameter/libfdproto.h
diffstat 15 files changed, 763 insertions(+), 99 deletions(-) [+]
line wrap: on
line diff
--- a/extensions/app_diameap/diameap_eap.c	Thu May 02 16:09:06 2013 +0800
+++ b/extensions/app_diameap/diameap_eap.c	Thu May 02 16:09:50 2013 +0800
@@ -372,7 +372,7 @@
 
 		case EAP_INTEGRITY_CHECK:
 			if ((*eap_sm->selectedMethod->eap_method_check)(eap_sm,
-					eap_i->aaaEapRespData) == FALSE)
+					&eap_i->aaaEapRespData) == FALSE)
 			{
 				TRACE_DEBUG(INFO,"%s[EAP Protocol] Invalid EAP packet received {Type=%d, Vendor=%d}. Integrity check failed (non fatal error).",DIAMEAP_EXTENSION,eap_sm->currentMethod,eap_sm->currentVendor);
 				//non_fata_error
@@ -433,7 +433,7 @@
 				}
 			}
 			if ((*eap_sm->selectedMethod->eap_method_process)(eap_sm,
-					eap_i->aaaEapRespData))
+					&eap_i->aaaEapRespData))
 			{
 				TRACE_DEBUG(INFO,"%s[EAP Protocol] [%s plugin] Authentication process failed.",DIAMEAP_EXTENSION,eap_sm->selectedMethod->methodname);
 				*non_fatal_error = TRUE;
--- a/extensions/app_diameap/diameap_plugins.c	Thu May 02 16:09:06 2013 +0800
+++ b/extensions/app_diameap/diameap_plugins.c	Thu May 02 16:09:50 2013 +0800
@@ -262,7 +262,7 @@
 		if (registerplugin->check)
 		{
 			plugin->eap_method_check = (boolean(*)(struct eap_state_machine *,
-					struct eap_packet)) dlsym(plugin->handler,
+					struct eap_packet*)) dlsym(plugin->handler,
 					registerplugin->check);
 			if (plugin->eap_method_check == NULL)
 			{
@@ -284,7 +284,7 @@
 		if (registerplugin->process)
 		{
 			plugin->eap_method_process = (int(*)(struct eap_state_machine *,
-					struct eap_packet)) dlsym(plugin->handler,
+					struct eap_packet*)) dlsym(plugin->handler,
 					registerplugin->process);
 			if (plugin->eap_method_process == NULL)
 			{
--- a/extensions/app_diameap/libdiameap.h	Thu May 02 16:09:06 2013 +0800
+++ b/extensions/app_diameap/libdiameap.h	Thu May 02 16:09:50 2013 +0800
@@ -109,9 +109,9 @@
 			u8 identifier,struct eap_packet * eapPacket); /* address of the eap_method_buildReq method */
 	int (*eap_method_getTimeout)(struct eap_state_machine *smd, int * timeout); /* address of the eap_method_getTimeout method */
 	boolean (*eap_method_check)(struct eap_state_machine *smd,
-			struct eap_packet eapRespData); /* address of the eap_method_check method */
+			struct eap_packet * eapRespData); /* address of the eap_method_check method */
 	int (*eap_method_process)(struct eap_state_machine *smd,
-			struct eap_packet eapRespData); /* address of the eap_method_process method */
+			struct eap_packet * eapRespData); /* address of the eap_method_process method */
 	boolean (*eap_method_isDone)(struct eap_state_machine *smd); /* address of the eap_method_isDone method */
 	int (*eap_method_getKey)(struct eap_state_machine *smd, u8 ** msk,int *msklength, 
 			u8 ** emsk,int *emsklength); /* address of the eap_method_getKey method */
--- a/extensions/dbg_interactive/queues.i	Thu May 02 16:09:06 2013 +0800
+++ b/extensions/dbg_interactive/queues.i	Thu May 02 16:09:50 2013 +0800
@@ -65,12 +65,7 @@
 	
 	/* Get the length of the queue (nb elements) */
 	int length() {
-		int l;
-		int ret = fd_fifo_length ( $self, &l, NULL );
-		if (ret != 0) {
-			DI_ERROR(ret, NULL, NULL);
-		}
-		return l;
+		return fd_fifo_length ( $self ) ;
 	}
 
 	/* Is the threashold function useful here? TODO... */
--- a/extensions/dbg_monitor/dbg_monitor.c	Thu May 02 16:09:06 2013 +0800
+++ b/extensions/dbg_monitor/dbg_monitor.c	Thu May 02 16:09:50 2013 +0800
@@ -49,6 +49,28 @@
 
 EXTENSION_ENTRY("dbg_monitor", monitor_main);
 
+
+
+/* Display information about a queue */
+static void display_info(char * queue_desc, char * peer, int current_count, int limit_count, int highest_count, long long total_count,
+			struct timespec * total, struct timespec * blocking, struct timespec * last)
+{
+	long long ms = (total->tv_sec * 1000000) + (total->tv_nsec / 1000);
+	long double throughput = (long double)total_count * 1000000;
+	throughput /= ms;
+	if (peer) {
+		TRACE_DEBUG(INFO, "'%s'@'%s': cur:%d/%d, h:%d, T:%lld in %ld.%06lds (%.2LFitems/s), blocked:%ld.%06lds, last processing:%ld.%06lds",
+			queue_desc, peer, current_count, limit_count, highest_count,
+			total_count, total->tv_sec, total->tv_nsec, throughput,
+			blocking->tv_sec, blocking->tv_nsec, last->tv_sec, last->tv_nsec);
+	} else {
+		TRACE_DEBUG(INFO, "Global '%s': cur:%d/%d, h:%d, T:%lld in %ld.%06lds (%.2LFitems/s), blocked:%ld.%06lds, last processing:%ld.%06lds",
+			queue_desc, current_count, limit_count, highest_count,
+			total_count, total->tv_sec, total->tv_nsec, throughput,
+			blocking->tv_sec, blocking->tv_nsec, last->tv_sec, last->tv_nsec);
+	}
+}
+
 /* Thread to display periodical debug information */
 static pthread_t thr;
 static void * mn_thr(void * arg)
@@ -58,18 +80,51 @@
 	
 	/* Loop */
 	while (1) {
+		int current_count, limit_count, highest_count;
+		long long total_count;
+		struct timespec total, blocking, last;
+		struct fd_list * li;
+	
 		#ifdef DEBUG
 		for (i++; i % 30; i++) {
 			fd_log_debug("[dbg_monitor] %ih%*im%*is", i/3600, 2, (i/60) % 60 , 2, i%60); /* This makes it easier to detect inactivity periods in the log file */
 			sleep(1);
 		}
 		#else /* DEBUG */
-		sleep(3600); /* 1 hour */
+		sleep(3599); /* 1 hour */
 		#endif /* DEBUG */
-		fd_log_debug("[dbg_monitor] Dumping current information");
-		CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_QUEUES, 0, NULL), /* continue */);
+		TRACE_DEBUG(INFO, "[dbg_monitor] Dumping queues statistics");
+		
+		CHECK_FCT_DO( fd_stat_getstats(STAT_G_LOCAL, NULL, &current_count, &limit_count, &highest_count, &total_count, &total, &blocking, &last), );
+		display_info("Local delivery", NULL, current_count, limit_count, highest_count, total_count, &total, &blocking, &last);
+		
+		CHECK_FCT_DO( fd_stat_getstats(STAT_G_INCOMING, NULL, &current_count, &limit_count, &highest_count, &total_count, &total, &blocking, &last), );
+		display_info("Total received", NULL, current_count, limit_count, highest_count, total_count, &total, &blocking, &last);
+		
+		CHECK_FCT_DO( fd_stat_getstats(STAT_G_OUTGOING, NULL, &current_count, &limit_count, &highest_count, &total_count, &total, &blocking, &last), );
+		display_info("Total sending", NULL, current_count, limit_count, highest_count, total_count, &total, &blocking, &last);
+		
+		
+		CHECK_FCT_DO( pthread_rwlock_rdlock(&fd_g_peers_rw), /* continue */ );
+
+		for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
+			struct peer_hdr * p = (struct peer_hdr *)li->o;
+			
+			fd_peer_dump(p, NONE);
+			
+			CHECK_FCT_DO( fd_stat_getstats(STAT_P_PSM, p, &current_count, &limit_count, &highest_count, &total_count, &total, &blocking, &last), );
+			display_info("Events, incl. recept", p->info.pi_diamid, current_count, limit_count, highest_count, total_count, &total, &blocking, &last);
+			
+			CHECK_FCT_DO( fd_stat_getstats(STAT_P_TOSEND, p, &current_count, &limit_count, &highest_count, &total_count, &total, &blocking, &last), );
+			display_info("Outgoing", p->info.pi_diamid, current_count, limit_count, highest_count, total_count, &total, &blocking, &last);
+			
+		}
+
+		CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ );
+
+		
+		
 		CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_SERV, 0, NULL), /* continue */);
-		CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_PEERS, 0, NULL), /* continue */);
 		sleep(1);
 	}
 	
--- a/include/freeDiameter/libfdcore.h	Thu May 02 16:09:06 2013 +0800
+++ b/include/freeDiameter/libfdcore.h	Thu May 02 16:09:50 2013 +0800
@@ -860,8 +860,8 @@
 /*                         MONITORING                         */
 /*============================================================*/
 
-/* These functions allows an extension to collect state information about the
- * framework state, as well as hooks at some key checkpoints in the processing
+/* These functions allow an extension to collect state information about the
+ * framework, as well as being hooked at some key checkpoints in the processing
  * for logging / statistics purpose.
  */
  
@@ -1096,8 +1096,8 @@
  * PARAMETERS:
  *  stat	  : Which queue is being queried
  *  peer	  : (depending on the stat parameter) which peer is being queried
- *  len	  	  : (out) The number of items in the queue currently
- *  max	  	  : (out) The max number of items the queue accepts before becoming blocking -- 0 means no max.
+ *  current_count : (out) The number of items in the queue currently
+ *  limit_count   : (out) The max number of items the queue accepts before becoming blocking -- 0 means no max.
  *  highest_count : (out) The highest count the queue has reached since startup
  *  total_count	  : (out) Total number of items that this queue has processed (always growing, use deltas for monitoring)
  *  total	  : (out) Cumulated time all items spent in this queue, including blocking time (always growing, use deltas for monitoring)
@@ -1113,7 +1113,7 @@
  *  EINVAL 	: A parameter is invalid.
  */
 int fd_stat_getstats(enum fd_stat_type stat, struct peer_hdr * peer, 
-			int * len, int * max, int * highest_count, long long * total_count, 
+			int * current_count, int * limit_count, int * highest_count, long long * total_count,
 			struct timespec * total, struct timespec * blocking, struct timespec * last);
 
 /*============================================================*/
--- a/include/freeDiameter/libfdproto.h	Thu May 02 16:09:06 2013 +0800
+++ b/include/freeDiameter/libfdproto.h	Thu May 02 16:09:50 2013 +0800
@@ -2988,32 +2988,17 @@
 int fd_fifo_move ( struct fifo * oldq, struct fifo * newq, struct fifo ** loc_update );
 
 /*
- * FUNCTION:	fd_fifo_length
- *
- * PARAMETERS:
- *  queue	: The queue from which to retrieve the number of elements.
- *  length	: Upon success, the current number of elements in the queue is stored here.
- *  max		: the maximum number of elements as specified during creation. Can be NULL.
- *
- * DESCRIPTION: 
- *  Retrieve the number of elements in a queue.
- *
- * RETURN VALUE:
- *  0		: The length of the queue has been written.
- *  EINVAL 	: A parameter is invalid.
- */
-int fd_fifo_length ( struct fifo * queue, int * length, int * max);
-int fd_fifo_length_noerr ( struct fifo * queue ); /* no error checking version */
-
-/*
  * FUNCTION:	fd_fifo_getstats
  *
  * PARAMETERS:
- *  queue	: The queue from which to retrieve the timings information.
- *  items       : the total number of items that went through the queue (already pop'd). Always increasing.
- *  total	: Cumulated time all items spent in this queue, including blocking time (always growing, use deltas for monitoring)
- *  blocking    : Cumulated time threads trying to post new items were blocked (queue full).
- *  last        : For the last element retrieved from the queue, how long it take between posting (including blocking) and poping
+ *  queue	  : The queue from which to retrieve the information.
+ *  current_count : How many items in the queue at the time of execution. This changes each time an item is pushed or poped.
+ *  limit_count   : The maximum number of items allowed in this queue. This is specified during queue creation.
+ *  highest_count : The maximum number of items this queue has contained. This enables to see if limit_count count was reached.
+ *  total_count   : the total number of items that went through the queue (already pop'd). Always increasing.
+ *  total	  : Cumulated time all items spent in this queue, including blocking time (always growing, use deltas for monitoring)
+ *  blocking      : Cumulated time threads trying to post new items were blocked (queue full).
+ *  last          : For the last element retrieved from the queue, how long it take between posting (including blocking) and poping
  *  
  * DESCRIPTION: 
  *  Retrieve the timing information associated with a queue, for monitoring purpose.
@@ -3022,8 +3007,22 @@
  *  0		: The statistics have been updated.
  *  EINVAL 	: A parameter is invalid.
  */
-int fd_fifo_getstats( struct fifo * queue, long long *items, struct timespec * total, struct timespec * blocking, struct timespec * last);
-
+int fd_fifo_getstats( struct fifo * queue, int * current_count, int * limit_count, int * highest_count, long long * total_count, 
+				           struct timespec * total, struct timespec * blocking, struct timespec * last);
+
+/*
+ * FUNCTION:	fd_fifo_length
+ *
+ * PARAMETERS:
+ *  queue	: The queue from which to retrieve the number of elements.
+ *
+ * DESCRIPTION: 
+ *  Retrieve the number of elements in a queue, without error checking.
+ *
+ * RETURN VALUE:
+ *  The number of items currently queued.
+ */
+int fd_fifo_length ( struct fifo * queue );
 
 /*
  * FUNCTION:	fd_fifo_setthrhd
--- a/libfdcore/CMakeLists.txt	Thu May 02 16:09:06 2013 +0800
+++ b/libfdcore/CMakeLists.txt	Thu May 02 16:09:50 2013 +0800
@@ -17,6 +17,8 @@
 	endpoints.c
 	events.c
 	extensions.c
+	fifo_stats.c
+	hooks.c
 	dict_base_proto.c
 	messages.c
 	queues.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfdcore/fifo_stats.c	Thu May 02 16:09:50 2013 +0800
@@ -0,0 +1,79 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+/* See include/freeDiameter/libfdcore.h for more information */
+int fd_stat_getstats(enum fd_stat_type stat, struct peer_hdr * peer, 
+			int * current_count, int * limit_count, int * highest_count, long long * total_count, 
+			struct timespec * total, struct timespec * blocking, struct timespec * last)
+{
+	struct fd_peer * p = (struct fd_peer *)peer;
+	TRACE_ENTRY( "%d %p %p %p %p %p %p %p %p", stat, peer, current_count, limit_count, highest_count, total_count, total, blocking, last);
+	
+	switch (stat) {
+		case STAT_G_LOCAL: {
+			CHECK_FCT( fd_fifo_getstats(fd_g_local, current_count, limit_count, highest_count, total_count, total, blocking, last) );
+		}
+		break;
+
+		case STAT_G_INCOMING: {
+			CHECK_FCT( fd_fifo_getstats(fd_g_incoming, current_count, limit_count, highest_count, total_count, total, blocking, last) );
+		}
+		break;
+
+		case STAT_G_OUTGOING: {
+			CHECK_FCT( fd_fifo_getstats(fd_g_outgoing, current_count, limit_count, highest_count, total_count, total, blocking, last) );
+		}
+		break;
+
+		case STAT_P_PSM: {
+			CHECK_PARAMS( CHECK_PEER( peer ) );
+			CHECK_FCT( fd_fifo_getstats(p->p_events, current_count, limit_count, highest_count, total_count, total, blocking, last) );
+		}
+		break;
+
+		case STAT_P_TOSEND: {
+			CHECK_PARAMS( CHECK_PEER( peer ) );
+			CHECK_FCT( fd_fifo_getstats(p->p_tosend, current_count, limit_count, highest_count, total_count, total, blocking, last) );
+		}
+		break;
+
+		default:
+			return EINVAL;
+	}
+	
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfdcore/hooks.c	Thu May 02 16:09:50 2013 +0800
@@ -0,0 +1,64 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "fdcore-internal.h"
+
+struct fd_hook_hdl; 
+struct fd_hook_data_hdl;
+
+int fd_hook_data_register(
+	struct fd_hook_permsgdata * (*permsgdata_new_cb)     (void),
+        void (*permsgdata_destroy_cb) (struct fd_hook_permsgdata *),
+        struct fd_hook_data_hdl **    new_handle
+)
+{
+	return ENOTSUP;
+}
+
+int fd_hook_register (  enum fd_hook_type type, 
+			void (*fd_hook_cb)(enum fd_hook_type type, struct msg * msg, struct peer_hdr * peer, void * other, void * regdata), 
+			void * regdata, 
+			struct fd_hook_data_hdl *data_hdl,
+			struct fd_hook_hdl ** handler )
+{
+	return ENOTSUP;
+}
+
+
+int fd_hook_unregister( struct fd_hook_hdl * handler )
+{
+	return ENOTSUP;
+}
+
--- a/libfdproto/fifo.c	Thu May 02 16:09:06 2013 +0800
+++ b/libfdproto/fifo.c	Thu May 02 16:09:50 2013 +0800
@@ -151,7 +151,7 @@
 		int i = 0;
 		for (li = queue->list.next; li != &queue->list; li = li->next) {
 			struct fifo_item * fi = (struct fifo_item *)li;
-			fd_log_debug("  [%i] item %p in fifo %p, posted:ld.%06ld", 
+			fd_log_debug("  [%i] item %p in fifo %p, posted:%ld.%06ld", 
 				i++, fi->item.o, queue, (long)fi->posted_on.tv_sec,(long)(fi->posted_on.tv_nsec/1000));
 			(*dump_item)(level, fi->item.o);
 		}
@@ -283,34 +283,11 @@
 	return 0;
 }
 
-/* Get the length of the queue */
-int fd_fifo_length ( struct fifo * queue, int * length, int * max )
+/* Get the information on the queue */
+int fd_fifo_getstats( struct fifo * queue, int * current_count, int * limit_count, int * highest_count, long long * total_count, 
+				           struct timespec * total, struct timespec * blocking, struct timespec * last)
 {
-	TRACE_ENTRY( "%p %p %p", queue, length, max );
-	
-	/* Check the parameters */
-	CHECK_PARAMS( CHECK_FIFO( queue ) && length );
-	
-	/* lock the queue */
-	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
-	
-	/* Retrieve the count */
-	*length = queue->count;
-	
-	if (max)
-		*max = queue->max;
-	
-	/* Unlock */
-	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
-	
-	/* Done */
-	return 0;
-}
-
-/* Get the timings */
-int fd_fifo_getstats( struct fifo * queue, long long *items, struct timespec * total, struct timespec * blocking, struct timespec * last)
-{
-	TRACE_ENTRY( "%p %p %p %p %p", queue, items, total, blocking, last);
+	TRACE_ENTRY( "%p %p %p %p %p %p %p %p", queue, current_count, limit_count, highest_count, total_count, total, blocking, last);
 	
 	/* Check the parameters */
 	CHECK_PARAMS( CHECK_FIFO( queue ) );
@@ -318,8 +295,17 @@
 	/* lock the queue */
 	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
 	
-	if (items)
-		*items = queue->total_items;
+	if (current_count)
+		*current_count = queue->count;
+	
+	if (limit_count)
+		*limit_count = queue->max;
+	
+	if (highest_count)
+		*highest_count = queue->highest_ever;
+	
+	if (total_count)
+		*total_count = queue->total_items;
 	
 	if (total)
 		memcpy(total, &queue->total_time, sizeof(struct timespec));
@@ -339,7 +325,7 @@
 
 
 /* alternate version with no error checking */
-int fd_fifo_length_noerr ( struct fifo * queue )
+int fd_fifo_length ( struct fifo * queue )
 {
 	if ( !CHECK_FIFO( queue ) )
 		return 0;
--- a/libfdproto/ostr.c	Thu May 02 16:09:06 2013 +0800
+++ b/libfdproto/ostr.c	Thu May 02 16:09:50 2013 +0800
@@ -187,7 +187,7 @@
 */
 int fd_os_validate_DiameterIdentity(char ** id, size_t * inoutsz, int memory)
 {
-#if defined(DIAMID_IDNA_IGNORE) || defined(DIAMID_IDNA_REJECT)
+#if !defined(DIAMID_IDNA_IGNORE) && !defined(DIAMID_IDNA_REJECT)
 	int gotsize = 0;
 #endif /* defined(DIAMID_IDNA_IGNORE) || defined(DIAMID_IDNA_REJECT) */
 	
@@ -196,7 +196,7 @@
 	
 	if (!*inoutsz)
 		*inoutsz = strlen(*id);
-#if defined(DIAMID_IDNA_IGNORE) || defined(DIAMID_IDNA_REJECT)
+#if !defined(DIAMID_IDNA_IGNORE) && !defined(DIAMID_IDNA_REJECT)
 	else
 		gotsize = 1;
 #endif /* defined(DIAMID_IDNA_IGNORE) || defined(DIAMID_IDNA_REJECT) */
--- a/tests/CMakeLists.txt	Thu May 02 16:09:06 2013 +0800
+++ b/tests/CMakeLists.txt	Thu May 02 16:09:50 2013 +0800
@@ -25,6 +25,7 @@
 	testpeers
 	testdict
 	testmesg
+	testmesg_stress
 	testsess
 	testdisp
 	testcnx
--- a/tests/testfifo.c	Thu May 02 16:09:06 2013 +0800
+++ b/tests/testfifo.c	Thu May 02 16:09:50 2013 +0800
@@ -216,16 +216,15 @@
 	/* Basic operation */
 	{
 		struct fifo * queue = NULL;
-		int count, max;
 		struct msg * msg  = NULL;
+		int max;
+		long long count;
 		
 		/* Create the queue */
 		CHECK( 0, fd_fifo_new(&queue, 0) );
 		
 		/* Check the count is 0 */
-		CHECK( 0, fd_fifo_length(queue, &count, &max) );
-		CHECK( 0, count);
-		CHECK( 0, max);
+		CHECK( 0, fd_fifo_length(queue) );
 		
 		/* Now enqueue */
 		msg = msg1;
@@ -236,34 +235,28 @@
 		CHECK( 0, fd_fifo_post(queue, &msg) );
 		
 		/* Check the count is 3 */
-		CHECK( 0, fd_fifo_length(queue, &count, &max) );
-		CHECK( 3, count);
-		CHECK( 0, max);
+		CHECK( 3, fd_fifo_length(queue) );
 		
 		/* Retrieve the first message using fd_fifo_get */
 		CHECK( 0, fd_fifo_get(queue, &msg) );
 		CHECK( msg1, msg);
-		CHECK( 0, fd_fifo_length(queue, &count, NULL) );
-		CHECK( 2, count);
+		CHECK( 2, fd_fifo_length(queue) );
 		
 		/* Retrieve the second message using fd_fifo_timedget */
 		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
 		ts.tv_sec += 1; /* Set the timeout to 1 second */
 		CHECK( 0, fd_fifo_timedget(queue, &msg, &ts) );
 		CHECK( msg2, msg);
-		CHECK( 0, fd_fifo_length(queue, &count, NULL) );
-		CHECK( 1, count);
+		CHECK( 1, fd_fifo_length(queue) );
 		
 		/* Retrieve the third message using meq_tryget */
 		CHECK( 0, fd_fifo_tryget(queue, &msg) );
 		CHECK( msg3, msg);
-		CHECK( 0, fd_fifo_length(queue, &count, NULL) );
-		CHECK( 0, count);
+		CHECK( 0, fd_fifo_length(queue) );
 		
 		/* Check that another meq_tryget does not block */
 		CHECK( EWOULDBLOCK, fd_fifo_tryget(queue, &msg) );
-		CHECK( 0, fd_fifo_length(queue, &count, NULL) );
-		CHECK( 0, count);
+		CHECK( 0, fd_fifo_length(queue) );
 		
 		/* Check the timedget actually timesout */
 		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
@@ -273,8 +266,18 @@
 			ts.tv_sec += 1;
 		}
 		CHECK( ETIMEDOUT, fd_fifo_timedget(queue, &msg, &ts) );
-		CHECK( 0, fd_fifo_length(queue, &count, NULL) );
-		CHECK( 0, count);
+		CHECK( 0, fd_fifo_length(queue) );
+		
+		/* Post & get another message */
+		msg = msg1;
+		CHECK( 0, fd_fifo_post(queue, &msg) );
+		CHECK( 0, fd_fifo_timedget(queue, &msg, &ts) );
+		CHECK( msg1, msg);		
+		
+		/* Check some statistics */
+		CHECK( 0, fd_fifo_getstats(queue, NULL, NULL, &max, &count, NULL, NULL, NULL) );
+		CHECK( 3, max );
+		CHECK( 4, count );	
 		
 		/* We're done for basic tests */
 		CHECK( 0, fd_fifo_del(&queue) );
@@ -291,7 +294,6 @@
 		struct msg   		*msgs[NBR_MSG * NBR_THREADS * 2], *msg;
 		pthread_t  		 thr [NBR_THREADS * 2];
 		struct dict_object	*dwr_model = NULL;
-		int 			 count;
 		int			 i;
 		int			 nbr_threads;
 #ifdef _POSIX_THREAD_THREADS_MAX
@@ -362,8 +364,7 @@
 		}
 		
 		/* Check the count of the queue is back to 0 */
-		CHECK( 0, fd_fifo_length(queue, &count, NULL) );
-		CHECK( 0, count);
+		CHECK( 0, fd_fifo_length(queue) );
 		
 		/* Destroy this queue and the messages */
 		CHECK( 0, fd_fifo_del(&queue) );
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/testmesg_stress.c	Thu May 02 16:09:50 2013 +0800
@@ -0,0 +1,482 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@freediameter.net>							 *
+*													 *
+* Copyright (c) 2013, WIDE Project and NICT								 *
+* All rights reserved.											 *
+* 													 *
+* Redistribution and use of this software in source and binary forms, with or without modification, are  *
+* permitted provided that the following conditions are met:						 *
+* 													 *
+* * Redistributions of source code must retain the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer.										 *
+*    													 *
+* * Redistributions in binary form must reproduce the above 						 *
+*   copyright notice, this list of conditions and the 							 *
+*   following disclaimer in the documentation and/or other						 *
+*   materials provided with the distribution.								 *
+* 													 *
+* * Neither the name of the WIDE Project or NICT nor the 						 *
+*   names of its contributors may be used to endorse or 						 *
+*   promote products derived from this software without 						 *
+*   specific prior written permission of WIDE Project and 						 *
+*   NICT.												 *
+* 													 *
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
+* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
+* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
+* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
+* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
+* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
+*********************************************************************************************************/
+
+#include "tests.h"
+
+/* The number of times each operation is repeated to measure the average operation time */
+#define NUMBER_OF_SAMPLES	100000
+
+/* Main test routine */
+int main(int argc, char *argv[])
+{
+	struct msg * acr = NULL;
+	struct avp * pi = NULL, *avp1, *avp2;
+	unsigned char * buf = NULL;
+	
+	/* First, initialize the daemon modules */
+	INIT_FD();
+	
+	{
+		struct dict_object * acr_model = NULL;
+
+		/* Now find the ACR dictionary object */
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &acr_model, ENOENT ) );
+
+		/* Create the instance, using the templates */
+		CHECK( 0, fd_msg_new ( acr_model, 0, &acr ) );
+	}
+	
+	/* Now let's create some additional Dictionary objects for the test */
+	{
+		/* The constant values used here are totally arbitrary chosen */
+		struct dict_object * vendor;
+		{
+			struct dict_vendor_data vendor_data = { 73565, "Vendor test" };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_VENDOR, &vendor_data , NULL, &vendor ) );
+		}
+		
+		{
+			struct dict_application_data app_data = { 73566, "Application test" };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_APPLICATION, &app_data , vendor, NULL ) );
+		}
+		
+		{
+			struct dict_avp_data avp_data = { 73567, 0, "AVP Test - no vendor - f32", 0, 0, AVP_TYPE_FLOAT32 };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+		}
+		
+		{
+			struct dict_avp_data avp_data = { 139103, 0, "AVP Test - no vendor - f64", 0, 0, AVP_TYPE_FLOAT64 };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+		}
+		
+		{ 
+			struct dict_object  * type = NULL;
+			struct dict_type_data type_data = { AVP_TYPE_INTEGER64, "Int64 test" };
+			struct dict_avp_data  avp_data = { 73568, 73565, "AVP Test - i64", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_INTEGER64 };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) );
+		}
+		
+		{
+			struct dict_object     * type = NULL;
+			struct dict_type_data    type_data = { AVP_TYPE_INTEGER32, "Enum32 test" };
+			struct dict_enumval_data val1 = { "i32 const test (val 1)", { .i32 = 1 } };
+			struct dict_enumval_data val2 = { "i32 const test (val 2)", { .i32 = 2 } };
+			struct dict_enumval_data val3 = { "i32 const test (val -5)",{ .i32 = -5 } };
+			struct dict_avp_data     avp_data = { 73569, 73565, "AVP Test - enumi32", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_INTEGER32 };
+			
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val1 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val2 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val3 , type, NULL ) );
+		}
+			
+		{ 
+			struct dict_object  * type = NULL;
+			struct dict_type_data type_data = { AVP_TYPE_OCTETSTRING, "OS test" };
+			struct dict_avp_data  avp_data = { 73570, 73565, "AVP Test - os", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_OCTETSTRING };
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) );
+		}
+		
+		{
+			struct dict_object     * type = NULL;
+			struct dict_type_data    type_data = { AVP_TYPE_OCTETSTRING, "OS enum test" };
+			struct dict_enumval_data val1 = { "os const test (Test)", { .os = { (unsigned char *)"Test", 4 } } };
+			struct dict_enumval_data val2 = { "os const test (waaad)", { .os = { (unsigned char *)"waaad", 5 } } };
+			struct dict_enumval_data val3 = { "os const test (waa)", { .os = { (unsigned char *)"waaad", 3 } } };
+			struct dict_avp_data     avp_data = { 73571, 73565, "AVP Test - enumos", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_OCTETSTRING };
+			
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val1 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val2 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_ENUMVAL, &val3 , type, NULL ) );
+		}
+		
+		{
+			struct dict_object * gavp = NULL;
+			struct dict_avp_data avp_data = { 73572, 73565, "AVP Test - grouped", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_GROUPED };
+			
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, &gavp ) );
+			
+			/* Macro to search AVP and create a rule */		
+			#define ADD_RULE( _parent, _vendor, _avpname, _pos, _min, _max, _ord ) {		\
+				struct dict_object * _avp = NULL;						\
+				struct dict_avp_request _req = { (_vendor), 0, (_avpname) };			\
+				struct dict_rule_data _data;							\
+				CHECK( 0, fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));\
+				_data.rule_avp = _avp;								\
+				_data.rule_position = (_pos);							\
+				_data.rule_order = (_ord);							\
+				_data.rule_min = (_min);							\
+				_data.rule_max = (_max);							\
+				CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_RULE, &_data , (_parent), NULL ) );	\
+			}
+			
+			ADD_RULE(gavp, 73565, "AVP Test - os", RULE_OPTIONAL,   -1, -1,  0);
+			
+		}
+			
+		{
+			struct dict_object  * application = NULL;
+			struct dict_object  * command = NULL;
+			struct dict_cmd_data  cmd_data = { 73573, "Test-Command-Request", CMD_FLAG_REQUEST, CMD_FLAG_REQUEST };
+			
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Application test", &application, ENOENT ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_COMMAND, &cmd_data , application, &command ) );
+			ADD_RULE(command, 0,     "AVP Test - no vendor - f32", 	RULE_FIXED_HEAD, -1,  1,  1);
+			ADD_RULE(command, 73565, "AVP Test - i64",		RULE_REQUIRED,   -1, -1,  0);
+			ADD_RULE(command, 73565, "AVP Test - enumi32", 		RULE_OPTIONAL,   -1, -1,  0);
+			ADD_RULE(command, 73565, "AVP Test - os", 		RULE_OPTIONAL,   -1, -1,  0);
+			ADD_RULE(command, 73565, "AVP Test - enumos", 		RULE_OPTIONAL,   -1, -1,  0);
+			ADD_RULE(command, 73565, "AVP Test - grouped", 		RULE_OPTIONAL,   -1, -1,  0);
+		}
+		
+		{
+			struct dict_object  * application = NULL;
+			struct dict_object  * command = NULL;
+			struct dict_cmd_data  cmd_data = { 73573, "Test-Command-Answer", CMD_FLAG_REQUEST, 0 };
+			
+			CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Application test", &application, ENOENT ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_COMMAND, &cmd_data , application, &command ) );
+		}
+		
+		{
+			struct dict_object  * gavp = NULL;
+			struct dict_avp_data  avp_data = { 73574, 73565, "AVP Test - rules", AVP_FLAG_VENDOR, AVP_FLAG_VENDOR, AVP_TYPE_GROUPED };
+			
+			CHECK( 0, fd_dict_new ( fd_g_config->cnf_dict, DICT_AVP, &avp_data , NULL, &gavp ) );
+			
+			ADD_RULE(gavp,     0, "AVP Test - no vendor - f32", RULE_FIXED_HEAD,   0, 1, 1);
+			ADD_RULE(gavp, 73565, "AVP Test - i64", 	    RULE_FIXED_HEAD,  -1, 1, 2);
+			ADD_RULE(gavp, 73565, "AVP Test - enumi32", 	    RULE_FIXED_HEAD,  -1, 1, 3);
+			ADD_RULE(gavp, 73565, "AVP Test - os", 	    	    RULE_REQUIRED,     2, 3, 0);
+			ADD_RULE(gavp, 73565, "AVP Test - enumos",     	    RULE_OPTIONAL,     0, 1, 0);
+			ADD_RULE(gavp, 73565, "AVP Test - grouped",         RULE_FIXED_TAIL,  -1, 1, 1);
+			/* ABNF : 
+				< no vendor - f32 >
+				< i64 >
+				< enumi32 >
+			    2*3 { os }
+			     *1 [ enumos ]
+				< grouped >
+						*/
+			#if 0
+			fd_dict_dump_object ( gavp );
+			#endif
+		}
+		#if 0
+		{
+			fd_dict_dump_object ( vendor );
+		}
+		#endif
+	}
+	
+	/* Now create some values and check the length is correctly handled */
+	{
+		struct dict_object * cmd_model = NULL;
+		struct msg         * msg = NULL;
+		struct dict_object * avp_model = NULL;
+		struct avp         * avp = NULL;
+		union avp_value      value;
+		
+		CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Test-Command-Request", &cmd_model, ENOENT ) );
+		
+		/* Check the sizes are handled properly */
+		{
+			struct avp * avpi = NULL;
+			struct avp * avpch = NULL;
+			struct avp_hdr * avpdata = NULL;
+			struct msg_hdr * msgdata = NULL;
+			#define ADD_AVP( _parent, _position, _avpi, _avpvendor, _avpname) {			\
+				struct dict_object * _avp = NULL;						\
+				struct dict_avp_request _req = { (_avpvendor), 0, (_avpname) };			\
+				CHECK( 0, fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));\
+				CHECK( 0, fd_msg_avp_new ( _avp, 0, &_avpi ) );					\
+				CHECK( 0, fd_msg_avp_add ( (_parent), (_position), _avpi ) );			\
+			}
+			/* Create a message with many AVP inside */
+			CHECK( 0, fd_msg_new ( cmd_model, 0, &msg ) );
+			CHECK( 0, fd_msg_hdr ( msg, &msgdata ) );
+			
+			/* Avp no vendor, float32 => size = 12 */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 0,     "AVP Test - no vendor - f32" );
+			value.f32 = 3.1415;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+			
+			/* Add a vendor AVP, integer64 => size = 20 */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - i64" );
+			value.i64 = 0x123456789abcdeLL;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+			
+			/* Add an AVP with an enum value */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumi32" );
+			{
+				struct dict_object * type_model = NULL;
+				struct dict_object * value_model = NULL;
+				struct dict_enumval_request request;
+				
+				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				memset(&request, 0, sizeof(request));
+				request.type_obj = type_model;
+				request.search.enum_name = "i32 const test (val 2)";
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_getval ( value_model, &request.search ) );
+				CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) );
+			}
+			
+			/* Add an AVP with an enum value, negative */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumi32" );
+			{
+				struct dict_object  * type_model = NULL;
+				struct dict_object  * value_model = NULL;
+				struct dict_enumval_request request;
+				
+				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				memset(&request, 0, sizeof(request));
+				request.type_obj = type_model;
+				request.search.enum_name = "i32 const test (val -5)";
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_getval ( value_model, &request.search ) );
+				CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) );
+			}
+			
+			/* Now add a value which is not a constant into an enumerated AVP */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumi32" );
+			value.i32 = -10;
+			CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+			
+			/* Add an octetstring AVP */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - os" );
+			{
+				unsigned char buf[90];
+				memcpy(&buf, "This\0 is a buffer of dat\a. It is not a string so we can have any c\0ntr\0l character here...\0\0", 89);
+				value.os.data = buf;
+				value.os.len = 89;
+				CHECK( 0, fd_msg_avp_setvalue ( avpi, &value ) );
+				memset(&buf, 0, sizeof(buf)); /* Test that the OS value is really copied */
+			}
+
+			/* Add an octetstring from an enumerated constant */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumos" );
+			{
+				struct dict_object  * type_model = NULL;
+				struct dict_object  * value_model = NULL;
+				struct dict_enumval_request request;
+				
+				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				memset(&request, 0, sizeof(request));
+				request.type_obj = type_model;
+				request.search.enum_name = "os const test (waaad)";
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_getval ( value_model, &request.search ) );
+				CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) );
+			}
+				
+			/* Add an octetstring from an enumerated constant */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - enumos" );
+			{
+				struct dict_object  * type_model = NULL;
+				struct dict_object  * value_model = NULL;
+				struct dict_enumval_request request;
+				
+				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				memset(&request, 0, sizeof(request));
+				request.type_obj = type_model;
+				request.search.enum_name = "os const test (waa)";
+				CHECK( 0, fd_dict_search ( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_getval ( value_model, &request.search ) );
+				CHECK( 0, fd_msg_avp_setvalue ( avpi, &request.search.enum_value ) );
+			}
+				
+			/* Now test the grouped AVPs */	
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - grouped" );
+			  ADD_AVP( avpi, MSG_BRW_LAST_CHILD, avpch, 73565, "AVP Test - os" );
+			  {
+				value.os.data = (unsigned char *)"12345678";
+				value.os.len = 8;
+				CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) );
+			  }
+			  ADD_AVP( avpi, MSG_BRW_LAST_CHILD, avpch, 73565, "AVP Test - os" );
+			  {
+				value.os.data = (unsigned char *)"123456789";
+				value.os.len = 9;
+				CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) );
+			  }
+			
+			/* Add another similar grouped AVP, to have lot of padding */
+			ADD_AVP( msg, MSG_BRW_LAST_CHILD, avpi, 73565, "AVP Test - grouped" );
+			  ADD_AVP( avpi, MSG_BRW_LAST_CHILD, avpch, 73565, "AVP Test - os" );
+			  {
+				value.os.data = (unsigned char *)"1";
+				value.os.len = 1;
+				CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) );
+			  }
+			  ADD_AVP( avpi, MSG_BRW_LAST_CHILD, avpch, 73565, "AVP Test - os" );
+			  {
+				value.os.data = (unsigned char *)"1234567";
+				value.os.len = 7;
+				CHECK( 0, fd_msg_avp_setvalue ( avpch, &value ) );
+			  }
+			
+			/* Set the application to the test application: 73566 */
+			msgdata->msg_appl = 73566;
+			
+			/* Set the hop-by-hop ID to a random value: 0x4b44b41d */
+			msgdata->msg_hbhid = 0x4b44b41d;
+			/* Set the end-to-end ID to a random value: 0xe2ee2e1d */
+			msgdata->msg_eteid = 0xe2ee2e1d;
+		}
+		
+		CHECK( 0, fd_msg_bufferize( msg, &buf, NULL ) );
+		
+		/* Now free the message, we keep only the buffer. */
+		CHECK( 0, fd_msg_free( msg ) );
+		
+	}
+	
+	/* We have our "buf" now, length is 344 -- cf. testmesg.c. */
+	
+	/* Test the throughput of the different functions function */
+	{
+		void ** stress_array;
+		int i;
+		struct timespec start, end;
+		
+		unsigned char * buf_cpy = NULL;
+		struct msg * msg;
+		
+		#define CPYBUF() {			\
+			buf_cpy = malloc(344);		\
+			CHECK( buf_cpy ? 1 : 0, 1);	\
+			memcpy(buf_cpy, buf, 344);	\
+		}
+		
+		/* Create the copies of the message buffer */
+		stress_array = calloc(NUMBER_OF_SAMPLES, sizeof(void *));
+		CHECK( stress_array ? 1 : 0, 1);
+		
+		for (i=0; i < NUMBER_OF_SAMPLES; i++) {
+			CPYBUF();
+			stress_array[i] = buf_cpy;
+		}
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) );
+		
+		/* Test the msg_parse_buffer function */
+		for (i=0; i < NUMBER_OF_SAMPLES; i++) {
+			CHECK( 0, fd_msg_parse_buffer( (uint8_t **)&stress_array[i], 344, &msg) );
+			stress_array[i] = msg;
+		}
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) );
+		
+		{
+			long us = (end.tv_sec - start.tv_sec) * 1000000;
+			us += (end.tv_nsec - start.tv_nsec) / 1000;
+			long double thrp = (NUMBER_OF_SAMPLES * (long double)1000000) / us;
+			printf("fd_msg_bufferize  : %d buffers  parsed in %ldus (%.2LFmsg/s)\n", NUMBER_OF_SAMPLES, us, thrp);
+		}
+		
+		
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) );
+		
+		/* Test the fd_msg_parse_dict function */
+		for (i=0; i < NUMBER_OF_SAMPLES; i++) {
+			CHECK( 0, fd_msg_parse_dict( stress_array[i], fd_g_config->cnf_dict, NULL ) );
+		}
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) );
+		
+		{
+			long us = (end.tv_sec - start.tv_sec) * 1000000;
+			us += (end.tv_nsec - start.tv_nsec) / 1000;
+			long double thrp = (NUMBER_OF_SAMPLES * (long double)1000000) / us;
+			printf("fd_msg_parse_dict : %d messages parsed in %ldus (%.2LFmsg/s)\n", NUMBER_OF_SAMPLES, us, thrp);
+		}
+		
+		
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) );
+		
+		/* Test the fd_msg_parse_rules function */
+		for (i=0; i < NUMBER_OF_SAMPLES; i++) {
+			CHECK( 0, fd_msg_parse_rules( stress_array[i], fd_g_config->cnf_dict, NULL ) );
+		}
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) );
+		
+		{
+			long us = (end.tv_sec - start.tv_sec) * 1000000;
+			us += (end.tv_nsec - start.tv_nsec) / 1000;
+			long double thrp = (NUMBER_OF_SAMPLES * (long double)1000000) / us;
+			printf("fd_msg_parse_rules: %d messages parsed in %ldus (%.2LFmsg/s)\n", NUMBER_OF_SAMPLES, us, thrp);
+		}
+		
+		
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &start) );
+		
+		/* Free those messages */
+		for (i=0; i < NUMBER_OF_SAMPLES; i++) {
+			fd_msg_free( stress_array[i]);
+			stress_array[i] = NULL;
+		}
+		
+		CHECK( 0, clock_gettime(CLOCK_REALTIME, &end) );
+		
+		{
+			long us = (end.tv_sec - start.tv_sec) * 1000000;
+			us += (end.tv_nsec - start.tv_nsec) / 1000;
+			long double thrp = (NUMBER_OF_SAMPLES * (long double)1000000) / us;
+			printf("fd_msg_free       : %d messages freed  in %ldus (%.2LFmsg/s)\n", NUMBER_OF_SAMPLES, us, thrp);
+		}
+		
+		free(stress_array);
+	}
+		
+	
+	/* That's all for the tests yet */
+	PASSTEST();
+} 
+	
"Welcome to our mercurial repository"