Пример #1
0
        void ValidateClient(Connection newConn, string data)
        {
            try
            {
                if (State == ServerState.GameStarted)
                {
                    Log.Write("server", "Rejected connection from {0}; game is already started.",
                              newConn.Socket.RemoteEndPoint);

                    SendOrderTo(newConn, "ServerError", "The game has already started");
                    DropClient(newConn);
                    return;
                }

                var handshake = HandshakeResponse.Deserialize(data);

                if (!string.IsNullOrEmpty(Settings.Password) && handshake.Password != Settings.Password)
                {
                    var message = string.IsNullOrEmpty(handshake.Password) ? "Server requires a password" : "Incorrect password";
                    SendOrderTo(newConn, "AuthenticationError", message);
                    DropClient(newConn);
                    return;
                }

                var client = new Session.Client
                {
                    Name           = OpenRA.Settings.SanitizedPlayerName(handshake.Client.Name),
                    IpAddress      = ((IPEndPoint)newConn.Socket.RemoteEndPoint).Address.ToString(),
                    Index          = newConn.PlayerIndex,
                    Slot           = LobbyInfo.FirstEmptySlot(),
                    PreferredColor = handshake.Client.PreferredColor,
                    Color          = handshake.Client.Color,
                    Faction        = "Random",
                    SpawnPoint     = 0,
                    Team           = 0,
                    State          = Session.ClientState.Invalid,
                    IsAdmin        = !LobbyInfo.Clients.Any(c1 => c1.IsAdmin)
                };

                if (client.IsObserver && !LobbyInfo.GlobalSettings.AllowSpectators)
                {
                    SendOrderTo(newConn, "ServerError", "The game is full");
                    DropClient(newConn);
                    return;
                }

                if (client.Slot != null)
                {
                    SyncClientToPlayerReference(client, Map.Players.Players[client.Slot]);
                }
                else
                {
                    client.Color = HSLColor.FromRGB(255, 255, 255);
                }

                if (ModData.Manifest.Id != handshake.Mod)
                {
                    Log.Write("server", "Rejected connection from {0}; mods do not match.",
                              newConn.Socket.RemoteEndPoint);

                    SendOrderTo(newConn, "ServerError", "Server is running an incompatible mod");
                    DropClient(newConn);
                    return;
                }

                if (ModData.Manifest.Metadata.Version != handshake.Version && !LobbyInfo.GlobalSettings.AllowVersionMismatch)
                {
                    Log.Write("server", "Rejected connection from {0}; Not running the same version.",
                              newConn.Socket.RemoteEndPoint);

                    SendOrderTo(newConn, "ServerError", "Server is running an incompatible version");
                    DropClient(newConn);
                    return;
                }

                // Check if IP is banned
                var bans = Settings.Ban.Union(TempBans);
                if (bans.Contains(client.IpAddress))
                {
                    Log.Write("server", "Rejected connection from {0}; Banned.", newConn.Socket.RemoteEndPoint);
                    SendOrderTo(newConn, "ServerError", "You have been {0} from the server".F(Settings.Ban.Contains(client.IpAddress) ? "banned" : "temporarily banned"));
                    DropClient(newConn);
                    return;
                }

                // Promote connection to a valid client
                PreConns.Remove(newConn);
                Conns.Add(newConn);
                LobbyInfo.Clients.Add(client);
                var clientPing = new Session.ClientPing {
                    Index = client.Index
                };
                LobbyInfo.ClientPings.Add(clientPing);

                Log.Write("server", "Client {0}: Accepted connection from {1}.",
                          newConn.PlayerIndex, newConn.Socket.RemoteEndPoint);

                foreach (var t in serverTraits.WithInterface <IClientJoined>())
                {
                    t.ClientJoined(this, newConn);
                }

                SyncLobbyInfo();

                Log.Write("server", "{0} ({1}) has joined the game.",
                          client.Name, newConn.Socket.RemoteEndPoint);

                if (Dedicated || !LobbyInfo.IsSinglePlayer)
                {
                    SendMessage("{0} has joined the game.".F(client.Name));
                }

                // Send initial ping
                SendOrderTo(newConn, "Ping", Game.RunTime.ToString(CultureInfo.InvariantCulture));

                if (Dedicated)
                {
                    var motdFile = Platform.ResolvePath("^", "motd.txt");
                    if (!File.Exists(motdFile))
                    {
                        File.WriteAllText(motdFile, "Welcome, have fun and good luck!");
                    }

                    var motd = File.ReadAllText(motdFile);
                    if (!string.IsNullOrEmpty(motd))
                    {
                        SendOrderTo(newConn, "Message", motd);
                    }
                }

                if (!LobbyInfo.IsSinglePlayer && Map.DefinesUnsafeCustomRules)
                {
                    SendOrderTo(newConn, "Message", "This map contains custom rules. Game experience may change.");
                }

                if (!LobbyInfo.GlobalSettings.EnableSingleplayer)
                {
                    SendOrderTo(newConn, "Message", TwoHumansRequiredText);
                }
                else if (Map.Players.Players.Where(p => p.Value.Playable).All(p => !p.Value.AllowBots))
                {
                    SendOrderTo(newConn, "Message", "Bots have been disabled on this map.");
                }

                if (handshake.Mod == "{DEV_VERSION}")
                {
                    SendMessage("{0} is running an unversioned development build, ".F(client.Name) +
                                "and may desynchronize the game state if they have incompatible rules.");
                }
            }
            catch (Exception ex)
            {
                Log.Write("server", "Dropping connection {0} because an error occurred:", newConn.Socket.RemoteEndPoint);
                Log.Write("server", ex.ToString());
                DropClient(newConn);
            }
        }
