Created
September 22, 2020 21:46
-
-
Save Micrified/8360d29f1b01da5d5ab0fa273642692f to your computer and use it in GitHub Desktop.
Packet processing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
recv_result recv_msg_queue (queue *rqp, msg_type *tp, void *msg_data_p) { | |
static unsigned char buffer[MSG_MAX_SIZE]; | |
static msg_type t; | |
static automaton_recv_state state = STATE_RECV_MARKERS; | |
static int markers = 0; | |
static off_t offset = 0; | |
static ssize_t payload_size = 0; | |
int exists_pending_data = 0, msg_is_valid; | |
unsigned char c; | |
// Check the queue for bytes to process (disable interrupts) | |
// __disable_irq(); | |
if (rqp->count > 0) { | |
exists_pending_data = 1; | |
c = dequeue(rqp); | |
} | |
// __enable_irq(); | |
// If there is nothing to process, return immediately | |
if (exists_pending_data == 0) { | |
return RECV_NOTHING; | |
} | |
// Otherwise, process the symbol in the automaton | |
switch (state) { | |
// Processes message markers [0xFF,0xFF] | |
case STATE_RECV_MARKERS: { | |
if (c == MSG_MARKER_BYTE) { | |
markers++; | |
} else { | |
markers = 0; | |
} | |
if (markers == 2) { | |
markers = 0; | |
buffer[0] = buffer[1] = MSG_MARKER_BYTE; | |
offset = 2; | |
state = STATE_RECV_TYPE; | |
} | |
} | |
return RECV_NOTHING; | |
// Processes the message type | |
case STATE_RECV_TYPE: { | |
if (msg_type_valid((msg_type)c)) { | |
t = buffer[offset++] = (msg_type)c; | |
payload_size = table_msg_payload_size[t]; | |
state = STATE_RECV_PAYLOAD; | |
} else { | |
ERR_MSG("Received an invalid message state"); | |
break; | |
} | |
} | |
return RECV_NOTHING; | |
// Processes the message payload | |
case STATE_RECV_PAYLOAD: { | |
if (payload_size > 1) { | |
buffer[offset++] = c; | |
payload_size--; | |
} else { | |
buffer[offset++] = c; | |
payload_size = 0; | |
state = STATE_RECV_CRC; | |
} | |
} | |
return RECV_NOTHING; | |
// Processes the CRC (reuses markers variable) | |
case STATE_RECV_CRC: { | |
if (markers == 1) { | |
buffer[offset++] = c; | |
markers = 0; | |
msg_is_valid = validate_buffer_crc(offset, buffer); | |
offset = 0; | |
state = STATE_RECV_MARKERS; | |
if (msg_is_valid == 1) { | |
*tp = t; | |
unpack_msg(t, msg_data_p, buffer + 3); | |
return RECV_MESSAGE; | |
} | |
break; | |
} else { | |
buffer[offset++] = c; | |
markers++; | |
} | |
} | |
return RECV_NOTHING; | |
default: | |
ERR_MSG("Unreachable code reached (god help us all)"); | |
break; | |
} | |
// Resets the machine. Should be executed on encountering anomalies | |
state = STATE_RECV_MARKERS; | |
markers = offset = payload_size = 0; | |
return RECV_ERROR; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment