package net.glowstone.net.pipeline;
import com.flowpowered.networking.Codec;
import com.flowpowered.networking.Message;
import com.flowpowered.networking.util.ByteBufUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.EncoderException;
import io.netty.handler.codec.MessageToMessageCodec;
import net.glowstone.GlowServer;
import net.glowstone.net.protocol.GlowProtocol;
import java.util.List;
/**
* Experimental pipeline component.
*/
public final class CodecsHandler extends MessageToMessageCodec<ByteBuf, Message> {
private final GlowProtocol protocol;
public CodecsHandler(GlowProtocol protocol) {
this.protocol = protocol;
}
@Override
protected void encode(ChannelHandlerContext ctx, Message msg, List<Object> out) throws Exception {
// find codec
final Class<? extends Message> clazz = msg.getClass();
Codec.CodecRegistration reg = protocol.getCodecRegistration(clazz);
if (reg == null) {
throw new EncoderException("Unknown message type: " + clazz + ".");
}
// write header
ByteBuf headerBuf = ctx.alloc().buffer(8);
ByteBufUtils.writeVarInt(headerBuf, reg.getOpcode());
// write body
ByteBuf messageBuf = ctx.alloc().buffer();
messageBuf = reg.getCodec().encode(messageBuf, msg);
out.add(Unpooled.wrappedBuffer(headerBuf, messageBuf));
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
// find codec and read header
final Codec<?> codec = protocol.newReadHeader(msg);
// read body
Message decoded = codec.decode(msg);
if (msg.readableBytes() > 0) {
GlowServer.logger.warning("Leftover bytes (" + msg.readableBytes() + ") after decoding: " + decoded);
}
out.add(decoded);
}
}