diff freeDiameter/p_psm.c @ 33:e6fcdf12b9a0

Added a lot of TODOs :)
author Sebastien Decugis <sdecugis@nict.go.jp>
date Thu, 29 Oct 2009 18:05:45 +0900
parents 5ba91682f0bc
children 0e2b57789361
line wrap: on
line diff
--- a/freeDiameter/p_psm.c	Thu Oct 29 10:23:12 2009 +0900
+++ b/freeDiameter/p_psm.c	Thu Oct 29 18:05:45 2009 +0900
@@ -35,40 +35,18 @@
 
 #include "fD.h"
 
-const char *peer_state_str[] = { 
-	  "STATE_NEW"
-	, "STATE_OPEN"
-	, "STATE_CLOSED"
-	, "STATE_CLOSING"
-	, "STATE_WAITCNXACK"
-	, "STATE_WAITCNXACK_ELEC"
-	, "STATE_WAITCEA"
-	, "STATE_OPEN_HANDSHAKE"
-	, "STATE_SUSPECT"
-	, "STATE_REOPEN"
-	, "STATE_ZOMBIE"
-	};
+/* The actual declaration of peer_state_str */
+DECLARE_STATE_STR();
 
-const char * fd_pev_str(int event)
-{
-	switch (event) {
-	#define case_str( _val )\
-		case _val : return #_val
-		case_str(FDEVP_DUMP_ALL);
-		case_str(FDEVP_TERMINATE);
-		case_str(FDEVP_CNX_MSG_RECV);
-		case_str(FDEVP_CNX_ERROR);
-		case_str(FDEVP_CNX_EP_CHANGE);
-		case_str(FDEVP_CNX_INCOMING);
-		case_str(FDEVP_PSM_TIMEOUT);
-		
-		default:
-			TRACE_DEBUG(FULL, "Unknown event : %d", event);
-			return "Unknown event";
-	}
-}
+/* Helper for next macro */
+#define case_str( _val )		\
+	case _val : return #_val
 
+DECLARE_PEV_STR();
 
+/************************************************************************/
+/*                      Delayed startup                                 */
+/************************************************************************/
 static int started = 0;
 static pthread_mutex_t  started_mtx = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t   started_cnd = PTHREAD_COND_INITIALIZER;
@@ -89,13 +67,78 @@
 	return 0;
 }
 
-/* Cancelation cleanup : set ZOMBIE state in the peer */
-void cleanup_state(void * arg) 
+/* Allow the state machines to start */
+int fd_psm_start()
+{
+	TRACE_ENTRY("");
+	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;
+}
+
+
+/************************************************************************/
+/*                 Manage the list of active peers                      */
+/************************************************************************/
+
+
+/* Enter/leave OPEN state */
+static int enter_open_state(struct fd_peer * peer)
+{
+	CHECK_POSIX( pthread_rwlock_wrlock(&fd_g_activ_peers_rw) );
+	TODO(" insert in fd_g_activ_peers ");
+	
+	CHECK_POSIX( pthread_rwlock_unlock(&fd_g_activ_peers_rw) );
+	
+	/* Start the thread to handle outgoing messages */
+	CHECK_FCT( fd_out_start(peer) );
+	
+	return ENOTSUP;
+}
+static int leave_open_state(struct fd_peer * peer)
 {
-	struct fd_peer * peer = (struct fd_peer *)arg;
-	CHECK_PARAMS_DO( CHECK_PEER(peer), return );
-	peer->p_hdr.info.pi_state = STATE_ZOMBIE;
-	return;
+	TODO("Remove from active list");
+	
+	/* Stop the "out" thread */
+	CHECK_FCT( fd_out_stop(peer) );
+	
+	TODO("Failover pending messages: requeue in global structures");
+	
+	return ENOTSUP;
+}
+
+/************************************************************************/
+/*                      Helpers for state changes                       */
+/************************************************************************/
+/* Change state */
+static int change_state(struct fd_peer * peer, int new_state)
+{
+	int old;
+	
+	TRACE_ENTRY("%p %d(%s)", peer, new_state, STATE_STR(new_state));
+	CHECK_PARAMS( CHECK_PEER(peer) );
+	old = peer->p_hdr.info.pi_state;
+	if (old == new_state)
+		return 0;
+	
+	TRACE_DEBUG(FULL, "'%s'\t-> '%s'\t'%s'",
+			STATE_STR(old),
+			STATE_STR(new_state),
+			peer->p_hdr.info.pi_diamid);
+	
+	if (old == STATE_OPEN) {
+		CHECK_FCT( leave_open_state(peer) );
+	}
+	
+	peer->p_hdr.info.pi_state = new_state;
+	
+	if (new_state == STATE_OPEN) {
+		CHECK_FCT( enter_open_state(peer) );
+	}
+	
+	return 0;
 }
 
 /* Set timeout timer of next event */
@@ -127,6 +170,19 @@
 #endif
 }
 
