class MessageFrameDecoder extends ByteToMessageDecoder {

  @Override
  protected void decode(final ChannelHandlerContext ctx, final ByteBuf in, final List<Object> out)
  {
    logger.trace("decoding {} bytes from {}", in.readableBytes(), in);
    if (in.readableBytes() <= 2) {
      return;
    }

    final int readerIdx = in.readerIndex();
    final int writerIdx = in.writerIndex();
    int len = 0;
    try {
      final DERBuffer buffer = new NettyDERBuffer(in.readSlice(in.readableBytes()));
      len = readMessageLength(buffer);
    } finally {
      logger.trace("decoded message length of {} for {}", len, in);
      // return the reader and writer indexes back to their initial position
      in.setIndex(readerIdx, writerIdx);
    }
    if (len > 0) {
      logger.trace("read enough bytes from {} to decode message", in);
      out.add(in.readRetainedSlice(len));
      if (ctx != null) {
        ctx.fireUserEventTriggered(NettyConnection.MessageStatus.READ);
      }
    } else {
      logger.trace("could not read enough bytes from {} to decode message", in);
    }
  }

}