changeset 36:1498b3c7304c

Backup
author Sebastien Decugis <sdecugis@nict.go.jp>
date Mon, 02 Nov 2009 17:31:36 +0900
parents 6486e97f56ae
children cc3c59fe98fe
files freeDiameter/CMakeLists.txt freeDiameter/fD.h freeDiameter/fdd.y freeDiameter/p_ce.c freeDiameter/p_dp.c freeDiameter/p_dw.c freeDiameter/p_expiry.c freeDiameter/p_psm.c freeDiameter/peers.c include/freeDiameter/freeDiameter.h
diffstat 10 files changed, 296 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/freeDiameter/CMakeLists.txt	Mon Nov 02 14:54:42 2009 +0900
+++ b/freeDiameter/CMakeLists.txt	Mon Nov 02 17:31:36 2009 +0900
@@ -20,6 +20,8 @@
 	queues.c
 	peers.c
 	p_ce.c
+	p_dw.c
+	p_dp.c
 	p_expiry.c
 	p_out.c
 	p_psm.c
--- a/freeDiameter/fD.h	Mon Nov 02 14:54:42 2009 +0900
+++ b/freeDiameter/fD.h	Mon Nov 02 17:31:36 2009 +0900
@@ -231,6 +231,9 @@
 int  fd_psm_begin(struct fd_peer * peer );
 int  fd_psm_terminate(struct fd_peer * peer );
 void fd_psm_abord(struct fd_peer * peer );
+void fd_psm_next_timeout(struct fd_peer * peer, int add_random, int delay);
+int fd_psm_change_state(struct fd_peer * peer, int new_state);
+void fd_psm_cleanup(struct fd_peer * peer);
 
 /* Peer out */
 int fd_out_send(struct msg ** msg, struct cnxctx * cnx, struct fd_peer * peer);
@@ -242,8 +245,13 @@
 int fd_p_sr_fetch(struct sr_list * srlist, uint32_t hbh, struct msg **req);
 void fd_p_sr_failover(struct sr_list * srlist);
 
-/* Capabilities Exchange */
-int fd_p_ce_merge(struct fd_peer * peer, struct msg * cer);
+/* Local Link messages (CER/CEA, DWR/DWA, DPR/DPA) */
+int fd_p_ce_handle(struct msg ** msg, struct fd_peer * peer);
+int fd_p_ce_handle_newCER(struct msg ** msg, struct fd_peer * peer, struct cnxctx ** cnx, int valid);
+int fd_p_dw_handle(struct msg ** msg, struct fd_peer * peer);
+int fd_p_dw_timeout(struct fd_peer * peer);
+int fd_p_dp_handle(struct msg ** msg, struct fd_peer * peer);
+int fd_p_dp_initiate(struct fd_peer * peer);
 
 /* Active peers -- routing process should only ever take the read lock, the write lock is managed by PSMs */
 extern struct fd_list fd_g_activ_peers;
--- a/freeDiameter/fdd.y	Mon Nov 02 14:54:42 2009 +0900
+++ b/freeDiameter/fdd.y	Mon Nov 02 17:31:36 2009 +0900
@@ -317,6 +317,7 @@
 				memset(&fddpi, 0, sizeof(fddpi));
 				fd_list_init( &fddpi.pi_endpoints, NULL );
 				fd_list_init( &fddpi.pi_apps, NULL );
