changeset 8:3e143f047f78

Backup for the week-end
author Sebastien Decugis <sdecugis@nict.go.jp>
date Fri, 18 Sep 2009 18:54:07 +0900
parents e5af94b04946
children fc7c18867cf7
files CMakeLists.txt cmake/Modules/FindGNUTLS.cmake cmake/Modules/FindSCTP.cmake cmake/Modules/LibFindMacros.cmake doc/freediameter.conf.sample extensions/CMakeLists.txt extensions/_sample/CMakeLists.txt extensions/_sample/fini.c extensions/_sample/sample.c freeDiameter/CMakeLists.txt freeDiameter/config.c freeDiameter/extensions.c freeDiameter/fD.h freeDiameter/fdd.l freeDiameter/fdd.y freeDiameter/main.c freeDiameter/tests/CMakeLists.txt freeDiameter/tests/testdict.c freeDiameter/tests/testdisp.c freeDiameter/tests/testmesg.c freeDiameter/tests/testmq.c freeDiameter/tests/testqueues.c freeDiameter/tests/tests.h include/freeDiameter/CMakeLists.txt include/freeDiameter/extension.h include/freeDiameter/freeDiameter-host.h.in include/freeDiameter/freeDiameter.h include/freeDiameter/libfreeDiameter.h libfreeDiameter/CMakeLists.txt libfreeDiameter/mqueues.c libfreeDiameter/queues.c
diffstat 31 files changed, 2549 insertions(+), 1140 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Fri Sep 04 18:05:25 2009 +0900
+++ b/CMakeLists.txt	Fri Sep 18 18:54:07 2009 +0900
@@ -3,6 +3,14 @@
 # Name of the project, and language
 PROJECT("freeDiameter" C)
 
+# Informations to display in daemon's help
+SET(FD_PROJECT_NAME freeDiameter)
+SET(FD_PROJECT_BINARY freeDiameterd)
+SET(FD_PROJECT_VERSION_MAJOR 0)
+SET(FD_PROJECT_VERSION_MINOR 1)
+SET(FD_PROJECT_VERSION_REV 0)
+SET(FD_PROJECT_COPYRIGHT "Copyright (c) 2008-2009, WIDE Project (www.wide.ad.jp) and NICT (www.nict.go.jp)")
+
 # Some subfolders may have tests
 ENABLE_TESTING()
 
@@ -15,11 +23,6 @@
 # All source code should be POSIX 200112L compatible, but some other extensions might be used, so:
 ADD_DEFINITIONS(-D_GNU_SOURCE)
 
-# Location for the include files
-INCLUDE_DIRECTORIES(include)
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/include)
-SUBDIRS(include/freeDiameter)
-
 # some subfolders use yacc and lex parsers
 SET(BISON_GENERATE_DEFINES TRUE)
 SET(BISON_PREFIX_OUTPUTS TRUE)
@@ -32,6 +35,11 @@
 # Check that flex is at least 2.5.20 to support bison-bridge
 # how to do the check with cmake???
 
+# Location for the include files
+INCLUDE_DIRECTORIES(include)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/include)
+SUBDIRS(include/freeDiameter)
+
 # Location for the source code
 SUBDIRS(libfreeDiameter)
 SUBDIRS(freeDiameter)
--- a/cmake/Modules/FindGNUTLS.cmake	Fri Sep 04 18:05:25 2009 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-# - Try to find GNU TLS library and headers
-# Once done, this will define
-#
-#  GNUTLS_FOUND - system has GNU TLS
-#  GNUTLS_INCLUDE_DIRS - the GNU TLS include directories
-#  GNUTLS_LIBRARIES - link these to use GNU TLS
-
-include(LibFindMacros)
-
-# Use pkg-config to get hints about paths
-libfind_pkg_check_modules(GNUTLS_PKGCONF gnutls)
-
-# Include dir
-find_path(GNUTLS_INCLUDE_DIR
-  NAMES gnutls/gnutls.h
-  PATHS ${GNUTLS_PKGCONF_INCLUDE_DIRS}
-)
-
-# Finally the library itself
-find_library(GNUTLS_LIBRARY
-  NAMES gnutls
-  PATHS ${GNUTLS_PKGCONF_LIBRARY_DIRS}
-)
-
-# Set the include dir variables and the libraries and let libfind_process do the rest.
-# NOTE: Singular variables for this library, plural for libraries this this lib depends on.
-set(GNUTLS_PROCESS_INCLUDES GNUTLS_INCLUDE_DIR)
-set(GNUTLS_PROCESS_LIBS GNUTLS_LIBRARY)
-libfind_process(GNUTLS)
--- a/cmake/Modules/FindSCTP.cmake	Fri Sep 04 18:05:25 2009 +0900
+++ b/cmake/Modules/FindSCTP.cmake	Fri Sep 18 18:54:07 2009 +0900
@@ -5,25 +5,42 @@
 #  SCTP_INCLUDE_DIRS - the SCTP include directories
 #  SCTP_LIBRARIES - link these to use SCTP
 
-include(LibFindMacros)
-
-# Use pkg-config to get hints about paths (Note: not yet supported?)
-# libfind_pkg_check_modules(SCTP_PKGCONF sctp)
+if (SCTP_INCLUDE_DIRS)
+  set(SCTP_FIND_QUIETLY TRUE)
+endif (SCTP_INCLUDE_DIRS)
 
 # Include dir
 find_path(SCTP_INCLUDE_DIR
   NAMES netinet/sctp.h
-  PATHS ${SCTP_PKGCONF_INCLUDE_DIRS}
 )
 
-# Finally the library itself
+# Library
 find_library(SCTP_LIBRARY
   NAMES sctp
-  PATHS ${SCTP_PKGCONF_LIBRARY_DIRS}
 )
 
 # Set the include dir variables and the libraries and let libfind_process do the rest.
 # NOTE: Singular variables for this library, plural for libraries this this lib depends on.