Пример #2
0
        void ValidateClient(Connection newConn, string data)
        {
            try
            {
                if (State == ServerState.GameStarted)
                {
                    Log.Write("server", "Rejected connection from {0}; game is already started.",
                              newConn.Socket.RemoteEndPoint);

                    SendOrderTo(newConn, "ServerError", "The game has already started");
                    DropClient(newConn);
                    return;
                }

                var handshake = HandshakeResponse.Deserialize(data);

                if (!string.IsNullOrEmpty(Settings.Password) && handshake.Password != Settings.Password)
                {
                    var message = string.IsNullOrEmpty(handshake.Password) ? "Server requires a password" : "Incorrect password";
                    SendOrderTo(newConn, "AuthenticationError", message);
                    DropClient(newConn);
                    return;
                }

                var client = new Session.Client
                {
                    Name           = OpenRA.Settings.SanitizedPlayerName(handshake.Client.Name),
                    IpAddress      = ((IPEndPoint)newConn.Socket.RemoteEndPoint).Address.ToString(),
                    Index          = newConn.PlayerIndex,
                    Slot           = LobbyInfo.FirstEmptySlot(),
                    PreferredColor = handshake.Client.PreferredColor,
                    Color          = handshake.Client.Color,
                    Faction        = "Random",
                    SpawnPoint     = 0,
                    Team           = 0,
                    State          = Session.ClientState.Invalid,
                    IsAdmin        = !LobbyInfo.Clients.Any(c1 => c1.IsAdmin)
                };

                if (client.IsObserver && !LobbyInfo.GlobalSettings.AllowSpectators)
                {
                    SendOrderTo(newConn, "ServerError", "The game is full");
                    DropClient(newConn);
                    return;
                }

                if (client.Slot != null)
                {
                    SyncClientToPlayerReference(client, Map.Players.Players[client.Slot]);
                }
                else
                {
                    client.Color = HSLColor.FromRGB(255, 255, 255);
                }

                if (ModData.Manifest.Id != handshake.Mod)
                {
                    Log.Write("server", "Rejected connection from {0}; mods do not match.",
                              newConn.Socket.RemoteEndPoint);

                    SendOrderTo(newConn, "ServerError", "Server is running an incompatible mod");
                    DropClient(newConn);
                    return;
                }

                if (ModData.Manifest.Metadata.Version != handshake.Version && !LobbyInfo.GlobalSettings.AllowVersionMismatch)
                {
                    Log.Write("server", "Rejected connection from {0}; Not running the same version.",
                              newConn.Socket.RemoteEndPoint);

                    SendOrderTo(newConn, "ServerError", "Server is running an incompatible version");
                    DropClient(newConn);
                    return;
                }

                // Check if IP is banned
                var bans = Settings.Ban.Union(TempBans);
                if (bans.Contains(client.IpAddress))
                {
                    Log.Write("server", "Rejected connection from {0}; Banned.", newConn.Socket.RemoteEndPoint);
                    SendOrderTo(newConn, "ServerError", "You have been {0} from the server".F(Settings.Ban.Contains(client.IpAddress) ? "banned" : "temporarily banned"));
                    DropClient(newConn);
                    return;
                }

                Action completeConnection = () =>
                {
                    // Promote connection to a valid client
                    PreConns.Remove(newConn);
                    Conns.Add(newConn);
                    LobbyInfo.Clients.Add(client);
                    newConn.Validated = true;

                    var clientPing = new Session.ClientPing {
                        Index = client.Index
                    };
                    LobbyInfo.ClientPings.Add(clientPing);

                    Log.Write("server", "Client {0}: Accepted connection from {1}.",
                              newConn.PlayerIndex, newConn.Socket.RemoteEndPoint);

                    if (client.Fingerprint != null)
                    {
                        Log.Write("server", "Client {0}: Player fingerprint is {1}.",
                                  newConn.PlayerIndex, client.Fingerprint);
                    }

                    foreach (var t in serverTraits.WithInterface <IClientJoined>())
                    {
                        t.ClientJoined(this, newConn);
                    }

                    SyncLobbyInfo();

                    Log.Write("server", "{0} ({1}) has joined the game.",
                              client.Name, newConn.Socket.RemoteEndPoint);

                    // Report to all other players
                    SendMessage("{0} has joined the game.".F(client.Name), newConn);

                    // Send initial ping
                    SendOrderTo(newConn, "Ping", Game.RunTime.ToString(CultureInfo.InvariantCulture));

                    if (Dedicated)
                    {
                        var motdFile = Platform.ResolvePath(Platform.SupportDirPrefix, "motd.txt");
                        if (!File.Exists(motdFile))
                        {
                            File.WriteAllText(motdFile, "Welcome, have fun and good luck!");
                        }

                        var motd = File.ReadAllText(motdFile);
                        if (!string.IsNullOrEmpty(motd))
                        {
                            SendOrderTo(newConn, "Message", motd);
                        }
                    }

                    if (Map.DefinesUnsafeCustomRules)
                    {
                        SendOrderTo(newConn, "Message", "This map contains custom rules. Game experience may change.");
                    }

                    if (!LobbyInfo.GlobalSettings.EnableSingleplayer)
                    {
                        SendOrderTo(newConn, "Message", TwoHumansRequiredText);
                    }
                    else if (Map.Players.Players.Where(p => p.Value.Playable).All(p => !p.Value.AllowBots))
                    {
                        SendOrderTo(newConn, "Message", "Bots have been disabled on this map.");
                    }
                };

                if (!string.IsNullOrEmpty(handshake.Fingerprint) && !string.IsNullOrEmpty(handshake.AuthSignature))
                {
                    waitingForAuthenticationCallback++;

                    Action <DownloadDataCompletedEventArgs> onQueryComplete = i =>
                    {
                        PlayerProfile profile = null;

                        if (i.Error == null)
                        {
                            try
                            {
                                var yaml = MiniYaml.FromString(Encoding.UTF8.GetString(i.Result)).First();
                                if (yaml.Key == "Player")
                                {
                                    profile = FieldLoader.Load <PlayerProfile>(yaml.Value);

                                    var publicKey  = Encoding.ASCII.GetString(Convert.FromBase64String(profile.PublicKey));
                                    var parameters = CryptoUtil.DecodePEMPublicKey(publicKey);
                                    if (!profile.KeyRevoked && CryptoUtil.VerifySignature(parameters, newConn.AuthToken, handshake.AuthSignature))
                                    {
                                        client.Fingerprint = handshake.Fingerprint;
                                        Log.Write("server", "{0} authenticated as {1} (UID {2})", newConn.Socket.RemoteEndPoint,
                                                  profile.ProfileName, profile.ProfileID);
                                    }
                                    else if (profile.KeyRevoked)
                                    {
                                        Log.Write("server", "{0} failed to authenticate as {1} (key revoked)", newConn.Socket.RemoteEndPoint, handshake.Fingerprint);
                                    }
                                    else
                                    {
                                        Log.Write("server", "{0} failed to authenticate as {1} (signature verification failed)",
                                                  newConn.Socket.RemoteEndPoint, handshake.Fingerprint);
                                    }
                                }
                                else
                                {
                                    Log.Write("server", "{0} failed to authenticate as {1} (invalid server response: `{2}` is not `Player`)",
                                              newConn.Socket.RemoteEndPoint, handshake.Fingerprint, yaml.Key);
                                }
                            }
                            catch (Exception ex)
                            {
                                Log.Write("server", "{0} failed to authenticate as {1} (exception occurred)",
                                          newConn.Socket.RemoteEndPoint, handshake.Fingerprint);
                                Log.Write("server", ex.ToString());
                            }
                        }
                        else
                        {
                            Log.Write("server", "{0} failed to authenticate as {1} (server error: `{2}`)",
                                      newConn.Socket.RemoteEndPoint, handshake.Fingerprint, i.Error);
                        }

                        delayedActions.Add(() =>
                        {
                            if (Dedicated && Settings.RequireAuthIDs.Any() &&
                                (profile == null || !Settings.RequireAuthIDs.Contains(profile.ProfileID)))
                            {
                                Log.Write("server", "Rejected connection from {0}; Not in server whitelist.", newConn.Socket.RemoteEndPoint);
                                SendOrderTo(newConn, "ServerError", "You are not authenticated for this server");
                                DropClient(newConn);
                            }
                            else
                            {
                                completeConnection();
                            }

                            waitingForAuthenticationCallback--;
                        }, 0);
                    };

                    new Download(playerDatabase.Profile + handshake.Fingerprint, _ => { }, onQueryComplete);
                }
                else
                {
                    if (Dedicated && Settings.RequireAuthIDs.Any())
                    {
                        Log.Write("server", "Rejected connection from {0}; Not authenticated and whitelist is set.", newConn.Socket.RemoteEndPoint);
                        SendOrderTo(newConn, "ServerError", "You are not authenticated for this server");
                        DropClient(newConn);
                    }
                    else
                    {
                        completeConnection();
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Write("server", "Dropping connection {0} because an error occurred:", newConn.Socket.RemoteEndPoint);
                Log.Write("server", ex.ToString());
                DropClient(newConn);
            }
        }
Пример #3
0
        void ValidateClient(Connection newConn, string data)
        {
            try
            {
                if (State == ServerState.GameStarted)
                {
                    SendOrderTo(newConn, "ServerError", "The game has already started");
                    DropClient(newConn);
                    return;
                }

                var handshake = HandshakeResponse.Deserialize(data);

                if (!string.IsNullOrEmpty(Settings.Password) && handshake.Password != Settings.Password)
                {
                    var message = string.IsNullOrEmpty(handshake.Password) ? "Server requires a password" : "Incorrect password";
                    SendOrderTo(newConn, "AuthenticationError", message);
                    DropClient(newConn);
                    return;
                }

                var client = new Session.Client
                {
                    Name           = EW.Settings.SanitizedPlayerName(handshake.Client.Name),
                    IpAddress      = ((IPEndPoint)newConn.Socket.RemoteEndPoint).Address.ToString(),
                    Index          = newConn.PlayerIndex,
                    Slot           = LobbyInfo.FirstEmptySlot(),
                    PreferredColor = handshake.Client.PreferredColor,
                    Color          = handshake.Client.Color,
                    Faction        = "Random",
                    SpawnPoint     = 0,
                    Team           = 0,
                    State          = Session.ClientState.Invalid,
                    IsAdmin        = !LobbyInfo.Clients.Any(cl => cl.IsAdmin)
                };

                if (client.IsObserver && !LobbyInfo.GlobalSettings.AllowSpectators)
                {
                    SendOrderTo(newConn, "ServerError", "The game is full");
                    DropClient(newConn);
                    return;
                }

                if (client.Slot != null)
                {
                    SyncClientToPlayerReference(client, Map.Players.Players[client.Slot]);
                }
                else
                {
                    client.Color = HSLColor.FromRGB(255, 255, 255);
                }

                if (ModData.Manifest.Id != handshake.Mod)
                {
                    SendOrderTo(newConn, "ServerError", "Server is running an incompatible mod");
                    DropClient(newConn);
                    return;
                }

                if (ModData.Manifest.Metadata.Version != handshake.Version && !LobbyInfo.GlobalSettings.AllowVersionMismatch)
                {
                    SendOrderTo(newConn, "ServerError", "Server is running an incompatible version");
                    DropClient(newConn);
                    return;
                }


                //Check if IP is banned
                var bans = Settings.Ban.Union(TempBans);
                if (bans.Contains(client.IpAddress))
                {
                    SendOrderTo(newConn, "ServerError", "You have been {0} from the server".F(Settings.Ban.Contains(client.IpAddress) ? "banned" : "temporarily banned"));
                    DropClient(newConn);
                    return;
                }

                //Promote connection to a valid client
                PreConns.Remove(newConn);
                Conns.Add(newConn);
                LobbyInfo.Clients.Add(client);
                newConn.Validated = true;


                var clientPing = new Session.ClientPing {
                    Index = client.Index
                };
                LobbyInfo.ClientPings.Add(clientPing);

                foreach (var t in serverTraits.WithInterface <IClientJoined>())
                {
                    t.ClientJoined(this, newConn);
                }

                SyncLobbyInfo();

                if (LobbyInfo.NonBotClients.Count() > 1)
                {
                    SendMessage("{0} has joined the game".F(client.Name));
                }

                SendOrderTo(newConn, "Ping", WarGame.RunTime.ToString(CultureInfo.InvariantCulture));

                if (Dedicated)
                {
                }

                if (Map.DefinesUnsafeCustomRules)
                {
                    SendOrderTo(newConn, "Message", "This map contains custom rules.Game experience may change.");
                }

                if (!LobbyInfo.GlobalSettings.EnableSinglePlayer)
                {
                    SendOrderTo(newConn, "Message", TwoHumansRequiredText);
                }
                else if (Map.Players.Players.Where(p => p.Value.Playable).All(p => !p.Value.AllowBots))
                {
                    SendOrderTo(newConn, "Message", "Bots have been disabled on this map");
                }
            }
            catch (Exception ex)
            {
                DropClient(newConn);
            }
        }
Пример #4
0
        void ValidateClient(Connection newConn, string data)
        {
            try
            {
                if (GameStarted)
                {
                    Log.Write("server", "Rejected connection from {0}; game is already started.",
                              newConn.socket.RemoteEndPoint);

                    SendOrderTo(newConn, "ServerError", "The game has already started");
                    DropClient(newConn);
                    return;
                }

                var handshake = HandshakeResponse.Deserialize(data);
                var client    = handshake.Client;
                var mods      = handshake.Mods;

                // Check that the client has compatable mods
                var valid = mods.All(m => m.Contains('@')) &&                  //valid format
                            mods.Count() == Game.CurrentMods.Count() &&        //same number
                            mods.Select(m => Pair.New(m.Split('@')[0], m.Split('@')[1])).All(kv => Game.CurrentMods.ContainsKey(kv.First) &&
                                                                                             (kv.Second == "{DEV_VERSION}" || Game.CurrentMods[kv.First].Version == "{DEV_VERSION}" || kv.Second == Game.CurrentMods[kv.First].Version));
                if (!valid)
                {
                    Log.Write("server", "Rejected connection from {0}; mods do not match.",
                              newConn.socket.RemoteEndPoint);

                    SendOrderTo(newConn, "ServerError", "Your mods don't match the server");
                    DropClient(newConn);
                    return;
                }

                // Promote connection to a valid client
                preConns.Remove(newConn);
                conns.Add(newConn);

                // Enforce correct PlayerIndex and Slot
                client.Index = newConn.PlayerIndex;
                client.Slot  = lobbyInfo.FirstEmptySlot();

                if (client.Slot != null)
                {
                    SyncClientToPlayerReference(client, Map.Players[client.Slot]);
                }

                lobbyInfo.Clients.Add(client);
                //Assume that first validated client is server admin
                if (lobbyInfo.Clients.Count == 1)
                {
                    client.IsAdmin = true;
                }

                Log.Write("server", "Client {0}: Accepted connection from {1}",
                          newConn.PlayerIndex, newConn.socket.RemoteEndPoint);

                foreach (var t in ServerTraits.WithInterface <IClientJoined>())
                {
                    t.ClientJoined(this, newConn);
                }

                SyncLobbyInfo();
                SendChat(newConn, "has joined the game.");
            }
            catch (Exception) { DropClient(newConn); }
        }
Пример #5
0
        void ValidateClient(Connection newConn, string data)
        {
            try
            {
                if (State == ServerState.GameStarted)
                {
                    Log.Write("server", "Rejected connection from {0}; game is already started.",
                              newConn.socket.RemoteEndPoint);

                    SendOrderTo(newConn, "ServerError", "The game has already started");
                    DropClient(newConn);
                    return;
                }

                var handshake = HandshakeResponse.Deserialize(data);

                var client = new Session.Client()
                {
                    Name           = handshake.Client.Name,
                    IpAddress      = ((IPEndPoint)newConn.socket.RemoteEndPoint).Address.ToString(),
                    Index          = newConn.PlayerIndex,
                    Slot           = lobbyInfo.FirstEmptySlot(),
                    PreferredColor = handshake.Client.Color,
                    Color          = handshake.Client.Color,
                    Country        = "random",
                    SpawnPoint     = 0,
                    Team           = 0,
                    State          = Session.ClientState.NotReady,
                    IsAdmin        = !lobbyInfo.Clients.Any(c1 => c1.IsAdmin)
                };

                if (client.Slot != null)
                {
                    SyncClientToPlayerReference(client, Map.Players[client.Slot]);
                }
                else
                {
                    client.Color = HSLColor.FromRGB(255, 255, 255);
                }

                // Check that the client has compatible mods
                var mods     = handshake.Mods;
                var validMod = mods.All(m => m.Contains('@')) &&                 //valid format
                               mods.Count() == Game.CurrentMods.Count() &&       //same number
                               mods.Select(m => Pair.New(m.Split('@')[0], m.Split('@')[1])).All(kv => Game.CurrentMods.ContainsKey(kv.First));

                if (!validMod)
                {
                    Log.Write("server", "Rejected connection from {0}; mods do not match.",
                              newConn.socket.RemoteEndPoint);

                    SendOrderTo(newConn, "ServerError", "Your mods don't match the server");
                    DropClient(newConn);
                    return;
                }

                var validVersion = mods.Select(m => Pair.New(m.Split('@')[0], m.Split('@')[1])).All(
                    kv => kv.Second == Game.CurrentMods[kv.First].Version);

                if (!validVersion && !lobbyInfo.GlobalSettings.AllowVersionMismatch)
                {
                    Log.Write("server", "Rejected connection from {0}; Not running the same version.",
                              newConn.socket.RemoteEndPoint);

                    SendOrderTo(newConn, "ServerError", "Not running the same version.");
                    DropClient(newConn);
                    return;
                }

                // Check if IP is banned
                var bans = Settings.Ban.Union(TempBans);
                if (bans.Contains(client.IpAddress))
                {
                    Log.Write("server", "Rejected connection from {0}; Banned.", newConn.socket.RemoteEndPoint);
                    SendOrderTo(newConn, "ServerError", "You are {0} from the server.".F(Settings.Ban.Contains(client.IpAddress) ? "banned" : "temporarily banned"));
                    DropClient(newConn);
                    return;
                }

                // Promote connection to a valid client
                preConns.Remove(newConn);
                conns.Add(newConn);
                lobbyInfo.Clients.Add(client);

                Log.Write("server", "Client {0}: Accepted connection from {1}.",
                          newConn.PlayerIndex, newConn.socket.RemoteEndPoint);

                foreach (var t in ServerTraits.WithInterface <IClientJoined>())
                {
                    t.ClientJoined(this, newConn);
                }

                SyncLobbyInfo();
                SendMessage("{0} has joined the server.".F(client.Name));

                // Send initial ping
                SendOrderTo(newConn, "Ping", Environment.TickCount.ToString());

                if (File.Exists("{0}motd_{1}.txt".F(Platform.SupportDir, lobbyInfo.GlobalSettings.Mods[0])))
                {
                    var motd = System.IO.File.ReadAllText("{0}motd_{1}.txt".F(Platform.SupportDir, lobbyInfo.GlobalSettings.Mods[0]));
                    SendOrderTo(newConn, "Message", motd);
                }

                if (mods.Any(m => m.Contains("{DEV_VERSION}")))
                {
                    SendMessage("{0} is running an unversioned development build, ".F(client.Name) +
                                "and may desynchronize the game state if they have incompatible rules.");
                }

                SetOrderLag();
            }
            catch (Exception) { DropClient(newConn); }
        }
Пример #6
0
        void ValidateClient(Connection newConn, string data)
        {
            try
            {
                if (State == ServerState.GameStarted)
                {
                    Log.Write("server", "Rejected connection from {0}; game is already started.",
                              newConn.socket.RemoteEndPoint);

                    SendOrderTo(newConn, "ServerError", "The game has already started");
                    DropClient(newConn);
                    return;
                }

                var handshake = HandshakeResponse.Deserialize(data);

                if (!string.IsNullOrEmpty(Settings.Password) && handshake.Password != Settings.Password)
                {
                    var message = string.IsNullOrEmpty(handshake.Password) ? "Server requires a password" : "Incorrect password";
                    SendOrderTo(newConn, "AuthenticationError", message);
                    DropClient(newConn);
                    return;
                }

                var client = new Session.Client()
                {
                    Name           = handshake.Client.Name,
                    IpAddress      = ((IPEndPoint)newConn.socket.RemoteEndPoint).Address.ToString(),
                    Index          = newConn.PlayerIndex,
                    Slot           = LobbyInfo.FirstEmptySlot(),
                    PreferredColor = handshake.Client.Color,
                    Color          = handshake.Client.Color,
                    Country        = "random",
                    SpawnPoint     = 0,
                    Team           = 0,
                    State          = Session.ClientState.Invalid,
                    IsAdmin        = !LobbyInfo.Clients.Any(c1 => c1.IsAdmin)
                };

                if (client.IsObserver && !LobbyInfo.GlobalSettings.AllowSpectators)
                {
                    SendOrderTo(newConn, "ServerError", "The game is full");
                    DropClient(newConn);
                    return;
                }

                if (client.Slot != null)
                {
                    SyncClientToPlayerReference(client, Map.Players[client.Slot]);
                }
                else
                {
                    client.Color = HSLColor.FromRGB(255, 255, 255);
                }

                if (ModData.Manifest.Mod.Id != handshake.Mod)
                {
                    Log.Write("server", "Rejected connection from {0}; mods do not match.",
                              newConn.socket.RemoteEndPoint);

                    SendOrderTo(newConn, "ServerError", "Server is running an incompatible mod");
                    DropClient(newConn);
                    return;
                }

                if (ModData.Manifest.Mod.Version != handshake.Version && !LobbyInfo.GlobalSettings.AllowVersionMismatch)
                {
                    Log.Write("server", "Rejected connection from {0}; Not running the same version.",
                              newConn.socket.RemoteEndPoint);

                    SendOrderTo(newConn, "ServerError", "Server is running an incompatible version");
                    DropClient(newConn);
                    return;
                }

                // Check if IP is banned
                var bans = Settings.Ban.Union(TempBans);
                if (bans.Contains(client.IpAddress))
                {
                    Log.Write("server", "Rejected connection from {0}; Banned.", newConn.socket.RemoteEndPoint);
                    SendOrderTo(newConn, "ServerError", "You have been {0} from the server".F(Settings.Ban.Contains(client.IpAddress) ? "banned" : "temporarily banned"));
                    DropClient(newConn);
                    return;
                }

                // Promote connection to a valid client
                PreConns.Remove(newConn);
                Conns.Add(newConn);
                LobbyInfo.Clients.Add(client);
                var clientPing = new Session.ClientPing();
                clientPing.Index = client.Index;
                LobbyInfo.ClientPings.Add(clientPing);

                Log.Write("server", "Client {0}: Accepted connection from {1}.",
                          newConn.PlayerIndex, newConn.socket.RemoteEndPoint);

                foreach (var t in serverTraits.WithInterface <IClientJoined>())
                {
                    t.ClientJoined(this, newConn);
                }

                SyncLobbyInfo();
                SendMessage("{0} has joined the server.".F(client.Name));

                // Send initial ping
                SendOrderTo(newConn, "Ping", Environment.TickCount.ToString());

                if (Settings.Dedicated)
                {
                    var motdFile = Path.Combine(Platform.SupportDir, "motd.txt");
                    if (!File.Exists(motdFile))
                    {
                        System.IO.File.WriteAllText(motdFile, "Welcome, have fun and good luck!");
                    }
                    var motd = System.IO.File.ReadAllText(motdFile);
                    if (!string.IsNullOrEmpty(motd))
                    {
                        SendOrderTo(newConn, "Message", motd);
                    }
                }

                if (handshake.Mod == "{DEV_VERSION}")
                {
                    SendMessage("{0} is running an unversioned development build, ".F(client.Name) +
                                "and may desynchronize the game state if they have incompatible rules.");
                }

                SetOrderLag();
            }
            catch (Exception) { DropClient(newConn); }
        }