using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using BasicServer.Management; namespace BasicServer.Arch { public static class Listener { private static TcpListener _tcpListener; private static UdpClient _udpListener; private static Dictionary Clients => Server.Clients; public static void Start() { _tcpListener = new TcpListener(IPAddress.Any, Server.Port); _tcpListener.Start(); _tcpListener.BeginAcceptTcpClient(TcpConnectCallback, null); _udpListener = new UdpClient(Server.Port); _udpListener.BeginReceive(UdpReceiveCallback, null); } private static void TcpConnectCallback(IAsyncResult result) { var client = _tcpListener.EndAcceptTcpClient(result); _tcpListener.BeginAcceptTcpClient(TcpConnectCallback, null); Console.WriteLine($"Incoming connection from {client.Client.RemoteEndPoint}..."); for (var i = 1; i <= Server.MaxPlayers; i++) { if (Clients[i].Tcp.Socket != null) continue; Clients[i].Tcp.Connect(client); return; } Console.WriteLine($"{client.Client.RemoteEndPoint} failed to connect: Server full!"); } private static void UdpReceiveCallback(IAsyncResult result) { try { var clientEndPoint = new IPEndPoint(IPAddress.Any, 0); var data = _udpListener.EndReceive(result, ref clientEndPoint); _udpListener.BeginReceive(UdpReceiveCallback, null); if (data.Length < 4) return; using var packet = new Packet(data); var clientId = packet.ReadInt(); if (clientId == 0) return; if (Clients[clientId].Tcp.Socket == null) return; if (Clients[clientId].Udp.EndPoint == null) { Clients[clientId].Udp.Connect(clientEndPoint); return; } if (Clients[clientId].Udp.EndPoint.ToString() == clientEndPoint.ToString()) Clients[clientId].Udp.HandleData(packet); } catch (Exception ex) { Console.WriteLine($"Error receiving UDP data: {ex}"); } } public static void SendUdpData(IPEndPoint clientEndPoint, Packet packet) { try { if (clientEndPoint != null) _udpListener.BeginSend(packet.ToArray(), packet.Length(), clientEndPoint, null, null); } catch (Exception ex) { Console.WriteLine($"Error sending data to {clientEndPoint} via UDP: {ex}"); } } } public class TcpManager { private readonly int _id; private byte[] _receiveBuffer; private Packet _receivedData; private NetworkStream _stream; public TcpClient Socket; public TcpManager(int id) { _id = id; } public void Connect(TcpClient socket) { Socket = socket; Socket.ReceiveBufferSize = Constants.DataBufferSize; Socket.SendBufferSize = Constants.DataBufferSize; _stream = Socket.GetStream(); _receivedData = new Packet(); _receiveBuffer = new byte[Constants.DataBufferSize]; _stream.BeginRead(_receiveBuffer, 0, Constants.DataBufferSize, ReceiveCallback, null); Server.Clients[_id].OnConnect(); } public void SendData(Packet packet) { try { if (Socket != null) _stream.BeginWrite(packet.ToArray(), 0, packet.Length(), null, null); } catch (Exception ex) { Console.WriteLine($"Error sending data to player {_id} via TCP: {ex}"); } } private void ReceiveCallback(IAsyncResult result) { try { var byteLength = _stream.EndRead(result); if (byteLength <= 0) { Server.Clients[_id].Disconnect(); return; } var data = new byte[byteLength]; Array.Copy(_receiveBuffer, data, byteLength); _receivedData.Reset(HandleData(data)); _stream.BeginRead(_receiveBuffer, 0, Constants.DataBufferSize, ReceiveCallback, null); } catch (Exception ex) { Console.WriteLine($"Error receiving TCP data: {ex}"); Server.Clients[_id].Disconnect(); } } private bool HandleData(byte[] data) { var packetLength = 0; _receivedData.SetBytes(data); if (_receivedData.UnreadLength() >= 4) { packetLength = _receivedData.ReadInt(); if (packetLength <= 0) return true; } while (packetLength > 0 && packetLength <= _receivedData.UnreadLength()) { var packetBytes = _receivedData.ReadBytes(packetLength); ThreadManager.ExecuteOnMainThread(() => ReadPacket.Read(packetBytes, _id)); packetLength = 0; if (_receivedData.UnreadLength() < 4) continue; packetLength = _receivedData.ReadInt(); if (packetLength <= 0) return true; } return packetLength <= 1; } public void Disconnect() { Socket.Close(); _stream = null; _receivedData = null; _receiveBuffer = null; Socket = null; } } public class UdpManager { private readonly int _id; public IPEndPoint EndPoint; public UdpManager(int id) { _id = id; } public void Connect(IPEndPoint endPoint) { EndPoint = endPoint; } public void SendData(Packet packet) { Listener.SendUdpData(EndPoint, packet); } public void HandleData(Packet packetData) { var packetLength = packetData.ReadInt(); var packetBytes = packetData.ReadBytes(packetLength); ThreadManager.ExecuteOnMainThread(() => ReadPacket.Read(packetBytes, _id)); } public void Disconnect() { EndPoint = null; } } internal static class ReadPacket { public static void Read(byte[] packetBytes, int clientId) { using var packet = new Packet(packetBytes); var packetTypeId = packet.ReadInt(); var packetActionId = packet.ReadInt(); Server.PacketHandlers[packetTypeId][packetActionId](clientId, packet); } } }