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

org.tron.p2p.connection.socket.P2pProtobufVarint32FrameDecoder Maven / Gradle / Ivy

The newest version!
package org.tron.p2p.connection.socket;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.CorruptedFrameException;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.tron.p2p.connection.Channel;

@Slf4j(topic = "net")
public class P2pProtobufVarint32FrameDecoder extends ByteToMessageDecoder {

  private static final int maxMsgLength = 5 * 1024 * 1024;//5M

  private final Channel channel;

  public P2pProtobufVarint32FrameDecoder(Channel channel) {
    this.channel = channel;
  }

  private static int readRawVarint32(ByteBuf buffer) {
    if (!buffer.isReadable()) {
      return 0;
    }
    buffer.markReaderIndex();
    byte tmp = buffer.readByte();
    if (tmp >= 0) {
      return tmp;
    } else {
      int result = tmp & 127;
      if (!buffer.isReadable()) {
        buffer.resetReaderIndex();
        return 0;
      }
      if ((tmp = buffer.readByte()) >= 0) {
        result |= tmp << 7;
      } else {
        result |= (tmp & 127) << 7;
        if (!buffer.isReadable()) {
          buffer.resetReaderIndex();
          return 0;
        }
        if ((tmp = buffer.readByte()) >= 0) {
          result |= tmp << 14;
        } else {
          result |= (tmp & 127) << 14;
          if (!buffer.isReadable()) {
            buffer.resetReaderIndex();
            return 0;
          }
          if ((tmp = buffer.readByte()) >= 0) {
            result |= tmp << 21;
          } else {
            result |= (tmp & 127) << 21;
            if (!buffer.isReadable()) {
              buffer.resetReaderIndex();
              return 0;
            }
            result |= (tmp = buffer.readByte()) << 28;
            if (tmp < 0) {
              throw new CorruptedFrameException("malformed varint.");
            }
          }
        }
      }
      return result;
    }
  }

  @Override
  protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) {
    in.markReaderIndex();
    int preIndex = in.readerIndex();
    int length = readRawVarint32(in);
    if (in.readableBytes() == 0 || length > maxMsgLength) {
      log.warn("Receive empty msg or big msg, not proto, host: {}, readableBytes: {}, length: {}",
          ctx.channel().remoteAddress(), in.readableBytes(), length);
      in.clear();
      channel.close();
      return;
    }
    if (preIndex == in.readerIndex()) {
      return;
    }
    if (length < 0) {
      throw new CorruptedFrameException("negative length: " + length);
    }

    if (in.readableBytes() < length) {
      in.resetReaderIndex();
    } else {
      out.add(in.readRetainedSlice(length));
    }
  }
}