示例#1
0
        void InterpretServerOrder(Connection conn, ServerOrder so)
        {
            var fromClient = GetClient(conn);
            var fromIndex  = fromClient != null ? fromClient.Index : 0;

            switch (so.Name)
            {
            case "Command":
                bool handled = false;
                foreach (var t in ServerTraits.WithInterface <IInterpretCommand>())
                {
                    if ((handled = t.InterpretCommand(this, conn, GetClient(conn), so.Data)))
                    {
                        break;
                    }
                }

                if (!handled)
                {
                    Log.Write("server", "Unknown server command: {0}", so.Data);
                    SendChatTo(conn, "Unknown server command: {0}".F(so.Data));
                }

                break;

            case "HandshakeResponse":
                ValidateClient(conn, so.Data);
                break;

            case "Chat":
            case "TeamChat":
                foreach (var c in conns.Except(conn).ToArray())
                {
                    DispatchOrdersToClient(c, fromIndex, 0, so.Serialize());
                }
                break;

            case "PauseRequest":
                foreach (var c in conns.ToArray())
                {
                    var x = Order.PauseGame();
                    DispatchOrdersToClient(c, fromIndex, 0, x.Serialize());
                }
                break;
            }
        }
示例#2
0
文件: Server.cs 项目: ushalin/OpenRA
        void InterpretServerOrders(Connection conn, byte[] data)
        {
            var ms = new MemoryStream(data);
            var br = new BinaryReader(ms);

            try
            {
                while (ms.Position < ms.Length)
                {
                    var so = ServerOrder.Deserialize(br);
                    if (so == null)
                    {
                        return;
                    }
                    InterpretServerOrder(conn, so);
                }
            }
            catch (EndOfStreamException) { }
            catch (NotImplementedException) { }
        }
示例#3
0
文件: Server.cs 项目: ushalin/OpenRA
        void InterpretServerOrder(Connection conn, ServerOrder so)
        {
            switch (so.Name)
            {
            case "Command":
            {
                var handled = false;
                foreach (var t in serverTraits.WithInterface <IInterpretCommand>())
                {
                    if (handled = t.InterpretCommand(this, conn, GetClient(conn), so.Data))
                    {
                        break;
                    }
                }

                if (!handled)
                {
                    Log.Write("server", "Unknown server command: {0}", so.Data);
                    SendOrderTo(conn, "Message", "Unknown server command: {0}".F(so.Data));
                }

                break;
            }

            case "HandshakeResponse":
                ValidateClient(conn, so.Data);
                break;

            case "Chat":
            case "TeamChat":
            case "PauseGame":
                DispatchOrdersToClients(conn, 0, so.Serialize());
                break;

            case "Pong":
            {
                int pingSent;
                if (!OpenRA.Exts.TryParseIntegerInvariant(so.Data, out pingSent))
                {
                    Log.Write("server", "Invalid order pong payload: {0}", so.Data);
                    break;
                }

                var pingFromClient = LobbyInfo.PingFromClient(GetClient(conn));
                if (pingFromClient == null)
                {
                    return;
                }

                var history = pingFromClient.LatencyHistory.ToList();
                history.Add(Game.RunTime - pingSent);

                // Cap ping history at 5 values (25 seconds)
                if (history.Count > 5)
                {
                    history.RemoveRange(0, history.Count - 5);
                }

                pingFromClient.Latency        = history.Sum() / history.Count;
                pingFromClient.LatencyJitter  = (history.Max() - history.Min()) / 2;
                pingFromClient.LatencyHistory = history.ToArray();

                SyncClientPing();

                break;
            }
            }
        }