+				fddpi.pi_flags.persist = PI_PRST_ALWAYS;
 			}
 			CONNPEER '=' QSTRING peerinfo ';'
 			{
--- a/freeDiameter/p_ce.c	Mon Nov 02 14:54:42 2009 +0900
+++ b/freeDiameter/p_ce.c	Mon Nov 02 17:31:36 2009 +0900
@@ -37,9 +37,33 @@
 
 /* This file contains code to handle Capabilities Exchange messages (CER and CEA) */
 
-int fd_p_ce_merge(struct fd_peer * peer, struct msg * cer)
+int fd_p_ce_handle(struct msg ** msg, struct fd_peer * peer)
 {
-	/* Save all information from the CER into the peer structure, after cleaning old information if any */
+	TODO("Handle depending on CER or CEA and peer state");
 	
 	return ENOTSUP;
 }
+
+int fd_p_ce_handle_newCER(struct msg ** msg, struct fd_peer * peer, struct cnxctx ** cnx, int valid)
+{
+	switch (peer->p_hdr.info.pi_state) {
+		case STATE_CLOSED:
+			TODO("Handle the CER, validate the peer if needed (and set expiry), set the alt_fifo in the connection, reply a CEA, eventually handshake, move to OPEN or REOPEN state");
+			/* In case of error : DIAMETER_UNKNOWN_PEER */
+			break;
+
+		case STATE_WAITCNXACK:
+		case STATE_WAITCEA:
+			TODO("Election");
+			break;
+
+		default:
+			TODO("Reply with error CEA");
+			TODO("Close the connection");
+			/* reject_incoming_connection */
+
+	}
+				
+	
+	return ENOTSUP;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/freeDiameter/p_dp.c	Mon Nov 02 17:31:36 2009 +0900
@@ -0,0 +1,57 @@
+/*********************************************************************************************************
+* 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"
+
+/* This file contains code to handle Disconnect Peer messages (DPR and DPA) */
+
+/* Handle a received message */
+int fd_p_dp_handle(struct msg ** msg, struct fd_peer * peer)
+{
+	TODO("Handle depending on DPR or DPA and peer state");
+	
+	return ENOTSUP;
+}
+
+/* Start disconnection of a peer: send DPR */
+int fd_p_dp_initiate(struct fd_peer * peer)
+{
+	TODO("Create the DPR message");
+	TODO("Send it");
+	TODO("Mark the peer as CLOSING");
+	TODO("Reset the timer");
+	
+	return ENOTSUP;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/freeDiameter/p_dw.c	Mon Nov 02 17:31:36 2009 +0900
@@ -0,0 +1,56 @@
+/*********************************************************************************************************
+* 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"
+
+/* This file contains code to handle Device Watchdog messages (DWR and DWA) */
+
+
+/* Handle an incoming message */
+int fd_p_dw_handle(struct msg ** msg, struct fd_peer * peer)
+{
+	TODO("Handle depending on DWR or DWA and peer state");
+	
+	return ENOTSUP;
+}
+
+/* Handle a timeout in the PSM : send DWR, fail the peer, manage reopen state */
+int fd_p_dw_timeout(struct fd_peer * peer)
+{
+	TODO("...");
+	
+	return ENOTSUP;
+}
+		
--- a/freeDiameter/p_expiry.c	Mon Nov 02 14:54:42 2009 +0900
+++ b/freeDiameter/p_expiry.c	Mon Nov 02 17:31:36 2009 +0900
@@ -35,8 +35,8 @@
 
 #include "fD.h"
 
-/* Delay for garbage collection of expired threads, in seconds */
-#define GC_TIME		60
+/* Delay for garbage collection of expired peers, in seconds */
+#define GC_TIME		120
 
 static pthread_t       exp_thr;
 static pthread_t       gc_thr;
@@ -63,8 +63,8 @@
 			if (peer->p_hdr.info.pi_state != STATE_ZOMBIE)
 				continue;
 			
-			if (peer->p_hdr.info.pi_flags.exp == PI_EXP_NONE)
-				continue; /* This peer was not supposed to expire, keep it in the list */
+			if (peer->p_hdr.info.pi_flags.persist == PI_PRST_ALWAYS)
+				continue; /* This peer was not supposed to terminate, keep it in the list for debug */
 			
 			/* Ok, the peer was expired, let's remove it */
 			li = li->prev; /* to avoid breaking the loop */
--- a/freeDiameter/p_psm.c	Mon Nov 02 14:54:42 2009 +0900
+++ b/freeDiameter/p_psm.c	Mon Nov 02 17:31:36 2009 +0900
@@ -145,7 +145,7 @@
 /*                      Helpers for state changes                       */
 /************************************************************************/
 /* Change state */
-static int change_state(struct fd_peer * peer, int new_state)
+int fd_psm_change_state(struct fd_peer * peer, int new_state)
 {
 	int old;
 	
@@ -170,11 +170,15 @@
 		CHECK_FCT( enter_open_state(peer) );
 	}
 	
+	if ((new_state == STATE_CLOSED) && (peer->p_hdr.info.pi_flags.persist == PI_PRST_NONE)) {
+		CHECK_FCT( fd_event_send(peer->p_events, FDEVP_TERMINATE, 0, NULL) );
+	}
+	
 	return 0;
 }
 
 /* Set timeout timer of next event */
-static void psm_next_timeout(struct fd_peer * peer, int add_random, int delay)
+void fd_psm_next_timeout(struct fd_peer * peer, int add_random, int delay)
 {
 	/* Initialize the timer */
 	CHECK_POSIX_DO(  clock_gettime( CLOCK_REALTIME,  &peer->p_psm_timer ), ASSERT(0) );
@@ -202,12 +206,29 @@
 #endif
 }
 
+/* Cleanup the peer */
+void fd_psm_cleanup(struct fd_peer * peer)
+{
+	/* Move to CLOSED state */
+	CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), /* continue */ );
+	
+	/* Destroy the connection */
+	if (peer->p_cnxctx) {
+		fd_cnx_destroy(peer->p_cnxctx);
+		peer->p_cnxctx = NULL;
+	}
+	
+	/* What else ? */
+	TODO("...");
+	
+}
+
 
 /************************************************************************/
 /*                      The PSM thread                                  */
 /************************************************************************/
 /* Cancelation cleanup : set ZOMBIE state in the peer */
