Index: extensions/dbg_monitor/monitor.c
===================================================================
--- extensions/dbg_monitor/monitor.c	(revision 10)
+++ extensions/dbg_monitor/monitor.c	(revision 11)
@@ -71,5 +71,9 @@
 	/* Loop */
 	while (1) {
-		sleep(60);
+		#ifdef DEBUG
+		sleep(30);
+		#else /* DEBUG */
+		sleep(3600); /* 1 hour */
+		#endif /* DEBUG */
 		TRACE_DEBUG(NONE, "Monitor information");
 		CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_DUMP_QUEUES, NULL), /* continue */);
Index: freeDiameter/CMakeLists.txt
===================================================================
--- freeDiameter/CMakeLists.txt	(revision 10)
+++ freeDiameter/CMakeLists.txt	(revision 11)
@@ -15,4 +15,5 @@
 	dict_base_proto.c
 	messages.c
+	peers.c
 	queues.c
 	)
Index: freeDiameter/fD.h
===================================================================
--- freeDiameter/fD.h	(revision 10)
+++ freeDiameter/fD.h	(revision 11)
@@ -69,3 +69,20 @@
 int fd_dict_base_protocol(struct dictionary * dict);
 
+/* Peers */
+struct fd_peer { /* The "real" definition of the peer structure */
+	
+	struct peer_hdr	p_hdr; /* contains all public data */
+	
+	int		p_eyec;	/* Eye catcher, EYEC_PEER */
+	#define EYEC_PEER	0x373C9336
+	
+	/* threads, message queues, socket & callbacks */
+	
+};
+
+int fd_peer_init();
+void fd_peer_dump(int details);
+int fd_peer_start();
+int fd_peer_waitstart();
+
 #endif /* _FD_H */
Index: freeDiameter/main.c
===================================================================
--- freeDiameter/main.c	(revision 10)
+++ freeDiameter/main.c	(revision 11)
@@ -80,4 +80,5 @@
 	CHECK_FCT(  fd_queues_init()  );
 	CHECK_FCT(  fd_msg_init()  );
+	CHECK_FCT(  fd_peer_init()  );
 	
 	/* Parse the configuration file */
@@ -88,5 +89,5 @@
 	
 	/* Start the peer state machines */
-	
+	CHECK_FCT( fd_peer_start() );
 	
 	/* Now, just wait for events */
@@ -115,4 +116,7 @@
 				break;
 			
+			case FDEV_DUMP_PEERS:
+				fd_peer_dump(FULL);
+				break;
 			
 			case FDEV_TERMINATE:
Index: freeDiameter/peers.c
===================================================================
--- freeDiameter/peers.c	(revision 11)
+++ freeDiameter/peers.c	(revision 11)
@@ -0,0 +1,120 @@
+/*********************************************************************************************************
+* 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"
+
+const char *peer_state_str[] = { "<error>"
+	, "STATE_DISABLED"
+	, "STATE_OPEN"
+	, "STATE_CLOSED"
+	, "STATE_CLOSING"
+	, "STATE_WAITCNXACK"
+	, "STATE_WAITCNXACK_ELEC"
+	, "STATE_WAITCEA"
+	, "STATE_SUSPECT"
+	, "STATE_REOPEN"
+	};
+#define STATE_STR(state) \
+	peer_state_str[ (state) <= STATE_REOPEN ? (state) : 0 ]
+
+struct fd_list   fd_g_peers;
+pthread_rwlock_t fd_g_peers_rw;
+
+static int started = 0;
+static pthread_mutex_t  started_mtx = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t   started_cnd = PTHREAD_COND_INITIALIZER;
+
+/* Wait for start signal */
+int fd_peer_waitstart()
+{
+	CHECK_POSIX( pthread_mutex_lock(&started_mtx) );
+awake:	
+	if (! started) {
+		pthread_cleanup_push( fd_cleanup_mutex, &started_mtx );
+		CHECK_POSIX( pthread_cond_wait(&started_cnd, &started_mtx) );
+		pthread_cleanup_pop( 0 );
+		goto awake;
+	}
+	CHECK_POSIX( pthread_mutex_unlock(&started_mtx) );
+	return 0;
+}
+
+/* Allow the state machines to start */
+int fd_peer_start()
+{
+	CHECK_POSIX( pthread_mutex_lock(&started_mtx) );
+	started = 1;
+	CHECK_POSIX( pthread_cond_broadcast(&started_cnd) );
+	CHECK_POSIX( pthread_mutex_unlock(&started_mtx) );
+	return 0;
+}
+
+/* Initialize the peers list */
+int fd_peer_init()
+{
+	TRACE_ENTRY();
+	
+	fd_list_init(&fd_g_peers, NULL);
+	CHECK_POSIX( pthread_rwlock_init(&fd_g_peers_rw, NULL) );
+	
+	return 0;
+}
+
+/* Dump the list of peers */
+void fd_peer_dump(int details)
+{
+	struct fd_list * li;
+	
+	fd_log_debug("Dumping list of peers :\n");
+	CHECK_FCT_DO( pthread_rwlock_rdlock(&fd_g_peers_rw), /* continue */ );
+	
+	for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
+		struct fd_peer * np = (struct fd_peer *)li;
+		if (np->p_eyec != EYEC_PEER) {
+			fd_log_debug("  Invalid entry @%p !\n", li);
+			continue;
+		}
+		
+		fd_log_debug("   %s %s", np->p_hdr.info.pi_diamid, STATE_STR(np->p_hdr.info.pi_state));
+		if (details > INFO) {
+			fd_log_debug(" (rlm:%s)", np->p_hdr.info.pi_realm);
+			if (np->p_hdr.info.pi_prodname)
+				fd_log_debug(" ['%s' %u]", np->p_hdr.info.pi_prodname, np->p_hdr.info.pi_firmrev);
+		}
+		fd_log_debug("\n");
+	}
+	
+	CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ );
+}
Index: include/freeDiameter/freeDiameter.h
===================================================================
--- include/freeDiameter/freeDiameter.h	(revision 10)
+++ include/freeDiameter/freeDiameter.h	(revision 11)
@@ -160,5 +160,5 @@
 	STATE_REOPEN		/* Connection has been re-established, waiting for 3 DWR/DWA exchanges before putting back to service */
 };
