using System; using System.Collections.Generic; public class TCP { private static bool IsInitialized = false; private static Dictionary> Transitions = new Dictionary>(); private static void InitializeIfNeeded() { if (IsInitialized) { return; } IsInitialized = true; var transitions = new List<(string, string, string)>() { ("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"), }; foreach (var (fromState, byEvent, toState) in transitions) { var fromStateDictionary = Transitions.GetValueOrDefault(fromState, new Dictionary()); fromStateDictionary.Add(byEvent, toState); Transitions[fromState] = fromStateDictionary; } } public static string TraverseStates(string[] events) { InitializeIfNeeded(); var state = "CLOSED"; // initial state, always foreach (var ev in events) { state = Transitions .GetValueOrDefault(state, new Dictionary()) .GetValueOrDefault(ev, "ERROR"); } return state; } }