示例#4
0
        void InterpretServerOrder(Connection conn, ServerOrder so)
        {
            // Only accept handshake responses from unvalidated clients
            // Anything else may be an attempt to exploit the server
            if (!conn.Validated)
            {
                if (so.Name == "HandshakeResponse")
                {
                    ValidateClient(conn, so.Data);
                }
                else
                {
                    Log.Write("server", "Rejected connection from {0}; Order `{1}` is not a `HandshakeResponse`.",
                              conn.Socket.RemoteEndPoint, so.Name);

                    DropClient(conn);
                }

                return;
            }

            switch (so.Name)
            {
            case "Command":
            {
                var handledBy = serverTraits.WithInterface <IInterpretCommand>()
                                .FirstOrDefault(t => t.InterpretCommand(this, conn, GetClient(conn), so.Data));

                if (handledBy == null)
                {
                    Log.Write("server", "Unknown server command: {0}", so.Data);
                    SendOrderTo(conn, "Message", "Unknown server command: {0}".F(so.Data));
                }

                break;
            }

            case "Chat":
            case "TeamChat":
            case "PauseGame":
                DispatchOrdersToClients(conn, 0, so.Serialize());
                break;

            case "Pong":
            {
                long pingSent;
                if (!OpenRA.Exts.TryParseInt64Invariant(so.Data, out pingSent))
                {
                    Log.Write("server", "Invalid order pong payload: {0}", so.Data);
                    break;
                }

                var client = GetClient(conn);
                if (client == null)
                {
                    return;
                }

                var pingFromClient = LobbyInfo.PingFromClient(client);
                if (pingFromClient == null)
                {
                    return;
                }

                var history = pingFromClient.LatencyHistory.ToList();
                history.Add(Game.RunTime - pingSent);

                // Cap ping history at 5 values (25 seconds)
                if (history.Count > 5)
                {
                    history.RemoveRange(0, history.Count - 5);
                }

                pingFromClient.Latency        = history.Sum() / history.Count;
                pingFromClient.LatencyJitter  = (history.Max() - history.Min()) / 2;
                pingFromClient.LatencyHistory = history.ToArray();

                SyncClientPing();

                break;
            }
            }
        }
示例#5
0
文件: Server.cs 项目: pchote/OpenRA
        void InterpretServerOrder(Connection conn, ServerOrder so)
        {
            switch (so.Name)
            {
                case "Command":
                    {
                        var handledBy = serverTraits.WithInterface<IInterpretCommand>()
                            .FirstOrDefault(t => t.InterpretCommand(this, conn, GetClient(conn), so.Data));

                        if (handledBy == null)
                        {
                            Log.Write("server", "Unknown server command: {0}", so.Data);
                            SendOrderTo(conn, "Message", "Unknown server command: {0}".F(so.Data));
                        }

                        break;
                    }

                case "HandshakeResponse":
                    ValidateClient(conn, so.Data);
                    break;
                case "Chat":
                case "TeamChat":
                case "PauseGame":
                    DispatchOrdersToClients(conn, 0, so.Serialize());
                    break;
                case "Pong":
                    {
                        long pingSent;
                        if (!OpenRA.Exts.TryParseInt64Invariant(so.Data, out pingSent))
                        {
                            Log.Write("server", "Invalid order pong payload: {0}", so.Data);
                            break;
                        }

                        var client = GetClient(conn);
                        if (client == null)
                            return;

                        var pingFromClient = LobbyInfo.PingFromClient(client);
                        if (pingFromClient == null)
                            return;

                        var history = pingFromClient.LatencyHistory.ToList();
                        history.Add(Game.RunTime - pingSent);

                        // Cap ping history at 5 values (25 seconds)
                        if (history.Count > 5)
                            history.RemoveRange(0, history.Count - 5);

                        pingFromClient.Latency = history.Sum() / history.Count;
                        pingFromClient.LatencyJitter = (history.Max() - history.Min()) / 2;
                        pingFromClient.LatencyHistory = history.ToArray();

                        SyncClientPing();

                        break;
                    }
            }
        }
示例#6
0
        void InterpretServerOrder(Connection conn, ServerOrder so)
        {
            switch (so.Name)
            {
                case "Command":
                    bool handled = false;
                    foreach (var t in ServerTraits.WithInterface<IInterpretCommand>())
                        if ((handled = t.InterpretCommand(this, conn, GetClient(conn), so.Data)))
                            break;

                    if (!handled)
                    {
                        Log.Write("server", "Unknown server command: {0}", so.Data);
                        SendOrderTo(conn, "Message", "Unknown server command: {0}".F(so.Data));
                    }

                    break;

                case "HandshakeResponse":
                    ValidateClient(conn, so.Data);
                    break;
                case "Chat":
                case "TeamChat":
                case "PauseGame":
                    DispatchOrdersToClients(conn, 0, so.Serialize());
                    break;
                case "Pong":
                {
                    int pingSent;
                    if (!int.TryParse(so.Data, out pingSent))
                    {
                        Log.Write("server", "Invalid order pong payload: {0}", so.Data);
                        break;
                    }

                    var fromClient = GetClient(conn);
                    var history = fromClient.LatencyHistory.ToList();
                    history.Add(Environment.TickCount - pingSent);

                    // Cap ping history at 5 values (25 seconds)
                    if (history.Count > 5)
                        history.RemoveRange(0, history.Count - 5);

                    fromClient.Latency = history.Sum() / history.Count;
                    fromClient.LatencyJitter = (history.Max() - history.Min())/2;
                    fromClient.LatencyHistory = history.ToArray();

                    if (State == ServerState.WaitingPlayers)
                        SyncLobbyInfo();

                    break;
                }
            }
        }