-set(SCTP_PROCESS_INCLUDES SCTP_INCLUDE_DIR)
-set(SCTP_PROCESS_LIBS SCTP_LIBRARY)
-libfind_process(SCTP)
+#set(SCTP_PROCESS_INCLUDES SCTP_INCLUDE_DIR)
+#set(SCTP_PROCESS_LIBS SCTP_LIBRARY)
+#libfind_process(SCTP)
+
+
+# handle the QUIETLY and REQUIRED arguments and set SCTP_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SCTP DEFAULT_MSG SCTP_LIBRARY SCTP_INCLUDE_DIR)
+
+# If we successfully found the sctp library then add the library to the
+# SCTP_LIBRARIES cmake variable otherwise set SCTP_LIBRARIES to nothing.
+IF(SCTP_FOUND)
+   SET( SCTP_LIBRARIES ${SCTP_LIBRARY} )
+ELSE(SCTP_FOUND)
+   SET( SCTP_LIBRARIES )
+ENDIF(SCTP_FOUND)
+
+
+# Lastly make it so that the SCTP_LIBRARY and SCTP_INCLUDE_DIR variables
+# only show up under the advanced options in the gui cmake applications.
+MARK_AS_ADVANCED( SCTP_LIBRARY SCTP_INCLUDE_DIR )
+
--- a/cmake/Modules/LibFindMacros.cmake	Fri Sep 04 18:05:25 2009 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-# Works the same as find_package, but forwards the "REQUIRED" and "QUIET" arguments
-# used for the current package. For this to work, the first parameter must be the
-# prefix of the current package, then the prefix of the new package etc, which are
-# passed to find_package.
-macro (libfind_package PREFIX)
-  set (LIBFIND_PACKAGE_ARGS ${ARGN})
-  if (${PREFIX}_FIND_QUIETLY)
-    set (LIBFIND_PACKAGE_ARGS ${LIBFIND_PACKAGE_ARGS} QUIET)
-  endif (${PREFIX}_FIND_QUIETLY)
-  if (${PREFIX}_FIND_REQUIRED)
-    set (LIBFIND_PACKAGE_ARGS ${LIBFIND_PACKAGE_ARGS} REQUIRED)
-  endif (${PREFIX}_FIND_REQUIRED)
-  find_package(${LIBFIND_PACKAGE_ARGS})
-endmacro (libfind_package)
-
-# Damn CMake developers made the UsePkgConfig system deprecated in the same release (2.6)
-# where they added pkg_check_modules. Consequently I need to support both in my scripts
-# to avoid those deprecated warnings. Here's a helper that does just that.
-# Works identically to pkg_check_modules, except that no checks are needed prior to use.
-macro (libfind_pkg_check_modules PREFIX PKGNAME)
-  if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
-    include(UsePkgConfig)
-    pkgconfig(${PKGNAME} ${PREFIX}_INCLUDE_DIRS ${PREFIX}_LIBRARY_DIRS ${PREFIX}_LDFLAGS ${PREFIX}_CFLAGS)
-  else (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
-    find_package(PkgConfig)
-    if (PKG_CONFIG_FOUND)
-      pkg_check_modules(${PREFIX} ${PKGNAME})
-    endif (PKG_CONFIG_FOUND)
-  endif (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
-endmacro (libfind_pkg_check_modules)
-
-# Do the final processing once the paths have been detected.
-# If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain
-# all the variables, each of which contain one include directory.
-# Ditto for ${PREFIX}_PROCESS_LIBS and library files.
-# Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES.
-# Also handles errors in case library detection was required, etc.
-macro (libfind_process PREFIX)
-  # Skip processing if already processed during this run
-  if (NOT ${PREFIX}_FOUND)
-    # Start with the assumption that the library was found
-    set (${PREFIX}_FOUND TRUE)
-
-    # Process all includes and set _FOUND to false if any are missing
-    foreach (i ${${PREFIX}_PROCESS_INCLUDES})
-      if (${i})
-        set (${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIRS} ${${i}})
-        mark_as_advanced(${i})
-      else (${i})
-        set (${PREFIX}_FOUND FALSE)
-      endif (${i})
-    endforeach (i)
-
-    # Process all libraries and set _FOUND to false if any are missing
-    foreach (i ${${PREFIX}_PROCESS_LIBS})
-      if (${i})
-        set (${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARIES} ${${i}})
-        mark_as_advanced(${i})
-      else (${i})
-        set (${PREFIX}_FOUND FALSE)
-      endif (${i})
-    endforeach (i)
-
-    # Print message and/or exit on fatal error
-    if (${PREFIX}_FOUND)
-      if (NOT ${PREFIX}_FIND_QUIETLY)
-        message (STATUS "Found ${PREFIX} ${${PREFIX}_VERSION}")
-      endif (NOT ${PREFIX}_FIND_QUIETLY)
-    else (${PREFIX}_FOUND)
-      if (${PREFIX}_FIND_REQUIRED)
-        foreach (i ${${PREFIX}_PROCESS_INCLUDES} ${${PREFIX}_PROCESS_LIBS})
-          message("${i}=${${i}}")
-        endforeach (i)
-        message (FATAL_ERROR "Required library ${PREFIX} NOT FOUND.\nInstall the library (dev version) and try again. If the library is already installed, use ccmake to set the missing variables manually.")
-      endif (${PREFIX}_FIND_REQUIRED)
-    endif (${PREFIX}_FOUND)
-  endif (NOT ${PREFIX}_FOUND)
-endmacro (libfind_process)
-
-macro(libfind_library PREFIX basename)
-  set(TMP "")
-  if(MSVC80)
-    set(TMP -vc80)
-  endif(MSVC80)
-  if(MSVC90)
-    set(TMP -vc90)
-  endif(MSVC90)
-  set(${PREFIX}_LIBNAMES ${basename}${TMP})
-  if(${ARGC} GREATER 2)
-    set(${PREFIX}_LIBNAMES ${basename}${TMP}-${ARGV2})
-    string(REGEX REPLACE "\\." "_" TMP ${${PREFIX}_LIBNAMES})
-    set(${PREFIX}_LIBNAMES ${${PREFIX}_LIBNAMES} ${TMP})
-  endif(${ARGC} GREATER 2)
-  find_library(${PREFIX}_LIBRARY
-    NAMES ${${PREFIX}_LIBNAMES}
-    PATHS ${${PREFIX}_PKGCONF_LIBRARY_DIRS}
-  )
-endmacro(libfind_library)
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/freediameter.conf.sample	Fri Sep 18 18:54:07 2009 +0900
@@ -0,0 +1,132 @@
+# This is a sample configuration file for freeDiameter daemon.
+
+##############################################################
+##  Peer identity and realm 
+
+# The Diameter Identity of this daemon.
+# This must be a valid FQDN that resolves to the local host.
+# Default: hostname's FQDN
+#LocalIdentity = "aaa.koganei.wide.ad.jp";
+
+# The Diameter Realm of this daemon.
+# Default: the domain part of LocalIdentity.
+#LocalRealm = "wide.ad.jp";
+
+##############################################################
+##  Transport protocol configuration
+
+# The port this peer is listening on for incoming connections (TCP and SCTP).
+# Default: 3868
+#LocalPort = 3868;
+
+# The port this peer is listening on for incoming TLS connections (TCP and SCTP).
+# See TLS_old_method for more information.
+# Default: 3869
+#LocalSecPort = 3869;
+
+# Use RFC3588 method for TLS protection, where TLS is negociated after CER/CEA
+# on the same port. This only affects outgoing connections. It can be overwritten
+# on per peer basis.
+# Default: use RFC3588bis method with separate port for TLS.
+#TLS_old_method;
+
+# Disable use of TCP protocol (only SCTP)
+# Default : TCP enabled
+#No_TCP;
+
+# Disable use of SCTP protocol (only TCP)
+# Default : SCTP enabled
+#No_SCTP;
+# This option has no effect if freeDiameter is compiled with DISABLE_SCTP option,
+# in which case the value is forced to "SCTP disabled".
+
+# Prefer TCP over SCTP for establishing new connections.
+# It may be overwritten per peer in peer configuration blocs.
+# Default : SCTP is prefered.
+#Prefer_TCP;
+
+# Default number of streams per SCTP associations.
+# It can be overwritten per peer basis.
+# Default : 30 streams
+#SCTP_streams = 30;
+
+##############################################################
+##  Endpoints configuration
+
+# Disable use of IP addresses (only IPv6)
+# Default : IP enabled
+#No_IP;
+
+# Disable use of IPv6 addresses (only IP)
+# Default : IPv6 enabled
+#No_IPv6;
+
+# Specify local addresses where the server must listen
+# Default : listen on all addresses available.
+#ListenOn = "202.249.37.5";
+#ListenOn = "2001:200:903:2::202:1";
+
+##############################################################
+##  Timers configuration
+
+# The Tc timer of this peer.
+# It is the delay before a new attempt is made to reconnect a disconnected peer.
+# The value is expressed in seconds. The recommended value is 30 seconds.
+# Default: 30
+#TcTimer = 30;
+
+# The Tw timer of this peer.
+# It is the delay before a watchdog message is sent, as described in RFC 3539.
+# The value is expressed in seconds. The default value is 30 seconds. Value must
+# be greater or equal to 6 seconds. See details in the RFC.
+# Default: 30
+#TwTimer = 30;
+
+##############################################################
+##  Applications configuration
+
+# Disable the relaying of Diameter messages?
+# For messages not handled locally, the default behavior is to forward the
+# message to another peer if any is available, according to the routing 
+# algorithms. In addition the "0xffffff" application is advertised in CER/CEA 
+# exchanges.
+# Default: Relaying is enabled.
+#NoRelay;
+
+# Other applications are configured by extensions.
+
+##############################################################
+##  Extensions configuration
+
+#  The freeDiameter daemon merely provides support for
+# Diameter Base Protocol. The specific application behaviors,
+# as well as advanced functions of the daemon, are provided
+# by loadable extensions (plug-ins).
+#  These extensions may in addition receive the name of a 
+# configuration file, the format of which is extension-specific.
+
+# Format:
+#LoadExtension = "/path/to/extension" [ : "/optional/configuration/file" ] ;
+# Exemples:
+#LoadExtension = "extensions/sample.so";
+#LoadExtension = "extensions/sample.so":"conf/sample.conf";
+
+
+
+##############################################################
+# -------- Test configuration ---------
+LocalIdentity = "aaa.koganei.wide.ad.jp";
+LocalRealm = "wide.ad.jp";
+LocalPort = 3866;
+LocalSecPort = 3867;
+TLS_old_method;
+No_IP;
+Prefer_TCP;
+SCTP_streams = 50;
+ListenOn = "202.249.37.5";
+ListenOn = "2001:200:903:2::202:1";
+TcTimer = 60;
+TwTimer = 6;
+NoRelay;
+LoadExtension = "extensions/sample.so";
+LoadExtension = "extensions/sample.so":"conf/sample.conf";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/CMakeLists.txt	Fri Sep 18 18:54:07 2009 +0900
@@ -0,0 +1,75 @@
+PROJECT("freeDiameter extensions" C)
+
+# We want all resulting objects in the same folder
+SET(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR})
+# And named fdext_XXX instead of libXXX.so
+
+#-- faire une macro ici!
+SET(FD_EXT_PREFIX "fdext_" PARENT_SCOPE)
+SET(FD_EXT_SUFFIX "" PARENT_SCOPE)
+
+###########################
+# Extensions section
+
+####
+# Diameter applications dictionary
+# OPTION(BUILD_DICT_NASREQ "Build NASREQ (RFC4005) Dictionary definitions?" ON)
+# 	IF (BUILD_DICT_NASREQ)
+# 	   SUBDIRS(dict_nasreq)
+# 	ENDIF (BUILD_DICT_NASREQ)
+
+# OPTION(BUILD_DICT_EAP "Build Diameter EAP (RFC4072) Dictionary definitions?" ON)
+# 	IF (BUILD_DICT_EAP)
+# 	   SUBDIRS(dict_eap)
+# 	ENDIF (BUILD_DICT_EAP)
+
+
+
+####
+# Radius / Diameter gateway extension(s)
+# OPTION(BUILD_RADIUS_GW "Build radius_gw? (one-way RADIUS/Diameter gateway - RADIUS NAS <-> Diameter server)" ON)
+# 	IF (BUILD_RADIUS_GW)
+# 	   SUBDIRS(radius_gw)
+# 	ENDIF (BUILD_RADIUS_GW)
+
+
+####
+# Routing extensions
+
+# OPTION(BUILD_RT_DEFAULT "Build rt_default? (Routing extension using Destination-Host, Destination-Realm, and static configuration)" ON)
+# 	IF (BUILD_RT_DEFAULT)
+# 	   SUBDIRS(rt_default)
+# 	ENDIF (BUILD_RT_DEFAULT)
+
+
+####
+# Peers security extensions
+
+# OPTION(BUILD_PS_DEFAULT "Build ps_default? (white-list of peers)" ON)
+# 	IF (BUILD_PS_DEFAULT)
+# # -- enable once API is updated:	   SUBDIRS(ps_default)
+# 	ENDIF (BUILD_PS_DEFAULT)
+
+
+####
+# Debug / development extensions
+
+OPTION(BUILD_SAMPLE "Build sample? (Simple extension to demonstrate extension mechanism, for developpers only)" OFF)
+	IF (BUILD_SAMPLE)
+	   SUBDIRS(_sample)
+	ENDIF (BUILD_SAMPLE)
+
+# OPTION(BUILD_RT_ANY "Build rt_any? (Routing extension sending message to any peer available, for testing purpose only)" OFF)
+# 	IF (BUILD_RT_ANY)
+# 	   SUBDIRS(rt_any)
+# 	ENDIF (BUILD_RT_ANY)
+
+# OPTION(BUILD_RT_DEBUG "Build rt_debug? (Routing extension tracing routing list, for debug purpose only)" OFF)
+# 	IF (BUILD_RT_DEBUG)
+# 	   SUBDIRS(rt_debug)
+# 	ENDIF (BUILD_RT_DEBUG)
+
+# OPTION(BUILD_APP_TEST "Build app_test? (Testing application to send dummy message to another peer, for testing purpose only)" OFF)
+# 	IF (BUILD_APP_TEST)
+# 	   SUBDIRS(app_test)
+# 	ENDIF (BUILD_APP_TEST)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/_sample/CMakeLists.txt	Fri Sep 18 18:54:07 2009 +0900
@@ -0,0 +1,9 @@
+# The sample extension
+PROJECT("Sample extension" C)
+
+# Compile as a module
+ADD_LIBRARY(sample MODULE sample.c fini.c)
+
+# Comply to naming scheme
+SET_TARGET_PROPERTIES(sample PROPERTIES PREFIX "${FD_EXT_PREFIX}" )
+SET_TARGET_PROPERTIES(sample PROPERTIES SUFFIX "${FD_EXT_SUFFIX}" )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/_sample/fini.c	Fri Sep 18 18:54:07 2009 +0900
@@ -0,0 +1,45 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2008, 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.								 *
+*********************************************************************************************************/
+
+/* Sample extension exit point */
+
+#include <freeDiameter/extension.h>
+
+void fd_ext_fini(void)
+{
+	log_debug("Extension is terminated... Bye!\n");
+	return ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/extensions/_sample/sample.c	Fri Sep 18 18:54:07 2009 +0900
@@ -0,0 +1,84 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2009, 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.								 *
+*********************************************************************************************************/
+
+/* Sample extension to test extensions mechanism in freeDiameter */
+#include <freeDiameter/extension.h>
+
+static int sample_main(char * conffile);
+
+/* Define the entry point. A convenience macro is provided */
+EXTENSION_ENTRY("sample", sample_main);
+
+/* The extension-specific initialization code */
+static int sample_main(char * conffile)
+{
+	TRACE_ENTRY("%p", conffile);
+	
+	fprintf(stdout, "I am extension " __FILE__ " running on host %s\n", fd_g_config->diam_id);
+	
+	if (conffile) {
+		fprintf(stdout, "I should parse my configuration file there: %s\n", conffile);
+	} else {
+		fprintf(stdout, "I received no configuration file to parse\n");
+	}
+	
+	/* Use the dictionary for test */
+	log_debug("Let's create that 'Example-AVP'...\n");
+	{
+		struct dict_object * origin_host_avp = NULL;
+		struct dict_object * session_id_avp = NULL;
+		struct dict_object * example_avp_avp = NULL;
+		struct dict_rule_data rule_data = { NULL, RULE_REQUIRED, 0, -1, 1 };
+		struct dict_avp_data example_avp_data = { 999999, 0, "Example-AVP", AVP_FLAG_VENDOR , 0, AVP_TYPE_GROUPED };
+
+		CHECK_FCT( fd_dict_search ( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &origin_host_avp, ENOENT));
+		CHECK_FCT( fd_dict_search ( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &session_id_avp, ENOENT));
+		
+		CHECK_FCT( fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &example_avp_data , NULL, &example_avp_avp ));
+		
+		rule_data.rule_avp = origin_host_avp;
+		rule_data.rule_min = 1;
+		rule_data.rule_max = 1;
+		CHECK_FCT( fd_dict_new ( fd_g_config->g_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ));
+		
+		rule_data.rule_avp = session_id_avp;
+		rule_data.rule_min = 1;
+		rule_data.rule_max = -1;
+		CHECK_FCT( fd_dict_new ( fd_g_config->g_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ));
+	}
+	log_debug("'Example-AVP' created without error\n");
+	
+	return 0;
+}
--- a/freeDiameter/CMakeLists.txt	Fri Sep 04 18:05:25 2009 +0900
+++ b/freeDiameter/CMakeLists.txt	Fri Sep 18 18:54:07 2009 +0900
@@ -1,17 +1,28 @@
 # The subproject name
 Project("freeDiameterd" C)
 
-SET(PROJECT_VERSION 0.1)
-SET(PROJECT_COPYRIGHT "Copyright (c) 2008-2009, WIDE Project (www.wide.ad.jp) and NICT (www.nict.go.jp)")
+# Configuration parser
+BISON_FILE(fdd.y)
+FLEX_FILE(fdd.l)
+SET_SOURCE_FILES_PROPERTIES(lex.fdd.c fdd.tab.c PROPERTIES COMPILE_FLAGS "-I ${CMAKE_CURRENT_SOURCE_DIR}")
 
 # List of source files
 SET(FD_COMMON_SRC
 	fD.h
+	config.c
+	extensions.c
 	dict_base_proto.c
 	)
 
+SET(FD_COMMON_GEN_SRC
+		lex.fdd.c
+		fdd.tab.c
+		fdd.tab.h
+	)
+
+
 # Building the executable
-ADD_EXECUTABLE(freeDiameterd ${FD_COMMON_SRC} main.c)
+ADD_EXECUTABLE(freeDiameterd ${FD_COMMON_SRC} ${FD_COMMON_GEN_SRC} main.c)
 
 # The link command
 LINK_DIRECTORIES(${CURRENT_BINARY_DIR}/../libfreeDiameter)
@@ -19,6 +30,7 @@
 
 # Save the list of files, if needed
 SET(FD_COMMON_SRC ${FD_COMMON_SRC} PARENT_SCOPE)
+SET(FD_COMMON_GEN_SRC ${FD_COMMON_GEN_SRC} PARENT_SCOPE)
 
 # The unary tests directory
 OPTION(SKIP_TESTS "Skip compilation of the tests?" OFF)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/freeDiameter/config.c	Fri Sep 18 18:54:07 2009 +0900
@@ -0,0 +1,189 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2009, 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 "fD.h"
+
+/* Configuration management */
+
+/* Initialize the fd_g_config structure to default values */
+int fd_conf_init()
+{
+	TRACE_ENTRY();
+	
+	fd_g_config->eyec = EYEC_CONFIG;
+	fd_g_config->conf_file = DEFAULT_CONF_FILE;
+	
+	fd_g_config->loc_port     = 3868;
+	fd_g_config->loc_port_tls = 3869;
+	fd_g_config->loc_sctp_str = 30;
+	fd_list_init(&fd_g_config->loc_endpoints, NULL);
+	
+	#ifdef DISABLE_SCTP
+	fd_g_config->flags.no_sctp = 1;
+	#endif /* DISABLE_SCTP */
+	
+	fd_g_config->timer_tc = 30;
+	fd_g_config->timer_tw = 30;
+	
+	fd_g_config->or_state_id = (uint32_t) time(NULL);
+	
+	CHECK_FCT( fd_dict_init(&fd_g_config->g_dict) );
+	CHECK_FCT( fd_fifo_new(&fd_g_config->g_fifo_main) );
+	
+	return 0;
+}
+
+void fd_conf_dump()
+{
+	if (!TRACE_BOOL(INFO))
+		return;
+	
+	fd_log_debug("-- Configuration :\n");
+	fd_log_debug("  Debug trace level ...... : %+d\n", fd_g_debug_lvl);
+	fd_log_debug("  Configuration file ..... : %s\n", fd_g_config->conf_file);
+	fd_log_debug("  Diameter Identity ...... : %s (l:%Zi)\n", fd_g_config->diam_id, fd_g_config->diam_id_len);
+	fd_log_debug("  Diameter Realm ......... : %s (l:%Zi)\n", fd_g_config->diam_realm, fd_g_config->diam_realm_len);
+	fd_log_debug("  Local port ............. : %hu\n", fd_g_config->loc_port);
+	fd_log_debug("  Local secure port ...... : %hu\n", fd_g_config->loc_port_tls);
+	fd_log_debug("  Number of SCTP streams . : %hu\n", fd_g_config->loc_sctp_str);
+	if (FD_IS_LIST_EMPTY(&fd_g_config->loc_endpoints)) {
+		fd_log_debug("  Local endpoints ........ : Default (use all available)\n");
+	} else {
+		struct fd_list * li = fd_g_config->loc_endpoints.next;
+		fd_log_debug("  Local endpoints ........ : ");
+		while (li != &fd_g_config->loc_endpoints) {
+			struct fd_endpoint * ep = (struct fd_endpoint *)li;
+			if (li != fd_g_config->loc_endpoints.next) fd_log_debug("                             ");
+			sSA_DUMP_NODE( &ep->ss, NI_NUMERICHOST );
+			fd_log_debug("\n");
+			li = li->next;
+		}
+	}
+	fd_log_debug("  Flags : - IP ........... : %s\n", fd_g_config->flags.no_ip4 ? "DISABLED" : "Enabled");
+	fd_log_debug("          - IPv6 ......... : %s\n", fd_g_config->flags.no_ip6 ? "DISABLED" : "Enabled");
+	fd_log_debug("          - Relay app .... : %s\n", fd_g_config->flags.no_fwd ? "DISABLED" : "Enabled");
+	fd_log_debug("          - TCP .......... : %s\n", fd_g_config->flags.no_tcp ? "DISABLED" : "Enabled");
+	#ifdef DISABLE_SCTP
+	fd_log_debug("          - SCTP ......... : DISABLED (at compilation)\n");
+	#else /* DISABLE_SCTP */
+	fd_log_debug("          - SCTP ......... : %s\n", fd_g_config->flags.no_sctp ? "DISABLED" : "Enabled");
+	#endif /* DISABLE_SCTP */
+	fd_log_debug("          - Pref. proto .. : %s\n", fd_g_config->flags.pr_tcp ? "TCP" : "SCTP");
+	fd_log_debug("          - TLS method ... : %s\n", fd_g_config->flags.tls_alg ? "INBAND" : "Separate port");
+	fd_log_debug("  Tc Timer ............... : %u\n", fd_g_config->timer_tc);
+	fd_log_debug("  Tw Timer ............... : %u\n", fd_g_config->timer_tw);
+	fd_log_debug("  Origin-State-Id ........ : %u\n", fd_g_config->or_state_id);
+}
+
+/* Parse the configuration file (using the yacc parser) */
+int fd_conf_parse()
+{
+	extern FILE * fddin;
+	
+	TRACE_DEBUG (FULL, "Parsing configuration file: %s", fd_g_config->conf_file);
+	
+	fddin = fopen(fd_g_config->conf_file, "r");
+	if (fddin == NULL) {
+		int ret = errno;
+		fprintf(stderr, "Unable to open configuration file %s for reading: %s\n", fd_g_config->conf_file, strerror(ret));
+		return ret;
+	}
+	
+	/* call yacc parser */
+	CHECK_FCT(  fddparse(fd_g_config)  );
+	
+	/* close the file */
+	fclose(fddin);
+	
+	/* Resolve hostname if not provided */
+	if (fd_g_config->diam_id == NULL) {
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 1024
+#endif /* HOST_NAME_MAX */
+		char buf[HOST_NAME_MAX + 1];
+		struct addrinfo hints, *info;
+		int ret;
+		
+		/* local host name */
+		CHECK_SYS(gethostname(buf, sizeof(buf)));
+		
+		/* get FQDN */
+		memset(&hints, 0, sizeof hints);
+		hints.ai_flags = AI_CANONNAME;
+
+		ret = getaddrinfo(buf, NULL, &hints, &info);
+		if (ret != 0) {
+			fprintf(stderr, "Error resolving local FQDN :\n"
+					" '%s' : %s\n"
+					"Please provide LocalIdentity in configuration file.\n",
+					buf, gai_strerror(ret));
+			return EINVAL;
+		}
+		CHECK_MALLOC( fd_g_config->diam_id = strdup(info->ai_canonname) );
+		freeaddrinfo(info);
+	}
+	
+	/* cache the length of the diameter id for the session module */
+	fd_g_config->diam_id_len = strlen(fd_g_config->diam_id);
+	
+	/* Handle the realm part */
+	if (fd_g_config->diam_realm == NULL) {
+		char * start = NULL;
+		
+		/* Check the diameter identity is a fqdn */
+		start = strchr(fd_g_config->diam_id, '.');
+		if ((start == NULL) || (start[1] == '\0')) {
+			fprintf(stderr, "Unable to extract realm from the LocalIdentity '%s'.\n"
+					"Please fix your LocalIdentity setting or provide LocalRealm.\n",
+					fd_g_config->diam_id);
+			return EINVAL;
+		}		
+		
+		CHECK_MALLOC( fd_g_config->diam_realm = strdup( start + 1 )  ); 
+	}
+	fd_g_config->diam_realm_len = strlen(fd_g_config->diam_realm);
+	
+	/* Validate some flags */
+	if (fd_g_config->flags.no_ip4 && fd_g_config->flags.no_ip6) {
+		fprintf(stderr, "IP and IPv6 cannot be disabled at the same time.\n");
+		return EINVAL;
+	}
+	if (fd_g_config->flags.no_tcp && fd_g_config->flags.no_sctp) {
+		fprintf(stderr, "TCP and SCTP cannot be disabled at the same time.\n");
+		return EINVAL;
+	}
+	
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/freeDiameter/extensions.c	Fri Sep 18 18:54:07 2009 +0900
@@ -0,0 +1,180 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2009, 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 "fD.h"
+
+#include <dlfcn.h>	/* We may use libtool's <ltdl.h> later for better portability.... */
+
+/* plugins management */
+
+/* List of extensions to load, from the configuration parsing */
+struct fd_ext_info {
+	struct fd_list	chain;		/* link in the list */
+	char 		*filename;	/* extension filename. must be a dynamic library with fd_ext_init symbol. */
+	char 		*conffile;	/* optional configuration file name for the extension */
+	void 		*handler;	/* object returned by dlopen() */
+	void		(*fini)(void);	/* optional address of the fd_ext_fini callback */
+};
+
+/* list of extensions */
+static struct fd_list ext_list;
+
+/* Initialize the module */
+int fd_ext_init()
+{
+	TRACE_ENTRY();
+	fd_list_init(&ext_list, NULL);
+	return 0;
+}
+
+/* Add new extension */
+int fd_ext_add( char * filename, char * conffile )
+{
+	struct fd_ext_info * new;
+	
+	TRACE_ENTRY("%p(%s) %p(%s)", filename, filename?filename:"", conffile, conffile?conffile:"");
+	
+	/* Check the filename is valid */
+	CHECK_PARAMS( filename );
+	
+	/* Create a new object in the list */
+	CHECK_MALLOC(  new = malloc( sizeof(struct fd_ext_info) )  );
+	memset(new, 0, sizeof(struct fd_ext_info));
+	fd_list_init(&new->chain, NULL);
+	new->filename = filename;
+	new->conffile = conffile;
+	fd_list_insert_before( &ext_list, &new->chain );
+	TRACE_DEBUG (FULL, "Extension %s added to the list.", filename);
+	return 0;
+}
+
+/* Load all extensions in the list */
+int fd_ext_load()
+{
+	int ret;
+	int (*fd_ext_init)(int, int, char *) = NULL;
+	struct fd_list * li;
+	
+	TRACE_ENTRY();
+	
+	/* Loop on all extensions */
+	for (li = ext_list.next; li != &ext_list; li = li->next)
+	{
+		struct fd_ext_info * ext = (struct fd_ext_info *)li;
+		TRACE_DEBUG (INFO, "Loading : %s", ext->filename);
+		
+		/* Load the extension */
+		ext->handler = dlopen(ext->filename, RTLD_LAZY | RTLD_GLOBAL);
+		if (ext->handler == NULL) {
+			/* An error occured */
+			TRACE_DEBUG( NONE, "Loading of extension %s failed:\n %s\n", ext->filename, dlerror());
+			return EINVAL;
+		}
+		
+		/* Resolve the entry point of the extension */
+		fd_ext_init = ( int (*) (int, int, char *) )dlsym( ext->handler, "fd_ext_init" );
+		
+		if (fd_ext_init == NULL) {
+			/* An error occured */
+			TRACE_DEBUG( NONE, "Unable to resolve symbol 'fd_ext_init' for extension %s:\n %s\n", ext->filename, dlerror());
+			return EINVAL;
+		}
+		
+		/* Resolve the exit point of the extension, which is optional for extensions */
+		ext->fini = ( void (*) (void) )dlsym( ext->handler, "fd_ext_fini" );
+		
+		if (ext->fini == NULL) {
+			/* Not provided */
+			TRACE_DEBUG (FULL, "Extension [%s] has no fd_ext_fini function.", ext->filename);
+		} else {
+			/* Provided */
+			TRACE_DEBUG (FULL, "Extension [%s] fd_ext_fini has been resolved successfully.", ext->filename);
+		}
+		
+		/* Now call the entry point to initialize the extension */
+		ret = (*fd_ext_init)( FD_PROJECT_VERSION_MAJOR, FD_PROJECT_VERSION_MINOR, ext->conffile );
+		if (ret != 0) {
+			/* The extension was unable to load cleanly */
+			TRACE_DEBUG( NONE, "Extension %s returned an error during initialization: %s\n", ext->filename, strerror(ret));
+			return ret;
+		}
+		
+		/* Proceed to the next extension */
+	}
+
+	TRACE_DEBUG (INFO, "All extensions loaded.");
+	
+	/* We have finished. */
+	return 0;
+}
+
+/* Now unload the extensions and free the memory */
+int fd_ext_fini( void ) 
+{
+	TRACE_ENTRY();
+	
+	/* Loop on all extensions, in FIFO order */
+	while (!FD_IS_LIST_EMPTY(&ext_list))
+	{
+		struct fd_list * li = ext_list.next;
+		struct fd_ext_info * ext = (struct fd_ext_info *)li;
+	
+		/* Unlink this element from the list */
+		fd_list_unlink(li);
+		
+		/* Call the exit point of the extension, if it was resolved */
+		if (ext->fini != NULL) {
+			TRACE_DEBUG (FULL, "Calling [%s]->fd_ext_fini function.", ext->filename);
+			(*ext->fini)();
+		}
+		
+		/* Now unload the extension */
+		if (ext->handler) {
+			TRACE_DEBUG (FULL, "Unloading %s", ext->filename);
+			if ( dlclose(ext->handler) != 0 ) {
+				TRACE_DEBUG (INFO, "Unloading [%s] failed : %s\n", ext->filename, dlerror());
+			}
+		}
+		
+		/* Free the object and continue */
+		free(ext->filename);
+		free(ext->conffile);
+		free(ext);
+	}
+	
+	/* We always return 0 since we would not handle an error anyway... */
+	return 0;
+}
+
--- a/freeDiameter/fD.h	Fri Sep 04 18:05:25 2009 +0900
+++ b/freeDiameter/fD.h	Fri Sep 18 18:54:07 2009 +0900
@@ -41,8 +41,24 @@
 #include <freeDiameter/freeDiameter-host.h>
 #include <freeDiameter/freeDiameter.h>
 
+/* Events codespace for fd_g_config->g_fifo_main */
+enum {
+	FM_TERMINATE = 1000	/* request to terminate */
+};
+
+/* Configuration */
+int fd_conf_init();
+void fd_conf_dump();
+int fd_conf_parse();
+int fddparse(struct fd_config * conf); /* yacc generated */
+
+/* Extensions */
+int fd_ext_init();
+int fd_ext_add( char * filename, char * conffile );
+int fd_ext_load();
+int fd_ext_fini(void);
+
 /* Create all the dictionary objects defined in the Diameter base RFC. */
 int fd_dict_base_protocol(struct dictionary * dict);
 
-
 #endif /* _FD_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/freeDiameter/fdd.l	Fri Sep 18 18:54:07 2009 +0900
@@ -0,0 +1,143 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2009, 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.								 *
+*********************************************************************************************************/
+
+/* Lex configuration parser.
+ *
+ * This file defines the token for parsing the daemon's configuration file
+ * Note that each extension has a separate independant configuration file.
+ *
+ * Note : This module is NOT thread-safe. All processing must be done from one thread only.
+ */
+%{
+/* Include the daemon's header files */
+#include "fD.h"
+/* Include yacc tokens definitions */
+#include "fdd.tab.h"
+
+/* Update the column information */
+#ifdef DEBUG_LEX
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+	TRACE_DEBUG(FULL, 						\
+		"(%d:%d-%d:%d) matched rule %d, length=%d, txt='%s'\n",	\
+		yylloc->first_line, yylloc->first_column, 		\
+		yylloc->last_line, yylloc->last_column, 		\
+		yy_act, yyleng, yytext); 				\
+}
+#else /* DEBUG_LEX */
+#define YY_USER_ACTION { 						\
+	yylloc->first_column = yylloc->last_column + 1; 		\
+	yylloc->last_column = yylloc->first_column + yyleng - 1;	\
+}
+#endif
+
+/* %option noinput ? */
+#define YY_NO_INPUT
+%}
+
+%option bison-bridge bison-locations
+%option noyywrap
+%option nounput
+
+/* Quoted string. Multilines do not match. */
+qstring		\"[^\"\n]*\"
+
+%%
+
+<*>\n			{ 
+				/* Update the line count */
+				yylloc->first_line++; 
+				yylloc->last_line++; 
+				yylloc->last_column=0; 
+			} 
+
+<*>([[:space:]]{-}[\n])+	; /* Eat all spaces, not new lines */
+<*>#.*$			; /* Eat all comments */
+
+{qstring}		{
+				/* First copy the string without the quotes for use in the yacc parser */
+				CHECK_MALLOC_DO(	yylval->string = strdup(yytext+1), /* This allocates one useless tail char but... it's easier :D */ 
+							return LEX_ERROR  );/* on error, trig an error in yacc parser */
+
+				yylval->string[yyleng-2] = '\0';
+				
+				/* the yacc parser will check the string is valid */
+				return QSTRING;
+			}
+			
+[[:digit:]]+		{
+				/* Convert this to an integer value */
+				int ret = sscanf(yytext, "%i", &yylval->integer);
+				if (ret != 1) {
+					/* No matching: an error occurred */
+					fprintf(stderr, "Unable to convert the value '%s' to a valid number: %s\n", yytext, strerror(errno));
+					return LEX_ERROR; /* trig an error in yacc parser */
+					/* Maybe we could REJECT instead of failing here? */
+				}
+				return INTEGER;
+			}
+				
+	/* Full words tokens (keywords) */
+(?i:"LocalIdentity")	{ return LOCALIDENTITY;	}
+(?i:"LocalRealm")	{ return LOCALREALM;	}
+(?i:"LocalPort")	{ return LOCALPORT;	}
+(?i:"LocalSecPort")	{ return LOCALSECPORT;	}
+(?i:"No_IPv6")		{ return NOIP6;		}
+(?i:"No_IP")		{ return NOIP;		}
+(?i:"No_TCP")		{ return NOTCP;		}
+(?i:"No_SCTP")		{ return NOSCTP;	}
+(?i:"Prefer_TCP")	{ return PREFERTCP;	}
+(?i:"TLS_old_method")	{ return OLDTLS;	}
+(?i:"SCTP_streams")	{ return SCTPSTREAMS;	}
+(?i:"ListenOn")		{ return LISTENON;	}
+(?i:"TcTimer")		{ return TCTIMER;	}
+(?i:"TwTimer")		{ return TWTIMER;	}
+(?i:"NoRelay")		{ return NORELAY;	}
+(?i:"LoadExtension")	{ return LOADEXT;	}
+
+
+	/* Valid single characters for yyparse */
+<*>[=,:;{}]		{ return yytext[0]; }
+
+	/* Unrecognized token */
+<*>[[:alnum:]]+		|	/* This rule is only useful to print a complete token in error messages */
+	/* Unrecognized character */
+<*>.			{ 
+				fprintf(stderr, "Unrecognized text on line %d col %d: '%s'.\n", yylloc->first_line, yylloc->first_column, yytext);
+			 	return LEX_ERROR; 
+			}
+
+%%
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/freeDiameter/fdd.y	Fri Sep 18 18:54:07 2009 +0900
@@ -0,0 +1,261 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2009, 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.								 *
+*********************************************************************************************************/
+
+/* Yacc configuration parser.
+ *
+ * This file defines the grammar of the configuration file.
+ * Note that each extension has a separate independant configuration file.
+ *
+ * Note : This module is NOT thread-safe. All processing must be done from one thread only.
+ */
+
+/* For development only : */
+%debug 
+%error-verbose
+
+%parse-param {struct fd_config * conf}
+
+/* Keep track of location */
+%locations 
+%pure-parser
+
+%{
+#include "fD.h"
+#include "fdd.tab.h"	/* bug : bison does not define the YYLTYPE before including this bloc, so... */
+
+/* The Lex parser prototype */
+int fddlex(YYSTYPE *lvalp, YYLTYPE *llocp);
+
+/* Function to report error */
+void yyerror (YYLTYPE *ploc, struct fd_config * conf, char const *s)
+{
+	if (ploc->first_line != ploc->last_line)
+		fprintf(stderr, "%s:%d.%d-%d.%d : %s\n", conf->conf_file, ploc->first_line, ploc->first_column, ploc->last_line, ploc->last_column, s);
+	else if (ploc->first_column != ploc->last_column)
+		fprintf(stderr, "%s:%d.%d-%d : %s\n", conf->conf_file, ploc->first_line, ploc->first_column, ploc->last_column, s);
+	else
+		fprintf(stderr, "%s:%d.%d : %s\n", conf->conf_file, ploc->first_line, ploc->first_column, s);
+}
+
+%}
+
+/* Values returned by lex for token */
+%union {
+	char 		*string;	/* The string is allocated by strdup in lex.*/
+	int		 integer;	/* Store integer values */
+}
+
+/* In case of error in the lexical analysis */
+%token 		LEX_ERROR
+
+%token <string>	QSTRING
+%token <integer> INTEGER
+
+%type <string> extconf
+
+%token		LOCALIDENTITY
+%token		LOCALREALM
+%token		LOCALPORT
+%token		LOCALSECPORT
+%token		NOIP
+%token		NOIP6
+%token		NOTCP
+%token		NOSCTP
+%token		PREFERTCP
+%token		OLDTLS
+%token		SCTPSTREAMS
+%token		LISTENON
+%token		TCTIMER
+%token		TWTIMER
+%token		NORELAY
+%token		LOADEXT
+
+
+/* -------------------------------------- */
+%%
+
+	/* The grammar definition - Sections blocs. */
+conffile:		/* Empty is OK */
+			| conffile localidentity
+			| conffile localrealm
+			| conffile localport
+			| conffile localsecport
+			| conffile noip
+			| conffile noip6
+			| conffile notcp
+			| conffile nosctp
+			| conffile prefertcp
+			| conffile oldtls
+			| conffile sctpstreams
+			| conffile listenon
+			| conffile tctimer
+			| conffile twtimer
+			| conffile norelay
+			| conffile loadext
+			;
+
+localidentity:		LOCALIDENTITY '=' QSTRING ';'
+			{
+				conf->diam_id = $3;
+			}
+			;
+
+localrealm:		LOCALREALM '=' QSTRING ';'
+			{
+				conf->diam_realm = $3;
+			}
+			;
+
+localport:		LOCALPORT '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($3 > 0) && ($3 < 1<<16),
+					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+				conf->loc_port = (uint16_t)$3;
+			}
+			;
+
+localsecport:		LOCALSECPORT '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($3 > 0) && ($3 < 1<<16),
+					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+				conf->loc_port_tls = (uint16_t)$3;
+			}
+			;
+
+noip:			NOIP ';'
+			{
+				conf->flags.no_ip4 = 1;
+			}
+			;
+
+noip6:			NOIP6 ';'
+			{
+				conf->flags.no_ip6 = 1;
+			}
+			;
+
+notcp:			NOTCP ';'
+			{
+				conf->flags.no_tcp = 1;
+			}
+			;
+
+nosctp:			NOSCTP ';'
+			{
+				conf->flags.no_sctp = 1;
+			}
+			;
+
+prefertcp:		PREFERTCP ';'
+			{
+				conf->flags.pr_tcp = 1;
+			}
+			;
+
+oldtls:			OLDTLS ';'
+			{
+				conf->flags.tls_alg = 1;
+			}
+			;
+
+sctpstreams:		SCTPSTREAMS '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($3 > 0) && ($3 < 1<<16),
+					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+				conf->loc_sctp_str = (uint16_t)$3;
+			}
+			;
+
+listenon:		LISTENON '=' QSTRING ';'
+			{
+				struct fd_endpoint * ep;
+				struct addrinfo hints, *ai;
+				int ret;
+				
+				CHECK_MALLOC_DO( ep = malloc(sizeof(struct fd_endpoint)),
+					{ yyerror (&yylloc, conf, "Out of memory"); YYERROR; } );
+				memset(ep, 0, sizeof(struct fd_endpoint));
+				fd_list_init(&ep->chain, NULL);
+				
+				memset(&hints, 0, sizeof(hints));
+				hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
+				ret = getaddrinfo($3, NULL, &hints, &ai);
+				if (ret) { yyerror (&yylloc, conf, gai_strerror(ret)); YYERROR; }
+				
+				memcpy(&ep->ss, ai->ai_addr, ai->ai_addrlen);
+				free($3);
+				freeaddrinfo(ai);
+				fd_list_insert_before(&conf->loc_endpoints, &ep->chain);
+			}
+			;
+
+tctimer:		TCTIMER '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($3 > 0),
+					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+				conf->timer_tc = (unsigned int)$3;
+			}
+			;
+
+twtimer:		TWTIMER '=' INTEGER ';'
+			{
+				CHECK_PARAMS_DO( ($3 > 5),
+					{ yyerror (&yylloc, conf, "Invalid value"); YYERROR; } );
+				conf->timer_tw = (unsigned int)$3;
+			}
+			;
+
+norelay:		NORELAY ';'
+			{
+				conf->flags.no_fwd = 1;
+			}
+			;
+
+loadext:		LOADEXT '=' QSTRING extconf ';'
+			{
+				CHECK_FCT_DO( fd_ext_add( $3, $4 ),
+					{ yyerror (&yylloc, conf, "Error adding extension"); YYERROR; } );
+			}
+			;
+			
+extconf:		/* empty */
+			{
+				$$ = NULL;
+			}
+			| ':' QSTRING
+			{
+				$$ = $2;
+			}
+			;
--- a/freeDiameter/main.c	Fri Sep 04 18:05:25 2009 +0900
+++ b/freeDiameter/main.c	Fri Sep 18 18:54:07 2009 +0900
@@ -35,22 +35,218 @@
 
 #include "fD.h"
 
