package com.captainbern.minecraft.net.pipeline;
import com.captainbern.minecraft.net.util.ByteBufUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;
import java.util.List;
/**
* Splitter/prepender
*/
public class FramingHandler extends ByteToMessageCodec<ByteBuf> {
@Override
protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf packet, ByteBuf out) throws Exception {
ByteBufUtils.writeVarInt(out, packet.readableBytes());
out.writeBytes(packet);
}
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> list) throws Exception {
in.markReaderIndex();
// check for length field readability
in.markReaderIndex();
if (!readableVarInt(in)) {
return;
}
// check for contents readability
int length = ByteBufUtils.readVarInt(in);
if (in.readableBytes() < length) {
in.resetReaderIndex();
return;
}
// read contents into buf
ByteBuf buf = channelHandlerContext.alloc().buffer(length);
in.readBytes(buf, length);
list.add(buf);
}
private static boolean readableVarInt(ByteBuf buf) {
if (buf.readableBytes() > 5) {
// maximum varint size
return true;
}
int idx = buf.readerIndex();
byte in;
do {
if (buf.readableBytes() < 1) {
buf.readerIndex(idx);
return false;
}
in = buf.readByte();
} while ((in & 0x80) != 0);
buf.readerIndex(idx);
return true;
}
}