示例#7
0
文件: Server.cs 项目: subspace/OpenRA
        static void InterpretServerOrder(Connection conn, ServerOrder so)
        {
            switch (so.Name)
            {
                case "Command":
                {
                    if(GameStarted)
                        SendChatTo(conn, "Cannot change state when game started.");
                    else if (GetClient(conn).State == Session.ClientState.Ready && !(so.Data == "ready" || so.Data == "startgame") )
                        SendChatTo(conn, "Cannot change state when marked as ready.");
                    else if (!InterpretCommand(conn, so.Data))
                    {
                        Log.Write("server", "Bad server command: {0}", so.Data);
                        SendChatTo(conn, "Bad server command.");
                    };
                }
                break;

                case "Chat":
                case "TeamChat":
                    foreach (var c in conns.Except(conn).ToArray())
                        DispatchOrdersToClient(c, GetClient(conn).Index, 0, so.Serialize());
                break;
            }
        }
示例#8
0
        static void InterpretServerOrder(Connection conn, ServerOrder so)
        {
            switch (so.Name)
            {
                case "Chat":
                    if (so.Data.StartsWith("/"))
                    {
                        if (!InterpretCommand(conn, so.Data.Substring(1)))
                        {
                            Console.WriteLine("Bad server command: {0}", so.Data.Substring(1));
                            SendChatTo(conn, "Bad server command.");
                        }
                    }
                    else
                        foreach (var c in conns.Except(conn).ToArray())
                            DispatchOrdersToClient(c, GetClient(conn).Index, 0, so.Serialize());
                    break;

                case "RequestFile":
                    {
                        Console.WriteLine("** Requesting file: `{0}`", so.Data);
                        var client = GetClient(conn);
                        client.State = Session.ClientState.Downloading;

                        var filename = so.Data.Split(':')[0];

                        if (conn.Stream != null)
                            conn.Stream.Dispose();

                        conn.Stream = File.OpenRead(filename);
                        // todo: validate that the SHA1 they asked for matches what we've got.

                        var length = (int) new FileInfo(filename).Length;
                        conn.NextChunk = 0;
                        conn.NumChunks = (length + DownloadChunkSize - 1) / DownloadChunkSize;
                        conn.RemainingBytes = length;

                        SyncLobbyInfo();
                    }
                    break;
            }
        }
示例#9
0
文件: Server.cs 项目: nevelis/OpenRA
        void InterpretServerOrder(Connection conn, ServerOrder so)
        {
            var fromClient = GetClient(conn);
            var fromIndex = fromClient != null ? fromClient.Index : 0;

            switch (so.Name)
            {
                case "Command":
                    bool handled = false;
                    foreach (var t in ServerTraits.WithInterface<IInterpretCommand>())
                        if ((handled = t.InterpretCommand(this, conn, GetClient(conn), so.Data)))
                            break;

                    if (!handled)
                    {
                        Log.Write("server", "Unknown server command: {0}", so.Data);
                        SendChatTo(conn, "Unknown server command: {0}".F(so.Data));
                    }

                    break;

                case "HandshakeResponse":
                    ValidateClient(conn, so.Data);
                    break;

                case "Chat":
                case "TeamChat":
                    foreach (var c in conns.Except(conn).ToArray())
                        DispatchOrdersToClient(c, fromIndex, 0, so.Serialize());
                    break;

                case "PauseRequest":
                    foreach (var c in conns.ToArray())
                    {  var x = Order.PauseGame();
                        DispatchOrdersToClient(c, fromIndex, 0, x.Serialize());
                    }
                    break;
            }
        }
