class DefaultHttp2ConnectionEncoder implements Http2ConnectionEncoder, Http2SettingsReceivedConsumer {

  @Override
  public ChannelFuture writeData(
      final ChannelHandlerContext ctx,
      final int streamId,
      final ByteBuf data,
      final int padding,
      final boolean endOfStream,
      final ChannelPromise promise) {
    final Http2Stream stream;
    try {
      stream = requireStream(streamId);

      // Verify that the stream is in the appropriate state for sending DATA frames.
      switch (stream.state()) {
        case OPEN:
        case HALF_CLOSED_REMOTE:
          // Allowed sending DATA frames in these states.
          break;
        default:
          throw new IllegalStateException(
              "Stream " + stream.id() + " in unexpected state " + stream.state());
      }
    } catch (final Throwable e) {
      data.release();
      return promise.setFailure(e);
    }

    // Hand control of the frame to the flow controller.
    flowController()
        .addFlowControlled(
            stream, new FlowControlledData(stream, data, padding, endOfStream, promise));
    return promise;
  }

  public  DefaultHttp2ConnectionEncoder(
      final Http2Connection connection, final Http2FrameWriter frameWriter);

}