public void DropClient(Connection toDrop) { if (preConns.Contains(toDrop)) { preConns.Remove(toDrop); } else { conns.Remove(toDrop); OpenRA.Network.Session.Client dropClient = lobbyInfo.Clients.Where(c1 => c1.Index == toDrop.PlayerIndex).Single(); // Send disconnected order, even if still in the lobby SendMessage("{0} has disconnected.".F(dropClient.Name)); DispatchOrdersToClients(toDrop, 0, new ServerOrder("Disconnected", "").Serialize()); lobbyInfo.Clients.RemoveAll(c => c.Index == toDrop.PlayerIndex); // Client was the server admin // TODO: Reassign admin for game in progress via an order if (lobbyInfo.GlobalSettings.Dedicated && dropClient.IsAdmin && State == ServerState.WaitingPlayers) { // Remove any bots controlled by the admin lobbyInfo.Clients.RemoveAll(c => c.Bot != null && c.BotControllerClientIndex == toDrop.PlayerIndex); OpenRA.Network.Session.Client nextAdmin = lobbyInfo.Clients.Where(c1 => c1.Bot == null) .OrderBy(c => c.Index).FirstOrDefault(); if (nextAdmin != null) { nextAdmin.IsAdmin = true; SendMessage("{0} is now the admin.".F(nextAdmin.Name)); } } DispatchOrders(toDrop, toDrop.MostRecentFrame, new byte[] { 0xbf }); if (conns.Count != 0 || lobbyInfo.GlobalSettings.Dedicated) { SyncLobbyInfo(); } if (!lobbyInfo.GlobalSettings.Dedicated && dropClient.IsAdmin) { Shutdown(); } } try { toDrop.socket.Disconnect(false); } catch { } }
public void DropClient(Connection toDrop) { if (preConns.Contains(toDrop)) { preConns.Remove(toDrop); } else { conns.Remove(toDrop); SendChat(toDrop, "Connection Dropped"); OpenRA.Network.Session.Client dropClient = lobbyInfo.Clients.Where(c1 => c1.Index == toDrop.PlayerIndex).Single(); if (GameStarted) { SendDisconnected(toDrop); /* Report disconnection */ } lobbyInfo.Clients.RemoveAll(c => c.Index == toDrop.PlayerIndex); // reassign admin if necessary if (lobbyInfo.GlobalSettings.Dedicated && dropClient.IsAdmin && !GameStarted) { if (lobbyInfo.Clients.Count() > 0) { // client was not alone on the server but he was admin: set admin to the last connected client OpenRA.Network.Session.Client lastClient = lobbyInfo.Clients.Last(); lastClient.IsAdmin = true; SendChat(toDrop, "Admin left! {0} is a new admin now!".F(lastClient.Name)); } } DispatchOrders(toDrop, toDrop.MostRecentFrame, new byte[] { 0xbf }); if (conns.Count != 0 || lobbyInfo.GlobalSettings.Dedicated) { SyncLobbyInfo(); } } try { toDrop.socket.Disconnect(false); } catch { } }
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 = handshake.Client; var mods = handshake.Mods; // Check that the client has compatible 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; } client.IpAddress = ((IPEndPoint)newConn.socket.RemoteEndPoint).Address.ToString(); // Check if IP is banned if (lobbyInfo.GlobalSettings.Ban != null) { if (lobbyInfo.GlobalSettings.Ban.Contains(client.IpAddress)) { Console.WriteLine("Rejected connection from " + client.Name + "(" + newConn.socket.RemoteEndPoint + "); Banned."); Log.Write("server", "Rejected connection from {0}; Banned.", newConn.socket.RemoteEndPoint); SendOrderTo(newConn, "ServerError", "You are banned from 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.Where(c1 => c1.Bot == null).Count() == 1) { client.IsAdmin = true; } OpenRA.Network.Session.Client clientAdmin = lobbyInfo.Clients.Where(c1 => c1.IsAdmin).Single(); 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 (lobbyInfo.GlobalSettings.Dedicated) { var message = client.IsAdmin ? "You are the server admin." : "{0} is the server admin.".F(clientAdmin.Name); SendOrderTo(newConn, "Message", message); } 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."); } } catch (Exception) { DropClient(newConn); } }
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 compatible 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; } // Drop DEV_VERSION if it's a Dedicated if (lobbyInfo.GlobalSettings.Dedicated && mods.Any(m => m.Contains("{DEV_VERSION}"))) { Log.Write("server", "Rejected connection from {0}; DEV_VERSION is not allowed here.", newConn.socket.RemoteEndPoint); SendOrderTo(newConn, "ServerError", "DEV_VERSION is not allowed here"); DropClient(newConn); return; } // Check if IP is banned if (lobbyInfo.GlobalSettings.Ban != null) { var remote_addr = ((IPEndPoint)newConn.socket.RemoteEndPoint).Address.ToString(); if (lobbyInfo.GlobalSettings.Ban.Contains(remote_addr)) { Console.WriteLine("Rejected connection from " + client.Name + "(" + newConn.socket.RemoteEndPoint + "); Banned."); Log.Write("server", "Rejected connection from {0}; Banned.", newConn.socket.RemoteEndPoint); SendOrderTo(newConn, "ServerError", "You are banned from 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; } OpenRA.Network.Session.Client clientAdmin = lobbyInfo.Clients.Where(c1 => c1.IsAdmin).Single(); 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."); if (lobbyInfo.GlobalSettings.Dedicated) { if (lobbyInfo.GlobalSettings.DedicatedMOTD != null) { SendChatTo(newConn, lobbyInfo.GlobalSettings.DedicatedMOTD); } if (client.IsAdmin) { SendChatTo(newConn, " You are admin now!"); } else { SendChatTo(newConn, " Current admin is {0}".F(clientAdmin.Name)); } } if (mods.Any(m => m.Contains("{DEV_VERSION}"))) { SendChat(newConn, "is running a development version, " + "and may cause desync if they have any incompatible changes."); } } catch (Exception) { DropClient(newConn); } }