示例#10
0
        void InterpretServerOrder(Connection conn, ServerOrder so)
        {
            switch (so.Name)
            {
            case "Command":
                bool handled = false;
                foreach (var t in ServerTraits.WithInterface <IInterpretCommand>())
                {
                    if ((handled = t.InterpretCommand(this, conn, GetClient(conn), so.Data)))
                    {
                        break;
                    }
                }

                if (!handled)
                {
                    Log.Write("server", "Unknown server command: {0}", so.Data);
                    SendOrderTo(conn, "Message", "Unknown server command: {0}".F(so.Data));
                }

                break;

            case "HandshakeResponse":
                ValidateClient(conn, so.Data);
                break;

            case "Chat":
            case "TeamChat":
            case "PauseGame":
                DispatchOrdersToClients(conn, 0, so.Serialize());
                break;

            case "Pong":
            {
                int pingSent;
                if (!int.TryParse(so.Data, out pingSent))
                {
                    Log.Write("server", "Invalid order pong payload: {0}", so.Data);
                    break;
                }

                var fromClient = GetClient(conn);
                var history    = fromClient.LatencyHistory.ToList();
                history.Add(Environment.TickCount - pingSent);

                // Cap ping history at 5 values (25 seconds)
                if (history.Count > 5)
                {
                    history.RemoveRange(0, history.Count - 5);
                }

                fromClient.Latency        = history.Sum() / history.Count;
                fromClient.LatencyJitter  = (history.Max() - history.Min()) / 2;
                fromClient.LatencyHistory = history.ToArray();

                if (State == ServerState.WaitingPlayers)
                {
                    SyncLobbyInfo();
                }

                break;
            }
            }
        }
