Mercurial > hg > waaad
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);