120 lines
3.4 KiB
C
120 lines
3.4 KiB
C
#include "fsm.h"
|
|
|
|
char* fsm_textify(const char* pInp, int inp_len, char* pOut, int out_len) {
|
|
int iInp = 0;
|
|
int iOut = 0;
|
|
for (iInp = 0; iInp < inp_len; ++iInp) {
|
|
if ((pInp[iInp] < 32 || pInp[iInp] > 126)) {
|
|
if (iOut < out_len - 4) {
|
|
const char hex[] = "0123456789abcdef";
|
|
pOut[iOut++] = '\\';
|
|
pOut[iOut++] = hex[(pInp[iInp] >> 4) & 0xf];
|
|
pOut[iOut++] = hex[pInp[iInp] & 0xf];
|
|
}
|
|
else if (iOut < out_len - 1)
|
|
pOut[iOut++] = '.';
|
|
}
|
|
else if (iOut < out_len - 1)
|
|
pOut[iOut++] = pInp[iInp];
|
|
}
|
|
if (iOut < out_len)
|
|
pOut[iOut++] = '\0';
|
|
return pOut;
|
|
}
|
|
|
|
static void report_event(pStateMachine self, pEvtEvent event) {
|
|
char line[132];
|
|
char text[132];
|
|
snprintf(line, sizeof(line), "StateMachine=%s, State=%s(%d), event=%s",
|
|
self->name ? self->name : "<unknown>",
|
|
self->state_name ? self->state_name(self->myState) : "<unknown>",
|
|
self->mySubState,
|
|
self->event_name ? self->event_name(event, text, sizeof(text)) : "<unknown>");
|
|
SICSLogWrite(line, eStatus);
|
|
}
|
|
|
|
static void handle_event(pStateMachine self, pEvtEvent event) {
|
|
if (self->debug)
|
|
report_event(self, event);
|
|
if (self->myState)
|
|
self->myState(self, event);
|
|
}
|
|
|
|
int fsm_msg_callback(pAsyncTxn pCmd)
|
|
{
|
|
pStateMachine self = (pStateMachine) pCmd->cntx;
|
|
EvtEvent event;
|
|
|
|
if (pCmd->txn_status == ATX_TIMEOUT) {
|
|
if (self->debug) {
|
|
char line[1024];
|
|
fsm_textify(pCmd->out_buf, pCmd->out_len, line, sizeof(line));
|
|
SICSLogWrite(line, eStatus);
|
|
SICSLogWrite("<TIMEOUT>", eStatus);
|
|
}
|
|
event.event_type = eTimeoutEvent;
|
|
event.event.msg.cmd = pCmd;
|
|
}
|
|
else {
|
|
if (self->debug) {
|
|
char line[1024];
|
|
fsm_textify(pCmd->out_buf, pCmd->out_len, line, sizeof(line));
|
|
SICSLogWrite(line, eStatus);
|
|
fsm_textify(pCmd->inp_buf, pCmd->inp_idx, line, sizeof(line));
|
|
SICSLogWrite(line, eStatus);
|
|
}
|
|
event.event_type = eMessageEvent;
|
|
event.event.msg.cmd = pCmd;
|
|
}
|
|
handle_event(self, &event);
|
|
return 0;
|
|
}
|
|
|
|
int fsm_tmr_callback(void* ctx, int mode)
|
|
{
|
|
pStateMachine self = (pStateMachine) ctx;
|
|
EvtEvent event;
|
|
event.event_type = eTimerEvent;
|
|
handle_event(self, &event);
|
|
return 0;
|
|
}
|
|
|
|
int fsm_cmd_execute(pStateMachine self, const void* cmd) {
|
|
EvtEvent event;
|
|
event.event_type = eCommandEvent;
|
|
event.event.cmd.cmd_text = cmd;
|
|
handle_event(self, &event);
|
|
return 0;
|
|
}
|
|
|
|
void fsm_change_state(pStateMachine self, StateFunc func) {
|
|
if (self->debug) {
|
|
char line[132];
|
|
snprintf(line, sizeof(line), "StateMachine=%s, OldState=%s(%d), NewState=%s",
|
|
self->name ? self->name : "<unknown>",
|
|
self->state_name ? self->state_name(self->myState) : "<unknown>",
|
|
self->mySubState,
|
|
self->state_name ? self->state_name(func) : "<unknown>");
|
|
SICSLogWrite(line, eStatus);
|
|
}
|
|
self->myPrevState = self->myState;
|
|
self->myState = func;
|
|
self->mySubState = 0;
|
|
EvtEvent evt;
|
|
evt.event_type = eStateEvent;
|
|
if (self->myState)
|
|
self->myState(self, &evt);
|
|
}
|
|
|
|
void fsm_unhandled_event(pStateMachine self, pEvtEvent event) {
|
|
char line[132];
|
|
char text[132];
|
|
snprintf(line, sizeof(line), "StateMachine=%s, State=%s(%d), unhandled event=%s",
|
|
self->name ? self->name : "<unknown>",
|
|
self->state_name ? self->state_name(self->myState) : "<unknown>",
|
|
self->mySubState,
|
|
self->event_name ? self->event_name(event, text, sizeof(text)) : "<unknown>");
|
|
SICSLogWrite(line, eError);
|
|
}
|
|
|