示例#11
0
        void InterpretServerOrder(Connection conn, ServerOrder so)
        {
            // Only accept handshake responses from unvalidated clients
            // Anything else may be an attempt to exploit the server
            if (!conn.Validated)
            {
                if (so.Name == "HandshakeResponse")
                {
                    ValidateClient(conn, so.Data);
                }
                else
                {
                    Log.Write("server", "Rejected connection from {0}; Order `{1}` is not a `HandshakeResponse`.",
                              conn.Socket.RemoteEndPoint, so.Name);

                    DropClient(conn);
                }

                return;
            }

            switch (so.Name)
            {
            case "Command":
            {
                var handledBy = serverTraits.WithInterface <IInterpretCommand>()
                                .FirstOrDefault(t => t.InterpretCommand(this, conn, GetClient(conn), so.Data));

                if (handledBy == null)
                {
                    Log.Write("server", "Unknown server command: {0}", so.Data);
                    SendOrderTo(conn, "Message", "Unknown server command: {0}".F(so.Data));
                }

                break;
            }

            case "Chat":
            case "PauseGame":
                DispatchOrdersToClients(conn, 0, so.Serialize());
                break;

            case "Pong":
            {
                long pingSent;
                if (!Primitives.Exts.TryParseInt64Invariant(so.Data, out pingSent))
                {
                    Log.Write("server", "Invalid order pong payload: {0}", so.Data);
                    break;
                }

                var client = GetClient(conn);
                if (client == null)
                {
                    return;
                }

                var pingFromClient = LobbyInfo.PingFromClient(client);
                if (pingFromClient == null)
                {
                    return;
                }

                var history = pingFromClient.LatencyHistory.ToList();
                history.Add(Game.RunTime - pingSent);

                // Cap ping history at 5 values (25 seconds)
                if (history.Count > 5)
                {
                    history.RemoveRange(0, history.Count - 5);
                }

                pingFromClient.Latency        = history.Sum() / history.Count;
                pingFromClient.LatencyJitter  = (history.Max() - history.Min()) / 2;
                pingFromClient.LatencyHistory = history.ToArray();

                SyncClientPing();

                break;
            }

            case "GameSaveTraitData":
            {
                if (GameSave != null)
                {
                    var data = MiniYaml.FromString(so.Data)[0];
                    GameSave.AddTraitData(int.Parse(data.Key), data.Value);
                }

                break;
            }

            case "CreateGameSave":
            {
                if (GameSave != null)
                {
                    // Sanitize potentially malicious input
                    var filename     = so.Data;
                    var invalidIndex = -1;
                    var invalidChars = Path.GetInvalidFileNameChars();
                    while ((invalidIndex = filename.IndexOfAny(invalidChars)) != -1)
                    {
                        filename = filename.Remove(invalidIndex, 1);
                    }

                    var baseSavePath = Platform.ResolvePath(
                        Platform.SupportDirPrefix,
                        "Saves",
                        ModData.Manifest.Id,
                        ModData.Manifest.Metadata.Version);

                    if (!Directory.Exists(baseSavePath))
                    {
                        Directory.CreateDirectory(baseSavePath);
                    }

                    GameSave.Save(Path.Combine(baseSavePath, filename));
                    DispatchOrdersToClients(null, 0, new ServerOrder("GameSaved", filename).Serialize());
                }

                break;
            }

            case "LoadGameSave":
            {
                if (Dedicated || State >= ServerState.GameStarted)
                {
                    break;
                }

                // Sanitize potentially malicious input
                var filename     = so.Data;
                var invalidIndex = -1;
                var invalidChars = Path.GetInvalidFileNameChars();
                while ((invalidIndex = filename.IndexOfAny(invalidChars)) != -1)
                {
                    filename = filename.Remove(invalidIndex, 1);
                }

                var savePath = Platform.ResolvePath(
                    Platform.SupportDirPrefix,
                    "Saves",
                    ModData.Manifest.Id,
                    ModData.Manifest.Metadata.Version,
                    filename);

                GameSave = new GameSave(savePath);
                LobbyInfo.GlobalSettings = GameSave.GlobalSettings;
                LobbyInfo.Slots          = GameSave.Slots;

                // Reassign clients to slots
                //  - Bot ordering is preserved
                //  - Humans are assigned on a first-come-first-serve basis
                //  - Leftover humans become spectators

                // Start by removing all bots and assigning all players as spectators
                foreach (var c in LobbyInfo.Clients)
                {
                    if (c.Bot != null)
                    {
                        LobbyInfo.Clients.Remove(c);
                        var ping = LobbyInfo.PingFromClient(c);
                        if (ping != null)
                        {
                            LobbyInfo.ClientPings.Remove(ping);
                        }
                    }
                    else
                    {
                        c.Slot = null;
                    }
                }

                // Rebuild/remap the saved client state
                // TODO: Multiplayer saves should leave all humans as spectators so they can manually pick slots
                var adminClientIndex = LobbyInfo.Clients.First(c => c.IsAdmin).Index;
                foreach (var kv in GameSave.SlotClients)
                {
                    if (kv.Value.Bot != null)
                    {
                        var bot = new Session.Client()
                        {
                            Index = ChooseFreePlayerIndex(),
                            State = Session.ClientState.NotReady,
                            BotControllerClientIndex = adminClientIndex
                        };

                        kv.Value.ApplyTo(bot);
                        LobbyInfo.Clients.Add(bot);
                    }
                    else
                    {
                        // This will throw if the server doesn't have enough human clients to fill all player slots
                        // See TODO above - this isn't a problem in practice because MP saves won't use this
                        var client = LobbyInfo.Clients.First(c => c.Slot == null);
                        kv.Value.ApplyTo(client);
                    }
                }

                SyncLobbyInfo();
                SyncLobbyClients();
                SyncClientPing();

                break;
            }
            }
        }
示例#12
0
        void InterpretServerOrder(Connection conn, ServerOrder so)
        {
            switch (so.Name)
            {
                case "Command":
                    {
                        bool handled = false;
                        foreach (var t in ServerTraits.WithInterface<IInterpretCommand>())
                            if ((handled = t.InterpretCommand(this, conn, GetClient(conn), so.Data)))
                                break;

                        if (!handled)
                        {
                            Log.Write("server", "Unknown server command: {0}", so.Data);
                            SendChatTo(conn, "Unknown server command: {0}".F(so.Data));
                        }
                    }
                    break;

                case "Chat":
                case "TeamChat":
                    foreach (var c in conns.Except(conn).ToArray())
                        DispatchOrdersToClient(c, GetClient(conn).Index, 0, so.Serialize());
                break;
            }
        }