예제 #1
0
        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();
        }