minecraft-src/net/minecraft/network/CompressionDecoder.java
2025-07-04 01:41:11 +03:00

93 lines
2.9 KiB
Java

package net.minecraft.network;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.DecoderException;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
/**
* Handles decompression of network traffic.
*
* @see Connection#setupCompression
*/
public class CompressionDecoder extends ByteToMessageDecoder {
public static final int MAXIMUM_COMPRESSED_LENGTH = 2097152;
public static final int MAXIMUM_UNCOMPRESSED_LENGTH = 8388608;
private final Inflater inflater;
private int threshold;
private boolean validateDecompressed;
public CompressionDecoder(int threshold, boolean validateDecompressed) {
this.threshold = threshold;
this.validateDecompressed = validateDecompressed;
this.inflater = new Inflater();
}
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
if (byteBuf.readableBytes() != 0) {
int i = VarInt.read(byteBuf);
if (i == 0) {
list.add(byteBuf.readBytes(byteBuf.readableBytes()));
} else {
if (this.validateDecompressed) {
if (i < this.threshold) {
throw new DecoderException("Badly compressed packet - size of " + i + " is below server threshold of " + this.threshold);
}
if (i > 8388608) {
throw new DecoderException("Badly compressed packet - size of " + i + " is larger than protocol maximum of 8388608");
}
}
this.setupInflaterInput(byteBuf);
ByteBuf byteBuf2 = this.inflate(channelHandlerContext, i);
this.inflater.reset();
list.add(byteBuf2);
}
}
}
private void setupInflaterInput(ByteBuf buffer) {
ByteBuffer byteBuffer;
if (buffer.nioBufferCount() > 0) {
byteBuffer = buffer.nioBuffer();
buffer.skipBytes(buffer.readableBytes());
} else {
byteBuffer = ByteBuffer.allocateDirect(buffer.readableBytes());
buffer.readBytes(byteBuffer);
byteBuffer.flip();
}
this.inflater.setInput(byteBuffer);
}
private ByteBuf inflate(ChannelHandlerContext context, int size) throws DataFormatException {
ByteBuf byteBuf = context.alloc().directBuffer(size);
try {
ByteBuffer byteBuffer = byteBuf.internalNioBuffer(0, size);
int i = byteBuffer.position();
this.inflater.inflate(byteBuffer);
int j = byteBuffer.position() - i;
if (j != size) {
throw new DecoderException("Badly compressed packet - actual length of uncompressed payload " + j + " is does not match declared size " + size);
} else {
byteBuf.writerIndex(byteBuf.writerIndex() + j);
return byteBuf;
}
} catch (Exception var7) {
byteBuf.release();
throw var7;
}
}
public void setThreshold(int threshold, boolean validateDecompressed) {
this.threshold = threshold;
this.validateDecompressed = validateDecompressed;
}
}