changeset 40:7e1deaa89540

Some progress on the PSM
author Sebastien Decugis <sdecugis@nict.go.jp>
date Fri, 06 Nov 2009 13:05:36 +0900
parents d7535cf7bab5
children 8e027b57cf5f
files freeDiameter/fD.h freeDiameter/p_ce.c freeDiameter/p_dp.c freeDiameter/p_dw.c freeDiameter/p_psm.c
diffstat 5 files changed, 141 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/freeDiameter/fD.h	Thu Nov 05 18:43:42 2009 +0900
+++ b/freeDiameter/fD.h	Fri Nov 06 13:05:36 2009 +0900
@@ -261,11 +261,13 @@
 void fd_p_sr_failover(struct sr_list * srlist);
 
 /* 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_msgrcv(struct msg ** msg, int req, 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_ce_handle_newcnx(struct fd_peer * peer, struct cnxctx * initiator);
+int fd_p_ce_winelection(struct fd_peer * peer);
+int fd_p_dw_handle(struct msg ** msg, int req, 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_handle(struct msg ** msg, int req, 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 */
--- a/freeDiameter/p_ce.c	Thu Nov 05 18:43:42 2009 +0900
+++ b/freeDiameter/p_ce.c	Fri Nov 06 13:05:36 2009 +0900
@@ -35,24 +35,86 @@
 
 #include "fD.h"
 
-/* This file contains code to handle Capabilities Exchange messages (CER and CEA) */
+/* This file contains code to handle Capabilities Exchange messages (CER and CEA) and election process */
 
-int fd_p_ce_handle(struct msg ** msg, struct fd_peer * peer)
+/* Save a connection as peer's principal */
+static int set_peer_cnx(struct fd_peer * peer, struct cnxctx **cnx)
 {
-	TODO("Handle depending on CER or CEA and peer state");
+	TODO("Save *cnx into peer->p_cnxctx");
+	TODO("Set fifo of *cnx to peer->p_events");
+	TODO("If connection is already TLS, read the credentials");
+	TODO("Read the remote endpoints");
 	
 	return ENOTSUP;
 }
 
