All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.dongliu.prettypb.rpc.coder.VarIntFrameDecoder Maven / Gradle / Ivy

There is a newer version: 0.3.5
Show newest version
package net.dongliu.prettypb.rpc.coder;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.CorruptedFrameException;
import net.dongliu.prettypb.runtime.code.ProtoBufReader;

import java.io.ByteArrayInputStream;
import java.util.List;

/**
 * A decoder that splits the received {@link io.netty.buffer.ByteBuf}s dynamically by the
 * value of the Google Protocol Buffers
 * Base
 * 128 Varints integer length field in the message.  For example:
 * 
 * BEFORE DECODE (302 bytes)       AFTER DECODE (300 bytes)
 * +--------+---------------+      +---------------+
 * | Length | Protobuf Data |----- | Protobuf Data |
 * | 0xAC02 |  (300 bytes)  |      |  (300 bytes)  |
 * +--------+---------------+      +---------------+
 * 
* * @author dongliu */ public class VarIntFrameDecoder extends ByteToMessageDecoder { // TODO maxFrameLength + safe skip + fail-fast option // (just like LengthFieldBasedFrameDecoder) @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { in.markReaderIndex(); final byte[] buf = new byte[5]; for (int i = 0; i < buf.length; i++) { if (!in.isReadable()) { in.resetReaderIndex(); return; } buf[i] = in.readByte(); if (buf[i] >= 0) { int length; try (ProtoBufReader reader = new ProtoBufReader(new ByteArrayInputStream(buf))) { length = reader.readVarInt(); } if (length < 0) { throw new CorruptedFrameException("negative length: " + length); } if (in.readableBytes() < length) { in.resetReaderIndex(); return; } else { out.add(in.readBytes(length)); return; } } } // Couldn't find the byte whose MSB is off. throw new CorruptedFrameException("length wider than 32-bit"); } }