+#include <signal.h>
+#include <getopt.h>
+
+
+/* Display package version */
+static void main_version_core(void)
+{
+	printf("%s, version %d.%d.%d"
+#ifdef HG_VERSION
+		" (r%s"
+# ifdef PACKAGE_HG_REVISION
+		"/%s"
+# endif /* PACKAGE_HG_VERSION */
+		")"
+#endif /* HG_VERSION */
+		"\n", 
+		FD_PROJECT_NAME, FD_PROJECT_VERSION_MAJOR, FD_PROJECT_VERSION_MINOR, FD_PROJECT_VERSION_REV
+#ifdef HG_VERSION
+		, HG_VERSION
+# ifdef PACKAGE_HG_REVISION
+		, PACKAGE_HG_REVISION
+# endif /* PACKAGE_HG_VERSION */
+#endif /* HG_VERSION */
+		);
+}
+
+/* Display package version and general info */
+static void main_version(void)
+{
+	main_version_core();
+	printf( "%s\n", FD_PROJECT_COPYRIGHT);
+	printf( "\nSee " FD_PROJECT_NAME " homepage at http://aaa.koganei.wide.ad.jp/\n"
+		" for information, updates and bug reports on this software.\n");
+}
+
+/* Print command-line options */
+static void main_help( void )
+{
+	main_version_core();
+	printf(	"  This daemon is an implementation of the Diameter protocol\n"
+		"  used for Authentication, Authorization, and Accounting (AAA).\n");
+	printf("\nUsage:  " FD_PROJECT_BINARY " [OPTIONS]...\n");
+	printf( "  -h, --help             Print help and exit\n"
+  		"  -V, --version          Print version and exit\n"
+  		"  -c, --config=filename  Read configuration from this file instead of the \n"
+		"                           default location (%s).\n", DEFAULT_CONF_FILE);
+ 	printf( "\nDebug:\n"
+  		"  These options are mostly useful for developers\n"
+  		"  -d, --debug            Increase verbosity of debug messages\n"
+  		"  -q, --quiet            Decrease verbosity then remove debug messages\n");
+}
+
+/* Parse the command-line */
+static int main_cmdline(int argc, char *argv[])
+{
+	int c;
+	int option_index = 0;
+	
+      	struct option long_options[] = {
+		{ "help",	0, NULL, 'h' },
+		{ "version",	0, NULL, 'V' },
+		{ "config",	1, NULL, 'c' },
+		{ "debug",	0, NULL, 'd' },
+		{ "quiet",	0, NULL, 'q' },
+		{ NULL,	0, NULL, 0 }
+	};
+	
+	TRACE_ENTRY("%d %p", argc, argv);
+	
+	/* Loop on arguments */
+	while (1) {
+		c = getopt_long (argc, argv, "hVc:dq", long_options, &option_index);
+		if (c == -1) 
+			break;	/* Exit from the loop.  */
+		
+		switch (c) {
+			case 'h':	/* Print help and exit.  */
+				main_help();
+				exit(0);
+
+			case 'V':	/* Print version and exit.  */
+				main_version();
+				exit(0);
+
+			case 'c':	/* Read configuration from this file instead of the default location..  */
+				CHECK_PARAMS( optarg );
+				fd_g_config->conf_file = optarg;
+				break;
+
+			case 'd':	/* Increase verbosity of debug messages.  */
+				fd_g_debug_lvl++;
+				break;
+				
+			case 'q':	/* Decrease verbosity then remove debug messages.  */
+				fd_g_debug_lvl--;
+				break;
+
+			case '?':	/* Invalid option.  */
+				/* `getopt_long' already printed an error message.  */
+				TRACE_DEBUG(INFO, "getopt_long found an invalid character\n");
+				return EINVAL;
+
+			default:	/* bug: option not considered.  */
+				TRACE_DEBUG(INFO, "A command-line option is missing in parser: %c\n", c);
+				ASSERT(0);
+				return EINVAL;
+		}
+	}
+		
+	return 0;
+	
+}
+
+#ifdef HAVE_SIGNALENT_H
+const char *const signalstr[] = {
+# include "signalent.h"
+};
+const int nsignalstr = sizeof signalstr / sizeof signalstr[0];
+# define SIGNALSTR(sig) (((sig) < nsignalstr) ? signalstr[(sig)] : "unknown")
+#else /* HAVE_SIGNALENT_H */
+# define SIGNALSTR(sig) ("")
+#endif /* HAVE_SIGNALENT_H */
+
+
+/* signal handler */
+static void * sig_hdl(void * arg)
+{
+	sigset_t sig_main;
+	int sig = 0;
+	
+	TRACE_ENTRY();
+	fd_log_threadname("Main signal handler");
+	
+	sigemptyset(&sig_main);
+	sigaddset(&sig_main, SIGINT);
+	sigaddset(&sig_main, SIGTERM);
+	
+	CHECK_SYS_DO(  sigwait(&sig_main, &sig), TRACE_DEBUG(INFO, "Error in sigwait function") );
+	
+	TRACE_DEBUG(INFO, "Received signal %s (%d), exiting", SIGNALSTR(sig), sig);
+	CHECK_FCT_DO( fd_event_send(fd_g_config->g_fifo_main, FM_TERMINATE, NULL), exit(2) );
+	return NULL;
+}
+	
+/* The static configuration structure */
+static struct fd_config conf;
+struct fd_config * fd_g_config = &conf;
+
 /* Entry point */
 int main(int argc, char * argv[])
 {
+	int ret;
+	pthread_t sig_th;
+	sigset_t sig_all;
+	
+	memset(fd_g_config, 0, sizeof(struct fd_config));
+	sigfillset(&sig_all);
+	CHECK_POSIX(  pthread_sigmask(SIG_BLOCK, &sig_all, NULL)  );
+	
 	/* Initialize the library */
 	CHECK_FCT( fd_lib_init() );
 	
 	/* Name this thread */
 	fd_log_threadname("Main");
+	
+	/* Initialize the config */
+	CHECK_FCT( fd_conf_init() );
 
-	/* Initialize the dictionary */
-	CHECK_FCT( fd_dict_init(&fd_g_dict) );
+	/* Parse the command-line */
+	CHECK_FCT(  main_cmdline(argc, argv)  );
+	
+	/* Allow SIGINT and SIGTERM from this point */
+	CHECK_POSIX(  pthread_create(&sig_th, NULL, sig_hdl, NULL)  );
 	
 	/* Add definitions of the base protocol */
-	CHECK_FCT( fd_dict_base_protocol(fd_g_dict) );
+	CHECK_FCT( fd_dict_base_protocol(fd_g_config->g_dict) );
+	
+	/* Initialize other modules */
+	CHECK_FCT(  fd_ext_init()  );
+	
+	/* Parse the configuration file */
+	CHECK_FCT( fd_conf_parse() );
+	
+	/* Load the dynamic extensions */
+	CHECK_FCT(  fd_ext_load()  );
+	
+	/* Start the peer state machines */
+	
 	
-	TRACE_DEBUG(INFO, "freeDiameter daemon initialized.");
+	/* Now, just wait for events */
+	TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon initialized.");
+	fd_conf_dump();
+	while (1) {
+		int code;
+		CHECK_FCT_DO(  fd_event_get(fd_g_config->g_fifo_main, &code, NULL),  break  );
+		switch (code) {
+			case FM_TERMINATE:
+				ret = 0;
+				goto end;
+			
+			default:
+				TRACE_DEBUG(INFO, "Unexpected event in the daemon (%d), terminating.\n", code);
+				ret = -1;
+				goto end;
+		}
+	}
 	
-	return 0;
+end:
+	TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon is stopping...");
+	
+	/* cleanups */
+	CHECK_FCT( fd_thr_term(&sig_th) );
+	
+	return ret;
 }
