using System; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; namespace Mistox.Server { public class TCPConnection : IDisposable { TcpClient _client; TcpClientConnection _connection; public TCPConnection( TcpClient tcpClient, string ConnectionID ) { _client = tcpClient; _client.NoDelay = true; _connection = ServerInterface.Connections[ConnectionID]; ServerInterface.ServerInstance.InvokeUserConnected( ServerInterface.Connections[ConnectionID] ); // Start the receive thread Thread receiveThread = new Thread(async () => await ReceiveThread() ); receiveThread.Start(); } async Task ReceiveThread() { using( NetworkStream ns = _client.GetStream() ) { try { byte[] headerBuffer = new byte[DataPacket.HeaderLength]; byte[] payloadBuffer = new byte[65535]; // Upper limit for safety while( _connection.Connected ) { // Read the header off await ns.ReadExactlyAsync(headerBuffer, 0, 3); // Parse the header byte packetbyte = headerBuffer[0]; ushort dataLength = (ushort)((headerBuffer[1] << 8) | headerBuffer[2]); // Make sure the data looks valid if (dataLength > payloadBuffer.Length) { throw new Exception("Incoming TCP payload is too large for the pre-allocated buffer."); } // Read off the data await ns.ReadExactlyAsync(payloadBuffer, 0, dataLength); // Create the dataobject dynamic dataobject = DataPacket.Deserialize( packetbyte, dataLength, payloadBuffer.AsMemory(DataPacket.HeaderLength, dataLength) ); // Return the object ServerInterface.ServerInstance.InvokeDataReceived(dataobject); } } catch (Exception e) { ClientInterface.ServerClientInstance.Alive = false; Dispose(); Console.WriteLine("TCP Receive exception: " + e.Message); } } } public async Task Send( T packet ) { byte[] byteData = DataPacket.Serialize( packet ); await _client.GetStream().WriteAsync( byteData, 0, byteData.Length ); } public void Dispose() { _connection.Connected = false; ServerInterface.ServerInstance.InvokeUserDisconnected( _connection ); ServerInterface.ServerInstance.Alive = false; ServerInterface.Connections.TryRemove( _connection.UserName, out _ ); } } }