13
0
geforkt von Mirrors/Velocity

Readd safe and slow compression handling and hide it behind a system property

Dieser Commit ist enthalten in:
Andrew Steinborn 2021-05-08 18:40:23 -04:00
Ursprung 0a4e226571
Commit 6369a95ec9

Datei anzeigen

@ -29,6 +29,9 @@ import java.util.zip.DataFormatException;
public class MinecraftCompressorAndLengthEncoder extends MessageToByteEncoder<ByteBuf> { public class MinecraftCompressorAndLengthEncoder extends MessageToByteEncoder<ByteBuf> {
private static final boolean MUST_USE_SAFE_AND_SLOW_COMPRESSION_HANDLING =
Boolean.getBoolean("velocity.increased-compression-cap");
private int threshold; private int threshold;
private final VelocityCompressor compressor; private final VelocityCompressor compressor;
@ -46,29 +49,62 @@ public class MinecraftCompressorAndLengthEncoder extends MessageToByteEncoder<By
ProtocolUtils.writeVarInt(out, 0); ProtocolUtils.writeVarInt(out, 0);
out.writeBytes(msg); out.writeBytes(msg);
} else { } else {
handleCompressed(ctx, msg, out); if (MUST_USE_SAFE_AND_SLOW_COMPRESSION_HANDLING) {
handleCompressedSafe(ctx, msg, out);
} else {
handleCompressedFast(ctx, msg, out);
}
} }
} }
private void handleCompressed(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) private void handleCompressedFast(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out)
throws DataFormatException { throws DataFormatException {
ProtocolUtils.writeVarIntAs3Bytes(out, 0); //Dummy packet length
int uncompressed = msg.readableBytes(); int uncompressed = msg.readableBytes();
ProtocolUtils.writeVarIntAs3Bytes(out, 0); // Dummy packet length
ProtocolUtils.writeVarInt(out, uncompressed); ProtocolUtils.writeVarInt(out, uncompressed);
ByteBuf compatibleIn = MoreByteBufUtils.ensureCompatible(ctx.alloc(), compressor, msg); ByteBuf compatibleIn = MoreByteBufUtils.ensureCompatible(ctx.alloc(), compressor, msg);
int startCompressed = out.writerIndex();
try { try {
compressor.deflate(compatibleIn, out); compressor.deflate(compatibleIn, out);
} finally { } finally {
compatibleIn.release(); compatibleIn.release();
} }
int compressedLength = out.writerIndex() - startCompressed;
if (compressedLength >= 1 << 21) {
throw new DataFormatException("The server sent a very large (over 2MiB compressed) packet. "
+ "Please restart Velocity with the JVM flag -Dvelocity.increased-compression-cap=true "
+ "to fix this issue.");
}
int writerIndex = out.writerIndex(); int writerIndex = out.writerIndex();
int packetLength = out.readableBytes() - 3; int packetLength = out.readableBytes() - 3;
out.writerIndex(0); out.writerIndex(0);
ProtocolUtils.writeVarIntAs3Bytes(out, packetLength); //Rewrite packet length ProtocolUtils.writeVarIntAs3Bytes(out, packetLength); // Rewrite packet length
out.writerIndex(writerIndex); out.writerIndex(writerIndex);
} }
private void handleCompressedSafe(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);
try {
compressor.deflate(compatibleIn, tmpBuf);
} finally {
compatibleIn.release();
}
ProtocolUtils.writeVarInt(out, tmpBuf.readableBytes());
out.writeBytes(tmpBuf);
} finally {
tmpBuf.release();
}
}
@Override @Override
protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, ByteBuf msg, boolean preferDirect) protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, ByteBuf msg, boolean preferDirect)
throws Exception { throws Exception {