Skip to content

Instantly share code, notes, and snippets.

@angusjf
Last active October 4, 2023 10:34
Show Gist options
  • Save angusjf/560b05c854d663a4336824f639f0e23a to your computer and use it in GitHub Desktop.
Save angusjf/560b05c854d663a4336824f639f0e23a to your computer and use it in GitHub Desktop.
A Simplistic TCP Finite State Machine (FSM) - Javascript Solution
/*
The "transition table" from the instructions:
CLOSED: APP_PASSIVE_OPEN -> LISTEN
CLOSED: APP_ACTIVE_OPEN -> SYN_SENT
LISTEN: RCV_SYN -> SYN_RCVD
LISTEN: APP_SEND -> SYN_SENT
LISTEN: APP_CLOSE -> CLOSED
SYN_RCVD: APP_CLOSE -> FIN_WAIT_1
SYN_RCVD: RCV_ACK -> ESTABLISHED
SYN_SENT: RCV_SYN -> SYN_RCVD
SYN_SENT: RCV_SYN_ACK -> ESTABLISHED
SYN_SENT: APP_CLOSE -> CLOSED
ESTABLISHED: APP_CLOSE -> FIN_WAIT_1
ESTABLISHED: RCV_FIN -> CLOSE_WAIT
FIN_WAIT_1: RCV_FIN -> CLOSING
FIN_WAIT_1: RCV_FIN_ACK -> TIME_WAIT
FIN_WAIT_1: RCV_ACK -> FIN_WAIT_2
CLOSING: RCV_ACK -> TIME_WAIT
FIN_WAIT_2: RCV_FIN -> TIME_WAIT
TIME_WAIT: APP_TIMEOUT -> CLOSED
CLOSE_WAIT: APP_CLOSE -> LAST_ACK
LAST_ACK: RCV_ACK -> CLOSED
*/
// this isn't really code it's just the instructions above but represented as an object
const data = {
CLOSED: { APP_PASSIVE_OPEN: "LISTEN", APP_ACTIVE_OPEN: "SYN_SENT" },
LISTEN: { RCV_SYN: "SYN_RCVD", APP_SEND: "SYN_SENT", APP_CLOSE: "CLOSED" },
SYN_RCVD: {
APP_CLOSE: "FIN_WAIT_1",
RCV_ACK: "ESTABLISHED",
},
SYN_SENT: {
RCV_SYN: "SYN_RCVD",
RCV_SYN_ACK: "ESTABLISHED",
APP_CLOSE: "CLOSED",
},
ESTABLISHED: { APP_CLOSE: "FIN_WAIT_1", RCV_FIN: "CLOSE_WAIT" },
FIN_WAIT_1: {
RCV_FIN: "CLOSING",
RCV_FIN_ACK: "TIME_WAIT",
RCV_ACK: "FIN_WAIT_2",
},
CLOSING: { RCV_ACK: "TIME_WAIT" },
FIN_WAIT_2: { RCV_FIN: "TIME_WAIT" },
TIME_WAIT: { APP_TIMEOUT: "CLOSED" },
CLOSE_WAIT: { APP_CLOSE: "LAST_ACK" },
LAST_ACK: { RCV_ACK: "CLOSED" },
}
function traverseTCPStates(eventList) {
let state = "CLOSED"
for (event of eventList) {
let transitions = data[state]
if (transitions == undefined) {
return "ERROR"
}
state = transitions[event]
if (state === undefined) {
return "ERROR"
}
}
return state
}
@angusjf
Copy link
Author

angusjf commented Oct 4, 2023

You can actually write traverseTCPStates one line:

function traverseTCPStates(eventList) {
  return eventList.reduce((current, event) => data[current]?.[event] || "ERROR", "CLOSED")
}

But it's kinda hard to read because reduce & ?. are kinda advanced.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment