using System; using System.Net; using System.Net.Sockets; using System.Collections.Generic; using System.Threading; using Holo.Virtual.Users; using System.Collections; using Holo.Source.Managers; using Holo.Source.GameConnectionSystem; using Holo.Socketservers; using Holo.Managers; namespace Holo.GameConnectionSystem { public static class gameSocketServer { #region Declares private static Socket socketHandler; private static int _Port = int.Parse(Config.getTableEntry("server_game_port")); private static int _maxConnections = int.Parse(Config.getTableEntry("server_game_maxconnections")); private static int _acceptedConnections; private static HashSet _activeConnections; private static Hashtable connections = new Hashtable(2); private static bool AcceptConnections = true; public static string[] _activeIPs; private static Object connObj = new Object(); #endregion #region Methods public static bool Init(int bindPort, int maxConnections) { _Port = bindPort; _maxConnections = maxConnections + 64; _activeConnections = new HashSet(); _activeIPs = new string[((_maxConnections * 4) + 32)]; for (int i = 0; i < _activeIPs.Length; i++) { _activeIPs[i] = ""; } socketHandler = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { socketHandler.ReceiveTimeout = 4000; socketHandler.SendTimeout = 4000; socketHandler.NoDelay = true; socketHandler.LingerState = new LingerOption(true, 1); socketHandler.Bind(new IPEndPoint(IPAddress.Any, bindPort)); socketHandler.Listen(25); socketHandler.BeginAccept(new AsyncCallback(connectionRequest), socketHandler); return true; } catch { Out.WriteError("El puerto " + _Port + " es inválido o esta en uso."); return false; } } private static void connectionRequest(IAsyncResult iAr) { try { int connectionID = 0; for (int i = 1; i < _maxConnections; i++) { if (_activeConnections.Contains(i) == false) { connectionID = i; break; } } } catch { } socketHandler.BeginAccept(new AsyncCallback(connectionRequest), socketHandler); } internal static void SetupSocket() { connectionHelper.Init(); AcceptConnections = true; if (_activeConnections != null) _activeConnections.Clear(); _activeConnections = new HashSet(); StartListening(); } internal static void Destroy() { AcceptConnections = false; HashSet Data = _activeConnections; foreach (int ConnectionID in Data) { freeConnection(ConnectionID); } } internal static void StartListening() { bool SomethingWentWrong = false; try { if (_Port == 0 || _maxConnections == 0) { Out.WriteError("El puerto o las conexiones maximas estan nulas. No es posible continuar."); SomethingWentWrong = true; Eucalypt.Shutdown(); } else { socketHandler = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint Endpoint = new IPEndPoint(IPAddress.Any, _Port); socketHandler.Bind(Endpoint); socketHandler.Listen(1000); while (!AcceptConnections) { socketHandler.BeginAccept(new AsyncCallback(InncommingDataRequest), socketHandler); } } } catch { Out.WriteError("El puerto " + _Port + " es inválido o esta en uso."); SomethingWentWrong = true; Eucalypt.Shutdown(); } finally { if (!SomethingWentWrong) { socketHandler.BeginAccept(new AsyncCallback(InncommingDataRequest), socketHandler); Out.WriteLine("Conexiones escuchadas desde el puerto " + _Port); } } } internal static void InncommingDataRequest(IAsyncResult iAr) { try { Socket ReplyFromComputer = ((Socket)iAr.AsyncState).EndAccept(iAr); string IP = ReplyFromComputer.RemoteEndPoint.ToString().Split(':')[0]; int amount = GetConnectionAmount(IP); if (acceptedConnections >= maxConnections || AcceptConnections == false) { Out.WriteError("Las conexiones han llegado a su máxima capacidad. Conexión Denegada"); ReplyFromComputer.Shutdown(SocketShutdown.Both); ReplyFromComputer.Close(); } else if (amount > 30 || connectionHelper.IpIsBanned(IP) == true) { ReplyFromComputer.Shutdown(SocketShutdown.Both); ReplyFromComputer.Close(); } else { int ConnectionRequestID = NewConnectionRequestID(); if (ConnectionRequestID > 0) { Out.WriteLine("Conexión entrante [" + ConnectionRequestID + "] de " + IP, ConsoleColor.Blue); AddConnection(IP); new gameConnection(ReplyFromComputer, ConnectionRequestID); } } } catch { } socketHandler.BeginAccept(new AsyncCallback(InncommingDataRequest), socketHandler); } internal static int NewConnectionRequestID() { _acceptedConnections++; _activeConnections.Add(_acceptedConnections); return _acceptedConnections; } internal static void freeConnection(int connectionID) { if (_activeConnections.Contains(connectionID)) { _activeConnections.Remove(connectionID); Out.WriteLine("Conexión [" + connectionID + "] liberada.", ConsoleColor.DarkBlue); _acceptedConnections--; } } internal static void AddConnection(string IP) { int Amount = 0; if (connections.ContainsKey(IP) == true) { Amount = (int)connections[IP]; connections.Remove(IP); } else { Amount = 0; } int newamount = Amount + 1; connections.Add(IP, newamount); Thread.Sleep(50); } internal static void RemoveConnection(string IP) { int IpConnected = 0; if (connections.ContainsKey(IP) == true) { IpConnected = (int)connections[IP]; } else { connections.Remove(IP); } if (IpConnected > 1) //More than one connected { int NewAmount = IpConnected - 1; connections.Remove(IP); connections.Add(IP, NewAmount); } else //Only one connected { connections.Remove(IP); } } #endregion #region Properities internal static int GetConnectionAmount(string IP) { if (connections.ContainsKey(IP) == true) { return ((int)connections[IP]); } else { return 0; } } internal static int maxConnections { set { _maxConnections = value; } get { return _maxConnections; } } internal static int acceptedConnections { get { return _acceptedConnections; } } #endregion } }