--- a/freeDiameter/tests/CMakeLists.txt	Fri Sep 04 18:05:25 2009 +0900
+++ b/freeDiameter/tests/CMakeLists.txt	Fri Sep 18 18:54:07 2009 +0900
@@ -14,7 +14,7 @@
 	testlist
 	testdict
 	testmesg
-	testmq
+	testqueues
 	testsess
 	testdisp
 )
@@ -28,15 +28,18 @@
 INCLUDE_DIRECTORIES( ".." )
 INCLUDE_DIRECTORIES( "../../libfreeDiameter" )
 
+BISON_FILE(../fdd.y)
+FLEX_FILE(../fdd.l)
+
 SET(TEST_COMMON_SRC "")
 
 FOREACH( SRC_FILE ${FD_COMMON_SRC})
    SET(TEST_COMMON_SRC ${TEST_COMMON_SRC} "../${SRC_FILE}")
 ENDFOREACH(SRC_FILE)
 
-# FOREACH( SRC_FILE ${FD_COMMON_GEN_SRC})
-#    SET(TEST_COMMON_SRC ${TEST_COMMON_SRC} "${CMAKE_CURRENT_BINARY_DIR}/../${SRC_FILE}")
-# ENDFOREACH(SRC_FILE)
+FOREACH( SRC_FILE ${FD_COMMON_GEN_SRC})
+   SET(TEST_COMMON_SRC ${TEST_COMMON_SRC} "${CMAKE_CURRENT_BINARY_DIR}/../${SRC_FILE}")
+ENDFOREACH(SRC_FILE)
 
 FOREACH( SRC_FILE ${LFD_SRC})
    SET(TEST_COMMON_SRC ${TEST_COMMON_SRC} "../../libfreeDiameter/${SRC_FILE}")
--- a/freeDiameter/tests/testdict.c	Fri Sep 04 18:05:25 2009 +0900
+++ b/freeDiameter/tests/testdict.c	Fri Sep 18 18:54:07 2009 +0900
@@ -66,24 +66,24 @@
 		
 		
 		/* Create two vendors */
-		CHECK( 0, fd_dict_new ( fd_g_dict, DICT_VENDOR, &vendor1_data , NULL, &obj1 ) );
-		CHECK( 0, fd_dict_new ( fd_g_dict, DICT_VENDOR, &vendor2_data , NULL, NULL ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_VENDOR, &vendor1_data , NULL, &obj1 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_VENDOR, &vendor2_data , NULL, NULL ) );
 		
 		/* Check we always retrieve the correct vendor object */
-		CHECK( 0, fd_dict_search ( fd_g_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, &obj2, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, &obj2, ENOENT ) );
 		CHECK( obj1, obj2);
-		CHECK( 0, fd_dict_search ( fd_g_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 1", &obj2, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 1", &obj2, ENOENT ) );
 		CHECK( obj1, obj2);
 		
 		/* Check the error conditions */
-		CHECK( 0, fd_dict_search ( fd_g_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, NULL, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, NULL, ENOENT ) );
 		
 		vendor_id = 735673; /* Not defined */
-		CHECK( ENOENT, fd_dict_search ( fd_g_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, NULL, ENOENT ) );
-		CHECK( ENOENT, fd_dict_search ( fd_g_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 3", NULL, ENOENT ) );
-		CHECK( ENOENT, fd_dict_search ( fd_g_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, &obj2, ENOENT ) );
-		CHECK( ENOENT, fd_dict_search ( fd_g_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 3", &obj2, ENOENT ) );
-		CHECK( ENOTSUP, fd_dict_search ( fd_g_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 3", &obj2, ENOTSUP ) );
+		CHECK( ENOENT, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, NULL, ENOENT ) );
+		CHECK( ENOENT, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 3", NULL, ENOENT ) );
+		CHECK( ENOENT, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_BY_ID, &vendor_id, &obj2, ENOENT ) );
+		CHECK( ENOENT, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 3", &obj2, ENOENT ) );
+		CHECK( ENOTSUP, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_BY_NAME, "Vendor test 3", &obj2, ENOTSUP ) );
 		
 		/* Check the get_* functions */
 		CHECK( 0, fd_dict_getval ( obj1, &vendor1_data ) );
@@ -93,10 +93,10 @@
 		CHECK( EINVAL, fd_dict_getval ( (struct dict_object *)"not an object", &vendor1_data ) );
 		
 		/* Create the application with vendor1 as parent */
-		CHECK( EINVAL, fd_dict_new ( fd_g_dict, DICT_APPLICATION, &app1_data , (struct dict_object *)"bad object", &obj2 ) );
-		CHECK( 0, fd_dict_new ( fd_g_dict, DICT_APPLICATION, &app1_data , obj1, &obj2 ) );
+		CHECK( EINVAL, fd_dict_new ( fd_g_config->g_dict, DICT_APPLICATION, &app1_data , (struct dict_object *)"bad object", &obj2 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_APPLICATION, &app1_data , obj1, &obj2 ) );
 		
-		CHECK( 0, fd_dict_search ( fd_g_dict, DICT_VENDOR, VENDOR_OF_APPLICATION, obj2, &obj3, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_VENDOR, VENDOR_OF_APPLICATION, obj2, &obj3, ENOENT ) );
 		CHECK( obj1, obj3);
 		
 		/* Creating and searching the other objects is already done in dictionary initialization */
@@ -111,20 +111,20 @@
 		struct dict_rule_data rule_data = { NULL, RULE_REQUIRED, -1, -1 };
 		struct dict_avp_data example_avp_data = { 999999, 0, "Example-AVP", AVP_FLAG_VENDOR , 0, AVP_TYPE_GROUPED };
 
-		CHECK( 0, fd_dict_search ( fd_g_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &origin_host_avp, ENOENT ) );
-		CHECK( 0, fd_dict_search ( fd_g_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &session_id_avp, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME, "Origin-Host", &origin_host_avp, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &session_id_avp, ENOENT ) );
 		
-		CHECK( 0, fd_dict_new ( fd_g_dict, DICT_AVP, &example_avp_data , NULL, &example_avp_avp ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &example_avp_data , NULL, &example_avp_avp ) );
 		
 		rule_data.rule_avp = origin_host_avp;
 		rule_data.rule_min = 1;
 		rule_data.rule_max = 1;
-		CHECK( 0, fd_dict_new ( fd_g_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ) );
 		
 		rule_data.rule_avp = session_id_avp;
 		rule_data.rule_min = 1;
 		rule_data.rule_max = -1;
-		CHECK( 0, fd_dict_new ( fd_g_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_RULE, &rule_data, example_avp_avp, NULL ) );
 		
 		CHECK( 0, fd_dict_iterate_rules ( example_avp_avp, &nbr, iter_test) );
 		CHECK( 2, nbr );
--- a/freeDiameter/tests/testdisp.c	Fri Sep 04 18:05:25 2009 +0900
+++ b/freeDiameter/tests/testdisp.c	Fri Sep 18 18:54:07 2009 +0900
@@ -127,15 +127,15 @@
 		struct dict_enumval_data enu1_data = { "ENU test 1", { .u32 = 1 }};
 		struct dict_enumval_data enu2_data = { "ENU test 2", { .u32 = 2 }};
 		
-		CHECK( 0, fd_dict_new ( fd_g_dict, DICT_APPLICATION, &app1_data, NULL, &app1 ) );
-		CHECK( 0, fd_dict_new ( fd_g_dict, DICT_APPLICATION, &app2_data, NULL, &app2 ) );
-		CHECK( 0, fd_dict_new ( fd_g_dict, DICT_COMMAND, &cmd1_data, NULL, &cmd1 ) );
-		CHECK( 0, fd_dict_new ( fd_g_dict, DICT_COMMAND, &cmd2_data, NULL, &cmd2 ) );
-		CHECK( 0, fd_dict_new ( fd_g_dict, DICT_TYPE, &type_data, NULL, &enutype ) );
-		CHECK( 0, fd_dict_new ( fd_g_dict, DICT_AVP, &avp1_data, NULL,    &avp1 ) );
-		CHECK( 0, fd_dict_new ( fd_g_dict, DICT_AVP, &avp2_data, enutype, &avp2 ) );
-		CHECK( 0, fd_dict_new ( fd_g_dict, DICT_ENUMVAL, &enu1_data, enutype, &enu1 ) );
-		CHECK( 0, fd_dict_new ( fd_g_dict, DICT_ENUMVAL, &enu2_data, enutype, &enu2 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_APPLICATION, &app1_data, NULL, &app1 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_APPLICATION, &app2_data, NULL, &app2 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_COMMAND, &cmd1_data, NULL, &cmd1 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_COMMAND, &cmd2_data, NULL, &cmd2 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_TYPE, &type_data, NULL, &enutype ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp1_data, NULL,    &avp1 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp2_data, enutype, &avp2 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_ENUMVAL, &enu1_data, enutype, &enu1 ) );
+		CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_ENUMVAL, &enu2_data, enutype, &enu2 ) );
 	}
 	
 	/* Register first handler, very simple test */
--- a/freeDiameter/tests/testmesg.c	Fri Sep 04 18:05:25 2009 +0900
+++ b/freeDiameter/tests/testmesg.c	Fri Sep 18 18:54:07 2009 +0900
@@ -50,7 +50,7 @@
 		struct dict_object * acr_model = NULL;
 
 		/* Now find the ACR dictionary object */
-		CHECK( 0, fd_dict_search ( fd_g_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &acr_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->g_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 ) );
@@ -70,7 +70,7 @@
 		struct dict_object * pi_model = NULL;
 
 		/* Now find the ACR dictionary object */
-		CHECK( 0, fd_dict_search ( fd_g_dict, DICT_AVP, AVP_BY_NAME, "Proxy-Info", &pi_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME, "Proxy-Info", &pi_model, ENOENT ) );
 
 		/* Create the instance, using the templates */
 		CHECK( 0, fd_msg_avp_new ( pi_model, 0, &pi ) );
@@ -132,7 +132,7 @@
 		struct dict_object * rr_model = NULL;
 
 		/* Now find the dictionary object */
-		CHECK( 0, fd_dict_search ( fd_g_dict, DICT_AVP, AVP_BY_NAME, "Route-Record", &rr_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME, "Route-Record", &rr_model, ENOENT ) );
 
 		/* Create the instance, using the templates */
 		CHECK( 0, fd_msg_avp_new ( rr_model, 0, &avp1 ) );
@@ -160,7 +160,7 @@
 		struct dict_object * acr_model = NULL;
 
 		/* Now find the ACR dictionary object */
-		CHECK( 0, fd_dict_search ( fd_g_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &acr_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->g_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 ) );
@@ -172,25 +172,25 @@
 		struct dict_object * vendor;
 		{
 			struct dict_vendor_data vendor_data = { 73565, "Vendor test" };
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_VENDOR, &vendor_data , NULL, &vendor ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_VENDOR, &vendor_data , NULL, &vendor ) );
 		}
 		
 		{
 			struct dict_application_data app_data = { 73566, "Application test" };
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_APPLICATION, &app_data , vendor, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_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_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_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_dict, DICT_TYPE, &type_data , NULL, &type ) );
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_AVP, &avp_data , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , type, NULL ) );
 		}
 		
 		{
@@ -201,19 +201,19 @@
 			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_dict, DICT_TYPE, &type_data , NULL, &type ) );
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_AVP, &avp_data , type, NULL ) );
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_ENUMVAL, &val1 , type, NULL ) );
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_ENUMVAL, &val2 , type, NULL ) );
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_ENUMVAL, &val3 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_ENUMVAL, &val1 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_ENUMVAL, &val2 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_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_dict, DICT_TYPE, &type_data , NULL, &type ) );
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_AVP, &avp_data , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , type, NULL ) );
 		}
 		
 		{
@@ -224,31 +224,31 @@
 			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_dict, DICT_TYPE, &type_data , NULL, &type ) );
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_AVP, &avp_data , type, NULL ) );
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_ENUMVAL, &val1 , type, NULL ) );
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_ENUMVAL, &val2 , type, NULL ) );
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_ENUMVAL, &val3 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_TYPE, &type_data , NULL, &type ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_ENUMVAL, &val1 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_ENUMVAL, &val2 , type, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_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_dict, DICT_AVP, &avp_data , NULL, &gavp ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_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_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));\
+				CHECK( 0, fd_dict_search( fd_g_config->g_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_dict, DICT_RULE, &_data , (_parent), NULL ) );	\
+				CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_RULE, &_data , (_parent), NULL ) );	\
 			}
 			
 			ADD_RULE(gavp, 73565, "AVP Test - os", RULE_OPTIONAL,   -1, -1,  0);
@@ -260,8 +260,8 @@
 			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_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Application test", &application, ENOENT ) );
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_COMMAND, &cmd_data , application, &command ) );
+			CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Application test", &application, ENOENT ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_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);
@@ -274,7 +274,7 @@
 			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_dict, DICT_AVP, &avp_data , NULL, &gavp ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_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);
@@ -302,11 +302,11 @@
 		struct avp         * avp = NULL;
 		union avp_value      value;
 		
-		CHECK( 0, fd_dict_search ( fd_g_dict, DICT_COMMAND, CMD_BY_NAME, "Test-Command-Request", &cmd_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_COMMAND, CMD_BY_NAME, "Test-Command-Request", &cmd_model, ENOENT ) );
 		
 		/* Check an error is trigged if the AVP has no value set */
 		{
-			CHECK( 0, fd_dict_search ( fd_g_dict, DICT_AVP,     AVP_BY_NAME,     "AVP Test - no vendor - f32", &avp_model, ENOENT ) );
+			CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_AVP,     AVP_BY_NAME,     "AVP Test - no vendor - f32", &avp_model, ENOENT ) );
 			
 			CHECK( 0, fd_msg_new ( cmd_model, 0, &msg ) );
 			CHECK( 0, fd_msg_avp_new ( avp_model, 0, &avp ) );
@@ -328,7 +328,7 @@
 			#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_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));\
+				CHECK( 0, fd_dict_search( fd_g_config->g_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 ) );			\
 			}
@@ -377,11 +377,11 @@
 				struct dict_enumval_request request;
 				
 				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
-				CHECK( 0, fd_dict_search ( fd_g_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->g_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_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->g_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 ) );
 				#if 0
@@ -398,11 +398,11 @@
 				struct dict_enumval_request request;
 				
 				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
-				CHECK( 0, fd_dict_search ( fd_g_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->g_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_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->g_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 ) );
 				#if 0
@@ -457,11 +457,11 @@
 				struct dict_enumval_request request;
 				
 				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
-				CHECK( 0, fd_dict_search ( fd_g_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->g_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_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->g_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 ) );
 				#if 0
@@ -482,11 +482,11 @@
 				struct dict_enumval_request request;
 				
 				CHECK( 0, fd_msg_model ( avpi, &avp_model ) );
-				CHECK( 0, fd_dict_search ( fd_g_dict, DICT_TYPE, TYPE_OF_AVP, avp_model, &type_model, ENOENT ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->g_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_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &request, &value_model, ENOENT ) );
+				CHECK( 0, fd_dict_search ( fd_g_config->g_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 ) );
 				#if 0
@@ -653,7 +653,7 @@
 			struct avp_hdr     * avpdata = NULL;
 			
 			/* Now find the ACR dictionary object */
-			CHECK( 0, fd_dict_search ( fd_g_dict, DICT_AVP, AVP_BY_NAME, "AVP Test - no vendor - f32", &avp_model, ENOENT ) );
+			CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME, "AVP Test - no vendor - f32", &avp_model, ENOENT ) );
 			
 			CPYBUF();
 			CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
@@ -679,7 +679,7 @@
 				/* Change the command-code */
 				buf_cpy[5] = 0x11;
 				CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
-				CHECK( ENOTSUP, fd_msg_parse_dict( msg, fd_g_dict ) );
+				CHECK( ENOTSUP, fd_msg_parse_dict( msg, fd_g_config->g_dict ) );
 				
 				/* reset */
 				CHECK( 0, fd_msg_free ( msg ) );
@@ -694,7 +694,7 @@
 				
 				/* Check that we cannot support this message now */
 				CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
-				CHECK( ENOTSUP, fd_msg_parse_dict( msg, fd_g_dict ) );
+				CHECK( ENOTSUP, fd_msg_parse_dict( msg, fd_g_config->g_dict ) );
 				
 				/* reset */
 				CHECK( 0, fd_msg_free ( msg ) );
@@ -708,7 +708,7 @@
 				
 				/* Check that we can support this message now */
 				CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
-				CHECK( 0, fd_msg_parse_dict( msg, fd_g_dict ) );
+				CHECK( 0, fd_msg_parse_dict( msg, fd_g_config->g_dict ) );
 				
 				#if 0
 				fd_msg_dump_walk(0, msg);
@@ -719,7 +719,7 @@
 			}
 			
 			CHECK( 0, fd_msg_parse_buffer( &buf, 344, &msg) );
-			CHECK( 0, fd_msg_parse_dict( msg, fd_g_dict ) );
+			CHECK( 0, fd_msg_parse_dict( msg, fd_g_config->g_dict ) );
 			#if 0
 			fd_msg_dump_walk(0, msg);
 			#endif
@@ -729,7 +729,7 @@
 		{
 			struct dict_object * rule;
 			
-			CHECK( 0, fd_msg_parse_rules( msg, fd_g_dict, &rule ) );
+			CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->g_dict, &rule ) );
 			
 			/* Use the "AVP Test - rules" AVP to test the rules */
 			{
@@ -748,26 +748,26 @@
 				ADD_AVP( tavp, MSG_BRW_LAST_CHILD, childavp, 73565, "AVP Test - grouped" );
 				
 				/* Check the message is still conform */
-				CHECK( 0, fd_msg_parse_rules( msg, fd_g_dict, &rule ) );
+				CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->g_dict, &rule ) );
 				
 				/* The first avp is optional in fixed position, so remove it and check the message is still OK */
 				CHECK( 0, fd_msg_browse ( tavp, MSG_BRW_FIRST_CHILD, &childavp, NULL) );
 				CHECK( 0, fd_msg_free ( childavp ) );
-				CHECK( 0, fd_msg_parse_rules( msg, fd_g_dict, &rule ) );
+				CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->g_dict, &rule ) );
 				ADD_AVP( tavp, MSG_BRW_FIRST_CHILD, childavp,     0, "AVP Test - no vendor - f32" );
 				
 				
 				/* Now break some rules and check it is detected */
 				#define CHECK_CONFLICT( _msg, _ruleavp, _avpvendor )		{				\
 					struct dict_object * _rule;								\
-					CHECK( EBADMSG,  fd_msg_parse_rules( _msg, fd_g_dict, &_rule ) );			\
+					CHECK( EBADMSG,  fd_msg_parse_rules( _msg, fd_g_config->g_dict, &_rule ) );			\
 					if ((_ruleavp) == NULL) {								\
 						CHECK( NULL, _rule);								\
 					} else {										\
 						struct dict_rule_data   _ruledata;						\
 						struct dict_object *    _avp;							\
 						struct dict_avp_request _req = { (_avpvendor), 0, (_ruleavp) };			\
-						CHECK( 0, fd_dict_search( fd_g_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));	\
+						CHECK( 0, fd_dict_search( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME_AND_VENDOR, &_req, &_avp, ENOENT));	\
 						CHECK( 0, fd_dict_getval( _rule, &_ruledata ) );				\
 						CHECK( _avp, _ruledata.rule_avp );						\
 					}											\
