protected void InitFSM() { StartWith(State.Initial, null); WhenUnhandled(@event => { var clientDisconnected = @event.FsmEvent as Controller.ClientDisconnected; if (clientDisconnected != null) { if (@event.StateData != null) { @event.StateData.Tell(new Failure(new Controller.ClientDisconnectedException("client disconnected in state " + StateName + ": " + _channel))); } return(Stop()); } return(null); }); OnTermination(@event => { _controller.Tell(new Controller.ClientDisconnected(_roleName)); _channel.Close(); }); When(State.Initial, @event => { var hello = @event.FsmEvent as Hello; if (hello != null) { _roleName = new RoleName(hello.Name); _controller.Tell(new Controller.NodeInfo(_roleName, hello.Address, Self)); return(GoTo(State.Ready)); } if (@event.FsmEvent is INetworkOp) { _log.Warning("client {0}, sent not Hello in first message (instead {1}), disconnecting", _channel.RemoteHost.ToEndPoint(), @event.FsmEvent); _channel.Close(); return(Stop()); } if (@event.FsmEvent is IToClient) { _log.Warning("cannot send {0} in state Initial", @event.FsmEvent); return(Stay()); } if (@event.FsmEvent is StateTimeout) { _log.Info("closing channel to {0} because of Hello timeout", _channel.RemoteHost.ToEndPoint()); _channel.Close(); return(Stop()); } return(null); }, TimeSpan.FromSeconds(10)); When(State.Ready, @event => { if (@event.FsmEvent is Done && @event.StateData != null) { @event.StateData.Tell(@event.FsmEvent); return(Stay().Using(null)); } if (@event.FsmEvent is IServerOp) { _controller.Tell(@event.FsmEvent); return(Stay()); } if (@event.FsmEvent is INetworkOp) { _log.Warning("client {0} sent unsupported message {1}", _channel.RemoteHost.ToEndPoint(), @event.FsmEvent); return(Stop()); } var toClient = @event.FsmEvent as IToClient; if (toClient != null) { if (toClient.Msg is IUnconfirmedClientOp) { _channel.Write(toClient.Msg); return(Stay()); } if (@event.StateData == null) { _channel.Write(toClient.Msg); return(Stay().Using(Sender)); } _log.Warning("cannot send {0} while waiting for previous ACK", toClient.Msg); return(Stay()); } return(null); }); Initialize(); }