reduce clientbound compression limits

This commit is contained in:
Shane Freeder
2026-04-08 20:41:09 +01:00
parent ab99bde9d6
commit f6d48c90f9
2 changed files with 20 additions and 7 deletions

View File

@@ -38,6 +38,7 @@ import com.velocitypowered.proxy.connection.client.InitialLoginSessionHandler;
import com.velocitypowered.proxy.connection.client.StatusSessionHandler; import com.velocitypowered.proxy.connection.client.StatusSessionHandler;
import com.velocitypowered.proxy.network.Connections; import com.velocitypowered.proxy.network.Connections;
import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import com.velocitypowered.proxy.protocol.StateRegistry; import com.velocitypowered.proxy.protocol.StateRegistry;
import com.velocitypowered.proxy.protocol.VelocityConnectionEvent; import com.velocitypowered.proxy.protocol.VelocityConnectionEvent;
import com.velocitypowered.proxy.protocol.netty.MinecraftCipherDecoder; import com.velocitypowered.proxy.protocol.netty.MinecraftCipherDecoder;
@@ -544,9 +545,10 @@ public class MinecraftConnection extends ChannelInboundHandlerAdapter {
} else { } else {
int level = server.getConfiguration().getCompressionLevel(); int level = server.getConfiguration().getCompressionLevel();
VelocityCompressor compressor = Natives.compress.get().create(level); VelocityCompressor compressor = Natives.compress.get().create(level);
final MinecraftDecoder minecraftDecoder = (MinecraftDecoder) channel.pipeline().get(MINECRAFT_DECODER);
encoder = new MinecraftCompressorAndLengthEncoder(threshold, compressor); encoder = new MinecraftCompressorAndLengthEncoder(threshold, compressor);
decoder = new MinecraftCompressDecoder(threshold, compressor); decoder = new MinecraftCompressDecoder(threshold, compressor, minecraftDecoder.getDirection());
channel.pipeline().remove(FRAME_ENCODER); channel.pipeline().remove(FRAME_ENCODER);
channel.pipeline().addBefore(MINECRAFT_DECODER, COMPRESSION_DECODER, decoder); channel.pipeline().addBefore(MINECRAFT_DECODER, COMPRESSION_DECODER, decoder);

View File

@@ -33,20 +33,26 @@ import java.util.List;
*/ */
public class MinecraftCompressDecoder extends MessageToMessageDecoder<ByteBuf> { public class MinecraftCompressDecoder extends MessageToMessageDecoder<ByteBuf> {
private static final int SERVERBOUND_MAXIMUM_UNCOMPRESSED_SIZE = 2 * 1024 * 1024; // 2MiB
private static final int VANILLA_MAXIMUM_UNCOMPRESSED_SIZE = 8 * 1024 * 1024; // 8MiB private static final int VANILLA_MAXIMUM_UNCOMPRESSED_SIZE = 8 * 1024 * 1024; // 8MiB
private static final int HARD_MAXIMUM_UNCOMPRESSED_SIZE = 128 * 1024 * 1024; // 128MiB private static final int HARD_MAXIMUM_UNCOMPRESSED_SIZE = 128 * 1024 * 1024; // 128MiB
private static final int UNCOMPRESSED_CAP = private static final int CLIENTBOUND_UNCOMPRESSED_CAP =
Boolean.getBoolean("velocity.increased-compression-cap") Boolean.getBoolean("velocity.increased-compression-cap")
? HARD_MAXIMUM_UNCOMPRESSED_SIZE : VANILLA_MAXIMUM_UNCOMPRESSED_SIZE; ? HARD_MAXIMUM_UNCOMPRESSED_SIZE : VANILLA_MAXIMUM_UNCOMPRESSED_SIZE;
private static final int SERVERBOUND_UNCOMPRESSED_CAP =
Boolean.getBoolean("velocity.increased-compression-cap")
? HARD_MAXIMUM_UNCOMPRESSED_SIZE : SERVERBOUND_MAXIMUM_UNCOMPRESSED_SIZE;
private static final boolean SKIP_COMPRESSION_VALIDATION = Boolean.getBoolean("velocity.skip-uncompressed-packet-size-validation"); private static final boolean SKIP_COMPRESSION_VALIDATION = Boolean.getBoolean("velocity.skip-uncompressed-packet-size-validation");
private final ProtocolUtils.Direction direction;
private int threshold; private int threshold;
private final VelocityCompressor compressor; private final VelocityCompressor compressor;
public MinecraftCompressDecoder(int threshold, VelocityCompressor compressor) { public MinecraftCompressDecoder(int threshold, VelocityCompressor compressor, ProtocolUtils.Direction direction) {
this.threshold = threshold; this.threshold = threshold;
this.compressor = compressor; this.compressor = compressor;
this.direction = direction;
} }
@Override @Override
@@ -65,10 +71,15 @@ public class MinecraftCompressDecoder extends MessageToMessageDecoder<ByteBuf> {
checkFrame(claimedUncompressedSize >= threshold, "Uncompressed size %s is less than" checkFrame(claimedUncompressedSize >= threshold, "Uncompressed size %s is less than"
+ " threshold %s", claimedUncompressedSize, threshold); + " threshold %s", claimedUncompressedSize, threshold);
checkFrame(claimedUncompressedSize <= UNCOMPRESSED_CAP, if (direction == ProtocolUtils.Direction.CLIENTBOUND) {
"Uncompressed size %s exceeds hard threshold of %s", claimedUncompressedSize, checkFrame(claimedUncompressedSize <= CLIENTBOUND_UNCOMPRESSED_CAP,
UNCOMPRESSED_CAP); "Uncompressed size %s exceeds hard threshold of %s", claimedUncompressedSize,
CLIENTBOUND_UNCOMPRESSED_CAP);
} else {
checkFrame(claimedUncompressedSize <= SERVERBOUND_UNCOMPRESSED_CAP,
"Uncompressed size %s exceeds hard threshold of %s", claimedUncompressedSize,
SERVERBOUND_UNCOMPRESSED_CAP);
}
ByteBuf compatibleIn = ensureCompatible(ctx.alloc(), compressor, in); ByteBuf compatibleIn = ensureCompatible(ctx.alloc(), compressor, in);
ByteBuf uncompressed = preferredBuffer(ctx.alloc(), compressor, claimedUncompressedSize); ByteBuf uncompressed = preferredBuffer(ctx.alloc(), compressor, claimedUncompressedSize);
try { try {