@@ -823,7 +823,7 @@
 					ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - enumos" );
 					
 					/* The message is still conform */
-					CHECK( 0, fd_msg_parse_rules( msg, fd_g_dict, &rule ) );
+					CHECK( 0, fd_msg_parse_rules( msg, fd_g_config->g_dict, &rule ) );
 					
 					/* Now break the rule */
 					ADD_AVP( childavp, MSG_BRW_NEXT, tempavp, 73565, "AVP Test - enumos" );
@@ -864,10 +864,10 @@
 		struct sockaddr_in6 sin6, *psin6;
 		
 		/* Find the CER dictionary object */
-		CHECK( 0, fd_dict_search ( fd_g_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &cer_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &cer_model, ENOENT ) );
 
 		/* Now find the Host-IP-Address dictionary object */
-		CHECK( 0, fd_dict_search ( fd_g_dict, DICT_AVP, AVP_BY_NAME, "Host-IP-Address", &hia_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_AVP, AVP_BY_NAME, "Host-IP-Address", &hia_model, ENOENT ) );
 
 		/* Create the msg instance */
 		CHECK( 0, fd_msg_new ( cer_model, 0, &cer ) );
@@ -944,7 +944,7 @@
 		
 		/* Ok, now let's recreate the message */
 		CHECK( 0, fd_msg_parse_buffer( &buf, 64, &cer) );
-		CHECK( 0, fd_msg_parse_dict( cer, fd_g_dict ) );
+		CHECK( 0, fd_msg_parse_dict( cer, fd_g_config->g_dict ) );
 		
 		/* Get the pointers to the first and last AVP */
 		CHECK( 0, fd_msg_browse( cer, MSG_BRW_FIRST_CHILD, &avp4, NULL) );
@@ -971,31 +971,31 @@
 	{
 		{
 			struct dict_avp_data avp_data = { 91001, 0, "AVP Test 2 - os", 0, 0, AVP_TYPE_OCTETSTRING };
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
 		}
 		{
 			struct dict_avp_data avp_data = { 91002, 0, "AVP Test 2 - i32", 0, 0, AVP_TYPE_INTEGER32 };
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
 		}
 		{
 			struct dict_avp_data avp_data = { 91003, 0, "AVP Test 2 - i64", 0, 0, AVP_TYPE_INTEGER64 };
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
 		}
 		{
 			struct dict_avp_data avp_data = { 91004, 0, "AVP Test 2 - u32", 0, 0, AVP_TYPE_UNSIGNED32 };
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
 		}
 		{
 			struct dict_avp_data avp_data = { 91005, 0, "AVP Test 2 - u64", 0, 0, AVP_TYPE_UNSIGNED64 };
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
 		}
 		{
 			struct dict_avp_data avp_data = { 91006, 0, "AVP Test 2 - f32", 0, 0, AVP_TYPE_FLOAT32 };
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
 		}
 		{
 			struct dict_avp_data avp_data = { 91007, 0, "AVP Test 2 - f64", 0, 0, AVP_TYPE_FLOAT64 };
-			CHECK( 0, fd_dict_new ( fd_g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
+			CHECK( 0, fd_dict_new ( fd_g_config->g_dict, DICT_AVP, &avp_data , NULL, NULL ) );
 		}
 		
 		{
@@ -1009,7 +1009,7 @@
 			struct avp_hdr     * avpdata = NULL;
 			struct msg_hdr     * msgdata = NULL;
 
-			CHECK( 0, fd_dict_search ( fd_g_dict, DICT_COMMAND, CMD_BY_NAME, "Test-Command-Request", &cmd_model, ENOENT ) );
+			CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_COMMAND, CMD_BY_NAME, "Test-Command-Request", &cmd_model, ENOENT ) );
 
 			/* Create a message */
 			CHECK( 0, fd_msg_new ( cmd_model, 0, &msg ) );
@@ -1174,7 +1174,7 @@
 			CHECK( 0, fd_msg_free( msg ) );
 			
 			CHECK( 0, fd_msg_parse_buffer( &buf, 148, &msg) );
-			CHECK( 0, fd_msg_parse_dict( msg, fd_g_dict ) );
+			CHECK( 0, fd_msg_parse_dict( msg, fd_g_config->g_dict ) );
 			#if 0
 			fd_msg_dump_walk(0, msg);
 			#endif
--- a/freeDiameter/tests/testmq.c	Fri Sep 04 18:05:25 2009 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,423 +0,0 @@
-/*********************************************************************************************************
-* Software License Agreement (BSD License)                                                               *
-* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
-*													 *
-* Copyright (c) 2009, 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"
-
-/* Structure for testing threshold function */
-static struct thrh_test {
-	struct mqueue * queue; /* pointer to the queue */
-	int		h_calls; /* number of calls of h_cb */
-	int		l_calls; /* number of calls of l_cb */
-} thrh_td;
-
-/* Callbacks for threasholds test */
-void thrh_cb_h(struct mqueue *queue, void **data)
-{
-	if (thrh_td.h_calls == thrh_td.l_calls) {
-		CHECK( NULL, *data );
-		*data = &thrh_td;
-	} else {
-		CHECK( *data, &thrh_td );
-	}
-	CHECK( queue, thrh_td.queue );
-	
-	/* Update the count */
-	thrh_td.h_calls ++;
-}
-void thrh_cb_l(struct mqueue *queue, void **data)
-{
-	CHECK( 1, data ? 1 : 0 );
-	CHECK( *data, &thrh_td );
-
-	/* Check the queue parameter is correct */
-	CHECK( queue, thrh_td.queue );
-	
-	/* Update the count */
-	thrh_td.l_calls ++;
-	/* Cleanup the data ptr if needed */
-	if (thrh_td.l_calls == thrh_td.h_calls)
-		*data = NULL;
-	/* done */
-}
-
-
-/* Structure that is passed to the test function */
-struct test_data {
-	struct mqueue     * queue; /* pointer to the queue */
-	pthread_barrier_t * bar;   /* if not NULL, barrier to synchronize before getting messages */
-	struct timespec   * ts;	   /* if not NULL, use a timedget instead of a get */
-	int		    nbr;   /* number of messages to retrieve from the queue */
-};
-
-/* The test function, to be threaded */
-static void * test_fct(void * data)
-{
-	int ret = 0, i;
-	struct msg * msg = NULL;
-	struct test_data * td = (struct test_data *) data;
-	
-	if (td->bar != NULL) {
-		ret = pthread_barrier_wait(td->bar);
-		if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
-			CHECK( 0, ret);
-		} else {
-			CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret); /* just for the traces */
-		}
-	}
-	
-	for (i=0; i< td->nbr; i++) {
-		if (td->ts != NULL) {
-			CHECK( 0, fd_mq_timedget(td->queue, &msg, td->ts) );
-		} else {
-			CHECK( 0, fd_mq_get(td->queue, &msg) );
-		}
-	}
-	
-	return NULL;
-}
-
-
-/* Main test routine */
-int main(int argc, char *argv[])
-{
-	struct timespec ts;
-	
-	struct msg * msg1 = NULL;
-	struct msg * msg2 = NULL;
-	struct msg * msg3 = NULL;
-	
-	/* First, initialize the daemon modules */
-	INIT_FD();
-	
-	/* Prolog: create the messages */
-	{
-		struct dict_object * acr_model = NULL;
-		struct dict_object * cer_model = NULL;
-		struct dict_object * dwr_model = NULL;
-
-		CHECK( 0, fd_dict_search ( fd_g_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", 			&acr_model, ENOENT ) );
-		CHECK( 0, fd_dict_search ( fd_g_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", 	&cer_model, ENOENT ) );
-		CHECK( 0, fd_dict_search ( fd_g_dict, DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request",		&dwr_model, ENOENT ) );
-		CHECK( 0, fd_msg_new ( acr_model, 0, &msg1 ) );
-		CHECK( 0, fd_msg_new ( cer_model, 0, &msg2 ) );
-		CHECK( 0, fd_msg_new ( dwr_model, 0, &msg3 ) );
-	}
-	
-	/* Basic operation */
-	{
-		struct mqueue * queue = NULL;
-		int count;
-		struct msg * msg  = NULL;
-		
-		/* Create the queue */
-		CHECK( 0, fd_mq_new(&queue) );
-		
-		/* Check the count is 0 */
-		CHECK( 0, fd_mq_length(queue, &count) );
-		CHECK( 0, count);
-		
-		/* Now enqueue */
-		msg = msg1;
-		CHECK( 0, fd_mq_post(queue, &msg) );
-		msg = msg2;
-		CHECK( 0, fd_mq_post(queue, &msg) );
-		msg = msg3;
-		CHECK( 0, fd_mq_post(queue, &msg) );
-		
-		/* Check the count is 3 */
-		CHECK( 0, fd_mq_length(queue, &count) );
-		CHECK( 3, count);
-		
-		/* Retrieve the first message using fd_mq_get */
-		CHECK( 0, fd_mq_get(queue, &msg) );
-		CHECK( msg1, msg);
-		CHECK( 0, fd_mq_length(queue, &count) );
-		CHECK( 2, count);
-		
-		/* Retrieve the second message using fd_mq_timedget */
-		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
-		ts.tv_sec += 1; /* Set the timeout to 1 second */
-		CHECK( 0, fd_mq_timedget(queue, &msg, &ts) );
-		CHECK( msg2, msg);
-		CHECK( 0, fd_mq_length(queue, &count) );
-		CHECK( 1, count);
-		
-		/* Retrieve the third message using meq_tryget */
-		CHECK( 0, fd_mq_tryget(queue, &msg) );
-		CHECK( msg3, msg);
-		CHECK( 0, fd_mq_length(queue, &count) );
-		CHECK( 0, count);
-		
-		/* Check that another meq_tryget does not block */
-		CHECK( EWOULDBLOCK, fd_mq_tryget(queue, &msg) );
-		CHECK( 0, fd_mq_length(queue, &count) );
-		CHECK( 0, count);
-		
-		/* We're done for basic tests */
-		CHECK( 0, fd_mq_del(&queue) );
-	}
-	
-	/* Test robustness, ensure no messages are lost */
-	{
-#define NBR_MSG		200
-#define NBR_THREADS	60
-		struct mqueue  		*queue = NULL;
-		pthread_barrier_t	 bar;
-		struct test_data	 td_1;
-		struct test_data	 td_2;
-		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;
-		
-		/* Create the queue */
-		CHECK( 0, fd_mq_new(&queue) );
-		
-		/* Create the barrier */
-		CHECK( 0, pthread_barrier_init(&bar, NULL, NBR_THREADS * 2 + 1) );
-		
-		/* Initialize the ts */
-		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
-		ts.tv_sec += 2; /* Set the timeout to 2 second */
-		
-		/* Create the messages */
-		CHECK( 0, fd_dict_search ( fd_g_dict, DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request",		&dwr_model, ENOENT ) );
-		for (i = 0; i < NBR_MSG * NBR_THREADS * 2; i++) {
-			CHECK( 0, fd_msg_new ( dwr_model, 0, &msgs[i] ) );
-		}
-		
-		/* Initialize the test data structures */
-		td_1.queue = queue;
-		td_1.bar = &bar;
-		td_1.ts  = &ts;
-		td_1.nbr = NBR_MSG;
-		td_2.queue = queue;
-		td_2.bar = &bar;
-		td_2.ts  = NULL;
-		td_2.nbr = NBR_MSG;
-		
-		/* Create the threads */
-		for (i=0; i < NBR_THREADS * 2; i++) {
-			CHECK( 0, pthread_create( &thr[i], NULL, test_fct, (i & 1) ? &td_1 : &td_2 ) );
-		}
-		
-		/* Synchronize everyone */
-		{
-			int ret = pthread_barrier_wait(&bar);
-			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
-				CHECK( 0, ret);
-			} else {
-				CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret); /* for trace only */
-			}
-		}
-		
-		/* Now post all the messages */
-		for (i=0; i < NBR_MSG * NBR_THREADS * 2; i++) {
-			msg = msgs[i];
-			CHECK( 0, fd_mq_post(queue, &msg) );
-		}
-		
-		/* Join all threads. This blocks if messages are lost... */
-		for (i=0; i < NBR_THREADS * 2; i++) {
-			CHECK( 0, pthread_join( thr[i], NULL ) );
-		}
-		
-		/* Check the count of the queue is back to 0 */
-		CHECK( 0, fd_mq_length(queue, &count) );
-		CHECK( 0, count);
-		
-		/* Destroy this queue and the messages */
-		CHECK( 0, fd_mq_del(&queue) );
-		for (i=0; i < NBR_MSG * NBR_THREADS * 2; i++) {
-			CHECK( 0, fd_msg_free(  msgs[i] ) );
-		}
-	}
-	
-	/* Test thread cancelation */
-	{
-		struct mqueue      	*queue = NULL;
-		pthread_barrier_t	 bar;
-		struct test_data	 td;
-		pthread_t		 th;
-		
-		/* Create the queue */
-		CHECK( 0, fd_mq_new(&queue) );
-		
-		/* Create the barrier */
-		CHECK( 0, pthread_barrier_init(&bar, NULL, 2) );
-		
-		/* Initialize the ts */
-		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
-		ts.tv_sec += 2; /* Set the timeout to 2 second */
-		
-		/* Initialize the test data structures */
-		td.queue = queue;
-		td.bar = &bar;
-		td.ts  = &ts;
-		td.nbr = 1;
-		
-		/* Create the thread */
-		CHECK( 0, pthread_create( &th, NULL, test_fct, &td ) );
-		
-		/* Wait for the thread to be running */
-		{
-			int ret = pthread_barrier_wait(&bar);
-			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
-				CHECK( 0, ret);
-			} else {
-				CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret );
-			}
-		}
-		
-		/* Now cancel the thread */
-		CHECK( 0, pthread_cancel( th ) );
-		
-		/* Join it */
-		CHECK( 0, pthread_join( th, NULL ) );
-		
-		/* Do the same with the other function */
-		td.ts  = NULL;
-		
-		/* Create the thread */
-		CHECK( 0, pthread_create( &th, NULL, test_fct, &td ) );
-		
-		/* Wait for the thread to be running */
-		{
-			int ret = pthread_barrier_wait(&bar);
-			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
-				CHECK( 0, ret);
-			} else {
-				CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret );
-			}
-		}
-		
-		/* Now cancel the thread */
-		CHECK( 0, pthread_cancel( th ) );
-		
-		/* Join it */
-		CHECK( 0, pthread_join( th, NULL ) );
-		
-		/* Destroy the queue */
-		CHECK( 0, fd_mq_del(&queue) );
-	}
-	
-	/* Test the threashold function */
-	{
-		struct mqueue * queue = NULL;
-		int i;
-		struct msg * msg  = NULL;
-		
-		/* Create the queue */
-		CHECK( 0, fd_mq_new(&queue) );
-		
-		/* Prepare the test data */
-		memset(&thrh_td, 0, sizeof(thrh_td));
-		thrh_td.queue = queue;
-		
-		/* Set the thresholds for the queue */
-		CHECK( 0, fd_mq_setthrhd ( queue, NULL, 6, thrh_cb_h, 4, thrh_cb_l ) );
-		
-		/* Post 5 messages, no cb must be called. */
-		for (i=0; i<5; i++) {
-			msg = msg1;
-			CHECK( 0, fd_mq_post(queue, &msg) );
-		} /* 5 msg in queue */
-		CHECK( 0, thrh_td.h_calls );
-		CHECK( 0, thrh_td.l_calls );
-		
-		/* Get all these messages, and check again */
-		for (i=0; i<5; i++) {
-			CHECK( 0, fd_mq_get(queue, &msg) );
-		} /* 0 msg in queue */
-		CHECK( 0, thrh_td.h_calls );
-		CHECK( 0, thrh_td.l_calls );
-		
-		/* Now, post 6 messages, the high threashold */
-		for (i=0; i<6; i++) {
-			msg = msg1;
-			CHECK( 0, fd_mq_post(queue, &msg) );
-		} /* 6 msg in queue */
-		CHECK( 1, thrh_td.h_calls );
-		CHECK( 0, thrh_td.l_calls );
-		
-		/* Remove 2 messages, to reach the low threshold */
-		for (i=0; i<2; i++) {
-			CHECK( 0, fd_mq_get(queue, &msg) );
-		} /* 4 msg in queue */
-		CHECK( 1, thrh_td.h_calls );
-		CHECK( 1, thrh_td.l_calls );
-		
-		/* Come again at the high threshold */
-		for (i=0; i<2; i++) {
-			msg = msg1;
-			CHECK( 0, fd_mq_post(queue, &msg) );
-		} /* 6 msg in queue */
-		CHECK( 2, thrh_td.h_calls );
-		CHECK( 1, thrh_td.l_calls );
-		
-		/* Suppose the queue continues to grow */
-		for (i=0; i<6; i++) {
-			msg = msg1;
-			CHECK( 0, fd_mq_post(queue, &msg) );
-		} /* 12 msg in queue */
-		CHECK( 3, thrh_td.h_calls );
-		CHECK( 1, thrh_td.l_calls );
-		for (i=0; i<5; i++) {
-			msg = msg1;
-			CHECK( 0, fd_mq_post(queue, &msg) );
-		} /* 17 msg in queue */
-		CHECK( 3, thrh_td.h_calls );
-		CHECK( 1, thrh_td.l_calls );
-		
-		/* Now the queue goes back to 0 messages */
-		for (i=0; i<17; i++) {
-			CHECK( 0, fd_mq_get(queue, &msg) );
-		} /* 0 msg in queue */
-		CHECK( 3, thrh_td.h_calls );
-		CHECK( 3, thrh_td.l_calls );
-		
-		/* We're done for this test */
-		CHECK( 0, fd_mq_del(&queue) );
-	}
-	
-	/* Delete the messages */
-	CHECK( 0, fd_msg_free( msg1 ) );
-	CHECK( 0, fd_msg_free( msg2 ) );
-	CHECK( 0, fd_msg_free( msg3 ) );
-
-	/* That's all for the tests yet */
-	PASSTEST();
-} 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/freeDiameter/tests/testqueues.c	Fri Sep 18 18:54:07 2009 +0900
@@ -0,0 +1,423 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2009, 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"
+
+/* Structure for testing threshold function */
+static struct thrh_test {
+	struct fifo *   queue; /* pointer to the queue */
+	int		h_calls; /* number of calls of h_cb */
+	int		l_calls; /* number of calls of l_cb */
+} thrh_td;
+
+/* Callbacks for threasholds test */
+void thrh_cb_h(struct fifo *queue, void **data)
+{
+	if (thrh_td.h_calls == thrh_td.l_calls) {
+		CHECK( NULL, *data );
+		*data = &thrh_td;
+	} else {
+		CHECK( *data, &thrh_td );
+	}
+	CHECK( queue, thrh_td.queue );
+	
+	/* Update the count */
+	thrh_td.h_calls ++;
+}
+void thrh_cb_l(struct fifo *queue, void **data)
+{
+	CHECK( 1, data ? 1 : 0 );
+	CHECK( *data, &thrh_td );
+
+	/* Check the queue parameter is correct */
+	CHECK( queue, thrh_td.queue );
+	
+	/* Update the count */
+	thrh_td.l_calls ++;
+	/* Cleanup the data ptr if needed */
+	if (thrh_td.l_calls == thrh_td.h_calls)
+		*data = NULL;
+	/* done */
+}
+
+
+/* Structure that is passed to the test function */
+struct test_data {
+	struct fifo     * queue; /* pointer to the queue */
+	pthread_barrier_t * bar;   /* if not NULL, barrier to synchronize before getting messages */
+	struct timespec   * ts;	   /* if not NULL, use a timedget instead of a get */
+	int		    nbr;   /* number of messages to retrieve from the queue */
+};
+
+/* The test function, to be threaded */
+static void * test_fct(void * data)
+{
+	int ret = 0, i;
+	struct msg * msg = NULL;
+	struct test_data * td = (struct test_data *) data;
+	
+	if (td->bar != NULL) {
+		ret = pthread_barrier_wait(td->bar);
+		if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
+			CHECK( 0, ret);
+		} else {
+			CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret); /* just for the traces */
+		}
+	}
+	
+	for (i=0; i< td->nbr; i++) {
+		if (td->ts != NULL) {
+			CHECK( 0, fd_fifo_timedget(td->queue, &msg, td->ts) );
+		} else {
+			CHECK( 0, fd_fifo_get(td->queue, &msg) );
+		}
+	}
+	
+	return NULL;
+}
+
+
+/* Main test routine */
+int main(int argc, char *argv[])
+{
+	struct timespec ts;
+	
+	struct msg * msg1 = NULL;
+	struct msg * msg2 = NULL;
+	struct msg * msg3 = NULL;
+	
+	/* First, initialize the daemon modules */
+	INIT_FD();
+	
+	/* Prolog: create the messages */
+	{
+		struct dict_object * acr_model = NULL;
+		struct dict_object * cer_model = NULL;
+		struct dict_object * dwr_model = NULL;
+
+		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", 			&acr_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", 	&cer_model, ENOENT ) );
+		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request",		&dwr_model, ENOENT ) );
+		CHECK( 0, fd_msg_new ( acr_model, 0, &msg1 ) );
+		CHECK( 0, fd_msg_new ( cer_model, 0, &msg2 ) );
+		CHECK( 0, fd_msg_new ( dwr_model, 0, &msg3 ) );
+	}
+	
+	/* Basic operation */
+	{
+		struct fifo * queue = NULL;
+		int count;
+		struct msg * msg  = NULL;
+		
+		/* Create the queue */
+		CHECK( 0, fd_fifo_new(&queue) );
+		
+		/* Check the count is 0 */
+		CHECK( 0, fd_fifo_length(queue, &count) );
+		CHECK( 0, count);
+		
+		/* Now enqueue */
+		msg = msg1;
+		CHECK( 0, fd_fifo_post(queue, &msg) );
+		msg = msg2;
+		CHECK( 0, fd_fifo_post(queue, &msg) );
+		msg = msg3;
+		CHECK( 0, fd_fifo_post(queue, &msg) );
+		
+		/* Check the count is 3 */
+		CHECK( 0, fd_fifo_length(queue, &count) );
+		CHECK( 3, count);
+		
+		/* 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) );
+		CHECK( 2, count);
+		
+		/* 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) );
+		CHECK( 1, count);
+		
+		/* Retrieve the third message using meq_tryget */
+		CHECK( 0, fd_fifo_tryget(queue, &msg) );
+		CHECK( msg3, msg);
+		CHECK( 0, fd_fifo_length(queue, &count) );
+		CHECK( 0, count);
+		
+		/* Check that another meq_tryget does not block */
+		CHECK( EWOULDBLOCK, fd_fifo_tryget(queue, &msg) );
+		CHECK( 0, fd_fifo_length(queue, &count) );
+		CHECK( 0, count);
+		
+		/* We're done for basic tests */
+		CHECK( 0, fd_fifo_del(&queue) );
+	}
+	
+	/* Test robustness, ensure no messages are lost */
+	{
+#define NBR_MSG		200
+#define NBR_THREADS	60
+		struct fifo  		*queue = NULL;
+		pthread_barrier_t	 bar;
+		struct test_data	 td_1;
+		struct test_data	 td_2;
+		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;
+		
+		/* Create the queue */
+		CHECK( 0, fd_fifo_new(&queue) );
+		
+		/* Create the barrier */
+		CHECK( 0, pthread_barrier_init(&bar, NULL, NBR_THREADS * 2 + 1) );
+		
+		/* Initialize the ts */
+		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
+		ts.tv_sec += 2; /* Set the timeout to 2 second */
+		
+		/* Create the messages */
+		CHECK( 0, fd_dict_search ( fd_g_config->g_dict, DICT_COMMAND, CMD_BY_NAME, "Device-Watchdog-Request",		&dwr_model, ENOENT ) );
+		for (i = 0; i < NBR_MSG * NBR_THREADS * 2; i++) {
+			CHECK( 0, fd_msg_new ( dwr_model, 0, &msgs[i] ) );
+		}
+		
+		/* Initialize the test data structures */
+		td_1.queue = queue;
+		td_1.bar = &bar;
+		td_1.ts  = &ts;
+		td_1.nbr = NBR_MSG;
+		td_2.queue = queue;
+		td_2.bar = &bar;
+		td_2.ts  = NULL;
+		td_2.nbr = NBR_MSG;
+		
+		/* Create the threads */
+		for (i=0; i < NBR_THREADS * 2; i++) {
+			CHECK( 0, pthread_create( &thr[i], NULL, test_fct, (i & 1) ? &td_1 : &td_2 ) );
+		}
+		
+		/* Synchronize everyone */
+		{
+			int ret = pthread_barrier_wait(&bar);
+			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
+				CHECK( 0, ret);
+			} else {
+				CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret); /* for trace only */
+			}
+		}
+		
+		/* Now post all the messages */
+		for (i=0; i < NBR_MSG * NBR_THREADS * 2; i++) {
+			msg = msgs[i];
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		}
+		
+		/* Join all threads. This blocks if messages are lost... */
+		for (i=0; i < NBR_THREADS * 2; i++) {
+			CHECK( 0, pthread_join( thr[i], NULL ) );
+		}
+		
+		/* Check the count of the queue is back to 0 */
+		CHECK( 0, fd_fifo_length(queue, &count) );
+		CHECK( 0, count);
+		
+		/* Destroy this queue and the messages */
+		CHECK( 0, fd_fifo_del(&queue) );
+		for (i=0; i < NBR_MSG * NBR_THREADS * 2; i++) {
+			CHECK( 0, fd_msg_free(  msgs[i] ) );
+		}
+	}
+	
+	/* Test thread cancelation */
+	{
+		struct fifo      	*queue = NULL;
+		pthread_barrier_t	 bar;
+		struct test_data	 td;
+		pthread_t		 th;
+		
+		/* Create the queue */
+		CHECK( 0, fd_fifo_new(&queue) );
+		
+		/* Create the barrier */
+		CHECK( 0, pthread_barrier_init(&bar, NULL, 2) );
+		
+		/* Initialize the ts */
+		CHECK(0, clock_gettime(CLOCK_REALTIME, &ts));
+		ts.tv_sec += 2; /* Set the timeout to 2 second */
+		
+		/* Initialize the test data structures */
+		td.queue = queue;
+		td.bar = &bar;
+		td.ts  = &ts;
+		td.nbr = 1;
+		
+		/* Create the thread */
+		CHECK( 0, pthread_create( &th, NULL, test_fct, &td ) );
+		
+		/* Wait for the thread to be running */
+		{
+			int ret = pthread_barrier_wait(&bar);
+			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
+				CHECK( 0, ret);
+			} else {
+				CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret );
+			}
+		}
+		
+		/* Now cancel the thread */
+		CHECK( 0, pthread_cancel( th ) );
+		
+		/* Join it */
+		CHECK( 0, pthread_join( th, NULL ) );
+		
+		/* Do the same with the other function */
+		td.ts  = NULL;
+		
+		/* Create the thread */
+		CHECK( 0, pthread_create( &th, NULL, test_fct, &td ) );
+		
+		/* Wait for the thread to be running */
+		{
+			int ret = pthread_barrier_wait(&bar);
+			if (ret != PTHREAD_BARRIER_SERIAL_THREAD) {
+				CHECK( 0, ret);
+			} else {
+				CHECK( PTHREAD_BARRIER_SERIAL_THREAD, ret );
+			}
+		}
+		
+		/* Now cancel the thread */
+		CHECK( 0, pthread_cancel( th ) );
+		
+		/* Join it */
+		CHECK( 0, pthread_join( th, NULL ) );
+		
+		/* Destroy the queue */
+		CHECK( 0, fd_fifo_del(&queue) );
+	}
+	
+	/* Test the threashold function */
+	{
+		struct fifo * queue = NULL;
+		int i;
+		struct msg * msg  = NULL;
+		
+		/* Create the queue */
+		CHECK( 0, fd_fifo_new(&queue) );
+		
+		/* Prepare the test data */
+		memset(&thrh_td, 0, sizeof(thrh_td));
+		thrh_td.queue = queue;
+		
+		/* Set the thresholds for the queue */
+		CHECK( 0, fd_fifo_setthrhd ( queue, NULL, 6, thrh_cb_h, 4, thrh_cb_l ) );
+		
+		/* Post 5 messages, no cb must be called. */
+		for (i=0; i<5; i++) {
+			msg = msg1;
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		} /* 5 msg in queue */
+		CHECK( 0, thrh_td.h_calls );
+		CHECK( 0, thrh_td.l_calls );
+		
+		/* Get all these messages, and check again */
+		for (i=0; i<5; i++) {
+			CHECK( 0, fd_fifo_get(queue, &msg) );
+		} /* 0 msg in queue */
+		CHECK( 0, thrh_td.h_calls );
+		CHECK( 0, thrh_td.l_calls );
+		
+		/* Now, post 6 messages, the high threashold */
+		for (i=0; i<6; i++) {
+			msg = msg1;
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		} /* 6 msg in queue */
+		CHECK( 1, thrh_td.h_calls );
+		CHECK( 0, thrh_td.l_calls );
+		
+		/* Remove 2 messages, to reach the low threshold */
+		for (i=0; i<2; i++) {
+			CHECK( 0, fd_fifo_get(queue, &msg) );
+		} /* 4 msg in queue */
+		CHECK( 1, thrh_td.h_calls );
+		CHECK( 1, thrh_td.l_calls );
+		
+		/* Come again at the high threshold */
+		for (i=0; i<2; i++) {
+			msg = msg1;
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		} /* 6 msg in queue */
+		CHECK( 2, thrh_td.h_calls );
+		CHECK( 1, thrh_td.l_calls );
+		
+		/* Suppose the queue continues to grow */
+		for (i=0; i<6; i++) {
+			msg = msg1;
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		} /* 12 msg in queue */
+		CHECK( 3, thrh_td.h_calls );
+		CHECK( 1, thrh_td.l_calls );
+		for (i=0; i<5; i++) {
+			msg = msg1;
+			CHECK( 0, fd_fifo_post(queue, &msg) );
+		} /* 17 msg in queue */
+		CHECK( 3, thrh_td.h_calls );
+		CHECK( 1, thrh_td.l_calls );
+		
+		/* Now the queue goes back to 0 messages */
+		for (i=0; i<17; i++) {
+			CHECK( 0, fd_fifo_get(queue, &msg) );
+		} /* 0 msg in queue */
+		CHECK( 3, thrh_td.h_calls );
+		CHECK( 3, thrh_td.l_calls );
+		
+		/* We're done for this test */
+		CHECK( 0, fd_fifo_del(&queue) );
+	}
+	
+	/* Delete the messages */
+	CHECK( 0, fd_msg_free( msg1 ) );
+	CHECK( 0, fd_msg_free( msg2 ) );
+	CHECK( 0, fd_msg_free( msg3 ) );
+
+	/* That's all for the tests yet */
+	PASSTEST();
+} 
--- a/freeDiameter/tests/tests.h	Fri Sep 04 18:05:25 2009 +0900
+++ b/freeDiameter/tests/tests.h	Fri Sep 18 18:54:07 2009 +0900
@@ -74,6 +74,8 @@
 }
 
 static int test_verbo = 0;
