namespace Supercell.Laser.Server.Networking { using System.Net; using System.Net.Sockets; using Supercell.Laser.Server.Logic; public static class TCPGateway { private static Socket Socket; private static Thread Thread; private static ManualResetEvent AcceptEvent; public static void Init(string host, int port) { Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Socket.Bind(new IPEndPoint(IPAddress.Parse(host), port)); Socket.Listen(100); AcceptEvent = new ManualResetEvent(false); Thread = new Thread(TCPGateway.Update); Thread.Start(); Logger.Print($"TCP Server started at {host}:{port}"); } private static void Update() { while (true) { AcceptEvent.Reset(); Socket.BeginAccept(new AsyncCallback(OnAccept), null); AcceptEvent.WaitOne(); } } private static void OnAccept(IAsyncResult ar) { try { Socket client = Socket.EndAccept(ar); Connection connection = new Connection(client); Connections.AddConnection(connection); Logger.Network($"Accepted {(connection == null ? "conn#?" : connection.Describe())} — {Connections.Count} connections, {Session.Sessions.Count} online"); client.BeginReceive(connection.ReadBuffer, 0, Connection.TcpReceiveBufferSize, SocketFlags.None, new AsyncCallback(OnReceive), connection); } catch (Exception exception) { Logger.Exception("TCP accept failed", exception); } AcceptEvent.Set(); } private static void OnReceive(IAsyncResult ar) { Connection connection = (Connection)ar.AsyncState; if (connection == null) return; try { int r = connection.Socket.EndReceive(ar); if (r <= 0) { Connections.RemoveConnection(connection, "tcp-closed"); return; } connection.TotalBytesReceived += r; connection.Memory.Write(connection.ReadBuffer, 0, r); if (connection.Messaging.OnReceive() != 0) { Connections.RemoveConnection(connection, "invalid-packet"); return; } connection.Socket.BeginReceive(connection.ReadBuffer, 0, Connection.TcpReceiveBufferSize, SocketFlags.None, new AsyncCallback(OnReceive), connection); } catch (SocketException) { Connections.RemoveConnection(connection, "socket-exception"); } catch (Exception exception) { Connections.RemoveConnection(connection, "receive-exception"); Logger.Exception($"Unhandled TCP receive exception for {(connection == null ? "conn#?" : connection.Describe())}", exception); } } public static void OnSend(IAsyncResult ar) { try { Socket socket = (Socket)ar.AsyncState; socket.EndSend(ar); } catch (Exception) { ; } } } }