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
{
///
/// Asynchronous socket server for the game connections.
///
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 = 3000;
socketHandler.SendTimeout = 3000;
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);
Out.WriteLine("Max simultaneous connections is " + maxConnections);
return true;
}
catch
{
Out.WriteError("Error while setting up asynchronous socket server for game connections on port " + bindPort);
return false;
}
}
public static void DisconnectOK(IAsyncResult iAr)
{
// Nothing to do...
}
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()
{
Out.WriteLine("Setting up socket on port " + _Port);
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)
throw new NullReferenceException();
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 (Exception e)
{
Out.WriteError("Fatal error during socket setup:\r" + e.ToString());
SomethingWentWrong = true;
Holo.Eucalypt.Shutdown();
}
finally
{
if (!SomethingWentWrong)
{
socketHandler.BeginAccept(new AsyncCallback(InncommingDataRequest), socketHandler);
Out.WriteLine("Socket is ready");
}
}
}
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)
{
ReplyFromComputer.Shutdown(SocketShutdown.Both);
ReplyFromComputer.Close();
}
else if (amount > 10)
{
ReplyFromComputer.Shutdown(SocketShutdown.Both);
ReplyFromComputer.Close();
}
else if (connectionHelper.IpIsBanned(IP) == true)
{
ReplyFromComputer.Shutdown(SocketShutdown.Both);
ReplyFromComputer.Close();
}
else
{
int ConnectionRequestID = NewConnectionRequestID();
if (ConnectionRequestID > 0)
{
Out.WriteLine("Accepted connection: [" + ConnectionRequestID + "] from [" + IP + "]");
AddConnection(IP);
new gameConnection(ReplyFromComputer, ConnectionRequestID);
}
}
}
catch { }
socketHandler.BeginAccept(new AsyncCallback(InncommingDataRequest), socketHandler);
}
internal static int NewConnectionRequestID()
{
_acceptedConnections++;
_activeConnections.Add(_acceptedConnections);
return _acceptedConnections;
}
///
/// Flags a connection as free.
///
/// The ID of the connection.
internal static void freeConnection(int connectionID)
{
if (_activeConnections.Contains(connectionID))
{
_activeConnections.Remove(connectionID);
_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
{
///
/// Gets or set an Integer for the maximum amount of connections at the same time.
///
set
{
_maxConnections = value;
}
get
{
return _maxConnections;
}
}
internal static int acceptedConnections
{
///
/// Returns as integer of the accepted connections count since init.
///
get {
return _acceptedConnections;
}
}
#endregion
}
}