-extern char *peer_state_str[];
+extern const char *peer_state_str[];
 
 /* Information about a remote peer, used both for query and for creating a new entry */
@@ -214,4 +214,71 @@
 };
 
+struct peer_hdr {
+	struct fd_list	 chain;	/* List of all the peers, ordered by their Diameter Id */
+	struct peer_info info;	/* The public data */
+	
+	/* This header is followed by more data in the private peer structure definition */
+};
+
+/* the global list of peers. 
+  Since we are not expecting so many connections, we don't use a hash, but it might be changed.
+  The list items are peer_hdr structures (actually, fd_peer, but the cast is OK) */
+extern struct fd_list fd_g_peers;
+extern pthread_rwlock_t fd_g_peers_rw; /* protect the list */
+
+/*
+ * FUNCTION:	fd_peer_add
+ *
+ * PARAMETERS:
+ *  info 	: Information to create the peer.
+ *  cb		: optional, a callback to call (once) when the peer connection is established or failed
+ *  cb_data	: opaque data to pass to the callback.
+ *
+ * DESCRIPTION: 
+ *  Add a peer to the list of peers to which the daemon must maintain a connexion.
+ * If cb is not null, the callback is called when the connection is in OPEN state or
+ * when an error has occurred. The callback should use the pi_state information to 
+ * determine which one it is.
+ *
+ * RETURN VALUE:
+ *  0      	: The peer is added.
+ *  EINVAL 	: A parameter is invalid.
+ *  EEXIST 	: A peer with the same Diameter-Id is already in the list.
+ *  (other standard errors may be returned, too, with their standard meaning. Example:
+ *    ENOMEM 	: Memory allocation for the new object element failed.)
+ */
+int fd_peer_add ( struct peer_info * info, void (*cb)(struct peer_info *, void *), void * cb_data );
+
+/*
+ * FUNCTION:	peer_validate_register
+ *
+ * PARAMETERS:
+ *  peer_validate 	: Callback as defined bellow.
+ *
+ * DESCRIPTION: 
+ *  Add a callback to authorize / reject incoming peer connections.
+ * All registered callbacks are called until a callback sets auth = -1 or auth = 1.
+ * If no callback returns a clear decision, the default behavior is applied (reject unknown connections)
+ *
+ * RETURN VALUE:
+ *  0   : The callback is added.
+ * !0	: An error occurred.
+ */
+int fd_peer_validate_register ( int (*peer_validate)(struct peer_info * /* info */, int * /* auth */) );
+/*
+ * CALLBACK:	peer_validate
+ *
+ * PARAMETERS:
+ *   info     : Structure containing information about the peer attempting the connection.
+ *   auth     : Store there the result if the peer is accepted (1), rejected (-1), or unknown (0).
+ *
+ * DESCRIPTION: 
+ *   This callback is called when a new connection is being established from an unknown peer,
+ *  after the CER is received. An extension must register such callback with peer_validate_register.
+ *
+ * RETURN VALUE:
+ *  0      	: The authorization decision has been written in the location pointed by auth.
+ *  !0 		: An error occurred.
+ */
 
 /***************************************/
Index: libfreeDiameter/fifo.c
===================================================================
--- libfreeDiameter/fifo.c	(revision 10)
+++ libfreeDiameter/fifo.c	(revision 11)
@@ -117,7 +117,6 @@
 	
 	CHECK_POSIX_DO(  pthread_mutex_lock( &queue->mtx ), /* continue */  );
-	fd_log_debug("  %d elements in queue\n", queue->count);
-	fd_log_debug("  %d threads waiting\n", queue->thrs);
-	fd_log_debug("  thresholds: %d / %d, cb: %p / %p (%p), highest: %d\n",
+	fd_log_debug("   %d elements in queue / %d threads waiting\n", queue->count, queue->thrs);
+	fd_log_debug("   thresholds: %d / %d, cb: %p / %p (%p), highest: %d\n",
 			queue->high, queue->low,
 			queue->h_cb, queue->l_cb, queue->data,