+static struct fd_config conf;
+struct fd_config * fd_g_config = &conf;
 
 /* Define the standard check routines */
 #define CHECK( _val, _assert ){				\
@@ -96,12 +98,13 @@
 }
 
 /* Minimum inits */
-#define INIT_FD() {					\
-	CHECK( 0, fd_lib_init() );			\
-	fd_log_threadname(basename(__FILE__));		\
-	CHECK( 0, fd_dict_init(&fd_g_dict) );		\
-	CHECK( 0, fd_dict_base_protocol(fd_g_dict) );	\
-	parse_cmdline(argc, argv);			\
+#define INIT_FD() {						\
+	memset(fd_g_config, 0, sizeof(struct fd_config));	\
+	CHECK( 0, fd_lib_init() );				\
+	fd_log_threadname(basename(__FILE__));			\
+	CHECK( 0, fd_conf_init() );				\
+	CHECK( 0, fd_dict_base_protocol(fd_g_config->g_dict) );	\
+	parse_cmdline(argc, argv);				\
 }
 
 static inline void parse_cmdline(int argc, char * argv[]) {
--- a/include/freeDiameter/CMakeLists.txt	Fri Sep 04 18:05:25 2009 +0900
+++ b/include/freeDiameter/CMakeLists.txt	Fri Sep 18 18:54:07 2009 +0900
@@ -71,6 +71,9 @@
 # malloc.h ?
 CHECK_INCLUDE_FILES (malloc.h HAVE_MALLOC_H)
 
+# signalent.h ? -- found in strace distrib; just for nice signal names...
+CHECK_INCLUDE_FILES (signalent.h HAVE_SIGNALENT_H)
+
 # The default configuration file name
 IF (NOT DEFAULT_CONF_FILE)
    SET(DEFAULT_CONF_FILE "freeDiameter.conf")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/freeDiameter/extension.h	Fri Sep 18 18:54:07 2009 +0900
@@ -0,0 +1,63 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2009, 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.								 *
+*********************************************************************************************************/
+
+#ifndef _EXTENSION_H
+#define _EXTENSION_H
+
+/* Include definition of freeDiameter API */
+#include <freeDiameter/freeDiameter-host.h>
+#include <freeDiameter/freeDiameter.h>
+
+/* Macro that define the entry point of the extension */
+#define EXTENSION_ENTRY(_name, _function)						\
+static int extension_loaded = 0;							\
+int fd_ext_init(int major, int minor, char * conffile) {				\
+	if ((major != FD_PROJECT_VERSION_MAJOR)						\
+		|| (minor != FD_PROJECT_VERSION_MINOR)) {				\
+		fprintf(stderr, "This extension (" _name ") was compiled for a different version of freeDiameter.\n");	\
+		TRACE_DEBUG(INFO, "daemon %d.%d != ext %d.%d",				\
+			major, minor,							\
+			FD_PROJECT_VERSION_MAJOR, FD_PROJECT_VERSION_MINOR);		\
+		return EINVAL;								\
+	}										\
+	if (extension_loaded) {								\
+		fprintf(stderr, "Extension (" _name ") cannot be loaded twice!\n");	\
+		return ENOTSUP;								\
+	}										\
+	extension_loaded++;								\
+	return (_function)(conffile);							\
+}														
+
+#endif /* _EXTENSION_H */
--- a/include/freeDiameter/freeDiameter-host.h.in	Fri Sep 04 18:05:25 2009 +0900
+++ b/include/freeDiameter/freeDiameter-host.h.in	Fri Sep 18 18:54:07 2009 +0900
@@ -39,16 +39,31 @@
 
 #cmakedefine HAVE_NTOHLL
 #cmakedefine HAVE_MALLOC_H
+#cmakedefine HAVE_SIGNALENT_H
 
 #cmakedefine HOST_BIG_ENDIAN @HOST_BIG_ENDIAN@
 
 #cmakedefine DISABLE_SCTP
 
-#cmakedefine PROJECT_NAME "@PROJECT_NAME@"
-#cmakedefine CMAKE_PROJECT_NAME "@CMAKE_PROJECT_NAME@"
-#cmakedefine PROJECT_VERSION "@PROJECT_VERSION@"
-#cmakedefine PROJECT_COPYRIGHT "@PROJECT_COPYRIGHT@"
+#cmakedefine FD_PROJECT_BINARY "@FD_PROJECT_BINARY@"
+#cmakedefine FD_PROJECT_NAME "@FD_PROJECT_NAME@"
+#cmakedefine FD_PROJECT_VERSION_MAJOR @FD_PROJECT_VERSION_MAJOR@
+#ifndef FD_PROJECT_VERSION_MAJOR
+# define FD_PROJECT_VERSION_MAJOR 0
+#endif /*FD_PROJECT_VERSION_MAJOR*/
+#cmakedefine FD_PROJECT_VERSION_MINOR @FD_PROJECT_VERSION_MINOR@
+#ifndef FD_PROJECT_VERSION_MINOR
+# define FD_PROJECT_VERSION_MINOR 0
+#endif /*FD_PROJECT_VERSION_MINOR*/
+#cmakedefine FD_PROJECT_VERSION_REV   @FD_PROJECT_VERSION_REV@
+#ifndef FD_PROJECT_VERSION_REV
+# define FD_PROJECT_VERSION_REV 0
+#endif /*FD_PROJECT_VERSION_REV*/
+/* HG_VERSION */
+/* PACKAGE_HG_REVISION */
+#cmakedefine FD_PROJECT_COPYRIGHT "@FD_PROJECT_COPYRIGHT@"
 
 #cmakedefine DEFAULT_CONF_FILE "@DEFAULT_CONF_FILE@"
 
+
 #endif /* FD_IS_CONFIG */
--- a/include/freeDiameter/freeDiameter.h	Fri Sep 04 18:05:25 2009 +0900
+++ b/include/freeDiameter/freeDiameter.h	Fri Sep 18 18:54:07 2009 +0900
@@ -40,9 +40,77 @@
 #include <freeDiameter/libfreeDiameter.h>
 
 
-/* The global dictionary */
-extern struct dictionary * fd_g_dict;
+/* Structure to hold the configuration of the freeDiameter daemon */
+struct fd_config {
+	int		 eyec;		/* Eye catcher: EYEC_CONFIG */
+	char		*conf_file;	/* Configuration file to parse, default is DEFAULT_CONF_FILE */
+	
+	char   		*diam_id;	/* Diameter Identity of the local peer (FQDN -- UTF-8) */
+	size_t		 diam_id_len;	/* length of the previous string */
+	char		*diam_realm;	/* Diameter realm of the local peer, default to realm part of diam_id */
+	size_t		 diam_realm_len;/* length of the previous string */
+	
+	uint16_t	 loc_port;	/* the local port for legacy Diameter (default: 3868) in host byte order */
+	uint16_t	 loc_port_tls;	/* the local port for Diameter/TLS (default: 3869) in host byte order */
+	uint16_t	 loc_sctp_str;	/* default max number of streams for SCTP associations (def: 30) */
+	struct fd_list	 loc_endpoints;	/* the local endpoints to bind the server to. list of struct fd_endpoint. default is empty (bind all) */
+	struct {
+		unsigned no_ip4 : 1;	/* disable IP */
+		unsigned no_ip6 : 1;	/* disable IPv6 */
+		unsigned no_tcp : 1;	/* disable use of TCP */
+		unsigned no_sctp: 1;	/* disable the use of SCTP */
+		unsigned pr_tcp	: 1;	/* prefer TCP over SCTP */
+		unsigned tls_alg: 1;	/* TLS algorithm for initiated cnx. 0: separate port. 1: inband-security (old) */
+		unsigned no_fwd : 1;	/* the peer does not relay messages (0xffffff app id) */
+	} 		 flags;
+	
+	unsigned int	 timer_tc;	/* The value in seconds of the default Tc timer */
+	unsigned int 	 timer_tw;	/* The value in seconds of the default Tw timer */
+	
+	uint32_t	 or_state_id;	/* The value to use in Origin-State-Id, default to random value */
+	struct dictionary *g_dict;	/* pointer to the global dictionary */
+	struct fifo	  *g_fifo_main;	/* FIFO queue of events in the daemon main (struct fd_event items) */
+};
+
+#define	EYEC_CONFIG	0xC011F16
 
+/* The pointer to access the global configuration, initalized in main */
+extern struct fd_config *fd_g_config;
+
+/* Endpoints */
+struct fd_endpoint {
+	struct fd_list  chain;	/* link in loc_endpoints list */
+	sSS		ss;	/* the socket information. */
+};
+
+/* Events */
+struct fd_event {
+	int	 code; /* codespace depends on the queue */
+	void    *data;
+};
+
+/* send an event */
+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;
+}
+/* receive an event */
+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;
+}
 
 /***************************************/
 /*   Sending a message on the network  */
