changeset 222:b6eb2112a01f

Added some support for election
author Sebastien Decugis <sdecugis@nict.go.jp>
date Tue, 04 Nov 2008 17:01:30 +0900
parents adf7fea19de7
children 408106496938
files waaad/peer-internal.h waaad/peer-psm.c waaad/peer-struct.c
diffstat 3 files changed, 124 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/waaad/peer-internal.h	Tue Nov 04 14:18:38 2008 +0900
+++ b/waaad/peer-internal.h	Tue Nov 04 17:01:30 2008 +0900
@@ -181,6 +181,7 @@
 #define VALSTATE( _state_ ) ( (((_state_) > 0) && ((_state_) <= STATE_REOPEN)) ? (_state_) : 0 )
 #define STATESTR( _st_ ) statestr[VALSTATE( _st_ )]
 
+struct _ev_incoming;
 
 /***********************************************************************************/
 
@@ -257,6 +258,9 @@
 	uint32_t	 p_firmrev;	/* The firmware revision */
 	uint32_t	 p_orstate;	/* The origin-state id of the remote peer. May be used to detect resets of the remote peer (?) */
 	
+	/* Saved data that will be used in case of election */
+	struct _ev_incoming *p_electdata;	/* The data associated with the incoming CER */
+	
 } _peer_t;
 
 /* The eye-catcher value */
@@ -359,7 +363,7 @@
 } _pe_t;
 
 /* Structure for Incoming calls event data */
-typedef struct {
+typedef struct _ev_incoming {
 	_peer_t	* peer; /* The dummy peer containing all the CER data and incoming connection information */
 	uint32_t  ete; /* the end-to-end id of the received CER to create the matching answer */
 	uint32_t  hbh; /* the hop-by-hop id of the received CER to create the matching answer */
--- a/waaad/peer-psm.c	Tue Nov 04 14:18:38 2008 +0900
+++ b/waaad/peer-psm.c	Tue Nov 04 17:01:30 2008 +0900
@@ -86,6 +86,13 @@
 {
 	TRACE_ENTRY("%p(%s/%s) %d(%s) %p", peer, peer->p_diamid ?: "null", STATESTR(peer->p_state), event, EVENTSTR(event), ev_data);
 	
+	/* Handle some simple events */
+	if (event == PEVENT_SHUTDOWN)
+		peer->p_flags |= PEERFL_DISABLE_AFTER_SHUTDOWN;
+	
+	if (event == PEVENT_DESTROY)
+		peer->p_flags |= PEERFL_DESTROY_AFTER_SHUTDOWN;
+	
 	/* All is done by just returning 1 here */
 	return 1;
 }
@@ -133,7 +140,7 @@
 	/* We are called when we have been connected. do some sanity checks for debug */
 	ASSERT( event == PEVENT_CONNECTED );
 	ASSERT( con_data );
-	ASSERT( peer->p_state == STATE_WAITCNXACK );
+	ASSERT( (peer->p_state == STATE_WAITCNXACK) || (peer->p_state == STATE_WAITCNXACK_ELEC) );
 	
 	/* Initialize the connection data */
 	peer->p_sock = con_data->sock;
@@ -155,8 +162,12 @@
 	/* Send the CER */
 	CHECK_FCT_DO(  meq_post( peer->p_out_q, cer ),  return 1  ); 
 	
-	/* go to STATE_WAITCEA state */
-	_psm_change_state(peer, STATE_WAITCEA);
+	/* go to next state */
+	if (peer->p_state == STATE_WAITCNXACK) {
+		_psm_change_state(peer, STATE_WAITCEA);
+	} else {
+		_psm_change_state(peer, STATE_WAITRETURNS_ELEC);
+	}
 	
 	/* and re-arm the timer */
 	_psm_reset_ts(peer, 0, CEA_TIMEOUT);
@@ -179,6 +190,9 @@
 	ASSERT( peer->p_state == STATE_CLOSED );
 	ASSERT( peer->p_sec_hdl == NULL );
 	
+	/* Cleanup some flags */
+	peer->p_flags &= ~ (PEERFL_SHUTTING_DOWN | PEERFL_DISABLE_AFTER_SHUTDOWN | PEERFL_DESTROY_AFTER_SHUTDOWN );
+	
 	/* Push two cancelation handlers to free the event data in case of we are cancelled */
 	pthread_cleanup_push( free, inc );
 	pthread_cleanup_push( (void (*)(void *))_peer_struct_destroy, &inc->peer );
@@ -312,6 +326,81 @@
 	return 1;
 }
 
+/* Received a CER on new connection that we reject */
+static int _psm_reject_incoming_CER( _peer_t * peer, _pevent_t event, void * ev_data )
+{
+	_ev_incoming_t * inc = (_ev_incoming_t *)ev_data;
+	msg_t * cea = NULL;
+	
+	TRACE_ENTRY("%p(%s/%s) %d(%s) %p", peer, peer->p_diamid ?: "null", STATESTR(peer->p_state), event, EVENTSTR(event), ev_data);
+	
+	ASSERT( event == PEVENT_INCNX );
+	ASSERT( inc && VALIDATE_PEER(inc->peer) );
+	
+	/* Push two cancelation handlers to free the event data in case of we are cancelled */
+	pthread_cleanup_push( free, inc );
+	pthread_cleanup_push( (void (*)(void *))_peer_struct_destroy, &inc->peer );
+	
+	/* The inc->peer object already contains all parsed data from the received CER, copy this data into the main peer structure */
+	
+	/* Create a CEA message */
+	CHECK_FCT_DO( _peer_cea_create( inc->peer, &cea, inc->ete, inc->hbh ), goto error );
+	pthread_cleanup_push( _cleanup_msg, cea );
+	
+	/* Now set the error code */
+	CHECK_FCT_DO( msg_rescode_set( cea, "DIAMETER_UNABLE_TO_COMPLY", NULL, NULL ), goto error );
+		
+	/* send the message (the out thread is not running at this time) */
+	CHECK_FCT_DO( _peer_out_sendmsg( inc->peer, cea ), goto error );
+	
+	/* Free everything */
+	pthread_cleanup_pop(1);
+	pthread_cleanup_pop(1);
+	pthread_cleanup_pop(1);
+	
+	/* If we were in SUSPECT state, we may want to reset the peer now? Ignore for now ... */
+	
+	return 0;
+	
+error:
+	if (inc) {
+		if (inc->peer)
+			_peer_struct_destroy(&inc->peer);
+		free(inc);
+		inc = NULL;
+	}
+	if (cea) {
+		CHECK_FCT_DO( msg_free(cea, 1), /* continue */ );
+	}
+	return 1;
+}
+
+/* Save incoming connection data for the upcoming election */
+static int _psm_incon_elect( _peer_t * peer, _pevent_t event, void * ev_data )
+{
+	_ev_incoming_t * inc = (_ev_incoming_t *)ev_data;
+	
+	TRACE_ENTRY("%p(%s/%s) %d(%s) %p", peer, peer->p_diamid ?: "null", STATESTR(peer->p_state), event, EVENTSTR(event), ev_data);
+	
+	ASSERT( inc && VALIDATE_PEER(inc->peer) );
+	
+	/* For now, just save the event data in the peer structure */
+	ASSERT( peer->p_electdata == NULL );
+	peer->p_electdata = inc;
+	
+	/* And change state accordingly to previous state */
+	ASSERT( (peer->p_state == STATE_WAITCNXACK) || (peer->p_state == STATE_WAITCEA) );
+	
+	if (peer->p_state == STATE_WAITCNXACK) {
+		_psm_change_state(peer, STATE_WAITCNXACK_ELEC);
+	}
+	if (peer->p_state == STATE_WAITCEA) {
+		_psm_change_state(peer, STATE_WAITRETURNS_ELEC);
+	}
+		
+	return 0;
+}
+
 /* A message has been received while we were waiting for a CEA */
 static int _psm_receive_CEA( _peer_t * peer, _pevent_t event, void * ev_data )
 {
@@ -383,7 +472,7 @@
 }
 
 /* A message has been received, we must handle application 0 and forward others to the routing module (we are in open state) */
-static int _psm_receive_OPEN( _peer_t * peer, _pevent_t event, void * ev_data )
+static int _psm_receive_message( _peer_t * peer, _pevent_t event, void * ev_data )
 {
 	msg_t * msg = NULL;
 	msg_data_t *mdata = NULL;
@@ -392,7 +481,7 @@
 	
 	/* Do some sanity checks for debug */
 	ASSERT( event == PEVENT_MSGRCVD );
-	ASSERT( peer->p_state == STATE_OPEN );
+	ASSERT( (peer->p_state == STATE_OPEN) || (peer->p_state == STATE_CLOSING) );
 	
 	/* Retrieve the new message from the incoming queue */
 	CHECK_FCT_DO(  meq_tryget(peer->p_in_q, &msg),  return 1  );
@@ -437,7 +526,7 @@
 	switch (mdata->msg_code) {
 		case CC_CAPABILITIES_EXCHANGE:
 			/* We do not handle additional CER/CEA messages (no renegotiation). */
-			log_error("CER/CEA message received from peer '%s' in OPEN state (not supported), resetting connection...", peer->p_diamid);
+			log_error("CER/CEA message received from peer '%s' in state %s (not supported), resetting connection...", peer->p_diamid, STATESTR(peer->p_state));
 			msg_dump_walk(msg);
 			msg_free(msg, 1);
 			return 1;
@@ -487,7 +576,10 @@
 				/* and queue the message for delivery */
 				CHECK_FCT_DO( meq_post( peer->p_out_q, dpa ),
 					{ msg_free(dpa, 1); return 1; } );
-
+				
+				/* Now go to CLOSING state */
+				_psm_change_state(peer, STATE_CLOSING);
+				
 			} else {
 				/* We received a DPA. Did we really ask for disconnection? */
 				if ( ! (peer->p_flags & PEERFL_SHUTTING_DOWN)) {
@@ -678,8 +770,8 @@
 		/* PEVENT_EXPIRE 	*/ {  _psm_expire		}, /* Handle dynamic peers end-of-lifetime */
 		/* PEVENT_TIMEOUT 	*/ {  _psm_do_watchdog		}, /* the handler may overwrite the next state to SUSPECT */
 		/* PEVENT_CONNECTED 	*/ {  _psm_assert		}, /* Did we initiate two connections?? */
-		/* PEVENT_MSGRCVD 	*/ {  _psm_receive_OPEN		}, /* Handle received messages */
-		/* PEVENT_INCNX 	*/ {  _psm_NOTSUP		}, /* We must reject the new connection */
+		/* PEVENT_MSGRCVD 	*/ {  _psm_receive_message	}, /* Handle received messages */
+		/* PEVENT_INCNX 	*/ {  _psm_reject_incoming_CER	}, /* We must reject the new connection */
 		/* PEVENT_ASSOC_CHG 	*/ {  _psm_ignore		}, /* I guess it will depend on the change... ignore for now */
 		/* PEVENT_PEERADDR_CHG 	*/ {  _psm_NOTSUP		}, /* Security issue? We may want to check the address change is compatible with advertised host-ip-addresses */
 		/* PEVENT_REMOTE_ERR 	*/ {  _psm_NOTSUP		}, /* should mark as SUSPECT and probe the cnx with DWR/DWA ? */
@@ -689,8 +781,8 @@
 		/* PEVENT_TH_TERM_OUT 	*/ {  _psm_reset		}  /* A serious error occurred in sender   thread: cleanup open resources and reset the PSM */
 		},
 	/* STATE_CLOSED 	*/  {
-		/* PEVENT_SHUTDOWN 	*/ {  _psm_ignore 	 	}, /* The peer is already shutdown. */
-		/* PEVENT_DESTROY 	*/ {  _psm_NOTSUP 	 	},
+		/* PEVENT_SHUTDOWN 	*/ {  _psm_reset 	 	}, /* May force stopping reconnections */
+		/* PEVENT_DESTROY 	*/ {  _psm_reset 	 	},
 		/* PEVENT_EXPIRE 	*/ {  _psm_expire 	 	}, /* Handle dynamic peers end-of-lifetime */
 		/* PEVENT_TIMEOUT 	*/ {  _psm_connect	 	}, /* Timeout reached, it's time to attempt new connection */
 		/* PEVENT_CONNECTED 	*/ {  _psm_assert 	 	}, /* This should never happen, but anyway we can ignore it */
@@ -708,10 +800,10 @@
 		/* PEVENT_SHUTDOWN 	*/ {  _psm_NOTSUP	 	},
 		/* PEVENT_DESTROY 	*/ {  _psm_NOTSUP	 	},
 		/* PEVENT_EXPIRE 	*/ {  _psm_expire	 	},
-		/* PEVENT_TIMEOUT 	*/ {  _psm_NOTSUP	 	},
+		/* PEVENT_TIMEOUT 	*/ {  _psm_reset	 	},
 		/* PEVENT_CONNECTED 	*/ {  _psm_NOTSUP	 	},
-		/* PEVENT_MSGRCVD 	*/ {  _psm_NOTSUP	 	},
-		/* PEVENT_INCNX 	*/ {  _psm_NOTSUP		},
+		/* PEVENT_MSGRCVD 	*/ {  _psm_receive_message 	},
+		/* PEVENT_INCNX 	*/ {  _psm_reject_incoming_CER	},
 		/* PEVENT_ASSOC_CHG 	*/ {  _psm_NOTSUP	 	},
 		/* PEVENT_PEERADDR_CHG 	*/ {  _psm_NOTSUP	 	},
 		/* PEVENT_REMOTE_ERR 	*/ {  _psm_NOTSUP	 	},
@@ -727,7 +819,7 @@
 		/* PEVENT_TIMEOUT 	*/ {  _psm_reset		}, /* The attempt failed, reset the PSM */
 		/* PEVENT_CONNECTED 	*/ {  _psm_send_CER		}, /* Send a CER */
 		/* PEVENT_MSGRCVD 	*/ {  _psm_NOTSUP		},
-		/* PEVENT_INCNX 	*/ {  _psm_NOTSUP		},
+		/* PEVENT_INCNX 	*/ {  _psm_incon_elect		}, /* We will have to handle an election */
 		/* PEVENT_ASSOC_CHG 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_PEERADDR_CHG 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_REMOTE_ERR 	*/ {  _psm_NOTSUP		},
@@ -741,9 +833,9 @@
 		/* PEVENT_DESTROY 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_EXPIRE 	*/ {  _psm_expire		},
 		/* PEVENT_TIMEOUT 	*/ {  _psm_NOTSUP		},
-		/* PEVENT_CONNECTED 	*/ {  _psm_NOTSUP		},
+		/* PEVENT_CONNECTED 	*/ {  _psm_send_CER		},
 		/* PEVENT_MSGRCVD 	*/ {  _psm_NOTSUP		},
-		/* PEVENT_INCNX 	*/ {  _psm_NOTSUP		},
+		/* PEVENT_INCNX 	*/ {  _psm_reject_incoming_CER	},
 		/* PEVENT_ASSOC_CHG 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_PEERADDR_CHG 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_REMOTE_ERR 	*/ {  _psm_NOTSUP		},
@@ -759,7 +851,7 @@
 		/* PEVENT_TIMEOUT 	*/ {  _psm_reset		}, /* Did not receive a CEA in the given time, reset the PSM */
 		/* PEVENT_CONNECTED 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_MSGRCVD 	*/ {  _psm_receive_CEA		},
-		/* PEVENT_INCNX 	*/ {  _psm_NOTSUP		},
+		/* PEVENT_INCNX 	*/ {  _psm_incon_elect		}, /* We will have to handle an election */
 		/* PEVENT_ASSOC_CHG 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_PEERADDR_CHG 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_REMOTE_ERR 	*/ {  _psm_NOTSUP		},
@@ -775,7 +867,7 @@
 		/* PEVENT_TIMEOUT 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_CONNECTED 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_MSGRCVD 	*/ {  _psm_NOTSUP		},
-		/* PEVENT_INCNX 	*/ {  _psm_NOTSUP		},
+		/* PEVENT_INCNX 	*/ {  _psm_reject_incoming_CER	},
 		/* PEVENT_ASSOC_CHG 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_PEERADDR_CHG 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_REMOTE_ERR 	*/ {  _psm_NOTSUP		},
@@ -791,7 +883,7 @@
 		/* PEVENT_TIMEOUT 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_CONNECTED 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_MSGRCVD 	*/ {  _psm_NOTSUP		},
-		/* PEVENT_INCNX 	*/ {  _psm_NOTSUP		},
+		/* PEVENT_INCNX 	*/ {  _psm_reject_incoming_CER	},
 		/* PEVENT_ASSOC_CHG 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_PEERADDR_CHG 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_REMOTE_ERR 	*/ {  _psm_NOTSUP		},
@@ -807,7 +899,7 @@
 		/* PEVENT_TIMEOUT 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_CONNECTED 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_MSGRCVD 	*/ {  _psm_NOTSUP		},
-		/* PEVENT_INCNX 	*/ {  _psm_NOTSUP		},
+		/* PEVENT_INCNX 	*/ {  _psm_reject_incoming_CER	},
 		/* PEVENT_ASSOC_CHG 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_PEERADDR_CHG 	*/ {  _psm_NOTSUP		},
 		/* PEVENT_REMOTE_ERR 	*/ {  _psm_NOTSUP		},
--- a/waaad/peer-struct.c	Tue Nov 04 14:18:38 2008 +0900
+++ b/waaad/peer-struct.c	Tue Nov 04 17:01:30 2008 +0900
@@ -347,6 +347,12 @@
 	/* Product name */
 	free( p->p_prodname );
 	
+	/* Election data if any */
+	if (p->p_electdata) {
+		(void)_peer_struct_destroy(&p->p_electdata->peer);
+		free(p->p_electdata);
+	}
+	
 	/* Finally, free the peer itself */
 	free(p);
 	
"Welcome to our mercurial repository"