/**
  * Returns a new {@link EmbeddedChannel} that decodes the HTTP2 message content encoded in the
  * specified {@code contentEncoding}.
  *
  * @param contentEncoding the value of the {@code content-encoding} header
  * @return a new {@link ByteToMessageDecoder} if the specified encoding is supported. {@code null}
  *     otherwise (alternatively, you can throw a {@link Http2Exception} to block unknown
  *     encoding).
  * @throws Http2Exception If the specified encoding is not not supported and warrants an exception
  */
 protected EmbeddedChannel newContentDecoder(CharSequence contentEncoding) throws Http2Exception {
   if (GZIP.equalsIgnoreCase(contentEncoding) || XGZIP.equalsIgnoreCase(contentEncoding)) {
     return new EmbeddedChannel(ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP));
   }
   if (DEFLATE.equalsIgnoreCase(contentEncoding) || XDEFLATE.equalsIgnoreCase(contentEncoding)) {
     final ZlibWrapper wrapper = strict ? ZlibWrapper.ZLIB : ZlibWrapper.ZLIB_OR_NONE;
     // To be strict, 'deflate' means ZLIB, but some servers were not implemented correctly.
     return new EmbeddedChannel(ZlibCodecFactory.newZlibDecoder(wrapper));
   }
   // 'identity' or unsupported
   return null;
 }
  @Override
  public void initChannel(SocketChannel ch) throws Exception {
    ChannelPipeline pipeline = ch.pipeline();

    // Enable stream compression (you can remove these two if unnecessary)
    pipeline.addLast("deflater", ZlibCodecFactory.newZlibEncoder(ZlibWrapper.GZIP));
    pipeline.addLast("inflater", ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP));

    // Add the number codec first,
    pipeline.addLast("decoder", new BigIntegerDecoder());
    pipeline.addLast("encoder", new NumberEncoder());

    // and then business logic.
    // Please note we create a handler for every new channel
    // because it has stateful properties.
    pipeline.addLast("handler", new FactorialServerHandler());
  }
  @Override
  public void initChannel(SocketChannel ch) throws Exception {
    ChannelPipeline pipeline = ch.pipeline();

    // Enable stream compression (you can remove these two if unnecessary)
    if (compress) {
      pipeline.addLast("deflater", ZlibCodecFactory.newZlibEncoder(ZlibWrapper.GZIP));
      pipeline.addLast("inflater", ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP));
    }

    /**
     * length (4 bytes).
     *
     * <p>Note: max message size is 64 Mb = 67108864 bytes this defines a framer with a max of 64 Mb
     * message, 4 bytes are the length, and strip 4 bytes
     */
    pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(67108864, 0, 4, 0, 4));

    // pipeline.addLast("frameDecoder", new
    // DebugFrameDecoder(67108864, 0, 4, 0, 4));

    // decoder must be first
    Object[] messageTypes = {
      Management.getDefaultInstance(),
      Image.Request.getDefaultInstance(),
      App.Request.getDefaultInstance()
    };
    pipeline.addLast("protobufDecoder", new CustomRaftDecoder(messageTypes));
    // pipeline.addLast("protobufDecoder", new ProtobufDecoder(Management.getDefaultInstance()));
    // pipeline.addLast("protobufDecoder2", new ProtobufDecoder(Request.getDefaultInstance()));
    pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
    pipeline.addLast("protobufEncoder", new ProtobufEncoder());

    // our server processor (new instance for each connection)
    pipeline.addLast("handler", handler);
  }