--- a/include/freeDiameter/libfreeDiameter.h	Fri Sep 04 18:05:25 2009 +0900
+++ b/include/freeDiameter/libfreeDiameter.h	Fri Sep 18 18:54:07 2009 +0900
@@ -36,10 +36,19 @@
 /* This file contains the definitions of functions and types used by the libfreeDiameter library.
  *
  * This library is meant to be used by both the freeDiameter daemon and its extensions.
+ * It provides the tools to manipulate Diameter messages and related data.
+ * This file should always be included as #include <freeDiameter/libfreeDiameter.h>
  *
- * It provides the tools to manipulate Diameter messages and related data.
- *
- * This file should always be included as #include <freeDiameter/libfreeDiameter.h>
+ * The file contains the following parts:
+ *	DEBUG
+ *	MACROS
+ *	THREADS
+ *	LISTS
+ *	DICTIONARY
+ *	SESSIONS
+ *	MESSAGES
+ *	DISPATCH
+ *	QUEUES
  */
 
 #ifndef _LIBFREEDIAMETER_H
@@ -296,10 +305,10 @@
 #define sSA4	struct sockaddr_in
 #define sSA6	struct sockaddr_in6
 
-/* Dump one sockaddr */
-#define sSA_DUMP( level, text, sa ) {				\
+/* Dump one sockaddr Node information */
+#define sSA_DUMP_NODE( sa, flag ) {				\
 	sSA * __sa = (sSA *)(sa);				\
-	char *__str, __addrbuf[INET6_ADDRSTRLEN];		\
+	char __addrbuf[INET6_ADDRSTRLEN];			\
 	if (__sa) {						\
 	  int __rc = getnameinfo(__sa, 				\
 	  		sizeof(sSS),				\
@@ -307,16 +316,16 @@
 			sizeof(__addrbuf),			\
 			NULL,					\
 			0,					\
-			0);					\
+			flag);					\
 	  if (__rc)						\
-	  	__str = (char *)gai_strerror(__rc);		\
+	  	fd_log_debug((char *)gai_strerror(__rc));	\
 	  else							\
-	  	__str = &__addrbuf[0];				\
+	  	fd_log_debug(&__addrbuf[0]);			\
 	} else {						\
-		__str = "(NULL / ANY)";				\
+		fd_log_debug("(NULL / ANY)");			\
 	}							\
-	TRACE_DEBUG(level, text "%s", __str);			\
 }
+/* if needed, add sSA_DUMP_SERVICE */
 
 /* The sockaddr length of a sSS structure */
 #define sSSlen( _ss_ )	\
@@ -2274,65 +2283,65 @@
 
 
 /*============================================================*/
-/*                    MESSAGE QUEUES                          */
+/*                     QUEUES                                 */
 /*============================================================*/
 
-/* Management of queues of messages */
+/* Management of FIFO queues of elements */
 
-/* A message queue is an opaque object */
-struct mqueue;
+/* A queue is an opaque object */
+struct fifo;
 
 /*
- * FUNCTION:	fd_mq_new
+ * FUNCTION:	fd_fifo_new
  *
  * PARAMETERS:
- *  queue	: Upon success, a pointer to the new message queue is saved here.
+ *  queue	: Upon success, a pointer to the new queue is saved here.
  *
  * DESCRIPTION: 
- *  Create a new empty message queue.
+ *  Create a new empty queue.
  *
  * RETURN VALUE :
- *  0		: The message queue has been initialized successfully.
+ *  0		: The queue has been initialized successfully.
  *  EINVAL 	: The parameter is invalid.
  *  ENOMEM	: Not enough memory to complete the creation.  
  */
-int fd_mq_new ( struct mqueue ** queue );
+int fd_fifo_new ( struct fifo ** queue );
 
 /*
- * FUNCTION:	fd_mq_del
+ * FUNCTION:	fd_fifo_del
  *
  * PARAMETERS:
- *  queue	: Pointer to an empty message queue to delete.
+ *  queue	: Pointer to an empty queue to delete.
  *
  * DESCRIPTION: 
- *  Destroys a message queue. This is only possible if no thread is waiting for a message,
+ *  Destroys a queue. This is only possible if no thread is waiting for an element,
  * and the queue is empty.
  *
  * RETURN VALUE:
- *  0		: The message queue has been destroyed successfully.
+ *  0		: The queue has been destroyed successfully.
  *  EINVAL 	: The parameter is invalid.
  */
-int fd_mq_del ( struct mqueue  ** queue );
+int fd_fifo_del ( struct fifo  ** queue );
 
 /*
- * FUNCTION:	fd_mq_length
+ * FUNCTION:	fd_fifo_length
  *
  * PARAMETERS:
- *  queue	: The queue from which to retrieve the length.
- *  length	: Upon success, the current number of messages in the queue is stored here.
+ *  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.
  *
  * DESCRIPTION: 
- *  Retrieve the number of messages pending in a queue.
+ *  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_mq_length ( struct mqueue * queue, int * length );
-int fd_mq_length_noerr ( struct mqueue * queue ); /* alternate with no error checking */
+int fd_fifo_length ( struct fifo * queue, int * length );
+int fd_fifo_length_noerr ( struct fifo * queue ); /* no error checking version */
 
 /*
- * FUNCTION:	fd_mq_setthrhd
+ * FUNCTION:	fd_fifo_setthrhd
  *
  * PARAMETERS:
  *  queue	: The queue for which the thresholds are being set.
@@ -2344,98 +2353,106 @@
  *
  * DESCRIPTION: 
  *  This function allows to adjust the number of producer / consumer threads of a queue.
- * If the consumer are slower than the producers, the number of messages in the queue increase.
+ * If the consumer are slower than the producers, the number of elements in the queue increase.
  * By setting a "high" value, we allow a callback to be called when this number is too high.
  * The typical use would be to create an additional consumer thread in this callback.
  * If the queue continues to grow, the callback will be called again when the length is 2 * high, then 3*high, ... N * high
- * (the callback itself may implement a limit on the number of consumers that can be created)
+ * (the callback itself should implement a limit on the number of consumers that can be created)
  * When the queue starts to decrease, and the number of elements go under ((N - 1) * high + low, the l_cb callback is called
- * and would typially stop one of the consumer threads. If the queue continue to reduce, l_cb is again called at (N-2)*high + low,
+ * and would typially stop one of the consumer threads. If the queue continues to reduce, l_cb is again called at (N-2)*high + low,
  * and so on.
  *
  * Since there is no destructor for the data pointer, if cleanup operations are required, they should be performed in
  * l_cb when the length of the queue is becoming < low.
  *
- * Note that the callbacks are called synchronously, during fd_mq_post or fd_mq_get. Their operation should be quick.
+ * Note that the callbacks are called synchronously, during fd_fifo_post or fd_fifo_get. Their operation should be quick.
  *
  * RETURN VALUE:
  *  0		: The thresholds have been set
  *  EINVAL 	: A parameter is invalid.
  */
-int fd_mq_setthrhd ( struct mqueue * queue, void * data, uint16_t high, void (*h_cb)(struct mqueue *, void **), uint16_t low, void (*l_cb)(struct mqueue *, void **) );
+int fd_fifo_setthrhd ( struct fifo * queue, void * data, uint16_t high, void (*h_cb)(struct fifo *, void **), uint16_t low, void (*l_cb)(struct fifo *, void **) );
 
 /*
- * FUNCTION:	fd_mq_post
+ * FUNCTION:	fd_fifo_post
  *
  * PARAMETERS:
- *  queue	: The queue in which the message must be posted.
- *  msg		: The message that is put in the queue.
+ *  queue	: The queue in which the element must be posted.
+ *  item	: The element that is put in the queue.
  *
  * DESCRIPTION: 
- *  A message is added in a queue. Messages are retrieved from the queue (in FIFO order)
- *  with the fd_mq_get, fd_mq_tryget, or fd_mq_timedget functions.
+ *  An element is added in a queue. Elements are retrieved from the queue in FIFO order
+ *  with the fd_fifo_get, fd_fifo_tryget, or fd_fifo_timedget functions.
  *
  * RETURN VALUE:
- *  0		: The message is queued.
+ *  0		: The element is queued.
  *  EINVAL 	: A parameter is invalid.
  *  ENOMEM 	: Not enough memory to complete the operation.
  */
-int fd_mq_post ( struct mqueue * queue, struct msg ** msg );
+int fd_fifo_post_int ( struct fifo * queue, void ** item );
+#define fd_fifo_post(queue, item) \
+	fd_fifo_post_int((queue), (void *)(item))
 
 /*
- * FUNCTION:	fd_mq_get
+ * FUNCTION:	fd_fifo_get
  *
  * PARAMETERS:
- *  queue	: The queue from which the message must be retrieved.
- *  msg		: On return, the first message of the queue is stored here.
+ *  queue	: The queue from which the first element must be retrieved.
+ *  item	: On return, the first element of the queue is stored here.
  *
  * DESCRIPTION: 
- *  This function retrieves a message from a queue. If the queue is empty, the function will block the 
- * thread until a new message is posted to the queue, or until the thread is canceled (in which case the 
+ *  This function retrieves the first element from a queue. If the queue is empty, the function will block the 
+ * thread until a new element is posted to the queue, or until the thread is canceled (in which case the 
  * function does not return).
  *
  * RETURN VALUE:
- *  0		: A new message has been retrieved.
+ *  0		: A new element has been retrieved.
  *  EINVAL 	: A parameter is invalid.
  */
-int fd_mq_get ( struct mqueue * queue, struct msg ** msg );
+int fd_fifo_get_int ( struct fifo * queue, void ** item );
+#define fd_fifo_get(queue, item) \
+	fd_fifo_get_int((queue), (void *)(item))
 
 /*
- * FUNCTION:	fd_mq_tryget
+ * FUNCTION:	fd_fifo_tryget
  *
  * PARAMETERS:
- *  queue	: The queue from which the message must be retrieved.
+ *  queue	: The queue from which the element must be retrieved.
  *  msg		: On return, the message is stored here.
  *
  * DESCRIPTION: 
- *  This function is similar to fd_mq_get, except that it will not block if 
+ *  This function is similar to fd_fifo_get, except that it will not block if 
  * the queue is empty, but return EWOULDBLOCK instead.
  *
  * RETURN VALUE:
- *  0		: A new message has been retrieved.
+ *  0		: A new element has been retrieved.
  *  EINVAL 	: A parameter is invalid.
  *  EWOULDBLOCK : The queue was empty.
  */
-int fd_mq_tryget ( struct mqueue * queue, struct msg ** msg );
+int fd_fifo_tryget_int ( struct fifo * queue, void ** item );
+#define fd_fifo_tryget(queue, item) \
+	fd_fifo_tryget_int((queue), (void *)(item))
 
 /*
- * FUNCTION:	fd_mq_timedget
+ * FUNCTION:	fd_fifo_timedget
  *
  * PARAMETERS:
- *  queue	: The queue from which the message must be retrieved.
- *  msg		: On return, the message is stored here.
- *  abstime	: the absolute time until which we allow waiting for a message.
+ *  queue	: The queue from which the element must be retrieved.
+ *  item	: On return, the element is stored here.
+ *  abstime	: the absolute time until which we allow waiting for an item.
  *
  * DESCRIPTION: 
- *  This function is similar to fd_mq_get, except that it will block if the queue is empty 
+ *  This function is similar to fd_fifo_get, except that it will block if the queue is empty 
  * only until the absolute time abstime (see pthread_cond_timedwait for + info).
  * If the queue is still empty when the time expires, the function returns ETIMEDOUT
  *
  * RETURN VALUE:
- *  0		: A new message has been retrieved.
+ *  0		: A new item has been retrieved.
  *  EINVAL 	: A parameter is invalid.
- *  ETIMEDOUT   : The time out has passed and no message has been received.
+ *  ETIMEDOUT   : The time out has passed and no item has been received.
  */
-int fd_mq_timedget ( struct mqueue * queue, struct msg ** msg, const struct timespec *abstime );
+int fd_fifo_timedget_int ( struct fifo * queue, void ** item, const struct timespec *abstime );
+#define fd_fifo_timedget(queue, item, abstime) \
+	fd_fifo_timedget_int((queue), (void *)(item), (abstime))
 
 #endif /* _LIBFREEDIAMETER_H */
--- a/libfreeDiameter/CMakeLists.txt	Fri Sep 04 18:05:25 2009 +0900
+++ b/libfreeDiameter/CMakeLists.txt	Fri Sep 18 18:54:07 2009 +0900
@@ -1,8 +1,6 @@
 # Name of the subproject
 Project("libfreeDiameter" C)
 
-SET(PROJECT_COPYRIGHT "Copyright (c) 2008-2009, WIDE Project (www.wide.ad.jp) and NICT (www.nict.go.jp)")
-
 # List of source files for the library
 SET(LFD_SRC
 	libfD.h
@@ -12,7 +10,7 @@
 	lists.c
 	log.c
 	messages.c
-	mqueues.c
+	queues.c
 	sessions.c
 	)
 