-void cleanup_state(void * arg) 
+void cleanup_setstate(void * arg) 
 {
 	struct fd_peer * peer = (struct fd_peer *)arg;
 	CHECK_PARAMS_DO( CHECK_PEER(peer), return );
@@ -226,7 +247,7 @@
 	
 	CHECK_PARAMS_DO( CHECK_PEER(peer), ASSERT(0) );
 	
-	pthread_cleanup_push( cleanup_state, arg );
+	pthread_cleanup_push( cleanup_setstate, arg );
 	
 	/* Set the thread name */
 	{
@@ -243,9 +264,9 @@
 	
 	/* Initialize the timer */
 	if (peer->p_flags.pf_responder) {
-		psm_next_timeout(peer, 0, INCNX_TIMEOUT);
+		fd_psm_next_timeout(peer, 0, INCNX_TIMEOUT);
 	} else {
-		psm_next_timeout(peer, created_started, 0);
+		fd_psm_next_timeout(peer, created_started, 0);
 	}
 	
 psm_loop:
@@ -278,22 +299,23 @@
 	/* Requests to terminate the peer object */
 	if (event == FDEVP_TERMINATE) {
 		switch (peer->p_hdr.info.pi_state) {
+			case STATE_OPEN:
+			case STATE_REOPEN:
+				/* We cannot just close the conenction, we have to send a DPR first */
+				CHECK_FCT_DO( fd_p_dp_initiate(peer), goto psm_end );
+				goto psm_loop;
+			
+			/*	
 			case STATE_CLOSING:
 			case STATE_WAITCNXACK:
 			case STATE_WAITCNXACK_ELEC:
 			case STATE_WAITCEA:
 			case STATE_SUSPECT:
-				/* In these cases, we just cleanup the peer object and terminate now */
-				TODO("Cleanup the PSM: terminate connection object, ...");
 			case STATE_CLOSED:
-				/* Then we just terminate the PSM */
+			*/
+			default:
+				/* In these cases, we just cleanup the peer object (if needed) and terminate */
 				goto psm_end;
-				
-			case STATE_OPEN:
-			case STATE_REOPEN:
-				/* We cannot just close the conenction, we have to send a DPR first */
-				TODO("Send DPR, mark the peer as CLOSING");
-				goto psm_loop;
 		}
 	}
 	
@@ -310,8 +332,8 @@
 				goto psm_loop;
 			} );
 		
