public OperationStatus HandlePacket(ref ReceiveState state) { var connection = state.Connection; Debug.Assert(connection != null); OperationStatus status; var clientReader = state.Reader; long initialClientPosition = clientReader.Position; long initialClientLength = clientReader.Length; if (clientReader.PeekByte() == LegacyServerListPingPacketDefinition.RawId) { clientReader.Position++; if ((status = ReadLegacyServerListPing(connection, clientReader)) != OperationStatus.NeedMoreData) { connection.Close(immediate: false); } goto ResetReaderAndReturn; } if ((status = clientReader.Read(out VarInt packetLength, out int packetLengthBytes)) != OperationStatus.Done) { goto ResetReaderAndReturn; } if (packetLength > NetManager.MaxClientPacketSize) { connection.Kick($"Packet length {packetLength} exceeds {NetManager.MaxClientPacketSize}."); return(OperationStatus.InvalidData); } if (clientReader.Remaining < packetLength) { status = OperationStatus.NeedMoreData; goto ResetReaderAndReturn; } VarInt dataLength; Stream packetStream; // CompressionThreshold < 0 == disabled // CompressionThreshold = 0 == enabled for all // CompressionThreshold > x == enabled for sizes >= x if (connection.CompressionThreshold >= 0) { if ((status = clientReader.Read(out dataLength, out int dataLengthBytes)) != OperationStatus.Done) { return(status); } if (dataLength != 0) { if ((status = ValidateDataLength(connection, dataLength)) != OperationStatus.Done) { return(status); } var decompressionBuffer = connection.DecompressionBuffer; using (var decompressor = new ZlibStream(clientReader.BaseStream, CompressionMode.Decompress, true)) { decompressionBuffer.SetLength(0); decompressionBuffer.Position = 0; if (decompressor.SpanWriteTo(decompressionBuffer, dataLength) != dataLength) { return(OperationStatus.InvalidData); } } decompressionBuffer.Position = 0; packetStream = decompressionBuffer; } else { dataLength = packetLength - packetLengthBytes - dataLengthBytes; if ((status = ValidateDataLength(connection, dataLength)) != OperationStatus.Done) { return(status); } packetStream = clientReader.BaseStream; } } else { dataLength = packetLength - packetLengthBytes; status = ValidateDataLength(connection, dataLength); if (status != OperationStatus.Done) { return(status); } packetStream = clientReader.BaseStream; } var packetReader = new NetBinaryReader(packetStream); if ((status = packetReader.Read(out VarInt rawPacketId, out int packetIdBytes)) != OperationStatus.Done) { connection.Kick("Packet ID is incorrectly encoded."); return(status); } if (!Decoder.TryGetPacketIdDefinition( state.ProtocolOverride ?? connection.ProtocolState, rawPacketId, out var packetIdDefinition)) { connection.Kick($"Unknown packet ID \"{rawPacketId}\"."); return(OperationStatus.InvalidData); } // Ensure that the packet handler only gets as much data as the packet contains. if (packetStream == clientReader.BaseStream) { packetStream.SetLength(packetStream.Position + dataLength); } var packetHandler = GetPacketHandler(packetIdDefinition.Id); status = packetHandler.Invoke(connection, packetReader, packetIdDefinition, out int readLength); if (status != OperationStatus.Done) { connection.Kick( $"Internal server error caused by packet handler of {packetIdDefinition.Id} with status " + status); return(status); } Debug.Assert(readLength <= dataLength, "Packet handler read too many bytes."); clientReader.Length = initialClientLength; // Reset length after read. // Skip data that was not read by the packet handler long totalRead = clientReader.Position - initialClientPosition; long toSkip = packetLength + packetLengthBytes - totalRead; clientReader.Seek(toSkip, SeekOrigin.Current); return(OperationStatus.Done); ResetReaderAndReturn: clientReader.Position = initialClientPosition; return(status); }