using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; using System.Net.Sockets; using System.Threading; namespace Chop { public class ClientManager { private int mMaxClients; private Hashtable mClients; private Thread PingPong; private string lastConnectionIP; // For anti-ddos internal void Init(int MaxClients) { this.mClients = new Hashtable(); this.mMaxClients = MaxClients; PingPong = new Thread(new ThreadStart(Pong)); PingPong.Name = "PingPong"; PingPong.Start(); } internal void Destroy() { Hashtable Copy = (Hashtable)mClients.Clone(); foreach (GameClient client in Copy.Values) { RemoveClient(client.ID); } } internal GameClient GetClient(string IP) { foreach (GameClient client in mClients.Values) if (client.IP == IP) return client; return null; } internal GameClient GetClient(uint ID) { foreach (GameClient client in mClients.Values) if (client.ID == ID) return client; return null; } private uint GenerateClientID() { uint i = 0; while (mClients.Contains(i)) i++; return i; } internal void AddClient(Socket socket) { if (mClients.Count >= mMaxClients || (lastConnectionIP == GetIP(socket) && Core.Config.GetBoolean("socket.ddos.block"))) { socket.Shutdown(SocketShutdown.Both); socket.Close(); socket.Dispose(); } else { if (Core.Config.GetBoolean("socket.ddos.block")) lastConnectionIP = GetIP(socket); GameClient oldClient = GetClient(GetIP(socket)); if (oldClient != null) { RemoveClient(oldClient.ID); } GameClient Client = new GameClient(GenerateClientID(), socket); mClients.Add(Client.ID, Client); Console.WriteLine("Accepted new client [" + Client.ID + "] from " + Client.IP); Response WelcomeMessage = new Response(0); // "@@", say hello Client.SendMessage(WelcomeMessage); } } internal void RemoveClient(uint ID) { try { GameClient Client = GetClient(ID); if (Client != null) { Console.WriteLine("Disconnected client [" + ID + "] from " + Client.IP); Client.Destroy(); mClients.Remove(ID); } } catch (Exception) { } } public string GetIP(Socket socket) { return socket.RemoteEndPoint.ToString().Split(':')[0]; } private void Pong() { int wait = Core.Config.GetInt("managers.client.pong.interval"); while (true) { foreach(GameClient client in mClients.Values) if (client.Ponged) { client.Ponged = false; Response r = new Response(50); // "@r" client.SendMessage(r); } else RemoveClient(client.ID); Thread.Sleep(wait); } } } }