/** Apply connection-wide flow control to the incoming data frame. */
  private void applyConnectionFlowControl(int dataLength, FrameWriter frameWriter)
      throws Http2Exception {
    // Remove the data length from the available window size. Throw if the lower bound
    // was exceeded.
    connectionState.addAndGet(-dataLength);

    // If less than the window update threshold remains, restore the window size
    // to the initial value and send a window update to the remote endpoint indicating
    // the new window size.
    if (connectionState.windowSize() <= getWindowUpdateThreshold()) {
      connectionState.updateWindow(frameWriter);
    }
  }
  /** Apply stream-based flow control to the incoming data frame. */
  private void applyStreamFlowControl(
      int streamId, int dataLength, boolean endOfStream, FrameWriter frameWriter)
      throws Http2Exception {
    // Remove the data length from the available window size. Throw if the lower bound
    // was exceeded.
    FlowState state = getStateOrFail(streamId);
    state.addAndGet(-dataLength);

    // If less than the window update threshold remains, restore the window size
    // to the initial value and send a window update to the remote endpoint indicating
    // the new window size.
    if (state.windowSize() <= getWindowUpdateThreshold() && !endOfStream) {
      state.updateWindow(frameWriter);
    }
  }