-		TRACE_DEBUG(FULL, "Received this message from '%s':", peer->p_hdr.info.pi_diamid);
-		fd_msg_dump_walk(FULL, msg);
+		TRACE_DEBUG(FULL, "Received a message (%zdb) from '%s'", ev_sz, peer->p_hdr.info.pi_diamid);
+		fd_msg_dump_walk(FULL + 1, msg);
 	
 		/* Extract the header */
 		CHECK_FCT_DO( fd_msg_hdr(msg, &hdr), goto psm_end );
@@ -332,9 +354,6 @@
 			CHECK_FCT_DO( fd_msg_answ_associate( msg, req ), goto psm_end );
 		}
 		
-		/* We received a valid message, update the expiry timer */
-		CHECK_FCT_DO( fd_p_expi_update(peer), goto psm_end );
-
 		/* Now handle non-link-local messages */
 		if (fd_msg_is_routable(msg)) {
 			/* If we are not in OPEN state, discard the message */
@@ -343,6 +362,9 @@
 				fd_msg_dump_walk(NONE, msg);
 				fd_msg_free(msg);
 			} else {
+				/* We received a valid message, update the expiry timer */
+				CHECK_FCT_DO( fd_p_expi_update(peer), goto psm_end );
+
 				/* Set the message source and add the Route-Record */
 				CHECK_FCT_DO( fd_msg_source_set( msg, peer->p_hdr.info.pi_diamid, 1, fd_g_config->cnf_dict ), goto psm_end);
 
@@ -351,7 +373,7 @@
 				
 				/* Update the peer timer */
 				if (!peer->p_flags.pf_dw_pending) {
-					psm_next_timeout(peer, 1, peer->p_hdr.info.pi_twtimer ?: fd_g_config->cnf_timer_tw);
+					fd_psm_next_timeout(peer, 1, peer->p_hdr.info.pi_twtimer ?: fd_g_config->cnf_timer_tw);
 				}
 			}
 			goto psm_loop;
@@ -373,16 +395,53 @@
 				} );
 		}
 		
+		ASSERT( hdr->msg_appl == 0 ); /* buggy fd_msg_is_routable() ? */
+		
 		/* Handle the LL message and update the expiry timer appropriately */
-		TODO("...");
+		switch (hdr->msg_code) {
+			case CC_DEVICE_WATCHDOG:
+				CHECK_FCT_DO( fd_p_dw_handle(&msg, peer), goto psm_end );
+				break;
+			
+			case CC_DISCONNECT_PEER:
+				CHECK_FCT_DO( fd_p_dp_handle(&msg, peer), goto psm_end );
+				break;
+			
+			case CC_CAPABILITIES_EXCHANGE:
+				CHECK_FCT_DO( fd_p_ce_handle(&msg, peer), goto psm_end );
+				break;
+			
+			default:
+				/* Unknown / unexpected / invalid message */
+				TODO("Log, return error message if request");
+		};
+		
+		/* At this point the message must have been fully handled already */
+		if (msg) {
+			fd_log_debug("Internal error: unhandled message (discarded)!\n");
+			fd_msg_dump_walk(NONE, msg);
+			fd_msg_free(msg);
+		}
+		
+		goto psm_loop;
 	}
 	
 	/* The connection object is broken */
 	if (event == FDEVP_CNX_ERROR) {
-		TODO("Destroy the connection object");
-		TODO("Mark the error in the peer (pf_cnx_pb)");
-		TODO("Move to closed state, Requeue all messages to a different connection (failover)");
-		TODO("If pi_flags.exp, terminate the peer");
+		/* Cleanup the peer */
+		fd_psm_cleanup(peer);
+		
+		/* Mark the connection problem */
+		peer->p_flags.pf_cnx_pb = 1;
+		
+		/* Move to CLOSED */
+		CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), goto psm_end );
+		
+		/* Reset the timer */
+		fd_psm_next_timeout(peer, 1, peer->p_hdr.info.pi_tctimer ?: fd_g_config->cnf_timer_tc);
+		
+		/* Loop */
+		goto psm_loop;
 	}
 	
 	/* The connection notified a change in endpoints */
@@ -408,30 +467,20 @@
 		struct cnx_incoming * params = ev_data;
 		ASSERT(params);
 		
-		switch (peer->p_hdr.info.pi_state) {
-			case STATE_CLOSED:
-				TODO("Handle the CER, validate the peer if needed (and set expiry), set the alt_fifo in the connection, reply a CEA, eventually handshake, move to OPEN or REOPEN state");
-				/* In case of error : DIAMETER_UNKNOWN_PEER */
-				
-				CHECK_FCT_DO( fd_p_ce_merge(peer, params->cer),
-					{
-						
-					} );
-				
-				break;
-				
-			case STATE_WAITCNXACK:
-			case STATE_WAITCEA:
-				TODO("Election");
-				break;
-				
-			default:
-				TODO("Reply with error CEA");
-				TODO("Close the connection");
-				/* reject_incoming_connection */
-			
+		/* Handle the message */
+		CHECK_FCT_DO( fd_p_ce_handle_newCER(&params->cer, peer, &params->cnx, params->validate), goto psm_end );
+		
+		/* Cleanup if needed */
+		if (params->cnx) {
+			fd_cnx_destroy(params->cnx);
+			params->cnx = NULL;
+		}
+		if (params->cer) {
+			CHECK_FCT_DO( fd_msg_free(params->cer), );
+			params->cer = NULL;
 		}
 		
+		/* Loop */
 		free(ev_data);
 		goto psm_loop;
 	}
@@ -439,8 +488,28 @@
 	/* The timeout for the current state has been reached */
 	if (event == FDEVP_PSM_TIMEOUT) {
 		switch (peer->p_hdr.info.pi_state) {
-			
-			
+			case STATE_OPEN:
+			case STATE_REOPEN:
+				CHECK_FCT_DO( fd_p_dw_timeout(peer), goto psm_end );
+				break;
+				
+			case STATE_CLOSED:
+				TODO("Initiate a new connection");
+				break;
+				
+			case STATE_CLOSING:
+			case STATE_SUSPECT:
+			case STATE_WAITCNXACK:
+			case STATE_WAITCEA:
+				/* Destroy the connection, restart the timer to a new connection attempt */
+				fd_psm_cleanup(peer);
+				fd_psm_next_timeout(peer, 1, peer->p_hdr.info.pi_tctimer ?: fd_g_config->cnf_timer_tc);
+				CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), goto psm_end );
+				break;
+				
+			case STATE_WAITCNXACK_ELEC:
+				TODO("Abort initiating side, handle the receiver side");
+				break;
 		}
 	}
 	
@@ -448,12 +517,13 @@
 	TODO("Missing handler in PSM : '%s'\t<-- '%s'", STATE_STR(peer->p_hdr.info.pi_state), fd_pev_str(event));
 	if (event == FDEVP_PSM_TIMEOUT) {
 		/* We have not handled timeout in this state, let's postpone next alert */
-		psm_next_timeout(peer, 0, 60);
+		fd_psm_next_timeout(peer, 0, 60);
 	}
 	
 	goto psm_loop;
 
 psm_end:
+	fd_psm_cleanup(peer);
 	pthread_cleanup_pop(1); /* set STATE_ZOMBIE */
 	peer->p_psm = (pthread_t)NULL;
 	pthread_detach(pthread_self());
--- a/freeDiameter/peers.c	Mon Nov 02 14:54:42 2009 +0900
+++ b/freeDiameter/peers.c	Mon Nov 02 17:31:36 2009 +0900
@@ -101,16 +101,17 @@
 		CHECK_MALLOC( p->p_hdr.info.pi_realm = strdup(info->pi_realm) );
 	}
 	
-	p->p_hdr.info.pi_flags.pro3 = info->pi_flags.pro3;
-	p->p_hdr.info.pi_flags.pro4 = info->pi_flags.pro4;
-	p->p_hdr.info.pi_flags.alg  = info->pi_flags.alg;
-	p->p_hdr.info.pi_flags.sec  = info->pi_flags.sec;
-	p->p_hdr.info.pi_flags.exp  = info->pi_flags.exp;
+	p->p_hdr.info.pi_flags.pro3 	= info->pi_flags.pro3;
+	p->p_hdr.info.pi_flags.pro4 	= info->pi_flags.pro4;
+	p->p_hdr.info.pi_flags.alg  	= info->pi_flags.alg;
+	p->p_hdr.info.pi_flags.sec  	= info->pi_flags.sec;
+	p->p_hdr.info.pi_flags.exp  	= info->pi_flags.exp;
+	p->p_hdr.info.pi_flags.persist 	= info->pi_flags.persist;
 	
-	p->p_hdr.info.pi_lft     = info->pi_lft;
-	p->p_hdr.info.pi_port    = info->pi_port;
-	p->p_hdr.info.pi_tctimer = info->pi_tctimer;
-	p->p_hdr.info.pi_twtimer = info->pi_twtimer;
+	p->p_hdr.info.pi_lft     	= info->pi_lft;
+	p->p_hdr.info.pi_port    	= info->pi_port;
+	p->p_hdr.info.pi_tctimer 	= info->pi_tctimer;
+	p->p_hdr.info.pi_twtimer 	= info->pi_twtimer;
 	
 	if (info->pi_sec_data.priority) {
 		CHECK_MALLOC( p->p_hdr.info.pi_sec_data.priority = strdup(info->pi_sec_data.priority) );
@@ -441,6 +442,10 @@
 		CHECK_MALLOC_DO( peer->p_dbgorig = strdup(fd_cnx_getid(*cnx)), { ret = ENOMEM; goto out; } );
 		peer->p_flags.pf_responder = 1;
 		
+		/* Set this peer to expire on inactivity */
+		peer->p_hdr.info.pi_flags.exp 	= PI_EXP_INACTIVE;
+		peer->p_hdr.info.pi_lft		= 3600 * 3;	/* 3 hours without any message */
+		
 		/* Upgrade the lock to write lock */
 		CHECK_POSIX_DO( ret = pthread_rwlock_wrlock(&fd_g_peers_rw), goto out );
 		
--- a/include/freeDiameter/freeDiameter.h	Mon Nov 02 14:54:42 2009 +0900
+++ b/include/freeDiameter/freeDiameter.h	Mon Nov 02 17:31:36 2009 +0900
@@ -247,7 +247,7 @@
 				   We have sent a CER on our initiated connection, and received a CER from the remote peer on another connection. Election.
 				   If we win the election, we must disconnect the initiated connection and send a CEA on the other => we go to OPEN state.
 				   If we lose, we disconnect the other connection (receiver) and fallback to WAITCEA state. */
-	STATE_OPEN_HANDSHAKE,	/* TLS Handshake and validation are in progress in open state */
+	STATE_OPEN_HANDSHAKE,	/* TLS Handshake and validation are in progress in open state -- we show the state because it can last a long time */
 	
 	/* Failover state machine */
 	STATE_SUSPECT,		/* A DWR was sent and not answered within TwTime. Failover in progress. */
@@ -306,6 +306,10 @@
 		#define PI_EXP_INACTIVE	1	/* the peer entry expires (i.e. is deleted) after pi_lft seconds without activity */
 		unsigned	exp :1;
 		
+		#define PI_PRST_NONE	0	/* the peer entry is deleted after disconnection / error */
+		#define PI_PRST_ALWAYS	1	/* the peer entry is persistant (will be kept as ZOMBIE in case of error) */
+		unsigned	persist :1;
+		
 		unsigned	inband_none :1;	/* This is only meaningful with pi_flags.sec == 3 */
 		unsigned	inband_tls  :1;	/* This is only meaningful with pi_flags.sec == 3 */
 		
"Welcome to our mercurial repository"