public static OperationStatus ValidateDataLength(NetConnection connection, int dataLength) { if (connection == null) { throw new ArgumentNullException(nameof(connection)); } if (dataLength > NetManager.MaxClientPacketSize) { connection.Kick($"Packet data length {dataLength} exceeds {NetManager.MaxClientPacketSize}."); return(OperationStatus.InvalidData); } return(OperationStatus.Done); }
/// <summary> /// Connection flow/lifetime: /// Every connection begins in <see cref="EngageClientConnection"/>, where a loop reads /// asynchrounsly from the client socket. /// Successful reads get copied to the connection's receive buffer. /// </summary> public async Task EngageClientConnection(NetConnection connection, CancellationToken cancellationToken) { if (connection == null) { throw new ArgumentNullException(nameof(connection)); } var readBuffer = new byte[1024 * 4]; // Clients don't really need a big read buffer. var readMemory = readBuffer.AsMemory(); var socket = connection.Socket; var receiveBuffer = connection.ReceiveBuffer; var state = new ReceiveState( connection, new NetBinaryReader(receiveBuffer), cancellationToken); try { int read; while ((read = await socket.ReceiveAsync( readMemory, SocketFlags.None, state.CancellationToken).Unchain()) != 0) { // Insert received data into beginning of receive buffer. var readSlice = readMemory.Slice(0, read); receiveBuffer.Seek(0, SeekOrigin.End); receiveBuffer.Write(readSlice.Span); receiveBuffer.Seek(0, SeekOrigin.Begin); connection.BytesReceived += readSlice.Length; // We process by the message length (unless it's a legacy server list ping), // so don't worry if we received parts of the next message. OperationStatus handleStatus; while ((handleStatus = HandlePacket(ref state)) == OperationStatus.Done) { if (!connection.IsAlive) { break; } } if (!connection.IsAlive) { break; } receiveBuffer.TrimStart((int)receiveBuffer.Position); } } catch (SocketException sockEx) when(sockEx.SocketErrorCode == SocketError.ConnectionReset) { // TODO: increment statistic? } catch (SocketException sockEx) when(sockEx.SocketErrorCode == SocketError.ConnectionAborted) { Console.WriteLine("Connection aborted for " + connection.RemoteEndPoint); // TODO: increment statistic? } catch (Exception ex) { Console.WriteLine(ex); connection.Kick(ex); return; } connection.Close(immediate: false); }