+static int process_valid_CEA(struct fd_peer * peer, struct msg ** cea)
+{
+	/* Save info from the CEA into the peer */
+	
+	/* Handshake if needed */
+	
+	/* Save credentials if needed */
+	
+	TODO("...");
+	return ENOTSUP;
+	
+}
+
+/* We have received a Capabilities Exchange message on the peer connection */
+int fd_p_ce_msgrcv(struct msg ** msg, int req, struct fd_peer * peer)
+{
+	TRACE_ENTRY("%p %p", msg, peer);
+	CHECK_PARAMS( msg && *msg && CHECK_PEER(peer) );
+	
+	/* The only valid situation where we are called is in WAITCEA and we receive a CEA */
+	
+	/* Note : to implement Capabilities Update, we would need to change here */
+	
+	/* If it is a CER, just reply an error */
+	if (req) {
+		/* Create the error message */
+		CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, MSGFL_ANSW_ERROR ) );
+		
+		/* Set the error code */
+		CHECK_FCT( fd_msg_rescode_set(*msg, "DIAMETER_COMMAND_UNSUPPORTED", "No CER in current state", NULL, 1 ) );
+
+		/* msg now contains an answer message to send back */
+		CHECK_FCT_DO( fd_out_send(msg, peer->p_cnxctx, peer), /* In case of error the message has already been dumped */ );
+
+	}
+	
+	/* If the state is not WAITCEA, just discard the message */
+	if ((req) || (peer->p_hdr.info.runtime.pir_state != STATE_WAITCEA)) {
+		if (*msg) {
+			fd_log_debug("Received CER/CEA message while in state '%s', discarded.\n", STATE_STR(peer->p_hdr.info.runtime.pir_state));
+			fd_msg_dump_walk(NONE, *msg);
+			CHECK_FCT_DO( fd_msg_free(*msg), /* continue */);
+			*msg = NULL;
+		}
+		
+		return 0;
+	}
+	
+	/* Ok, now we can accept the CEA */
+	TODO("process_valid_CEA");
+	
+	return ENOTSUP;
+}
+
+/* We have received a CER on a new connection for this peer */
 int fd_p_ce_handle_newCER(struct msg ** msg, struct fd_peer * peer, struct cnxctx ** cnx, int valid)
 {
 	switch (peer->p_hdr.info.runtime.pir_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");
+			TODO("Handle the CER, validate the peer if needed (and set expiry), set the alt_fifo in the connection, reply a CEA, eventually handshake (OPEN_HANDSHAKE), move to OPEN or REOPEN state");
 			/* In case of error : DIAMETER_UNKNOWN_PEER */
 			break;
 
 		case STATE_WAITCNXACK:
+			TODO("Save the parameters in the peer, move to STATE_WAITCNXACK_ELEC");
+			break;
+			
 		case STATE_WAITCEA:
 			TODO("Election");
 			break;
@@ -67,3 +129,38 @@
 	
 	return ENOTSUP;
 }
+
+static int do_election(struct fd_peer * peer)
+{
+	TODO("Compare diameter Ids");
+	
+	/* ELECTION_LOST error code ?*/
+	
+	TODO("If we lost the election, we close the received connection and go to WAITCEA");
+	TODO("If we won the election, we close initiator cnx, then call fd_p_ce_winelection");
+	
+	
+}
+
+/* We have established a new connection to the remote peer, send CER and eventually do election */
+int fd_p_ce_handle_newcnx(struct fd_peer * peer, struct cnxctx * initiator)
+{
+	/* if not election */
+	TODO("Set the connection as peer's (setaltfifo)");
+	TODO("Send CER");
+	TODO("Move to WAITCEA");
+	TODO("Change timer to CEA_TIMEOUT");
+	
+	/* if election */				
+	TODO("Send CER on cnx");
+	TODO("Do the election");
+	
+	return ENOTSUP;
+}
+
+/* Handle the receiver side after winning an election (or timeout on initiator side) */
+int fd_p_ce_winelection(struct fd_peer * peer)
+{
+	TODO("Move the receiver side connection to peer principal, set the altfifo");
+	TODO("Then handle the received CER");
+}
--- a/freeDiameter/p_dp.c	Thu Nov 05 18:43:42 2009 +0900
+++ b/freeDiameter/p_dp.c	Fri Nov 06 13:05:36 2009 +0900
@@ -38,7 +38,7 @@
 /* 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)
+int fd_p_dp_handle(struct msg ** msg, int req, struct fd_peer * peer)
 {
 	TODO("Handle depending on DPR or DPA and peer state");
 	
--- a/freeDiameter/p_dw.c	Thu Nov 05 18:43:42 2009 +0900
+++ b/freeDiameter/p_dw.c	Fri Nov 06 13:05:36 2009 +0900
@@ -39,7 +39,7 @@
 
 
 /* Handle an incoming message */
-int fd_p_dw_handle(struct msg ** msg, struct fd_peer * peer)
+int fd_p_dw_handle(struct msg ** msg, int req, struct fd_peer * peer)
 {
 	TODO("Handle depending on DWR or DWA and peer state");
 	
--- a/freeDiameter/p_psm.c	Thu Nov 05 18:43:42 2009 +0900
+++ b/freeDiameter/p_psm.c	Fri Nov 06 13:05:36 2009 +0900
@@ -247,7 +247,6 @@
 	/* Move to CLOSED state: failover messages, stop OUT thread, unlink peer from active list */
 	CHECK_FCT_DO( fd_psm_change_state(peer, STATE_CLOSED), /* continue */ );
 	
-
 	fd_p_cnx_abort(peer, terminate);
 	
 	if (peer->p_cnxctx) {
@@ -467,15 +466,15 @@
 		/* Handle the LL message and update the expiry timer appropriately */
 		switch (hdr->msg_code) {
 			case CC_CAPABILITIES_EXCHANGE:
-				CHECK_FCT_DO( fd_p_ce_handle(&msg, peer), goto psm_end );
+				CHECK_FCT_DO( fd_p_ce_msgrcv(&msg, (hdr->msg_flags & CMD_FLAG_REQUEST), peer), goto psm_end );
 				break;
 			
 			case CC_DISCONNECT_PEER:
-				CHECK_FCT_DO( fd_p_dp_handle(&msg, peer), goto psm_end );
+				CHECK_FCT_DO( fd_p_dp_handle(&msg, (hdr->msg_flags & CMD_FLAG_REQUEST), peer), goto psm_end );
 				break;
 			
 			case CC_DEVICE_WATCHDOG:
-				CHECK_FCT_DO( fd_p_dw_handle(&msg, peer), goto psm_end );
+				CHECK_FCT_DO( fd_p_dw_handle(&msg, (hdr->msg_flags & CMD_FLAG_REQUEST), peer), goto psm_end );
 				break;
 			
 			default:
@@ -589,6 +588,29 @@
 		goto psm_loop;
 	}
 	
+	/* A new connection has been established with the remote peer */
+	if (event == FDEVP_CNX_ESTABLISHED) {
+		struct cnxctx * cnx = ev_data;
+		
+		/* Release the resources of the thread */
+		CHECK_POSIX_DO( pthread_join( peer->p_ini_thr, NULL), /* ignore, it is not a big deal */);
+		peer->p_ini_thr = (pthread_t)NULL;
+		
+		switch (peer->p_hdr.info.runtime.pir_state) {
+			case STATE_WAITCNXACK_ELEC:
+			case STATE_WAITCNXACK:
+				fd_p_ce_handle_newcnx(peer, cnx);
+				break;
+				
+			default:
+				/* Just abort the attempt and continue */
+				TRACE_DEBUG(FULL, "Connection attempt successful but current state is %s, closing...", STATE_STR(peer->p_hdr.info.runtime.pir_state));
+				fd_cnx_destroy(cnx);
+		}
+		
+		goto psm_loop;
+	}
+	
 	/* The timeout for the current state has been reached */
 	if (event == FDEVP_PSM_TIMEOUT) {
 		switch (peer->p_hdr.info.runtime.pir_state) {
@@ -613,7 +635,12 @@
 				break;
 				
 			case STATE_WAITCNXACK_ELEC:
-				TODO("Abort initiating side, handle the receiver side");
+				
+				/* Abort the initiating side */
+				fd_p_cnx_abort(peer, 0);
+				
+				/* Handle receiver side */
+				CHECK_FCT_DO( fd_p_ce_winelection(peer), goto psm_end );
 				break;
 		}
 	}
@@ -621,7 +648,7 @@
 	/* Default action : the handling has not yet been implemented. [for debug only] */
 	TODO("Missing handler in PSM : '%s'\t<-- '%s'", STATE_STR(peer->p_hdr.info.runtime.pir_state), fd_pev_str(event));
 	if (event == FDEVP_PSM_TIMEOUT) {
-		/* We have not handled timeout in this state, let's postpone next alert */
+		/* We have not handled timeout in this state, let's postpone next alert to avoid flood */
 		fd_psm_next_timeout(peer, 0, 60);
 	}
 	
"Welcome to our mercurial repository"