using System; using System.Collections.Generic; public class TCP { private class State { //TcpFSM state name public string Name { get; set; } // list of trasitions for this state public Dictionary Transitions { get; set; } = new Dictionary(); public State GetNextState(string eventName) { if (Transitions.TryGetValue(eventName, out var result)) { return result; } return null; } } public static string TraverseStates(string[] events) { var state = "CLOSED"; // initial state, always // Your code here! var tcpStateMachine = Init(); var currentState = tcpStateMachine; foreach (var e in events) { currentState = currentState.GetNextState(e); if (currentState is null) { state = "ERROR"; break; } state = currentState.Name; } return state; } private static State Init() { State initialState = new State() { Name = "CLOSED" }; State listen = new State() { Name = "LISTEN", }; State synSent = new State() { Name = "SYN_SENT", }; State synRcvd = new State() { Name = "SYN_RCVD", }; State established = new State() { Name = "ESTABLISHED", }; State closeWait = new State() { Name = "CLOSE_WAIT" }; State lastAck = new State() { Name = "LAST_ACK" }; State finWait1 = new State() { Name = "FIN_WAIT_1" }; State finWait2 = new State() { Name = "FIN_WAIT_2" }; State timeWait = new State() { Name = "TIME_WAIT" }; State closing = new State() { Name = "CLOSING" }; initialState.Transitions["APP_PASSIVE_OPEN"] = listen; initialState.Transitions["APP_ACTIVE_OPEN"] = synSent; listen.Transitions["RCV_SYN"] = synRcvd; listen.Transitions["APP_SEND"] = synSent; listen.Transitions["APP_CLOSE"] = initialState; synRcvd.Transitions["APP_CLOSE"] = finWait1; synRcvd.Transitions["RCV_ACK"] = established; synSent.Transitions["RCV_SYN"] = synRcvd; synSent.Transitions["RCV_SYN_ACK"] = established; synSent.Transitions["APP_CLOSE"] = initialState; established.Transitions["APP_CLOSE"] = finWait1; established.Transitions["RCV_FIN"] = closeWait; finWait1.Transitions["RCV_FIN"] = closing; finWait1.Transitions["RCV_FIN_ACK"] = timeWait; finWait1.Transitions["RCV_ACK"] = finWait2; closing.Transitions["RCV_ACK"] = timeWait; finWait2.Transitions["RCV_FIN"] = timeWait; timeWait.Transitions["APP_TIMEOUT"] = initialState; closeWait.Transitions["APP_CLOSE"] = lastAck; lastAck.Transitions["RCV_ACK"] = initialState; return initialState; } }