Index: freeDiameter/peers.c
===================================================================
--- freeDiameter/peers.c	(revision 20)
+++ freeDiameter/peers.c	(revision 29)
@@ -101,8 +101,11 @@
 	
 	p->p_hdr.info.pi_lft     = info->pi_lft;
-	p->p_hdr.info.pi_streams = info->pi_streams;
 	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) );
+	}
 	
 	/* Move the items from one list to the other */
@@ -114,4 +117,5 @@
 		}
 	
+	
 	/* The internal data */
 	if (orig_dbg) {
@@ -127,7 +131,7 @@
 	
 	for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
-		struct fd_peer * prev = (struct fd_peer *)li;
-		int cmp = strcasecmp( p->p_hdr.info.pi_diamid, prev->p_hdr.info.pi_diamid );
-		if (cmp < 0)
+		struct fd_peer * next = (struct fd_peer *)li;
+		int cmp = strcasecmp( p->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamid );
+		if (cmp > 0)
 			continue;
 		if (cmp == 0)
@@ -229,5 +233,5 @@
 	
 	if (p->p_cnxctx) {
-		TODO("destroy p->p_cnxctx");
+		fd_cnx_destroy(p->p_cnxctx);
 	}
 	
@@ -293,4 +297,5 @@
 		list_empty = FD_IS_LIST_EMPTY(&fd_g_peers);
 		CHECK_FCT_DO( pthread_rwlock_unlock(&fd_g_peers_rw), /* continue */ );
+		CHECK_SYS(  clock_gettime(CLOCK_REALTIME, &now)  );
 	}
 	
@@ -370,2 +375,100 @@
 }
 
+/* Handle an incoming CER request on a new connection */
+int fd_peer_handle_newCER( struct msg ** cer, struct cnxctx ** cnx )
+{
+	struct msg * msg;
+	struct dict_object *avp_oh_model;
+	avp_code_t code = AC_ORIGIN_HOST;
+	struct avp *avp_oh;
+	struct avp_hdr * avp_hdr;
+	struct fd_list * li;
+	int found = 0;
+	int ret = 0;
+	struct fd_peer * peer;
+	struct cnx_incoming * ev_data;
+	
+	TRACE_ENTRY("%p %p", cer, cnx);
+	CHECK_PARAMS(cer && *cer && cnx && *cnx);
+	
+	msg = *cer; 
+	
+	/* Find the Diameter Identity of the remote peer in the message */
+	CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_CODE, &code, &avp_oh_model, ENOENT) );
+	CHECK_FCT( fd_msg_search_avp ( msg, avp_oh_model, &avp_oh ) );
+	CHECK_FCT( fd_msg_avp_hdr ( avp_oh, &avp_hdr ) );
+	
+	/* Search if we already have this peer id in our list */
+	CHECK_POSIX( pthread_rwlock_rdlock(&fd_g_peers_rw) );
+	
+	for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
+		peer = (struct fd_peer *)li;
+		int cmp = strncasecmp( avp_hdr->avp_value->os.data, peer->p_hdr.info.pi_diamid, avp_hdr->avp_value->os.len );
+		if (cmp > 0)
+			continue;
+		if (cmp == 0)
+			found = 1;
+		break;
+	}
+	
+	if (!found) {
+		/* Create a new peer entry for this new remote peer */
+		peer = NULL;
+		CHECK_FCT_DO( ret = fd_peer_alloc(&peer), goto out );
+		
+		/* Set the peer Diameter Id and the responder flag parameters */
+		CHECK_MALLOC_DO( peer->p_hdr.info.pi_diamid = malloc(avp_hdr->avp_value->os.len + 1), { ret = ENOMEM; goto out; } );
+		CHECK_MALLOC_DO( peer->p_dbgorig = strdup(fd_cnx_getid(*cnx)), { ret = ENOMEM; goto out; } );
+		peer->p_flags.pf_responder = 1;
+		
+		/* Upgrade the lock to write lock */
+		CHECK_POSIX_DO( ret = pthread_rwlock_wrlock(&fd_g_peers_rw), goto out );
+		
+		/* Insert the new peer in the list (the PSM will take care of setting the expiry after validation) */
+		fd_list_insert_before( li, &peer->p_hdr.chain );
+		
+		/* Release the write lock */
+		CHECK_POSIX_DO( ret = pthread_rwlock_unlock(&fd_g_peers_rw), goto out );
+		
+		/* Start the PSM, which will receive the event bellow */
+		CHECK_FCT_DO( ret = fd_psm_begin(peer), goto out );
+	}
+		
+	/* Send the new connection event to the PSM */
+	CHECK_MALLOC_DO( ev_data = malloc(sizeof(struct cnx_incoming)), { ret = ENOMEM; goto out; } );
+	memset(ev_data, 0, sizeof(ev_data));
+	
+	ev_data->cer = msg;
+	ev_data->cnx = *cnx;
+	ev_data->validate = !found;
+	
+	CHECK_FCT_DO( ret = fd_event_send(peer->p_events, FDEVP_CNX_INCOMING, sizeof(ev_data), ev_data), goto out );
+	
+out:	
+	CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) );
+
+	if (ret == 0) {
+		/* Reset the "out" parameters, so that they are not cleanup on function return. */
+		*cer = NULL;
+		*cnx = NULL;
+	}
+	
+	return ret;
+}
+
+/* Save a callback to accept / reject incoming unknown peers */
+int fd_peer_validate_register ( int (*peer_validate)(struct peer_info * /* info */, int * /* auth */, int (**cb2)(struct peer_info *)) )
+{
+	
+	TODO("...");
+	return ENOTSUP;
+}
+
+/* Validate a peer by calling the callbacks in turn -- return 0 if the peer is validated, ! 0 in case of error or if the peer is rejected */
+int fd_peer_validate( struct fd_peer * peer )
+{
+	TODO("Default to reject");
+	TODO("Call all callbacks in turn");
+	TODO("Save cb2 in the peer if needed");
+	return ENOTSUP;
+}