+
+/************************************************************************/
+/*                      The PSM thread                                  */
+/************************************************************************/
+/* Cancelation cleanup : set ZOMBIE state in the peer */
+void cleanup_state(void * arg) 
+{
+	struct fd_peer * peer = (struct fd_peer *)arg;
+	CHECK_PARAMS_DO( CHECK_PEER(peer), return );
+	peer->p_hdr.info.pi_state = STATE_ZOMBIE;
+	return;
+}
+
 /* The state machine thread (controler) */
 static void * p_psm_th( void * arg )
 {
@@ -170,16 +226,26 @@
 
 	/* Now, the action depends on the current state and the incoming event */
 
-	/* The following two states are impossible */
+	/* The following states are impossible */
 	ASSERT( peer->p_hdr.info.pi_state != STATE_NEW );
 	ASSERT( peer->p_hdr.info.pi_state != STATE_ZOMBIE );
+	ASSERT( peer->p_hdr.info.pi_state != STATE_OPEN_HANDSHAKE ); /* because it exists only between two loops */
 
 	/* Purge invalid events */
-	if (!CHECK_EVENT(event)) {
+	if (!CHECK_PEVENT(event)) {
 		TRACE_DEBUG(INFO, "Invalid event received in PSM '%s' : %d", peer->p_hdr.info.pi_diamid, event);
 		goto psm_loop;
 	}
 
+	/* Call the extension callback if needed */
+	if (peer->p_cb) {
+		/* Check if we must call it */
+			/*  */
+		/* OK */
+		TODO("Call CB");
+		TODO("Clear CB");
+	}
+
 	/* Handle the (easy) debug event now */
 	if (event == FDEVP_DUMP_ALL) {
 		fd_peer_dump(peer, ANNOYING);
@@ -208,6 +274,42 @@
 		}
 	}
 	
+	/* A message was received */
+	if (event == FDEVP_CNX_MSG_RECV) {
+		TODO("Parse the buffer into a message");
+		/* parse_and_get_local_ccode */
+		TODO("Check if it is a local message (CER, DWR, ...)");
+		TODO("If not, check we are in OPEN state");
+		TODO("Update expiry timer if needed");
+		TODO("Handle the message");
+	}
+	
+	/* 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");
+	}
+	
+	/* The connection notified a change in endpoints */
+	if (event == FDEVP_CNX_EP_CHANGE) {
+		/* Cleanup the remote LL and primary addresses */
+		CHECK_FCT_DO( fd_ep_filter( &peer->p_hdr.info.pi_endpoints, EP_FL_CONF | EP_FL_DISC | EP_FL_ADV ), /* ignore the error */);
+		CHECK_FCT_DO( fd_ep_clearflags( &peer->p_hdr.info.pi_endpoints, EP_FL_PRIMARY ), /* ignore the error */);
+		
+		/* Get the new ones */
+		CHECK_FCT_DO( fd_cnx_getendpoints(peer->p_cnxctx, NULL, &peer->p_hdr.info.pi_endpoints), /* ignore the error */);
+		
+		if (TRACE_BOOL(ANNOYING)) {
+			fd_log_debug("New remote endpoint(s):\n");
+			fd_ep_dump(6, &peer->p_hdr.info.pi_endpoints);
+		}
+		
+		/* Done */
+		goto psm_loop;
+	}
+	
 	/* A new connection was established and CER containing this peer id was received */
 	if (event == FDEVP_CNX_INCOMING) {
 		struct cnx_incoming * params = ev_data;
@@ -234,10 +336,15 @@
 		goto psm_loop;
 	}
 	
-	/* MSG_RECEIVED: fd_p_expi_update(struct fd_peer * peer ) */
-	/* If timeout or OPEN : call cb if defined */
-
-	/* Default action : the handling has not yet been implemented. */
+	/* The timeout for the current state has been reached */
+	if (event == FDEVP_PSM_TIMEOUT) {
+		switch (peer->p_hdr.info.pi_state) {
+			
+			
+		}
+	}
+	
+	/* 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.pi_state), fd_pev_str(event));
 	if (event == FDEVP_PSM_TIMEOUT) {
 		/* We have not handled timeout in this state, let's postpone next alert */
@@ -251,8 +358,12 @@
 	peer->p_psm = (pthread_t)NULL;
 	pthread_detach(pthread_self());
 	return NULL;
-}	
+}
+
 
+/************************************************************************/
+/*                      Functions to control the PSM                    */
+/************************************************************************/
 /* Create the PSM thread of one peer structure */
 int fd_psm_begin(struct fd_peer * peer )
 {
@@ -282,26 +393,16 @@
 	return 0;
 }
 
-/* End the PSM violently */
+/* End the PSM & cleanup the peer structure */
 void fd_psm_abord(struct fd_peer * peer )
 {
 	TRACE_ENTRY("%p", peer);
 	TODO("Cancel PSM thread");
-	TODO("Cancel IN thread");
 	TODO("Cancel OUT thread");
 	TODO("Cleanup the peer connection object");
 	TODO("Cleanup the message queues (requeue)");
+	TODO("Call p_cb with NULL parameter if needed");
+	
 	return;
 }
 
-/* Allow the state machines to start */
-int fd_psm_start()
-{
-	TRACE_ENTRY("");
-	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;
-}
-
"Welcome to our mercurial repository"