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<string, State> Transitions { get; set; } = new Dictionary<string, State>();
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;
}
}