diff --git a/src/fsmpico.c b/src/fsmpico.c index 667170c..8ebf85e 100644 --- a/src/fsmpico.c +++ b/src/fsmpico.c @@ -69,6 +69,8 @@ // Defines +#define READ_TIMEOUT (5000) +#define CONTINUOUS_TIMEOUT_LEEWAY (1000) #define RECONNECT_DELAY (10000) // Structure definitions @@ -111,6 +113,8 @@ struct _FsmPico { FSMPICOSTATE state; AuthFsmComms * comms; void * user_data; + + int reauthDelay; }; // Function prototypes @@ -165,6 +169,8 @@ FsmPico * fsmpico_new() { fsmpico->comms->sessionEnded = FsmSessionEndedNull; fsmpico->comms->statusUpdate = FsmStatusUpdateNull; + fsmpico->reauthDelay = 0; + return fsmpico; } @@ -348,12 +354,14 @@ void fsmpico_read(FsmPico * fsmpico, char const * data, size_t length) { int timeout; Buffer * message; Buffer * dataread; + Buffer * extraDataToSend; char status; receivedExtraData = buffer_new(0); message = buffer_new(0); dataread = buffer_new(length); buffer_append(dataread, data, length); + extraDataToSend = buffer_new(0); // TODO: If the reads fail, should move to an error state switch (fsmpico->state) { @@ -364,6 +372,8 @@ void fsmpico_read(FsmPico * fsmpico, char const * data, size_t length) { createMessagePicoAuth(fsmpico, message, fsmpico->extraData); fsmpico->comms->write(buffer_get_buffer(message), buffer_get_pos(message), fsmpico->user_data); stateTransition(fsmpico, FSMPICOSTATE_STATUS); + // set a timeout for waiting for the status message + fsmpico->comms->setTimeout(READ_TIMEOUT, fsmpico->user_data); } break; case FSMPICOSTATE_STATUS: @@ -390,9 +400,13 @@ void fsmpico_read(FsmPico * fsmpico, char const * data, size_t length) { result = readMessageServiceReauth(fsmpico, dataread, &timeout); if (result) { stateTransition(fsmpico, FSMPICOSTATE_PICOREAUTH); - LOG(LOG_DEBUG, "Timeout set to: %d", timeout); - // Wait for timeout - fsmpico->comms->setTimeout(timeout, fsmpico->user_data); + fsmpico->reauthDelay = timeout; + // reply with the PicoReauth message + createMessagePicoReauth(fsmpico, message, extraDataToSend); + fsmpico->comms->write(buffer_get_buffer(message), buffer_get_pos(message), fsmpico->user_data); + stateTransition(fsmpico, FSMPICOSTATE_SERVICEREAUTH); + // set a timeout for awaiting a response + fsmpico->comms->setTimeout(fsmpico->reauthDelay + CONTINUOUS_TIMEOUT_LEEWAY, fsmpico->user_data); } break; default: @@ -404,6 +418,7 @@ void fsmpico_read(FsmPico * fsmpico, char const * data, size_t length) { buffer_delete(receivedExtraData); buffer_delete(message); buffer_delete(dataread); + buffer_delete(extraDataToSend); } /** @@ -425,6 +440,8 @@ void fsmpico_connected(FsmPico * fsmpico) { createMessageStart(fsmpico, message); fsmpico->comms->write(buffer_get_buffer(message), buffer_get_pos(message), fsmpico->user_data); stateTransition(fsmpico, FSMPICOSTATE_SERVICEAUTH); + // set a timeout for waiting for the service auth message + fsmpico->comms->setTimeout(READ_TIMEOUT, fsmpico->user_data); break; case FSMPICOSTATE_CONTSTARTPICO: fsmpico->currentState = REAUTHSTATE_CONTINUE; @@ -480,31 +497,31 @@ void fsmpico_disconnected(FsmPico * fsmpico) { * @param fsmpico The object to apply to. */ void fsmpico_timeout(FsmPico * fsmpico) { - Buffer * extraData; - Buffer * message; - LOG(LOG_DEBUG, "Timeout"); - extraData = buffer_new(0); - message = buffer_new(0); - switch (fsmpico->state) { - case FSMPICOSTATE_CONTSTARTPICO: + case FSMPICOSTATE_CONTSTARTPICO: LOG(LOG_DEBUG, "Reconnecting for continuous authentication"); fsmpico->comms->reconnect(fsmpico->user_data); break; - case FSMPICOSTATE_PICOREAUTH: - createMessagePicoReauth(fsmpico, message, extraData); - fsmpico->comms->write(buffer_get_buffer(message), buffer_get_pos(message), fsmpico->user_data); - stateTransition(fsmpico, FSMPICOSTATE_SERVICEREAUTH); + case FSMPICOSTATE_SERVICEAUTH: + case FSMPICOSTATE_STATUS: + case FSMPICOSTATE_SERVICEREAUTH: + // gave up waiting for a reply to a sent message, enter error state + stateTransition(fsmpico, FSMPICOSTATE_ERROR); + fsmpico->comms->error(fsmpico->user_data); break; - default: + case FSMPICOSTATE_INVALID: + case FSMPICOSTATE_ERROR: + // in these states, the state machine is stopped, so ignore it (but log) LOG(LOG_DEBUG, "Timer fired during an invalid state"); break; + default: + // in any other state, we're not expecting a timeout and this is an error + stateTransition(fsmpico, FSMPICOSTATE_ERROR); + fsmpico->comms->error(fsmpico->user_data); + break; } - - buffer_delete(extraData); - buffer_delete(message); }