3
0
Mirror von https://github.com/PaperMC/Velocity.git synchronisiert 2024-11-16 21:10:30 +01:00

Combine VarInt prefix encoding with compression

This saves us a memory copy in the common "there is no need to compress this packet" case.
Dieser Commit ist enthalten in:
Andrew Steinborn 2021-05-06 19:56:45 -04:00
Ursprung 3d9a166892
Commit 37a4199d43
2 geänderte Dateien mit 26 neuen und 8 gelöschten Zeilen

Datei anzeigen

@ -36,12 +36,13 @@ import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.connection.client.HandshakeSessionHandler; import com.velocitypowered.proxy.connection.client.HandshakeSessionHandler;
import com.velocitypowered.proxy.connection.client.LoginSessionHandler; import com.velocitypowered.proxy.connection.client.LoginSessionHandler;
import com.velocitypowered.proxy.connection.client.StatusSessionHandler; import com.velocitypowered.proxy.connection.client.StatusSessionHandler;
import com.velocitypowered.proxy.network.Connections;
import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.StateRegistry; import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.netty.MinecraftCipherDecoder; import com.velocitypowered.proxy.protocol.netty.MinecraftCipherDecoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftCipherEncoder; import com.velocitypowered.proxy.protocol.netty.MinecraftCipherEncoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftCompressDecoder; import com.velocitypowered.proxy.protocol.netty.MinecraftCompressDecoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftCompressEncoder; import com.velocitypowered.proxy.protocol.netty.MinecraftCompressorAndLengthEncoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftDecoder; import com.velocitypowered.proxy.protocol.netty.MinecraftDecoder;
import com.velocitypowered.proxy.protocol.netty.MinecraftEncoder; import com.velocitypowered.proxy.protocol.netty.MinecraftEncoder;
import com.velocitypowered.proxy.util.except.QuietDecoderException; import com.velocitypowered.proxy.util.except.QuietDecoderException;
@ -402,8 +403,8 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
} else { } else {
MinecraftCompressDecoder decoder = (MinecraftCompressDecoder) channel.pipeline() MinecraftCompressDecoder decoder = (MinecraftCompressDecoder) channel.pipeline()
.get(COMPRESSION_DECODER); .get(COMPRESSION_DECODER);
MinecraftCompressEncoder encoder = (MinecraftCompressEncoder) channel.pipeline() MinecraftCompressorAndLengthEncoder encoder =
.get(COMPRESSION_ENCODER); (MinecraftCompressorAndLengthEncoder) channel.pipeline().get(COMPRESSION_ENCODER);
if (decoder != null && encoder != null) { if (decoder != null && encoder != null) {
decoder.setThreshold(threshold); decoder.setThreshold(threshold);
encoder.setThreshold(threshold); encoder.setThreshold(threshold);
@ -411,9 +412,10 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
int level = server.getConfiguration().getCompressionLevel(); int level = server.getConfiguration().getCompressionLevel();
VelocityCompressor compressor = Natives.compress.get().create(level); VelocityCompressor compressor = Natives.compress.get().create(level);
encoder = new MinecraftCompressEncoder(threshold, compressor); encoder = new MinecraftCompressorAndLengthEncoder(threshold, compressor);
decoder = new MinecraftCompressDecoder(threshold, compressor); decoder = new MinecraftCompressDecoder(threshold, compressor);
channel.pipeline().remove(FRAME_ENCODER);
channel.pipeline().addBefore(MINECRAFT_DECODER, COMPRESSION_DECODER, decoder); channel.pipeline().addBefore(MINECRAFT_DECODER, COMPRESSION_DECODER, decoder);
channel.pipeline().addBefore(MINECRAFT_ENCODER, COMPRESSION_ENCODER, encoder); channel.pipeline().addBefore(MINECRAFT_ENCODER, COMPRESSION_ENCODER, encoder);
} }

Datei anzeigen

@ -23,13 +23,14 @@ import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder; import io.netty.handler.codec.MessageToByteEncoder;
import java.util.zip.DataFormatException;
public class MinecraftCompressEncoder extends MessageToByteEncoder<ByteBuf> { public class MinecraftCompressorAndLengthEncoder extends MessageToByteEncoder<ByteBuf> {
private int threshold; private int threshold;
private final VelocityCompressor compressor; private final VelocityCompressor compressor;
public MinecraftCompressEncoder(int threshold, VelocityCompressor compressor) { public MinecraftCompressorAndLengthEncoder(int threshold, VelocityCompressor compressor) {
this.threshold = threshold; this.threshold = threshold;
this.compressor = compressor; this.compressor = compressor;
} }
@ -39,16 +40,31 @@ public class MinecraftCompressEncoder extends MessageToByteEncoder<ByteBuf> {
int uncompressed = msg.readableBytes(); int uncompressed = msg.readableBytes();
if (uncompressed < threshold) { if (uncompressed < threshold) {
// Under the threshold, there is nothing to do. // Under the threshold, there is nothing to do.
ProtocolUtils.writeVarInt(out, uncompressed + 1);
ProtocolUtils.writeVarInt(out, 0); ProtocolUtils.writeVarInt(out, 0);
out.writeBytes(msg); out.writeBytes(msg);
} else { } else {
ProtocolUtils.writeVarInt(out, uncompressed); handleCompressed(ctx, msg, out);
}
}
private void handleCompressed(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out)
throws DataFormatException {
int uncompressed = msg.readableBytes();
ByteBuf tmpBuf = MoreByteBufUtils.preferredBuffer(ctx.alloc(), compressor, uncompressed - 1);
try {
ProtocolUtils.writeVarInt(tmpBuf, uncompressed);
ByteBuf compatibleIn = MoreByteBufUtils.ensureCompatible(ctx.alloc(), compressor, msg); ByteBuf compatibleIn = MoreByteBufUtils.ensureCompatible(ctx.alloc(), compressor, msg);
try { try {
compressor.deflate(compatibleIn, out); compressor.deflate(compatibleIn, tmpBuf);
} finally { } finally {
compatibleIn.release(); compatibleIn.release();
} }
ProtocolUtils.writeVarInt(out, tmpBuf.readableBytes());
out.writeBytes(tmpBuf);
} finally {
tmpBuf.release();
} }
} }