using System; using System.IO; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Collections.Generic; using System.Collections.Concurrent; namespace MrHassan.Network.Sockets { public class ServerSocket { public event Action<ClientWrapper> OnClientConnect, OnClientDisconnect; public event Action<byte[], int, ClientWrapper> OnClientReceive; private ConcurrentDictionary<int, int> BruteforceProtection; private const int TimeLimit = 1000 * 15; // 1 connection every 10 seconds for one ip private object SyncRoot; private Socket Connection; private ushort port; private string ipString; private bool enabled; private Thread thread; public ServerSocket() { this.Connection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); this.SyncRoot = new object(); thread = new Thread(doSyncAccept); thread.Start(); } public void Enable(ushort port, string ip, bool BigSend = false) { this.ipString = ip; this.port = port; this.Connection.Bind(new IPEndPoint(IPAddress.Parse(ipString), this.port)); this.Connection.Listen((int)SocketOptionName.MaxConnections); if (BigSend) { this.Connection.ReceiveBufferSize = ushort.MaxValue; this.Connection.SendBufferSize = ushort.MaxValue; } this.enabled = true; BruteforceProtection = new ConcurrentDictionary<int, int>(); } public bool PrintoutIPs = false; private void doSyncAccept() { while (true) { if (this.enabled) { try { processSocket(this.Connection.Accept()); } catch { } } Thread.Sleep(1); } } private void doAsyncAccept(IAsyncResult res) { try { Socket socket = this.Connection.EndAccept(res); processSocket(socket); this.Connection.BeginAccept(doAsyncAccept, null); } catch { } } private void processSocket(Socket socket) { try { string ip = (socket.RemoteEndPoint as IPEndPoint).Address.ToString(); int ipHash = ip.GetHashCode(); /* if (!Program.ALEXPC) { int time = Time32.Now.GetHashCode(); int oldValue; if (!BruteforceProtection.TryGetValue(ipHash, out oldValue)) { BruteforceProtection[ipHash] = time; } else { if (time - oldValue < TimeLimit) { if (PrintoutIPs) Console.WriteLine("Dropped connection: " + ip); socket.Disconnect(false); socket.Close(); return; } else { BruteforceProtection[ipHash] = time; if (PrintoutIPs) Console.WriteLine("Allowed connection: " + ip); } } }*/ ClientWrapper wrapper = new ClientWrapper(); wrapper.Create(socket, this, OnClientReceive); wrapper.IsAlive = true; wrapper.IP = ip; if (this.OnClientConnect != null) this.OnClientConnect(wrapper); } catch { } } public void Reset() { this.Disable(); this.Enable(); } public void Disable() { this.enabled = false; this.Connection.Close(1); } public void Enable() { if (!this.enabled) { this.Connection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); this.Connection.Bind(new IPEndPoint(IPAddress.Parse(ipString), this.port)); this.Connection.Listen((int)SocketOptionName.MaxConnections); this.enabled = true; //this.Connection.BeginAccept(doAsyncAccept, null); } } public void InvokeDisconnect(ClientWrapper Client) { if (this.OnClientDisconnect != null) this.OnClientDisconnect(Client); } public bool Enabled { get { return this.enabled; } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Threading; using System.Collections.Concurrent; using System.Runtime.InteropServices; using MrHassan.Network.Cryptography; namespace MrHassan.Network.Sockets { public class ClientWrapper { [DllImport("ws2_32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern int closesocket(IntPtr s); [DllImport("ws2_32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern int shutdown(IntPtr s, ShutDownFlags how); public enum ShutDownFlags : int { SD_RECEIVE = 0, SD_SEND = 1, SD_BOTH = 2 } public int BufferSize; public byte[] Buffer; public Socket Socket; public object Owner; public ServerSocket Server; public string IP; public string MAC; public bool IsAlive; public bool OverrideTiming; private IDisposable[] TimerSubscriptions; private Queue<byte[]> SendQueue; private object SendSyncRoot; public Action<byte[], int, ClientWrapper> Callback; public void Create(Socket socket, ServerSocket server, Action<byte[], int, ClientWrapper> callBack) { Callback = callBack; BufferSize = 2047;//ushort.MaxValue Socket = socket; Server = server; Buffer = new byte[BufferSize]; LastReceive = Time32.Now; OverrideTiming = false; SendQueue = new Queue<byte[]>(); SendSyncRoot = new object(); TimerSubscriptions = new[] { World.Subscribe<ClientWrapper>(Program.World.ConnectionReview, this, World.GenericThreadPool), World.Subscribe<ClientWrapper>(Program.World.ConnectionReceive, this, World.ReceivePool), World.Subscribe<ClientWrapper>(Program.World.ConnectionSend, this, World.SendPool) }; } /// <summary> /// To be called only from a syncrhonized block of code /// </summary> /// <param name="data"></param> public void Send(byte[] data) { #if DIRECTSEND lock (SendSyncRoot) Socket.Send(data); #else lock (SendSyncRoot) { SendQueue.Enqueue(data); } #endif } public Time32 LastReceive; public Time32 LastReceiveCall; public bool Connected; public void Disconnect() { lock (Socket) { int K = 1000; while (SendQueue.Count > 0 && IsAlive && (K--) > 0) Thread.Sleep(1); if (!IsAlive) return; IsAlive = false; for (int i = 0; i < TimerSubscriptions.Length; i++) TimerSubscriptions[i].Dispose(); shutdown(Socket.Handle, ShutDownFlags.SD_BOTH); closesocket(Socket.Handle); Socket.Dispose(); } } public static void TryReview(ClientWrapper wrapper) { if (wrapper.IsAlive) { if (wrapper.OverrideTiming) { if (Time32.Now > wrapper.LastReceive.AddMilliseconds(180000)) wrapper.Server.InvokeDisconnect(wrapper); } else { if (Time32.Now < wrapper.LastReceiveCall.AddMilliseconds(2000)) if (Time32.Now > wrapper.LastReceive.AddMilliseconds(60000)) wrapper.Server.InvokeDisconnect(wrapper); } } } private bool isValid() { if (!IsAlive) { for (int i = 0; i < TimerSubscriptions.Length; i++) TimerSubscriptions[i].Dispose(); return false; } return true; } private void doReceive(int available) { LastReceive = Time32.Now; try { if (available > Buffer.Length) available = Buffer.Length; int size = Socket.Receive(Buffer, available, SocketFlags.None); if (size != 0) { if (Callback != null) { Callback(Buffer, size, this); } } else { Server.InvokeDisconnect(this); } } catch (SocketException) { Server.InvokeDisconnect(this); } catch (Exception e) { Console.WriteLine(e); } } public static void TryReceive(ClientWrapper wrapper) { wrapper.LastReceiveCall = Time32.Now; if (!wrapper.isValid()) return; try { bool poll = wrapper.Socket.Poll(0, SelectMode.SelectRead); int available = wrapper.Socket.Available; if (available > 0) wrapper.doReceive(available); else if (poll) wrapper.Server.InvokeDisconnect(wrapper); } catch (SocketException) { wrapper.Server.InvokeDisconnect(wrapper); } } private bool TryDequeueSend(out byte[] buffer) { buffer = null; lock (SendSyncRoot) if (SendQueue.Count != 0) buffer = SendQueue.Dequeue(); return buffer != null; } public static void TrySend(ClientWrapper wrapper) { if (!wrapper.isValid()) return; byte[] buffer; while (wrapper.TryDequeueSend(out buffer)) { try { wrapper.Socket.Send(buffer); //wrapper.Socket.BeginSend(buffer, 0, buffer.Length, SocketFlags.None, endSend, wrapper); } catch { wrapper.Server.InvokeDisconnect(wrapper); } } } private static void endSend(IAsyncResult ar) { var wrapper = ar.AsyncState as ClientWrapper; try { wrapper.Socket.EndSend(ar); } catch { wrapper.Server.InvokeDisconnect(wrapper); } } } }