--- a/libfreeDiameter/mqueues.c	Fri Sep 04 18:05:25 2009 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,394 +0,0 @@
-/*********************************************************************************************************
-* Software License Agreement (BSD License)                                                               *
-* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
-*													 *
-* Copyright (c) 2008, 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.								 *
-*********************************************************************************************************/
-
-/* Messages queues module.
- *
- * The threads that call these functions must be in the cancellation state PTHREAD_CANCEL_ENABLE and type PTHREAD_CANCEL_DEFERRED.
- * This is the default state and type on thread creation.
- *
- * In order to destroy properly a queue, the application must:
- *  -> shutdown any process that can add into the queue first.
- *  -> pthread_cancel any thread that could be waiting on the queue.
- *  -> consume any message that is in the queue, using meq_tryget.
- *  -> then destroy the queue using meq_del.
- */
-
-#include "libfD.h"
-
-/* Definition of a message queue object */
-struct mqueue {
-	int		eyec;	/* An eye catcher, also used to check a queue is valid. MQ_EYEC */
-	
-	pthread_mutex_t	mtx;	/* Mutex protecting this queue */
-	pthread_cond_t	cond;	/* condition variable of the list */
-	
-	struct fd_list	list;	/* sentinel for the list of messages */
-	int		count;	/* number of objects in the list */
-	int		thrs;	/* number of threads waiting for a new message (when count is 0) */
-	
-	uint16_t	high;	/* High level threshold (see libfreeDiameter.h for details) */
-	uint16_t	low;	/* Low level threshhold */
-	void 		*data;	/* Opaque pointer for threshold callbacks */
-	void		(*h_cb)(struct mqueue *, void **); /* The callbacks */
-	void		(*l_cb)(struct mqueue *, void **);
-	int 		highest;/* The highest count value for which h_cb has been called */
-};
-
-/* The eye catcher value */
-#define MQ_EYEC	0xe7ec1130
-
-/* Macro to check a pointer */
-#define CHECK_QUEUE( _queue ) (( (_queue) != NULL) && ( (_queue)->eyec == MQ_EYEC) )
-
-
-/* Create a new message queue */
-int fd_mq_new ( struct mqueue ** queue )
-{
-	struct mqueue * new;
-	
-	TRACE_ENTRY( "%p", queue );
-	
-	CHECK_PARAMS( queue );
-	
-	/* Create a new object */
-	CHECK_MALLOC( new = malloc (sizeof (struct mqueue) )  );
-	
-	/* Initialize the content */
-	memset(new, 0, sizeof(struct mqueue));
-	
-	new->eyec = MQ_EYEC;
-	CHECK_POSIX( pthread_mutex_init(&new->mtx, NULL) );
-	CHECK_POSIX( pthread_cond_init(&new->cond, NULL) );
-	
-	fd_list_init(&new->list, NULL);
-	
-	/* We're done */
-	*queue = new;
-	return 0;
-}
-
-/* Delete a message queue. It must be unused. */ 
-int fd_mq_del ( struct mqueue  ** queue )
-{
-	struct mqueue * q;
-	
-	TRACE_ENTRY( "%p", queue );
-
-	CHECK_PARAMS( queue && CHECK_QUEUE( *queue ) );
-	
-	q = *queue;
-	
-	CHECK_POSIX(  pthread_mutex_lock( &q->mtx )  );
-	
-	if ((q->count != 0) || (q->thrs != 0) || (q->data != NULL)) {
-		TRACE_DEBUG(INFO, "The queue cannot be destroyed (%d, %d, %p)", q->count, q->thrs, q->data);
-		CHECK_POSIX_DO(  pthread_mutex_unlock( &q->mtx ), /* no fallback */  );
-		return EINVAL;
-	}
-	
-	/* sanity check */
-	ASSERT(FD_IS_LIST_EMPTY(&q->list));
-	
-	/* Ok, now invalidate the queue */
-	q->eyec = 0xdead;
-	
-	/* And destroy it */
-	CHECK_POSIX(  pthread_mutex_unlock( &q->mtx )  );
-	
-	CHECK_POSIX(  pthread_cond_destroy( &q->cond )  );
-	
-	CHECK_POSIX(  pthread_mutex_destroy( &q->mtx )  );
-	
-	free(q);
-	*queue = NULL;
-	
-	return 0;
-}
-
-/* Get the length of the queue */
-int fd_mq_length ( struct mqueue * queue, int * length )
-{
-	TRACE_ENTRY( "%p %p", queue, length );
-	
-	/* Check the parameters */
-	CHECK_PARAMS( CHECK_QUEUE( queue ) && length );
-	
-	/* lock the queue */
-	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
-	
-	/* Retrieve the count */
-	*length = queue->count;
-	
-	/* Unlock */
-	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
-	
-	/* Done */
-	return 0;
-}
-
-/* alternate version with no error checking */
-int fd_mq_length_noerr ( struct mqueue * queue )
-{
-	if ( !CHECK_QUEUE( queue ) )
-		return 0;
-	
-	return queue->count; /* Let's hope it's read atomically, since we are not locking... */
-}
-
-/* Set the thresholds of the queue */
-int fd_mq_setthrhd ( struct mqueue * queue, void * data, uint16_t high, void (*h_cb)(struct mqueue *, void **), uint16_t low, void (*l_cb)(struct mqueue *, void **) )
-{
-	TRACE_ENTRY( "%p %p %hu %p %hu %p", queue, data, high, h_cb, low, l_cb );
-	
-	/* Check the parameters */
-	CHECK_PARAMS( CHECK_QUEUE( queue ) && (high > low) && (queue->data == NULL) );
-	
-	/* lock the queue */
-	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
-	
-	/* Save the values */
-	queue->high = high;
-	queue->low  = low;
-	queue->data = data;
-	queue->h_cb = h_cb;
-	queue->l_cb = l_cb;
-	
-	/* Unlock */
-	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
-	
-	/* Done */
-	return 0;
-}
-
-/* Post a new message in the queue */
-int fd_mq_post ( struct mqueue * queue, struct msg ** msg )
-{
-	struct fd_list * new;
-	int call_cb = 0;
-	
-	TRACE_ENTRY( "%p %p", queue, msg );
-	
-	/* Check the parameters */
-	CHECK_PARAMS( CHECK_QUEUE( queue ) && msg && *msg );
-	
-	/* Create a new list item */
-	CHECK_MALLOC(  new = malloc (sizeof (struct fd_list))  );
-	
-	fd_list_init(new, *msg);
-	*msg = NULL;
-	
-	/* lock the queue */
-	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
-	
-	/* Add the new message at the end */
-	fd_list_insert_before( &queue->list, new);
-	queue->count++;
-	if (queue->high && ((queue->count % queue->high) == 0)) {
-		call_cb = 1;
-		queue->highest = queue->count;
-	}
-	
-	/* Signal if threads are asleep */
-	if (queue->thrs > 0) {
-		CHECK_POSIX(  pthread_cond_signal(&queue->cond)  );
-	}
-	
-	/* Unlock */
-	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
-	
-	/* Call high-watermark cb as needed */
-	if (call_cb && queue->h_cb)
-		(*queue->h_cb)(queue, &queue->data);
-	
-	/* Done */
-	return 0;
-}
-
-/* Pop the first message from the queue */
-static struct msg * mq_pop(struct mqueue * queue)
-{
-	struct msg * ret = NULL;
-	struct fd_list * li;
-	
-	ASSERT( ! FD_IS_LIST_EMPTY(&queue->list) );
-	
-	fd_list_unlink(li = queue->list.next);
-	queue->count--;
-	ret = (struct msg *)(li->o);
-	free(li);
-	
-	return ret;
-}
-
-/* Check if the low watermark callback must be called. */
-static int test_l_cb(struct mqueue * queue)
-{
-	if ((queue->high == 0) || (queue->low == 0) || (queue->l_cb == 0))
-		return 0;
-	
-	if (((queue->count % queue->high) == queue->low) && (queue->highest > queue->count)) {
-		queue->highest -= queue->high;
-		return 1;
-	}
-	
-	return 0;
-}
-
-/* Try poping a message */
-int fd_mq_tryget ( struct mqueue * queue, struct msg ** msg )
-{
-	int wouldblock = 0;
-	int call_cb = 0;
-	
-	TRACE_ENTRY( "%p %p", queue, msg );
-	
-	/* Check the parameters */
-	CHECK_PARAMS( CHECK_QUEUE( queue ) && msg );
-	
-	/* lock the queue */
-	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
-	
-	/* Check queue status */
-	if (queue->count > 0) {
-		/* There are messages in the queue, so pick the first one */
-		*msg = mq_pop(queue);
-		call_cb = test_l_cb(queue);
-	} else {
-		wouldblock = 1;
-		*msg = NULL;
-	}
-		
-	/* Unlock */
-	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
-	
-	/* Call low watermark callback as needed */
-	if (call_cb)
-		(*queue->l_cb)(queue, &queue->data);
-	
-	/* Done */
-	return wouldblock ? EWOULDBLOCK : 0;
-}
-
-/* This handler is called when a thread is blocked on a queue, and cancelled */
-static void mq_cleanup(void * queue)
-{
-	struct mqueue * q = (struct mqueue *)queue;
-	TRACE_ENTRY( "%p", queue );
-	
-	/* Check the parameter */
-	if ( ! CHECK_QUEUE( q )) {
-		TRACE_DEBUG(INFO, "Invalid queue, skipping handler");
-		return;
-	}
-	
-	/* The thread has been cancelled, therefore it does not wait on the queue anymore */
-	q->thrs--;
-	
-	/* Now unlock the queue, and we're done */
-	CHECK_POSIX_DO(  pthread_mutex_unlock( &q->mtx ),  /* nothing */  );
-	
-	/* End of cleanup handler */
-	return;
-}
-
-/* The internal function for meq_timedget and meq_get */
-static int mq_tget ( struct mqueue * queue, struct msg ** msg, int istimed, const struct timespec *abstime)
-{
-	int timedout = 0;
-	int call_cb = 0;
-	
-	/* Check the parameters */
-	CHECK_PARAMS( CHECK_QUEUE( queue ) && msg && (abstime || !istimed) );
-	
-	/* Initialize the msg value */
-	*msg = NULL;
-	
-	/* lock the queue */
-	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
-	
-awaken:
-	/* Check queue status */
-	if (queue->count > 0) {
-		/* There are messages in the queue, so pick the first one */
-		*msg = mq_pop(queue);
-		call_cb = test_l_cb(queue);
-	} else {
-		int ret = 0;
-		/* We have to wait for a new message */
-		queue->thrs++ ;
-		pthread_cleanup_push( mq_cleanup, queue);
-		if (istimed) {
-			ret = pthread_cond_timedwait( &queue->cond, &queue->mtx, abstime );
-		} else {
-			ret = pthread_cond_wait( &queue->cond, &queue->mtx );
-		}
-		pthread_cleanup_pop(0);
-		queue->thrs-- ;
-		if (ret == 0)
-			goto awaken;  /* test for spurious wake-ups */
-		
-		if (istimed && (ret == ETIMEDOUT)) {
-			timedout = 1;
-		} else {
-			/* Unexpected error condition (means we need to debug) */
-			ASSERT( ret == 0 /* never true */ );
-		}
-	}
-	
-	/* Unlock */
-	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
-	
-	/* Call low watermark callback as needed */
-	if (call_cb)
-		(*queue->l_cb)(queue, &queue->data);
-	
-	/* Done */
-	return timedout ? ETIMEDOUT : 0;
-}
-
-/* Get the next available message, block until there is one */
-int fd_mq_get ( struct mqueue * queue, struct msg ** msg )
-{
-	TRACE_ENTRY( "%p %p", queue, msg );
-	return mq_tget(queue, msg, 0, NULL);
-}
-
-/* Get the next available message, block until there is one, or the timeout expires */
-int fd_mq_timedget ( struct mqueue * queue, struct msg ** msg, const struct timespec *abstime )
-{
-	TRACE_ENTRY( "%p %p %p", queue, msg, abstime );
-	return mq_tget(queue, msg, 1, abstime);
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfreeDiameter/queues.c	Fri Sep 18 18:54:07 2009 +0900
@@ -0,0 +1,394 @@
+/*********************************************************************************************************
+* Software License Agreement (BSD License)                                                               *
+* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
+*													 *
+* Copyright (c) 2008, 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.								 *
+*********************************************************************************************************/
+
+/* FIFO queues module.
+ *
+ * The threads that call these functions must be in the cancellation state PTHREAD_CANCEL_ENABLE and type PTHREAD_CANCEL_DEFERRED.
+ * This is the default state and type on thread creation.
+ *
+ * In order to destroy properly a queue, the application must:
+ *  -> shutdown any process that can add into the queue first.
+ *  -> pthread_cancel any thread that could be waiting on the queue.
+ *  -> consume any element that is in the queue, using fd_qu_tryget_int.
+ *  -> then destroy the queue using fd_mq_del.
+ */
+
+#include "libfD.h"
+
+/* Definition of a FIFO queue object */
+struct fifo {
+	int		eyec;	/* An eye catcher, also used to check a queue is valid. FIFO_EYEC */
+	
+	pthread_mutex_t	mtx;	/* Mutex protecting this queue */
+	pthread_cond_t	cond;	/* condition variable of the list */
+	
+	struct fd_list	list;	/* sentinel for the list of elements */
+	int		count;	/* number of objects in the list */
+	int		thrs;	/* number of threads waiting for a new element (when count is 0) */
+	
+	uint16_t	high;	/* High level threshold (see libfreeDiameter.h for details) */
+	uint16_t	low;	/* Low level threshhold */
+	void 		*data;	/* Opaque pointer for threshold callbacks */
+	void		(*h_cb)(struct fifo *, void **); /* The callbacks */
+	void		(*l_cb)(struct fifo *, void **);
+	int 		highest;/* The highest count value for which h_cb has been called */
+};
+
+/* The eye catcher value */
+#define FIFO_EYEC	0xe7ec1130
+
+/* Macro to check a pointer */
+#define CHECK_FIFO( _queue ) (( (_queue) != NULL) && ( (_queue)->eyec == FIFO_EYEC) )
+
+
+/* Create a new queue */
+int fd_fifo_new ( struct fifo ** queue )
+{
+	struct fifo * new;
+	
+	TRACE_ENTRY( "%p", queue );
+	
+	CHECK_PARAMS( queue );
+	
+	/* Create a new object */
+	CHECK_MALLOC( new = malloc (sizeof (struct fifo) )  );
+	
+	/* Initialize the content */
+	memset(new, 0, sizeof(struct fifo));
+	
+	new->eyec = FIFO_EYEC;
+	CHECK_POSIX( pthread_mutex_init(&new->mtx, NULL) );
+	CHECK_POSIX( pthread_cond_init(&new->cond, NULL) );
+	
+	fd_list_init(&new->list, NULL);
+	
+	/* We're done */
+	*queue = new;
+	return 0;
+}
+
+/* Delete a queue. It must be unused. */ 
+int fd_fifo_del ( struct fifo  ** queue )
+{
+	struct fifo * q;
+	
+	TRACE_ENTRY( "%p", queue );
+
+	CHECK_PARAMS( queue && CHECK_FIFO( *queue ) );
+	
+	q = *queue;
+	
+	CHECK_POSIX(  pthread_mutex_lock( &q->mtx )  );
+	
+	if ((q->count != 0) || (q->thrs != 0) || (q->data != NULL)) {
+		TRACE_DEBUG(INFO, "The queue cannot be destroyed (%d, %d, %p)", q->count, q->thrs, q->data);
+		CHECK_POSIX_DO(  pthread_mutex_unlock( &q->mtx ), /* no fallback */  );
+		return EINVAL;
+	}
+	
+	/* sanity check */
+	ASSERT(FD_IS_LIST_EMPTY(&q->list));
+	
+	/* Ok, now invalidate the queue */
+	q->eyec = 0xdead;
+	
+	/* And destroy it */
+	CHECK_POSIX(  pthread_mutex_unlock( &q->mtx )  );
+	
+	CHECK_POSIX(  pthread_cond_destroy( &q->cond )  );
+	
+	CHECK_POSIX(  pthread_mutex_destroy( &q->mtx )  );
+	
+	free(q);
+	*queue = NULL;
+	
+	return 0;
+}
+
+/* Get the length of the queue */
+int fd_fifo_length ( struct fifo * queue, int * length )
+{
+	TRACE_ENTRY( "%p %p", queue, length );
+	
+	/* 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;
+	
+	/* Unlock */
+	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
+	
+	/* Done */
+	return 0;
+}
+
+/* alternate version with no error checking */
+int fd_fifo_length_noerr ( struct fifo * queue )
+{
+	if ( !CHECK_FIFO( queue ) )
+		return 0;
+	
+	return queue->count; /* Let's hope it's read atomically, since we are not locking... */
+}
+
+/* Set the thresholds of the queue */
+int fd_fifo_setthrhd ( struct fifo * queue, void * data, uint16_t high, void (*h_cb)(struct fifo *, void **), uint16_t low, void (*l_cb)(struct fifo *, void **) )
+{
+	TRACE_ENTRY( "%p %p %hu %p %hu %p", queue, data, high, h_cb, low, l_cb );
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_FIFO( queue ) && (high > low) && (queue->data == NULL) );
+	
+	/* lock the queue */
+	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
+	
+	/* Save the values */
+	queue->high = high;
+	queue->low  = low;
+	queue->data = data;
+	queue->h_cb = h_cb;
+	queue->l_cb = l_cb;
+	
+	/* Unlock */
+	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
+	
+	/* Done */
+	return 0;
+}
+
+/* Post a new item in the queue */
+int fd_fifo_post_int ( struct fifo * queue, void ** item )
+{
+	struct fd_list * new;
+	int call_cb = 0;
+	
+	TRACE_ENTRY( "%p %p", queue, item );
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_FIFO( queue ) && item && *item );
+	
+	/* Create a new list item */
+	CHECK_MALLOC(  new = malloc (sizeof (struct fd_list))  );
+	
+	fd_list_init(new, *item);
+	*item = NULL;
+	
+	/* lock the queue */
+	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
+	
+	/* Add the new item at the end */
+	fd_list_insert_before( &queue->list, new);
+	queue->count++;
+	if (queue->high && ((queue->count % queue->high) == 0)) {
+		call_cb = 1;
+		queue->highest = queue->count;
+	}
+	
+	/* Signal if threads are asleep */
+	if (queue->thrs > 0) {
+		CHECK_POSIX(  pthread_cond_signal(&queue->cond)  );
+	}
+	
+	/* Unlock */
+	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
+	
+	/* Call high-watermark cb as needed */
+	if (call_cb && queue->h_cb)
+		(*queue->h_cb)(queue, &queue->data);
+	
+	/* Done */
+	return 0;
+}
+
+/* Pop the first item from the queue */
+static void * mq_pop(struct fifo * queue)
+{
+	void * ret = NULL;
+	struct fd_list * li;
+	
+	ASSERT( ! FD_IS_LIST_EMPTY(&queue->list) );
+	
+	fd_list_unlink(li = queue->list.next);
+	queue->count--;
+	ret = li->o;
+	free(li);
+	
+	return ret;
+}
+
+/* Check if the low watermark callback must be called. */
+static __inline__ int test_l_cb(struct fifo * queue)
+{
+	if ((queue->high == 0) || (queue->low == 0) || (queue->l_cb == 0))
+		return 0;
+	
+	if (((queue->count % queue->high) == queue->low) && (queue->highest > queue->count)) {
+		queue->highest -= queue->high;
+		return 1;
+	}
+	
+	return 0;
+}
+
+/* Try poping an item */
+int fd_fifo_tryget_int ( struct fifo * queue, void ** item )
+{
+	int wouldblock = 0;
+	int call_cb = 0;
+	
+	TRACE_ENTRY( "%p %p", queue, item );
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_FIFO( queue ) && item );
+	
+	/* lock the queue */
+	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
+	
+	/* Check queue status */
+	if (queue->count > 0) {
+		/* There are elements in the queue, so pick the first one */
+		*item = mq_pop(queue);
+		call_cb = test_l_cb(queue);
+	} else {
+		wouldblock = 1;
+		*item = NULL;
+	}
+		
+	/* Unlock */
+	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
+	
+	/* Call low watermark callback as needed */
+	if (call_cb)
+		(*queue->l_cb)(queue, &queue->data);
+	
+	/* Done */
+	return wouldblock ? EWOULDBLOCK : 0;
+}
+
+/* This handler is called when a thread is blocked on a queue, and cancelled */
+static void fifo_cleanup(void * queue)
+{
+	struct fifo * q = (struct fifo *)queue;
+	TRACE_ENTRY( "%p", queue );
+	
+	/* Check the parameter */
+	if ( ! CHECK_FIFO( q )) {
+		TRACE_DEBUG(INFO, "Invalid queue, skipping handler");
+		return;
+	}
+	
+	/* The thread has been cancelled, therefore it does not wait on the queue anymore */
+	q->thrs--;
+	
+	/* Now unlock the queue, and we're done */
+	CHECK_POSIX_DO(  pthread_mutex_unlock( &q->mtx ),  /* nothing */  );
+	
+	/* End of cleanup handler */
+	return;
+}
+
+/* The internal function for fd_fifo_timedget and fd_fifo_get */
+static int fifo_tget ( struct fifo * queue, void ** item, int istimed, const struct timespec *abstime)
+{
+	int timedout = 0;
+	int call_cb = 0;
+	
+	/* Check the parameters */
+	CHECK_PARAMS( CHECK_FIFO( queue ) && item && (abstime || !istimed) );
+	
+	/* Initialize the return value */
+	*item = NULL;
+	
+	/* lock the queue */
+	CHECK_POSIX(  pthread_mutex_lock( &queue->mtx )  );
+	
+awaken:
+	/* Check queue status */
+	if (queue->count > 0) {
+		/* There are items in the queue, so pick the first one */
+		*item = mq_pop(queue);
+		call_cb = test_l_cb(queue);
+	} else {
+		int ret = 0;
+		/* We have to wait for a new item */
+		queue->thrs++ ;
+		pthread_cleanup_push( fifo_cleanup, queue);
+		if (istimed) {
+			ret = pthread_cond_timedwait( &queue->cond, &queue->mtx, abstime );
+		} else {
+			ret = pthread_cond_wait( &queue->cond, &queue->mtx );
+		}
+		pthread_cleanup_pop(0);
+		queue->thrs-- ;
+		if (ret == 0)
+			goto awaken;  /* test for spurious wake-ups */
+		
+		if (istimed && (ret == ETIMEDOUT)) {
+			timedout = 1;
+		} else {
+			/* Unexpected error condition (means we need to debug) */
+			ASSERT( ret == 0 /* never true */ );
+		}
+	}
+	
+	/* Unlock */
+	CHECK_POSIX(  pthread_mutex_unlock( &queue->mtx )  );
+	
+	/* Call low watermark callback as needed */
+	if (call_cb)
+		(*queue->l_cb)(queue, &queue->data);
+	
+	/* Done */
+	return timedout ? ETIMEDOUT : 0;
+}
+
+/* Get the next available item, block until there is one */
+int fd_fifo_get_int ( struct fifo * queue, void ** item )
+{
+	TRACE_ENTRY( "%p %p", queue, item );
+	return fifo_tget(queue, item, 0, NULL);
+}
+
+/* Get the next available item, block until there is one, or the timeout expires */
+int fd_fifo_timedget_int ( struct fifo * queue, void ** item, const struct timespec *abstime )
+{
+	TRACE_ENTRY( "%p %p %p", queue, item, abstime );
+	return fifo_tget(queue, item, 1, abstime);
+}
+
"Welcome to our mercurial repository"