/** @file

  Http2ConnectionState.

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

#include "../../iocore/net/P_Net.h"
#include "../../iocore/net/P_UnixNetVConnection.h"
#include "iocore/eventsystem/Lock.h"
#include "proxy/http2/HTTP2.h"
#include "proxy/http2/Http2ConnectionState.h"
#include "proxy/http2/Http2ClientSession.h"
#include "ts/ats_probe.h"
#include "proxy/http2/Http2ServerSession.h"
#include "proxy/http2/Http2Stream.h"
#include "proxy/http2/Http2Frame.h"
#include "proxy/http2/Http2DebugNames.h"
#include "proxy/http/HttpDebugNames.h"
#include "proxy/http/HttpSM.h"
#include "proxy/http/HttpConfig.h"

#include "iocore/net/TLSSNISupport.h"

#include "tscore/ink_assert.h"
#include "tscore/ink_hrtime.h"
#include "tscore/ink_memory.h"
#include "tsutil/PostScript.h"
#include "tsutil/LocalBuffer.h"

#include <algorithm>
#include <cstdint>
#include <limits>
#include <numeric>
#include <sstream>

namespace
{
DbgCtl dbg_ctl_http2_con{"http2_con"};
DbgCtl dbg_ctl_http2_priority{"http2_priority"};

#define REMEMBER(e, r)                                     \
  {                                                        \
    if (this->session) {                                   \
      this->session->remember(MakeSourceLocation(), e, r); \
    }                                                      \
  }

#define Http2ConDebug(session, fmt, ...) Dbg(dbg_ctl_http2_con, "[%" PRId64 "] " fmt, session->get_connection_id(), ##__VA_ARGS__);

#define Http2StreamDebug(session, stream_id, fmt, ...) \
  Dbg(dbg_ctl_http2_con, "[%" PRId64 "] [%u] " fmt, session->get_connection_id(), stream_id, ##__VA_ARGS__);

const int buffer_size_index[HTTP2_FRAME_TYPE_MAX] = {
  BUFFER_SIZE_INDEX_16K, // HTTP2_FRAME_TYPE_DATA
  BUFFER_SIZE_INDEX_16K, // HTTP2_FRAME_TYPE_HEADERS
  -1,                    // HTTP2_FRAME_TYPE_PRIORITY
  -1,                    // HTTP2_FRAME_TYPE_RST_STREAM
  -1,                    // HTTP2_FRAME_TYPE_SETTINGS
  BUFFER_SIZE_INDEX_16K, // HTTP2_FRAME_TYPE_PUSH_PROMISE
  -1,                    // HTTP2_FRAME_TYPE_PING
  -1,                    // HTTP2_FRAME_TYPE_GOAWAY
  -1,                    // HTTP2_FRAME_TYPE_WINDOW_UPDATE
  BUFFER_SIZE_INDEX_16K, // HTTP2_FRAME_TYPE_CONTINUATION
};

inline unsigned
read_rcv_buffer(char *buf, size_t bufsize, unsigned &nbytes, const Http2Frame &frame)
{
  char *end;

  if (frame.header().length - nbytes > bufsize) {
    end = frame.reader()->memcpy(buf, bufsize, nbytes);
  } else {
    end = frame.reader()->memcpy(buf, frame.header().length - nbytes, nbytes);
  }
  nbytes += end - buf;

  return end - buf;
}

} // end anonymous namespace

Http2Error
Http2ConnectionState::rcv_data_frame(const Http2Frame &frame)
{
  unsigned       nbytes         = 0;
  Http2StreamId  id             = frame.header().streamid;
  uint8_t        pad_length     = 0;
  const uint32_t payload_length = frame.header().length;

  Http2StreamDebug(this->session, id, "Received DATA frame, flags: %d", frame.header().flags);

  // Update connection window size, before any stream specific handling
  this->decrement_local_rwnd(payload_length);

  if (this->get_zombie_event()) {
    Warning("Data frame for zombied session %" PRId64, this->session->get_connection_id());
  }

  // If a DATA frame is received whose stream identifier field is 0x0, the
  // recipient MUST
  // respond with a connection error of type PROTOCOL_ERROR.
  if (!http2_is_client_streamid(id)) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                      "recv data bad frame client id");
  }

  Http2Stream *stream = this->find_stream(id);
  if (stream == nullptr) {
    if (this->is_valid_streamid(id)) {
      // This error occurs fairly often, and is probably innocuous (SM initiates the shutdown)
      if (this->session->is_outbound()) {
        this->send_rst_stream_frame(id, Http2ErrorCode::HTTP2_ERROR_NO_ERROR);
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
      } else {
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_STREAM_CLOSED, nullptr);
      }
    } else {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                        "recv data stream freed with invalid id");
    }
  }

  if (stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_CLOSED ||
      stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE) {
    this->send_rst_stream_frame(id, Http2ErrorCode::HTTP2_ERROR_STREAM_CLOSED);
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
  }

  // If a DATA frame is received whose stream is not in "open" or "half closed
  // (local)" state,
  // the recipient MUST respond with a stream error of type STREAM_CLOSED.
  if (stream->get_state() != Http2StreamState::HTTP2_STREAM_STATE_OPEN &&
      stream->get_state() != Http2StreamState::HTTP2_STREAM_STATE_HALF_CLOSED_LOCAL) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_STREAM_CLOSED,
                      "recv data stream closed");
  }

  if (frame.header().flags & HTTP2_FLAGS_DATA_PADDED) {
    frame.reader()->memcpy(&pad_length, HTTP2_DATA_PADLEN_LEN, nbytes);
    nbytes += HTTP2_DATA_PADLEN_LEN;
    if (pad_length > payload_length) {
      // If the length of the padding is the length of the
      // frame payload or greater, the recipient MUST treat this as a
      // connection error of type PROTOCOL_ERROR.
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                        "recv data pad > payload");
    }
  }

  stream->increment_data_length(payload_length - pad_length - nbytes);
  if (frame.header().flags & HTTP2_FLAGS_DATA_END_STREAM) {
    stream->receive_end_stream = true;
    if (!stream->change_state(frame.header().type, frame.header().flags)) {
      this->send_rst_stream_frame(id, Http2ErrorCode::HTTP2_ERROR_STREAM_CLOSED);
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
    }
    if (!stream->payload_length_is_valid()) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                        "recv data bad payload length");
    }

    // Pure END_STREAM
    if (payload_length == 0) {
      if (stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_CLOSED) {
        stream->initiating_close();
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
      }

      stream->signal_final_read_event(VC_EVENT_READ_COMPLETE);

      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
    }
  } else {
    // Any headers that show up after we received data are by definition trailing headers
    stream->set_trailing_header_is_possible();
  }

  // If payload length is 0 without END_STREAM flag, just count it
  const uint32_t unpadded_length = payload_length - pad_length;
  if (unpadded_length == 0 && !stream->receive_end_stream) {
    this->increment_received_empty_frame_count();
    if (configured_max_empty_frames_per_minute >= 0 &&
        this->get_received_empty_frame_count() > static_cast<uint32_t>(configured_max_empty_frames_per_minute)) {
      Metrics::Counter::increment(http2_rsb.max_empty_frames_per_minute_exceeded);
      Http2StreamDebug(this->session, id, "Observed too many empty DATA frames: %u within the last minute",
                       this->get_received_empty_frame_count());
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
                        "recv data too frequent empty frame");
    }

    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
  }

  // Check whether Window Size is acceptable
  // compare to 0 because we already decreased the connection rwnd with payload_length
  if (!this->_local_rwnd_is_shrinking && this->get_local_rwnd() < 0) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FLOW_CONTROL_ERROR,
                      "recv data this->local_rwnd < payload_length");
  }
  if (stream->get_local_rwnd() < payload_length) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_FLOW_CONTROL_ERROR,
                      "recv data stream->local_rwnd < payload_length");
  }

  // Update stream window size
  stream->decrement_local_rwnd(payload_length);

  if (dbg_ctl_http2_con.on()) {
    uint32_t const stream_window  = this->acknowledged_local_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE);
    uint32_t const session_window = this->_get_configured_receive_session_window_size();
    Http2StreamDebug(this->session, id,
                     "Received DATA frame: payload_length=%" PRId32 " rwnd con=%zd/%" PRId32 " stream=%zd/%" PRId32, payload_length,
                     this->get_local_rwnd(), session_window, stream->get_local_rwnd(), stream_window);
  }

  MIOBuffer *writer = stream->read_vio_writer();
  if (writer == nullptr) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_INTERNAL_ERROR, "no writer");
  }

  // If we call write() multiple times, we must keep the same reader, so we can
  // update its offset via consume.  Otherwise, we will read the same data on the
  // second time through
  IOBufferReader *myreader = frame.reader()->clone();
  // Skip pad length field
  if (frame.header().flags & HTTP2_FLAGS_DATA_PADDED) {
    myreader->consume(HTTP2_DATA_PADLEN_LEN);
  }

  if (nbytes < unpadded_length) {
    size_t read_len = BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_DATA]);
    if (nbytes + read_len > unpadded_length) {
      read_len -= nbytes + read_len - unpadded_length;
    }
    unsigned int num_written = writer->write(myreader, read_len);
    if (num_written != read_len) {
      myreader->writer()->dealloc_reader(myreader);
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_INTERNAL_ERROR, "Write mismatch");
    }
    myreader->consume(num_written);
    stream->update_read_length(num_written);
  }
  myreader->writer()->dealloc_reader(myreader);

  if (frame.header().flags & HTTP2_FLAGS_DATA_END_STREAM) {
    stream->set_read_done();
  }

  if (frame.header().flags & HTTP2_FLAGS_DATA_END_STREAM) {
    if (stream->is_read_enabled() && this->get_peer_stream_count() > 1 && this->get_local_rwnd() == 0) {
      // This final DATA frame for this stream consumed all the bytes for the
      // session window. Send a WINDOW_UPDATE frame in order to open up the
      // session window for other streams.
      restart_receiving(nullptr);
    }
    stream->signal_final_read_event(VC_EVENT_READ_COMPLETE);
  } else if (stream->is_read_enabled()) {
    stream->signal_read_event(VC_EVENT_READ_READY);
  }

  return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
}

/*
 * [RFC 7540] 6.2 HEADERS Frame
 *
 * NOTE: HEADERS Frame and CONTINUATION Frame
 *   1. A HEADERS frame with the END_STREAM flag set can be followed by
 *      CONTINUATION frames on the same stream.
 *   2. A HEADERS frame without the END_HEADERS flag set MUST be followed by a
 *      CONTINUATION frame
 */
namespace
{
// An interim (1xx) response received on an outbound
// (origin) HTTP/2 connection is not the final response. Detect it after the
// header block is decoded so the caller can discard it and wait for the final
// response, instead of merging it with the final response headers (which would
// produce a duplicate :status pseudo-header that fails validation).
bool
is_outbound_interim_response(Http2Stream *stream)
{
  if (!stream->is_outbound_connection() || stream->trailing_header_is_possible()) {
    return false;
  }
  const MIMEField *status_field = stream->get_receive_header()->field_find(PSEUDO_HEADER_STATUS);
  if (status_field == nullptr) {
    return false;
  }
  // :status is origin-controlled and HeaderValidator only checks that it is present, so
  // bound the length before indexing. RFC 9110 15 requires exactly three digits.
  auto value{status_field->value_get()};
  return value.length() == 3 && value[0] == '1';
}

// Discard a decoded interim (1xx) response along with its encoded header block so the
// following final response is decoded into a clean buffer. Freeing header_blocks here
// avoids leaking it when the next HEADERS frame allocates a new buffer.
void
discard_interim_response(Http2Stream *stream)
{
  stream->reset_receive_headers();
  ats_free(stream->header_blocks);
  stream->header_blocks        = nullptr;
  stream->header_blocks_length = 0;
}
} // namespace

Http2Error
Http2ConnectionState::rcv_headers_frame(const Http2Frame &frame)
{
  const Http2StreamId stream_id      = frame.header().streamid;
  const uint32_t      payload_length = frame.header().length;

  Http2StreamDebug(this->session, stream_id, "Received HEADERS frame");

  if (!http2_is_client_streamid(stream_id)) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                      "recv headers bad client id");
  }

  Http2Stream *stream                      = nullptr;
  bool         new_stream                  = false;
  bool         reset_header_after_decoding = false;
  bool         free_stream_after_decoding  = false;

  if (this->is_valid_streamid(stream_id)) {
    stream = this->find_stream(stream_id);
    if (!this->session->is_outbound() && (stream == nullptr || !stream->trailing_header_is_possible())) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_STREAM_CLOSED,
                        "stream not expecting trailer header");
    } else if (stream == nullptr || stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_CLOSED) {
      if (this->session->is_outbound()) {
        reset_header_after_decoding = true;
        // return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
        // return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_STREAM_CLOSED,
        //                  "recv_header to closed stream");
      } else {
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_STREAM_CLOSED,
                          "recv_header to closed stream");
      }
    }
  }

  if (!http2_is_client_streamid(stream_id)) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                      "recv headers bad client id");
  }

  if (!stream) {
    if (reset_header_after_decoding) {
      free_stream_after_decoding                 = true;
      uint32_t const initial_local_stream_window = this->acknowledged_local_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE);
      ink_assert(dynamic_cast<Http2CommonSession *>(this->session->get_proxy_session()));
      ink_assert(this->session->is_outbound() == true);
      stream = THREAD_ALLOC_INIT(http2StreamAllocator, this_ethread(), this->session->get_proxy_session(), stream_id,
                                 this->peer_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE), initial_local_stream_window,
                                 !STREAM_IS_REGISTERED);
    } else {
      // Create new stream
      Http2Error error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
      stream     = this->create_stream(stream_id, error);
      new_stream = true;
      if (!stream) {
        // Terminate the connection with COMPRESSION_ERROR because we don't decompress the field block in this HEADERS frame.
        // TODO: try to decompress to keep HPACK Dynamic Table in sync.
        if (error.cls == Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM) {
          return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_COMPRESSION_ERROR,
                            error.msg);
        }

        return error;
      }
    }
  }

  // Record evidence on the registered stream before a decoding-only replacement.
  stream->mark_response_received();

  // HEADERS frame on a closed stream.  The HdrHeap has gone away and it will core.
  if (stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_CLOSED) {
    Http2StreamDebug(session, stream_id, "Replaced closed stream");
    free_stream_after_decoding = true;
    stream                     = THREAD_ALLOC_INIT(http2StreamAllocator, this_ethread(), session->get_proxy_session(), stream_id,
                                                   peer_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE), true, false);
    if (!stream) {
      // This happening is possibly catastrophic, the HPACK tables can be out of sync
      // Maybe this is a connection level error?
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
    }
  }

  Http2HeadersParameter params;
  uint32_t              header_block_fragment_offset = 0;
  uint32_t              header_block_fragment_length = payload_length;

  if (frame.header().flags & HTTP2_FLAGS_HEADERS_END_STREAM) {
    stream->receive_end_stream = true;
  }

  // NOTE: Strip padding if exists
  if (frame.header().flags & HTTP2_FLAGS_HEADERS_PADDED) {
    uint8_t buf[HTTP2_HEADERS_PADLEN_LEN] = {0};
    frame.reader()->memcpy(buf, HTTP2_HEADERS_PADLEN_LEN);

    if (!http2_parse_headers_parameter(make_iovec(buf, HTTP2_HEADERS_PADLEN_LEN), params)) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                        "recv headers failed to parse");
    }

    // Payload length can't be smaller than the pad length
    if ((params.pad_length + HTTP2_HEADERS_PADLEN_LEN) > header_block_fragment_length) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                        "recv headers pad > payload length");
    }

    header_block_fragment_offset += HTTP2_HEADERS_PADLEN_LEN;
    header_block_fragment_length -= (HTTP2_HEADERS_PADLEN_LEN + params.pad_length);
  }

  // NOTE: Parse priority parameters if exists
  if (frame.header().flags & HTTP2_FLAGS_HEADERS_PRIORITY) {
    uint8_t buf[HTTP2_PRIORITY_LEN] = {0};

    frame.reader()->memcpy(buf, HTTP2_PRIORITY_LEN, header_block_fragment_offset);
    if (!http2_parse_priority_parameter(make_iovec(buf, HTTP2_PRIORITY_LEN), params.priority)) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                        "recv headers priority parameters failed parse");
    }
    // Protocol error if the stream depends on itself
    if (stream_id == params.priority.stream_dependency) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_COMPRESSION_ERROR,
                        "recv headers self dependency");
    }

    // Payload length can't be smaller than the priority length
    if (HTTP2_PRIORITY_LEN > header_block_fragment_length) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                        "recv priority length > payload length");
    }

    header_block_fragment_offset += HTTP2_PRIORITY_LEN;
    header_block_fragment_length -= HTTP2_PRIORITY_LEN;
  }

  if (new_stream && Http2::stream_priority_enabled) {
    Http2DependencyTree::Node *node = this->dependency_tree->find(stream_id);
    if (node != nullptr) {
      stream->priority_node = node;
      node->t               = stream;
    } else {
      Http2StreamDebug(this->session, stream_id, "HEADER PRIORITY - dep: %d, weight: %d, excl: %d, tree size: %d",
                       params.priority.stream_dependency, params.priority.weight, params.priority.exclusive_flag,
                       this->dependency_tree->size());

      stream->priority_node = this->dependency_tree->add(params.priority.stream_dependency, stream_id, params.priority.weight,
                                                         params.priority.exclusive_flag, stream);
    }
  }

  stream->header_blocks_length = header_block_fragment_length;

  // ATS advertises SETTINGS_MAX_HEADER_LIST_SIZE as a limit of total header blocks length. (Details in [RFC 7560] 10.5.1.)
  // Make it double to relax the limit in cases of 1) HPACK is used naively, or 2) Huffman Encoding generates large header blocks.
  // The total "decoded" header length is strictly checked by hpack_decode_header_block().
  if (stream->header_blocks_length > std::max(Http2::max_header_list_size, Http2::max_header_list_size * 2)) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
                      "header blocks too large");
  }

  if (stream->trailing_header_is_possible()) {
    // Don't leak the header_blocks from the initial, non-trailing headers.
    ats_free(stream->header_blocks);
  }
  stream->header_blocks = static_cast<uint8_t *>(ats_malloc(header_block_fragment_length));
  frame.reader()->memcpy(stream->header_blocks, header_block_fragment_length, header_block_fragment_offset);

  if (frame.header().flags & HTTP2_FLAGS_HEADERS_END_HEADERS) {
    // NOTE: If there are END_HEADERS flag, decode stored Header Blocks.
    if (!stream->change_state(HTTP2_FRAME_TYPE_HEADERS, frame.header().flags)) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                        "recv headers end headers and not trailing header");
    }

    if (stream->trailing_header_is_possible()) {
      if (!(frame.header().flags & HTTP2_FLAGS_HEADERS_END_STREAM)) {
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                          "recv headers tailing header without endstream");
      }
    }

    if (stream->trailing_header_is_possible()) {
      stream->reset_receive_headers();
    } else {
      stream->mark_milestone(Http2StreamMilestone::START_DECODE_HEADERS);
    }
    Http2ErrorCode result = stream->decode_header_blocks(
      *this->local_hpack_handle, this->acknowledged_local_settings.get(HTTP2_SETTINGS_HEADER_TABLE_SIZE), _header_field_max_size);

    // If this was an outbound connection and the state was already closed, just clear the
    // headers after processing.  We just processed the header blocks to keep the dynamic table in
    // sync with peer to avoid future HPACK compression errors
    if (reset_header_after_decoding) {
      stream->reset_receive_headers();
      if (free_stream_after_decoding) {
        THREAD_FREE(stream, http2StreamAllocator, this_ethread());
      }
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
    }

    if (result != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
      if (result == Http2ErrorCode::HTTP2_ERROR_COMPRESSION_ERROR) {
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_COMPRESSION_ERROR,
                          "recv headers compression error");
      } else if (result == Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM) {
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
                          "recv headers enhance your calm");
      } else {
        if (!stream->trailing_header_is_possible() && !stream->is_outbound_connection()) {
          stream->log_non_http_sm_access(stream->get_receive_header(), "http/2");
        }
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                          "recv headers malformed request");
      }
    }

    // Check Content-Length & payload length when END_STREAM flag is true
    if (stream->receive_end_stream && !stream->payload_length_is_valid()) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                        "recv data bad payload length");
    }

    // Discard an interim (1xx) response from the
    // origin and wait for the final response on this stream.
    if (is_outbound_interim_response(stream)) {
      // RFC 9113 8.1: a HEADERS frame with END_STREAM carrying an informational (1xx)
      // status code is malformed. change_state() has already moved the stream toward
      // closed, so the final response would have nowhere to go; reject as a stream error.
      if (stream->receive_end_stream) {
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                          "1xx interim response must not set END_STREAM");
      }
      Http2StreamDebug(this->session, stream_id, "received interim 1xx response from origin; awaiting final response");
      discard_interim_response(stream);
      this->session->interrupt_reading_frames();
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
    }

    // Hard-enforce the global active-streams cap on inbound client streams.
    if (!stream->is_outbound_connection() && !stream->trailing_header_is_possible() && Http2::max_active_streams_policy_in == 1 &&
        Http2::max_active_streams_in > 0) {
      int64_t const current_streams = Metrics::Gauge::load(http2_rsb.current_client_stream_count);
      if (current_streams >= Http2::max_active_streams_in) {
        Metrics::Counter::increment(http2_rsb.max_active_streams_exceeded_in);
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_REFUSED_STREAM,
                          "active streams cap reached");
      }
    }

    // Set up the State Machine
    if (!stream->is_outbound_connection() && !stream->trailing_header_is_possible()) {
      SCOPED_MUTEX_LOCK(stream_lock, stream->mutex, this_ethread());
      stream->mark_milestone(Http2StreamMilestone::START_TXN);
      stream->cancel_active_timeout();
      stream->new_transaction(frame.is_from_early_data());
      // Send request header to SM
      stream->send_headers(*this);
    } else {
      // If this is a trailer, first signal to the SM that the body is done
      if (stream->trailing_header_is_possible()) {
        stream->set_expect_receive_trailer();
        // Propagate the  trailer header
        stream->send_headers(*this);
      } else {
        // Propagate the response
        stream->send_headers(*this);
      }
    }
    // Give a chance to send response before reading next frame.
    this->session->interrupt_reading_frames();
  } else {
    // NOTE: Expect CONTINUATION Frame. Do NOT change state of stream or decode
    // Header Blocks.
    Http2StreamDebug(this->session, stream_id, "No END_HEADERS flag, expecting CONTINUATION frame");
    this->set_continued_stream_id(stream_id);
  }

  return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
}

/*
 * [RFC 7540] 6.3 PRIORITY
 *
 */
Http2Error
Http2ConnectionState::rcv_priority_frame(const Http2Frame &frame)
{
  const Http2StreamId stream_id      = frame.header().streamid;
  const uint32_t      payload_length = frame.header().length;

  Http2StreamDebug(this->session, stream_id, "Received PRIORITY frame");

  if (this->get_zombie_event()) {
    Warning("Priority frame for zombied session %" PRId64, this->session->get_connection_id());
  }

  // If a PRIORITY frame is received with a stream identifier of 0x0, the
  // recipient MUST respond with a connection error of type PROTOCOL_ERROR.
  if (stream_id == HTTP2_CONNECTION_CONTROL_STREAM) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                      "priority 0 stream_id");
  }

  // A PRIORITY frame with a length other than 5 octets MUST be treated as
  // a stream error (Section 5.4.2) of type FRAME_SIZE_ERROR.
  if (payload_length != HTTP2_PRIORITY_LEN) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_FRAME_SIZE_ERROR,
                      "priority bad length");
  }

  uint8_t buf[HTTP2_PRIORITY_LEN] = {0};
  frame.reader()->memcpy(buf, HTTP2_PRIORITY_LEN, 0);

  Http2Priority priority;
  if (!http2_parse_priority_parameter(make_iovec(buf, HTTP2_PRIORITY_LEN), priority)) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                      "priority parse error");
  }

  //  A stream cannot depend on itself.  An endpoint MUST treat this as a stream error of type PROTOCOL_ERROR.
  if (stream_id == priority.stream_dependency) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                      "PRIORITY frame depends on itself");
  }

  if (!Http2::stream_priority_enabled) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
  }

  // Update PRIORITY frame count per minute
  this->increment_received_priority_frame_count();
  // Close this connection if its priority frame count received exceeds a limit
  if (configured_max_priority_frames_per_minute >= 0 &&
      this->get_received_priority_frame_count() > static_cast<uint32_t>(configured_max_priority_frames_per_minute)) {
    Metrics::Counter::increment(http2_rsb.max_priority_frames_per_minute_exceeded);
    Http2StreamDebug(this->session, stream_id, "Observed too frequent priority changes: %u priority changes within a last minute",
                     this->get_received_priority_frame_count());
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
                      "recv priority too frequent priority changes");
  }

  Http2StreamDebug(this->session, stream_id, "PRIORITY - dep: %d, weight: %d, excl: %d, tree size: %d", priority.stream_dependency,
                   priority.weight, priority.exclusive_flag, this->dependency_tree->size());

  Http2DependencyTree::Node *node = this->dependency_tree->find(stream_id);

  if (node != nullptr) {
    // [RFC 7540] 5.3.3 Reprioritization
    Http2StreamDebug(this->session, stream_id, "Reprioritize");
    this->dependency_tree->reprioritize(node, priority.stream_dependency, priority.exclusive_flag);
    if (dbg_ctl_http2_priority.on()) {
      std::stringstream output;
      this->dependency_tree->dump_tree(output);
      Dbg(dbg_ctl_http2_priority, "[%" PRId64 "] reprioritize %s", this->session->get_connection_id(), output.str().c_str());
    }
  } else {
    // PRIORITY frame is received before HEADERS frame.

    // Restrict number of inactive node in dependency tree smaller than max_concurrent_streams.
    // Current number of inactive node is size of tree minus active node count.
    if (this->_get_configured_max_concurrent_streams() > this->dependency_tree->size() - this->get_peer_stream_count() + 1) {
      this->dependency_tree->add(priority.stream_dependency, stream_id, priority.weight, priority.exclusive_flag, nullptr);
    }
  }

  return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
}

Http2Error
Http2ConnectionState::rcv_rst_stream_frame(const Http2Frame &frame)
{
  Http2RstStream      rst_stream;
  char                buf[HTTP2_RST_STREAM_LEN];
  char               *end;
  const Http2StreamId stream_id = frame.header().streamid;

  Http2StreamDebug(this->session, frame.header().streamid, "Received RST_STREAM frame");

  // RST_STREAM frames MUST be associated with a stream.  If a RST_STREAM
  // frame is received with a stream identifier of 0x0, the recipient MUST
  // treat this as a connection error (Section 5.4.1) of type
  // PROTOCOL_ERROR.
  if (stream_id == HTTP2_CONNECTION_CONTROL_STREAM) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                      "reset access stream with invalid id");
  }

  // A RST_STREAM frame with a length other than 4 octets MUST be treated
  // as a connection error (Section 5.4.1) of type FRAME_SIZE_ERROR.
  if (frame.header().length != HTTP2_RST_STREAM_LEN) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FRAME_SIZE_ERROR,
                      "reset frame wrong length");
  }

  Http2Stream *stream = this->find_stream(stream_id);
  if (stream == nullptr) {
    if (this->is_valid_streamid(stream_id)) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
    } else {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                        "reset frame bad id stream not found");
    }
  }

  // Update RST_STREAM frame count per minute
  this->increment_received_rst_stream_frame_count();
  // Close this connection if its RST_STREAM frame count exceeds a limit
  if (configured_max_rst_stream_frames_per_minute >= 0 &&
      this->get_received_rst_stream_frame_count() > static_cast<uint32_t>(configured_max_rst_stream_frames_per_minute)) {
    Metrics::Counter::increment(http2_rsb.max_rst_stream_frames_per_minute_exceeded);
    Http2StreamDebug(this->session, stream_id, "Observed too frequent RST_STREAM frames: %u frames within a last minute",
                     this->get_received_rst_stream_frame_count());
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
                      "reset too frequent RST_STREAM frames");
  }

  if (stream == nullptr || !stream->change_state(frame.header().type, frame.header().flags)) {
    // If a RST_STREAM frame identifying an idle stream is received, the
    // recipient MUST treat this as a connection error of type PROTOCOL_ERROR.
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                      "reset missing stream or bad stream state");
  }

  end = frame.reader()->memcpy(buf, sizeof(buf), 0);

  if (!http2_parse_rst_stream(make_iovec(buf, end - buf), rst_stream)) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                      "reset failed to parse");
  }

  if (stream != nullptr) {
    Http2StreamDebug(this->session, stream_id, "Parsed RST_STREAM frame: Error Code: %u", rst_stream.error_code);
    ATS_PROBE3(http2_rst_stream_rcvd, this->session->get_connection_id(), stream_id, rst_stream.error_code);
    stream->set_rx_error_code({ProxyErrorClass::TXN, static_cast<uint32_t>(rst_stream.error_code)});
    // Per RFC 9113 8.7: REFUSED_STREAM is the one stream-level error code with
    // an explicit guarantee that the request was not processed by the peer,
    // and so the request is safe to retry on a fresh connection -- including
    // for non-idempotent methods. Tag the stream so HttpSM converts the
    // resulting EOS into a connection-level retry rather than surfacing it as
    // ERR_CLIENT_ABORT to the client.
    if (this->session->is_outbound() &&
        static_cast<Http2ErrorCode>(rst_stream.error_code) == Http2ErrorCode::HTTP2_ERROR_REFUSED_STREAM) {
      Http2StreamDebug(this->session, stream_id, "Origin not-processed assertion: REFUSED_STREAM");
      stream->set_safe_to_retry();
    }
    stream->initiating_close();
  }

  return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
}

Http2Error
Http2ConnectionState::rcv_settings_frame(const Http2Frame &frame)
{
  Http2SettingsParameter param;
  char                   buf[HTTP2_SETTINGS_PARAMETER_LEN];
  unsigned               nbytes    = 0;
  const Http2StreamId    stream_id = frame.header().streamid;

  Http2StreamDebug(this->session, stream_id, "Received SETTINGS frame");

  if (this->get_zombie_event()) {
    Warning("Setting frame for zombied session %" PRId64, this->session->get_connection_id());
  }

  // [RFC 7540] 6.5. The stream identifier for a SETTINGS frame MUST be zero.
  // If an endpoint receives a SETTINGS frame whose stream identifier field is
  // anything other than 0x0, the endpoint MUST respond with a connection
  // error (Section 5.4.1) of type PROTOCOL_ERROR.
  if (stream_id != 0) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                      "recv settings stream not 0");
  }

  // [RFC 7540] 6.5. Receipt of a SETTINGS frame with the ACK flag set and a
  // length field value other than 0 MUST be treated as a connection
  // error of type FRAME_SIZE_ERROR.
  //
  // Exempt solicited ACKs in both directions. Dynamic flow control (policy=2)
  // can elicit many legitimate ACKs from clients as well as origins. _process_incoming_settings_ack_frame()
  // rejects unsolicited ACKs when the outstanding SETTINGS queue is empty,
  // so this exemption remains bounded by our own SETTINGS send rate.
  bool const is_ack = frame.header().flags & HTTP2_FLAGS_SETTINGS_ACK;
  if (!is_ack) {
    this->increment_received_settings_frame_count();
    if (configured_max_settings_frames_per_minute >= 0 &&
        this->get_received_settings_frame_count() > static_cast<uint32_t>(configured_max_settings_frames_per_minute)) {
      Metrics::Counter::increment(http2_rsb.max_settings_frames_per_minute_exceeded);
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
                        "recv settings too frequent SETTINGS frames");
    }
  }
  if (is_ack) {
    if (frame.header().length != 0) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FRAME_SIZE_ERROR,
                        "recv settings ACK header length not 0");
    }
    return this->_process_incoming_settings_ack_frame();
  }

  // A SETTINGS frame with a length other than a multiple of 6 octets MUST
  // be treated as a connection error (Section 5.4.1) of type
  // FRAME_SIZE_ERROR.
  if (frame.header().length % 6 != 0) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FRAME_SIZE_ERROR,
                      "recv settings header wrong length");
  }

  uint32_t n_settings = 0;
  while (nbytes < frame.header().length) {
    if (Http2::max_settings_per_frame >= 0 && n_settings >= static_cast<uint32_t>(Http2::max_settings_per_frame)) {
      Metrics::Counter::increment(http2_rsb.max_settings_per_frame_exceeded);
      Http2StreamDebug(this->session, stream_id, "Observed too many settings in a frame");
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
                        "recv settings too many settings in a frame");
    }

    unsigned read_bytes = read_rcv_buffer(buf, sizeof(buf), nbytes, frame);

    if (!http2_parse_settings_parameter(make_iovec(buf, read_bytes), param)) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                        "recv settings parse failed");
    }

    if (!http2_settings_parameter_is_valid(param)) {
      if (param.id == HTTP2_SETTINGS_INITIAL_WINDOW_SIZE) {
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FLOW_CONTROL_ERROR,
                          "recv settings bad initial window size");
      } else {
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                          "recv settings bad param");
      }
    }

    Http2StreamDebug(this->session, stream_id, "   %s : %u", Http2DebugNames::get_settings_param_name(param.id), param.value);

    // [RFC 7540] 6.9.2. When the value of SETTINGS_INITIAL_WINDOW_SIZE
    // changes, a receiver MUST adjust the size of all stream flow control
    // windows that it maintains by the difference between the new value and
    // the old value.
    if (param.id == HTTP2_SETTINGS_INITIAL_WINDOW_SIZE) {
      this->update_initial_peer_rwnd(param.value);
    }

    this->peer_settings.set(static_cast<Http2SettingsIdentifier>(param.id), param.value);
    ++n_settings;
  }

  // Update settings count per minute
  this->increment_received_settings_count(n_settings);
  // Close this connection if its settings count received exceeds a limit
  if (Http2::max_settings_per_minute >= 0 &&
      this->get_received_settings_count() > static_cast<uint32_t>(Http2::max_settings_per_minute)) {
    Metrics::Counter::increment(http2_rsb.max_settings_per_minute_exceeded);
    Http2StreamDebug(this->session, stream_id, "Observed too frequent setting changes: %u settings within a last minute",
                     this->get_received_settings_count());
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
                      "recv settings too frequent setting changes");
  }

  // [RFC 7540] 6.5. Once all values have been applied, the recipient MUST
  // immediately emit a SETTINGS frame with the ACK flag set.
  Http2SettingsFrame ack_frame(HTTP2_CONNECTION_CONTROL_STREAM, HTTP2_FLAGS_SETTINGS_ACK);
  Http2StreamDebug(this->session, stream_id, "Send SETTINGS ACK");
  this->session->xmit(ack_frame);
  return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
}

Http2Error
Http2ConnectionState::rcv_push_promise_frame(const Http2Frame &frame)
{
  Http2StreamDebug(this->session, frame.header().streamid, "Received PUSH_PROMISE frame");

  // [RFC 7540] 8.2. A client cannot push. Thus, servers MUST treat the receipt of a
  // PUSH_PROMISE frame as a connection error of type PROTOCOL_ERROR.
  return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                    "promise not allowed");
}

Http2Error
Http2ConnectionState::rcv_ping_frame(const Http2Frame &frame)
{
  uint8_t             opaque_data[HTTP2_PING_LEN];
  const Http2StreamId stream_id = frame.header().streamid;

  Http2StreamDebug(this->session, stream_id, "Received PING frame");

  this->schedule_zombie_event();

  //  If a PING frame is received with a stream identifier field value other
  //  than 0x0, the recipient MUST respond with a connection error of type
  //  PROTOCOL_ERROR.
  if (stream_id != 0x0) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR, "ping id not 0");
  }

  // Receipt of a PING frame with a length field value other than 8 MUST
  // be treated as a connection error (Section 5.4.1) of type FRAME_SIZE_ERROR.
  if (frame.header().length != HTTP2_PING_LEN) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FRAME_SIZE_ERROR,
                      "ping bad length");
  }

  // Update PING frame count per minute
  this->increment_received_ping_frame_count();
  // Close this connection if its ping count received exceeds a limit
  if (configured_max_ping_frames_per_minute >= 0 &&
      this->get_received_ping_frame_count() > static_cast<uint32_t>(configured_max_ping_frames_per_minute)) {
    Metrics::Counter::increment(http2_rsb.max_ping_frames_per_minute_exceeded);
    Http2StreamDebug(this->session, stream_id, "Observed too frequent PING frames: %u PING frames within a last minute",
                     this->get_received_ping_frame_count());
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
                      "recv ping too frequent PING frame");
  }

  // An endpoint MUST NOT respond to PING frames containing this flag.
  if (frame.header().flags & HTTP2_FLAGS_PING_ACK) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
  }

  frame.reader()->memcpy(opaque_data, HTTP2_PING_LEN, 0);

  // ACK (0x1): An endpoint MUST set this flag in PING responses.
  this->send_ping_frame(stream_id, HTTP2_FLAGS_PING_ACK, opaque_data);

  return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
}

Http2Error
Http2ConnectionState::rcv_goaway_frame(const Http2Frame &frame)
{
  Http2Goaway         goaway;
  char                buf[HTTP2_GOAWAY_LEN];
  char               *end;
  const Http2StreamId stream_id = frame.header().streamid;

  Http2StreamDebug(this->session, stream_id, "Received GOAWAY frame");

  // An endpoint MUST treat a GOAWAY frame with a stream identifier other
  // than 0x0 as a connection error of type PROTOCOL_ERROR.
  if (stream_id != 0x0) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                      "goaway id non-zero");
  }

  end = frame.reader()->memcpy(buf, sizeof(buf), 0);

  if (!http2_parse_goaway(make_iovec(buf, end - buf), goaway)) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                      "goaway failed parse");
  }

  Http2StreamDebug(this->session, stream_id, "GOAWAY: last stream id=%d, error code=%d", goaway.last_streamid,
                   static_cast<int>(goaway.error_code));

  this->rx_error_code = {ProxyErrorClass::SSN, static_cast<uint32_t>(goaway.error_code)};

  // Per RFC 9113 6.8: streams whose id is greater than `last_streamid` were
  // not (and will not be) processed by the peer, and the requests they carry
  // may be safely retried on a fresh connection. On an outbound H/2 session
  // the streams in question are the ones we initiated toward the origin
  // using odd-numbered client stream IDs. Tagging them before closing them
  // lets HttpSM decide to retry non-idempotent requests (e.g. POST) that
  // would otherwise surface to the client as ERR_CLIENT_ABORT. This is
  // especially important for AWS-style origin load balancers that
  // aggressively send GOAWAY(last_stream_id=0, NO_ERROR) when draining a
  // connection.
  //
  // After a NO_ERROR GOAWAY the origin may still complete the streams at or
  // below `last_streamid`, so those are left to finish. Half-closing the
  // session takes it out of the pool and stops new streams, and
  // release_stream() schedules the session close once every stream is gone.
  // An error GOAWAY means the origin is tearing the connection down, so the
  // session closes right away, as it does when no stream is left to finish.
  if (this->session->is_outbound()) {
    bool const   drain     = goaway.error_code == Http2ErrorCode::HTTP2_ERROR_NO_ERROR;
    uint32_t     survivors = 0;
    Http2Stream *s         = stream_list.head;

    // initiating_close() can unlink the stream, so advance before closing it.
    while (s != nullptr) {
      Http2Stream *next = static_cast<Http2Stream *>(s->link.next);
      if (http2_is_client_streamid(s->get_id()) && s->get_id() > goaway.last_streamid) {
        Http2StreamDebug(this->session, s->get_id(), "Origin not-processed assertion: GOAWAY last_stream_id=%u",
                         goaway.last_streamid);
        s->set_safe_to_retry();
        if (drain) {
          s->initiating_close();
        }
      } else if (!s->is_closed()) {
        ++survivors;
      }
      s = next;
    }

    if (drain && survivors > 0) {
      Http2ConDebug(session, "Draining %u streams after GOAWAY last_stream_id=%u", survivors, goaway.last_streamid);
      this->_peer_goaway_drain = true;
      this->session->set_half_close_local_flag(true);
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
    }
  }

  this->session->get_proxy_session()->do_io_close();

  return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
}

Http2Error
Http2ConnectionState::rcv_window_update_frame(const Http2Frame &frame)
{
  char                buf[HTTP2_WINDOW_UPDATE_LEN];
  uint32_t            size;
  const Http2StreamId stream_id = frame.header().streamid;

  //  A WINDOW_UPDATE frame with a length other than 4 octets MUST be
  //  treated as a connection error of type FRAME_SIZE_ERROR.
  if (frame.header().length != HTTP2_WINDOW_UPDATE_LEN) {
    Http2StreamDebug(this->session, stream_id, "Received WINDOW_UPDATE frame - length incorrect");
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FRAME_SIZE_ERROR,
                      "window update bad length");
  }

  frame.reader()->memcpy(buf, sizeof(buf), 0);
  http2_parse_window_update(make_iovec(buf, sizeof(buf)), size);

  // A receiver MUST treat the receipt of a WINDOW_UPDATE frame with a flow
  // control window increment of 0 as a connection error of type PROTOCOL_ERROR;
  if (size == 0) {
    if (stream_id == HTTP2_CONNECTION_CONTROL_STREAM) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                        "window update length=0 and id=0");
    } else {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                        "window update length=0");
    }
  }

  if (stream_id == HTTP2_CONNECTION_CONTROL_STREAM) {
    // Connection level window update
    Http2StreamDebug(this->session, stream_id, "Received WINDOW_UPDATE frame - updated to: %zd delta: %u",
                     (this->get_peer_rwnd() + size), size);

    // A sender MUST NOT allow a flow-control window to exceed 2^31-1
    // octets.  If a sender receives a WINDOW_UPDATE that causes a flow-
    // control window to exceed this maximum, it MUST terminate either the
    // stream or the connection, as appropriate.  For streams, the sender
    // sends a RST_STREAM with an error code of FLOW_CONTROL_ERROR; for the
    // connection, a GOAWAY frame with an error code of FLOW_CONTROL_ERROR
    // is sent.
    if (size > HTTP2_MAX_WINDOW_SIZE - this->get_peer_rwnd()) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FLOW_CONTROL_ERROR,
                        "window update too big");
    }

    auto error = this->increment_peer_rwnd(size);
    if (error != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, error, "Erroneous client window update");
    }
    ATS_PROBE4(http2_window_update_rcvd, this->session->get_connection_id(), HTTP2_CONNECTION_CONTROL_STREAM, size,
               this->get_peer_rwnd());
    this->restart_streams();
  } else {
    // Stream level window update
    Http2Stream *stream = this->find_stream(stream_id);

    if (stream == nullptr) {
      if (this->is_valid_streamid(stream_id)) {
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
      } else {
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                          "window update stream invalid id");
      }
    }

    Http2StreamDebug(this->session, stream_id, "Received WINDOW_UPDATE frame - updated to: %zd delta: %u",
                     (stream->get_peer_rwnd() + size), size);

    // A sender MUST NOT allow a flow-control window to exceed 2^31-1
    // octets.  If a sender receives a WINDOW_UPDATE that causes a flow-
    // control window to exceed this maximum, it MUST terminate either the
    // stream or the connection, as appropriate.  For streams, the sender
    // sends a RST_STREAM with an error code of FLOW_CONTROL_ERROR; for the
    // connection, a GOAWAY frame with an error code of FLOW_CONTROL_ERROR
    // is sent.
    if (size > HTTP2_MAX_WINDOW_SIZE - stream->get_peer_rwnd()) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_FLOW_CONTROL_ERROR,
                        "window update too big 2");
    }

    auto error = stream->increment_peer_rwnd(size);
    if (error != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, error, "Bad stream rwnd");
    }
    ATS_PROBE4(http2_window_update_rcvd, this->session->get_connection_id(), stream_id, size, stream->get_peer_rwnd());

    ssize_t wnd = std::min(this->get_peer_rwnd(), stream->get_peer_rwnd());
    if (wnd > 0) {
      SCOPED_MUTEX_LOCK(lock, stream->mutex, this_ethread());
      stream->restart_sending();
    }
  }

  return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
}

/*
 * [RFC 7540] 6.10 CONTINUATION
 *
 * NOTE: Logically, the CONTINUATION frames are part of the HEADERS frame. ([RFC
 *7540] 6.2 HEADERS)
 *
 */
Http2Error
Http2ConnectionState::rcv_continuation_frame(const Http2Frame &frame)
{
  const Http2StreamId stream_id      = frame.header().streamid;
  const uint32_t      payload_length = frame.header().length;

  Http2StreamDebug(this->session, stream_id, "Received CONTINUATION frame");

  if (!http2_is_client_streamid(stream_id)) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                      "continuation bad client id");
  }

  if (payload_length == 0 && (frame.header().flags & HTTP2_FLAGS_HEADERS_END_HEADERS) == 0x0) {
    this->increment_received_empty_frame_count();
    if (configured_max_empty_frames_per_minute >= 0 &&
        this->get_received_empty_frame_count() > static_cast<uint32_t>(configured_max_empty_frames_per_minute)) {
      Metrics::Counter::increment(http2_rsb.max_empty_frames_per_minute_exceeded);
      Http2StreamDebug(this->session, stream_id, "Observed too many empty CONTINUATION frames: %u within the last minute",
                       this->get_received_empty_frame_count());
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
                        "recv continuation too frequent empty frame");
    }
  }

  if (this->get_continued_stream_id() != stream_id) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                      "unsolicited CONTINUATION frame");
  }

  // Find the stream for the outstanding header block (RFC 9113 section 6.10).
  // The client-stream-id check above already rejects stream zero.
  Http2Stream *stream = this->find_stream(stream_id);
  if (stream == nullptr) {
    if (this->is_valid_streamid(stream_id)) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_STREAM_CLOSED,
                        "continuation stream freed with valid id");
    } else {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                        "continuation stream freed with invalid id");
    }
  } else {
    bool const is_outbound = this->session->is_outbound();
    switch (stream->get_state()) {
    case Http2StreamState::HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE:
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_STREAM_CLOSED,
                        "continuation half close remote");
    case Http2StreamState::HTTP2_STREAM_STATE_IDLE:
      break;
    case Http2StreamState::HTTP2_STREAM_STATE_OPEN:
    case Http2StreamState::HTTP2_STREAM_STATE_HALF_CLOSED_LOCAL:
      // On outbound (origin-side) connections, response HEADERS may be split
      // across CONTINUATION frames. The associated stream is OPEN if our
      // request body is still in flight, or HALF_CLOSED_LOCAL once we have
      // sent the request with END_STREAM (e.g. for GET or HEAD). [RFC 9113]
      // 6.10 only forbids interleaving CONTINUATION with frames of other
      // types or other streams, not these stream states.
      if (!is_outbound) {
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                          "continuation bad state");
      }
      break;
    default:
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                        "continuation bad state");
    }
  }

  // Update CONTINUATION frame count per minute.
  this->increment_received_continuation_frame_count();
  // Close this connection if its CONTINUATION frame count exceeds a limit.
  if (configured_max_continuation_frames_per_minute != 0 &&
      this->get_received_continuation_frame_count() > static_cast<uint32_t>(configured_max_continuation_frames_per_minute)) {
    Metrics::Counter::increment(http2_rsb.max_continuation_frames_per_minute_exceeded);
    Http2StreamDebug(this->session, stream_id, "Observed too frequent CONTINUATION frames: %u frames within a last minute",
                     this->get_received_continuation_frame_count());
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
                      "reset too frequent CONTINUATION frames");
  }

  uint32_t header_blocks_offset = stream->header_blocks_length;
  if (http2_continuation_length_would_overflow(stream->header_blocks_length, payload_length)) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
                      "header blocks length overflow");
  }
  stream->header_blocks_length += payload_length;

  // ATS advertises SETTINGS_MAX_HEADER_LIST_SIZE as a limit of total header blocks length. (Details in [RFC 7560] 10.5.1.)
  // Make it double to relax the limit in cases of 1) HPACK is used naively, or 2) Huffman Encoding generates large header blocks.
  // The total "decoded" header length is strictly checked by hpack_decode_header_block().
  if (stream->header_blocks_length > std::max(Http2::max_header_list_size, Http2::max_header_list_size * 2)) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
                      "header blocks too large");
  }

  if (payload_length > 0) {
    stream->header_blocks = static_cast<uint8_t *>(ats_realloc(stream->header_blocks, stream->header_blocks_length));
    frame.reader()->memcpy(stream->header_blocks + header_blocks_offset, payload_length);
  }

  if (frame.header().flags & HTTP2_FLAGS_HEADERS_END_HEADERS) {
    // NOTE: If there are END_HEADERS flag, decode stored Header Blocks.
    this->clear_continued_stream_id();

    if (!stream->change_state(HTTP2_FRAME_TYPE_CONTINUATION, frame.header().flags)) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                        "continuation no state change");
    }

    if (stream->trailing_header_is_possible()) {
      if (!stream->receive_end_stream) {
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                          "continuation trailing header without endstream");
      }
      stream->reset_receive_headers();
    }
    Http2ErrorCode result = stream->decode_header_blocks(
      *this->local_hpack_handle, this->acknowledged_local_settings.get(HTTP2_SETTINGS_HEADER_TABLE_SIZE), _header_field_max_size);

    if (result != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
      if (result == Http2ErrorCode::HTTP2_ERROR_COMPRESSION_ERROR) {
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_COMPRESSION_ERROR,
                          "continuation compression error");
      } else if (result == Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM) {
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
                          "continuation enhance your calm");
      } else {
        if (!stream->trailing_header_is_possible() && !stream->is_outbound_connection()) {
          stream->log_non_http_sm_access(stream->get_receive_header(), "http/2");
        }
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                          "continuation malformed request");
      }
    }

    // Check Content-Length & payload length when END_STREAM flag is true
    if (stream->receive_end_stream && !stream->payload_length_is_valid()) {
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                        "recv data bad payload length");
    }

    // Discard an interim (1xx) response from the
    // origin and wait for the final response on this stream.
    if (is_outbound_interim_response(stream)) {
      // RFC 9113 8.1: a HEADERS frame with END_STREAM carrying an informational (1xx)
      // status code is malformed. change_state() has already moved the stream toward
      // closed, so the final response would have nowhere to go; reject as a stream error.
      if (stream->receive_end_stream) {
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                          "1xx interim response must not set END_STREAM");
      }
      Http2StreamDebug(this->session, stream_id, "received interim 1xx response from origin; awaiting final response");
      discard_interim_response(stream);
      this->session->interrupt_reading_frames();
      return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
    }

    // Hard-enforce the global active-streams cap on inbound client streams.
    if (!stream->is_outbound_connection() && !stream->trailing_header_is_possible() && Http2::max_active_streams_policy_in == 1 &&
        Http2::max_active_streams_in > 0) {
      int64_t const current_streams = Metrics::Gauge::load(http2_rsb.current_client_stream_count);
      if (current_streams >= Http2::max_active_streams_in) {
        Metrics::Counter::increment(http2_rsb.max_active_streams_exceeded_in);
        return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_REFUSED_STREAM,
                          "active streams cap reached");
      }
    }

    // Match the HEADERS path: cancel the initial header timeout before
    // creating an inbound transaction. Inbound OPEN streams are rejected
    // above, so the trailer branch below currently serves outbound streams.
    // Set up the State Machine
    if (!stream->is_outbound_connection() && !stream->trailing_header_is_possible()) {
      SCOPED_MUTEX_LOCK(stream_lock, stream->mutex, this_ethread());
      stream->mark_milestone(Http2StreamMilestone::START_TXN);
      stream->cancel_active_timeout();
      stream->new_transaction(frame.is_from_early_data());
      // Send request header to SM
      stream->send_headers(*this);
    } else {
      // If this is a trailer, first signal to the SM that the body is done
      if (stream->trailing_header_is_possible()) {
        stream->set_expect_receive_trailer();
        // Propagate the trailer header
        stream->send_headers(*this);
      } else {
        // Propagate the response
        stream->send_headers(*this);
      }
    }
    // Give a chance to send response before reading next frame.
    this->session->interrupt_reading_frames();
  } else {
    // NOTE: Expect another CONTINUATION Frame. Do nothing.
    Http2StreamDebug(this->session, stream_id, "No END_HEADERS flag, expecting CONTINUATION frame");
  }

  return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
}

////////
// Configuration Getters.
//
uint32_t
Http2ConnectionState::_get_configured_max_concurrent_streams() const
{
  ink_assert(this->session != nullptr);
  if (this->session->is_outbound()) {
    return Http2::max_concurrent_streams_out;
  } else {
    return Http2::max_concurrent_streams_in;
  }
}

uint32_t
Http2ConnectionState::_get_configured_min_concurrent_streams() const
{
  ink_assert(this->session != nullptr);
  if (this->session->is_outbound()) {
    return Http2::min_concurrent_streams_out;
  } else {
    return Http2::min_concurrent_streams_in;
  }
}

uint32_t
Http2ConnectionState::_get_configured_max_active_streams() const
{
  ink_assert(this->session != nullptr);
  if (this->session->is_outbound()) {
    return Http2::max_active_streams_out;
  } else {
    return Http2::max_active_streams_in;
  }
}

uint32_t
Http2ConnectionState::_get_configured_initial_window_size() const
{
  ink_assert(this->session != nullptr);
  if (this->session->is_outbound()) {
    return Http2::initial_window_size_out;
  } else {
    uint32_t initial_window_size_in = Http2::initial_window_size_in;
    if (this->session) {
      if (auto snis = session->get_netvc()->get_service<TLSSNISupport>();
          snis && snis->hints_from_sni.http2_initial_window_size_in.has_value()) {
        initial_window_size_in = snis->hints_from_sni.http2_initial_window_size_in.value();
      }
    }

    return initial_window_size_in;
  }
}

Http2FlowControlPolicy
Http2ConnectionState::_get_configured_flow_control_policy() const
{
  return _flow_control_policy;
}

////////
// Http2ConnectionSettings
//
Http2ConnectionSettings::Http2ConnectionSettings()
{
  // 6.5.2.  Defined SETTINGS Parameters. These should generally not be
  // modified,
  // only if the protocol changes should these change.
  settings[indexof(HTTP2_SETTINGS_ENABLE_PUSH)]            = HTTP2_ENABLE_PUSH;
  settings[indexof(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS)] = HTTP2_MAX_CONCURRENT_STREAMS;
  settings[indexof(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE)]    = HTTP2_INITIAL_WINDOW_SIZE;
  settings[indexof(HTTP2_SETTINGS_MAX_FRAME_SIZE)]         = HTTP2_MAX_FRAME_SIZE;
  settings[indexof(HTTP2_SETTINGS_HEADER_TABLE_SIZE)]      = HTTP2_HEADER_TABLE_SIZE;
  settings[indexof(HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE)]   = HTTP2_MAX_HEADER_LIST_SIZE;
}

void
Http2ConnectionSettings::settings_from_configs(bool is_outbound)
{
  if (is_outbound) {
    settings[indexof(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS)] = Http2::max_concurrent_streams_out;
    settings[indexof(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE)]    = Http2::initial_window_size_out;
  } else {
    settings[indexof(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS)] = Http2::max_concurrent_streams_in;
    settings[indexof(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE)]    = Http2::initial_window_size_in;
  }
  settings[indexof(HTTP2_SETTINGS_MAX_FRAME_SIZE)]       = Http2::max_frame_size;
  settings[indexof(HTTP2_SETTINGS_HEADER_TABLE_SIZE)]    = Http2::header_table_size;
  settings[indexof(HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE)] = Http2::max_header_list_size;
}

unsigned
Http2ConnectionSettings::get(Http2SettingsIdentifier id) const
{
  if (0 < id && id < HTTP2_SETTINGS_MAX) {
    return this->settings[indexof(id)];
  } else {
    ink_assert(!"Bad Settings Identifier");
  }

  return 0;
}

unsigned
Http2ConnectionSettings::set(Http2SettingsIdentifier id, unsigned value)
{
  if (0 < id && id < HTTP2_SETTINGS_MAX) {
    return this->settings[indexof(id)] = value;
  } else {
    // Do nothing - 6.5.2 Unsupported parameters MUST be ignored
  }

  return 0;
}

unsigned
Http2ConnectionSettings::indexof(Http2SettingsIdentifier id)
{
  ink_assert(0 < id && id < HTTP2_SETTINGS_MAX);

  return id - 1;
}

////////
// Http2ConnectionState
//
Http2ConnectionState::Http2ConnectionState() : stream_list()
{
  SET_HANDLER(&Http2ConnectionState::main_event_handler);
}

void
Http2ConnectionState::init(Http2CommonSession *ssn)
{
  session = ssn;
  _flow_control_policy =
    (session->is_outbound() ? Http2::flow_control_policy_out : Http2::flow_control_policy_in).load(std::memory_order_relaxed);
  uint32_t const configured_session_window = this->_get_configured_receive_session_window_size();

  if (configured_session_window < HTTP2_INITIAL_WINDOW_SIZE) {
    // There is no HTTP/2 specified way to shrink the connection window size
    // other than to receive data and not send WINDOW_UPDATE frames for a
    // while.
    this->_local_rwnd              = HTTP2_INITIAL_WINDOW_SIZE;
    this->_local_rwnd_is_shrinking = true;
  } else {
    this->_local_rwnd              = configured_session_window;
    this->_local_rwnd_is_shrinking = false;
  }
  Http2ConDebug(session, "initial _local_rwnd: %zd", this->_local_rwnd);

  local_hpack_handle = new HpackHandle(HTTP2_HEADER_TABLE_SIZE);
  peer_hpack_handle  = new HpackHandle(HTTP2_HEADER_TABLE_SIZE);
  if (Http2::stream_priority_enabled) {
    dependency_tree = new DependencyTree(this->_get_configured_max_concurrent_streams());
  }

  // Generally speaking, before enforcing h2 settings we wait upon the client to
  // acknowledge the settings via a SETTINGS ACK. This is important for things
  // like correctly handling windows. However, the RFC default values for
  // MAX_CONCURRENT_STREAMS and MAX_HEADER_SIZE are infinite, which is not
  // practical and a client can run ATS out of resources by simply opening up
  // more streams than is reasonable. We enforce our configured defaults before
  // the client ACKs our SETTINGS by setting the configured defaults in the
  // acknowledged settings.
  Http2ConnectionSettings configured_settings;
  configured_settings.settings_from_configs(session->is_outbound());
  acknowledged_local_settings.set(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
                                  configured_settings.get(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS));
  acknowledged_local_settings.set(HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
                                  configured_settings.get(HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE));

  configured_max_settings_frames_per_minute     = Http2::max_settings_frames_per_minute;
  configured_max_ping_frames_per_minute         = Http2::max_ping_frames_per_minute;
  configured_max_priority_frames_per_minute     = Http2::max_priority_frames_per_minute;
  configured_max_rst_stream_frames_per_minute   = Http2::max_rst_stream_frames_per_minute;
  configured_max_continuation_frames_per_minute = Http2::max_continuation_frames_per_minute;
  configured_max_empty_frames_per_minute        = Http2::max_empty_frames_per_minute;

  HttpConfigParams *http_config = HttpConfig::acquire();
  if (http_config) {
    _header_field_max_size = http_config->http_hdr_field_max_size;
    HttpConfig::release(http_config);
  }

  if (auto snis = session->get_netvc()->get_service<TLSSNISupport>(); snis) {
    if (snis->hints_from_sni.http2_max_settings_frames_per_minute.has_value()) {
      configured_max_settings_frames_per_minute = snis->hints_from_sni.http2_max_settings_frames_per_minute.value();
    }
    if (snis->hints_from_sni.http2_max_ping_frames_per_minute.has_value()) {
      configured_max_ping_frames_per_minute = snis->hints_from_sni.http2_max_ping_frames_per_minute.value();
    }
    if (snis->hints_from_sni.http2_max_priority_frames_per_minute.has_value()) {
      configured_max_priority_frames_per_minute = snis->hints_from_sni.http2_max_priority_frames_per_minute.value();
    }
    if (snis->hints_from_sni.http2_max_rst_stream_frames_per_minute.has_value()) {
      configured_max_rst_stream_frames_per_minute = snis->hints_from_sni.http2_max_rst_stream_frames_per_minute.value();
    }
    if (snis->hints_from_sni.http2_max_continuation_frames_per_minute.has_value()) {
      configured_max_continuation_frames_per_minute = snis->hints_from_sni.http2_max_continuation_frames_per_minute.value();
    }
  }

  _cop = ActivityCop<Http2Stream>(this->mutex, &stream_list, 1);
  _cop.start();
}

/**
   Send connection preface

   The client connection preface is HTTP2_CONNECTION_PREFACE.
   The server connection preface consists of a potentially empty SETTINGS frame.

   Details in [RFC 7540] 3.5. HTTP/2 Connection Preface

   TODO: send client connection preface if the connection is outbound
 */
void
Http2ConnectionState::send_connection_preface()
{
  REMEMBER(NO_EVENT, this->recursion)

  Http2ConnectionSettings configured_settings;
  configured_settings.settings_from_configs(session->is_outbound());

  // We do not have PUSH_PROMISE implemented, so we communicate to the peer
  // that they should not send such frames to us. RFC 9113 6.5.2 says that
  // servers can send this too, but they  must always set a value of 0. Thus we
  // send a value of 0 for both inbound and outbound connections.
  configured_settings.set(HTTP2_SETTINGS_ENABLE_PUSH, 0);

  configured_settings.set(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, _adjust_concurrent_stream());

  // SETTINGS_INITIAL_WINDOW_SIZE controls each stream, not the connection.
  // Large-session policies must not give every stream the entire session window.
  uint32_t const configured_stream_window  = this->_get_configured_initial_window_size();
  uint32_t const configured_session_window = this->_get_configured_receive_session_window_size();
  configured_settings.set(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE, configured_stream_window);

  Http2Error error = send_settings_frame(configured_settings, SEND_EMPTY);
  if (error.cls != Http2ErrorClass::HTTP2_ERROR_CLASS_NONE) {
    this->_close_connection(error.code);
    return;
  }

  // If the session window size is non-default, send a WINDOW_UPDATE right
  // away. Note that there is no session window size setting in HTTP/2. The
  // session window size is controlled entirely by WINDOW_UPDATE frames.
  if (configured_session_window > HTTP2_INITIAL_WINDOW_SIZE) {
    auto const diff = configured_session_window - HTTP2_INITIAL_WINDOW_SIZE;
    Http2ConDebug(session, "Updating the session window with a WINDOW_UPDATE frame: %u", diff);
    send_window_update_frame(HTTP2_CONNECTION_CONTROL_STREAM, diff);
  }
}

void
Http2ConnectionState::destroy()
{
  if (in_destroy) {
    schedule_zombie_event();
    return;
  }
  in_destroy = true;

  _cop.stop();

  if (shutdown_cont_event) {
    shutdown_cont_event->cancel();
    shutdown_cont_event = nullptr;
  }
  cleanup_streams();

  delete local_hpack_handle;
  local_hpack_handle = nullptr;
  delete peer_hpack_handle;
  peer_hpack_handle = nullptr;
  delete dependency_tree;
  dependency_tree = nullptr;
  this->session   = nullptr;

  if (fini_event) {
    fini_event->cancel();
  }
  if (zombie_event) {
    zombie_event->cancel();
  }

  if (_priority_event) {
    _priority_event->cancel();
  }

  if (_data_event) {
    _data_event->cancel();
  }

  if (retransmit_event) {
    retransmit_event->cancel();
  }
  // release the mutex after the events are cancelled and sessions are destroyed.
  mutex = nullptr; // magic happens - assigning to nullptr frees the ProxyMutex
}

void
Http2ConnectionState::rcv_frame(const Http2Frame *frame)
{
  REMEMBER(NO_EVENT, this->recursion);
  const Http2StreamId stream_id = frame->header().streamid;
  Http2Error          error;

  // [RFC 7540] 5.5. Extending HTTP/2
  //   Implementations MUST discard frames that have unknown or unsupported types.
  if (frame->header().type >= HTTP2_FRAME_TYPE_MAX) {
    Http2StreamDebug(session, stream_id, "Discard a frame which has unknown type, type=%x", frame->header().type);
    return;
  }

  // We need to be careful here, certain frame types are not safe over 0-rtt, tentative for now.
  // DATA:          NO
  // HEADERS:       YES (safe http methods only, can only be checked after parsing the payload).
  // PRIORITY:      YES
  // RST_STREAM:    NO
  // SETTINGS:      YES
  // PUSH_PROMISE:  NO
  // PING:          YES
  // GOAWAY:        NO
  // WINDOW_UPDATE: YES
  // CONTINUATION:  YES (safe http methods only, same as HEADERS frame).
  if (frame->is_from_early_data() &&
      (frame->header().type == HTTP2_FRAME_TYPE_DATA || frame->header().type == HTTP2_FRAME_TYPE_RST_STREAM ||
       frame->header().type == HTTP2_FRAME_TYPE_PUSH_PROMISE || frame->header().type == HTTP2_FRAME_TYPE_GOAWAY)) {
    Http2StreamDebug(session, stream_id, "Discard a frame which is received from early data and has type=%x", frame->header().type);
    return;
  }

  if (this->_frame_handlers[frame->header().type]) {
    error = (this->*_frame_handlers[frame->header().type])(*frame);
  } else {
    error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_INTERNAL_ERROR, "no handler");
  }

  if (error.cls != Http2ErrorClass::HTTP2_ERROR_CLASS_NONE) {
    ip_port_text_buffer ipb;
    const char         *client_ip = ats_ip_ntop(session->get_proxy_session()->get_remote_addr(), ipb, sizeof(ipb));
    if (error.cls == Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION) {
      if (error.msg) {
        Error("HTTP/2 connection error code=0x%02x client_ip=%s session_id=%" PRId64 " stream_id=%u %s",
              static_cast<int>(error.code), client_ip, session->get_connection_id(), stream_id, error.msg);
      }
      this->_close_connection(error.code);

      // The streams will be cleaned up by the HTTP2_SESSION_EVENT_FINI event
      // The Http2ClientSession will shutdown because connection_state.is_state_closed() will be true
    } else if (error.cls == Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM) {
      if (error.msg) {
        Http2StreamDebug(session, stream_id, "HTTP/2 stream error code=0x%02x client_ip=%s %s", static_cast<int>(error.code),
                         client_ip, error.msg);
      }
      this->send_rst_stream_frame(stream_id, error.code);

      // start closing stream on stream error
      if (Http2Stream *stream = find_stream(stream_id); stream != nullptr) {
        ink_assert(stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_CLOSED);
        stream->initiating_close();
      }
    }
  }
}

int
Http2ConnectionState::main_event_handler(int event, void *edata)
{
  if (edata == zombie_event) {
    // zombie session is still around. Assert
    ink_release_assert(zombie_event == nullptr);
  } else if (edata == fini_event) {
    fini_event = nullptr;
  } else if (edata == _priority_event) {
    _priority_event = nullptr;
  } else if (edata == _data_event) {
    _data_event = nullptr;
  } else if (edata == retransmit_event) {
    retransmit_event = nullptr;
  }
  ++recursion;

  switch (event) {
  // Finalize HTTP/2 Connection
  case HTTP2_SESSION_EVENT_FINI: {
    SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
    REMEMBER(event, this->recursion);

    ink_assert(this->fini_received == false);
    this->fini_received = true;
    cleanup_streams();
    release_stream();
    SET_HANDLER(&Http2ConnectionState::state_closed);
  } break;

  case HTTP2_SESSION_EVENT_PRIO: {
    REMEMBER(event, this->recursion);
    SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
    send_data_frames_depends_on_priority();
  } break;

  case HTTP2_SESSION_EVENT_DATA: {
    REMEMBER(event, this->recursion);
    SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
    // mark the retry flag here so if the writes fail again we will
    // backoff the next attempt
    _data_event_retry = true;
    this->restart_streams();
    _data_event_retry = false;
  } break;

  case HTTP2_SESSION_EVENT_XMIT: {
    REMEMBER(event, this->recursion);
    SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
    this->session->flush();
  } break;

  case HTTP2_SESSION_EVENT_ERROR: {
    REMEMBER(event, this->recursion);

    Http2ErrorCode error_code = Http2ErrorCode::HTTP2_ERROR_INTERNAL_ERROR;
    if (edata != nullptr) {
      Http2Error *error = static_cast<Http2Error *>(edata);
      error_code        = error->code;
    }

    SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
    this->_close_connection(error_code);
  } break;

  // Initiate a graceful shutdown
  case HTTP2_SESSION_EVENT_SHUTDOWN_INIT: {
    REMEMBER(event, this->recursion);
    ink_assert(shutdown_state == HTTP2_SHUTDOWN_NOT_INITIATED);
    shutdown_state = HTTP2_SHUTDOWN_INITIATED;
    // [RFC 7540] 6.8.  GOAWAY
    // A server that is attempting to gracefully shut down a
    // connection SHOULD send an initial GOAWAY frame with the last stream
    // identifier set to 2^31-1 and a NO_ERROR code.
    send_goaway_frame(INT32_MAX, Http2ErrorCode::HTTP2_ERROR_NO_ERROR);
    // After allowing time for any in-flight stream creation (at least one round-trip time),
    shutdown_cont_event =
      this_ethread()->schedule_in(static_cast<Continuation *>(this), HRTIME_SECONDS(2), HTTP2_SESSION_EVENT_SHUTDOWN_CONT);
  } break;

  // Continue a graceful shutdown
  case HTTP2_SESSION_EVENT_SHUTDOWN_CONT: {
    REMEMBER(event, this->recursion);
    ink_assert(shutdown_state == HTTP2_SHUTDOWN_INITIATED);
    shutdown_cont_event = nullptr;
    shutdown_state      = HTTP2_SHUTDOWN_IN_PROGRESS;
    // [RFC 7540] 6.8.  GOAWAY
    // ..., the server can send another GOAWAY frame with an updated last stream identifier
    if (shutdown_reason == Http2ErrorCode::HTTP2_ERROR_MAX) {
      shutdown_reason = Http2ErrorCode::HTTP2_ERROR_NO_ERROR;
    }
    send_goaway_frame(latest_streamid_in, shutdown_reason);
    // Stop creating new streams
    SCOPED_MUTEX_LOCK(lock, this->session->get_mutex(), this_ethread());
    this->session->set_half_close_local_flag(true);
  } break;

  default:
    Http2ConDebug(session, "unexpected event=%d edata=%p", event, edata);
    ink_release_assert(0);
    break;
  }

  --recursion;
  if (recursion == 0 && session && !session->is_recursing()) {
    if (this->session->ready_to_free()) {
      MUTEX_TRY_LOCK(lock, this->session->get_mutex(), this_ethread());
      if (lock.is_locked()) {
        this->session->get_proxy_session()->free();
        // After the free, the Http2ConnectionState object is also freed.
        // The Http2ConnectionState object is allocated within the Http2ClientSession object
      }
    }
  }
  return 0;
}

int
Http2ConnectionState::state_closed(int event, void *edata)
{
  REMEMBER(event, this->recursion);

  if (edata == zombie_event) {
    // Zombie session is still around.  Assert!
    ink_release_assert(zombie_event == nullptr);
  } else if (edata == fini_event) {
    fini_event = nullptr;
  } else if (edata == _priority_event) {
    _priority_event = nullptr;
  } else if (edata == _data_event) {
    _data_event = nullptr;
  } else if (edata == shutdown_cont_event) {
    shutdown_cont_event = nullptr;
  } else if (edata == retransmit_event) {
    retransmit_event = nullptr;
  }
  return 0;
}

bool
Http2ConnectionState::is_peer_concurrent_stream_ub() const
{
  return peer_streams_count_in >= (peer_settings.get(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS)) * 0.9;
}

bool
Http2ConnectionState::is_peer_concurrent_stream_lb() const
{
  return peer_streams_count_in <= (peer_settings.get(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS)) / 2;
}

void
Http2ConnectionState::set_stream_id(Http2Stream *stream)
{
  if (stream->get_transaction_id() < 0) {
    Http2StreamId stream_id = (latest_streamid_in == 0) ? 3 : latest_streamid_in + 2;
    stream->set_transaction_id(stream_id);
    latest_streamid_in = stream_id;
  }
}

Http2Stream *
Http2ConnectionState::create_initiating_stream(Http2Error &error)
{
  // first check if we've hit the active connection limit
  if (!session->get_netvc()->add_to_active_queue()) {
    error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_NO_ERROR,
                       "refused to create new stream, maxed out active connections");
    return nullptr;
  }

  // In half_close state, TS doesn't create new stream. Because GOAWAY frame is sent to client
  if (session->get_half_close_local_flag()) {
    error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_REFUSED_STREAM,
                       "refused to create new stream, because session is in half_close state");
    return nullptr;
  }

  // Endpoints MUST NOT exceed the limit set by their peer.  An endpoint
  // that receives a HEADERS frame that causes their advertised concurrent
  // stream limit to be exceeded MUST treat this as a stream error.
  int check_max_concurrent_limit;
  int check_count;
  check_count = peer_streams_count_in;
  // If this is an outbound client stream, must check against the peer's max_concurrent
  if (session->is_outbound()) {
    check_max_concurrent_limit = peer_settings.get(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
  } else { // Inbound client stream check against our own max_connecurent limits
    check_max_concurrent_limit = local_settings.get(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
  }
  ink_release_assert(check_max_concurrent_limit != 0);

  // If we haven't got the peers settings yet, just hope for the best
  if (check_max_concurrent_limit >= 0) {
    if (session->is_outbound() && Http2ConnectionState::is_peer_concurrent_stream_ub()) {
      error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_REFUSED_STREAM,
                         "recv headers creating stream beyond max_concurrent limit");
      return nullptr;
    } else if (check_count >= check_max_concurrent_limit) {
      error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_REFUSED_STREAM,
                         "recv headers creating stream beyond max_concurrent limit");
      return nullptr;
    }
  }

  ink_assert(dynamic_cast<Http2CommonSession *>(this->session->get_proxy_session()));
  ink_assert(this->session->is_outbound() == true);
  uint32_t const initial_stream_window        = this->acknowledged_local_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE);
  uint32_t       initial_stream_window_target = initial_stream_window;
  bool const     update_dynamic_stream_window = session->is_outbound() && this->_has_dynamic_stream_window();

  if (update_dynamic_stream_window) {
    // See the comment in create_stream() concerning the difference between the
    // initial window size and the target window size for dynamic stream window
    // sizes.
    Http2ConnectionSettings new_settings = local_settings;
    initial_stream_window_target         = this->_get_configured_receive_session_window_size() / (peer_streams_count_in.load() + 1);
    new_settings.set(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE, initial_stream_window_target);
    error = this->_check_outgoing_settings_frame(new_settings, !SEND_EMPTY);
    if (error.cls != Http2ErrorClass::HTTP2_ERROR_CLASS_NONE) {
      this->_close_connection(error.code);
      return nullptr;
    }
  }

  Http2Stream *new_stream =
    THREAD_ALLOC_INIT(http2StreamAllocator, this_ethread(), session->get_proxy_session(), -1,
                      peer_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE), initial_stream_window, STREAM_IS_REGISTERED);

  ink_assert(nullptr != new_stream);
  ink_assert(!stream_list.in(new_stream));

  stream_list.enqueue(new_stream);
  ink_assert(peer_streams_count_in < UINT32_MAX);
  ++peer_streams_count_in;
  ++total_peer_streams_count;

  if (zombie_event != nullptr) {
    zombie_event->cancel();
    zombie_event = nullptr;
  }

  new_stream->mutex                     = new_ProxyMutex();
  new_stream->is_first_transaction_flag = get_stream_requests() == 0;
  increment_stream_requests();

  // Clear the session timeout.  Let the transaction timeouts reign
  session->get_proxy_session()->cancel_inactivity_timeout();

  if (update_dynamic_stream_window) {
    Http2ConnectionSettings new_settings = local_settings;
    new_settings.set(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE, initial_stream_window_target);
    Http2Error settings_error = this->send_settings_frame(new_settings, !SEND_EMPTY);
    ink_assert(settings_error.cls == Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
  }

  return new_stream;
}

Http2Stream *
Http2ConnectionState::create_stream(Http2StreamId new_id, Http2Error &error)
{
  // first check if we've hit the active connection limit
  if (!session->get_netvc()->add_to_active_queue()) {
    error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_NO_ERROR,
                       "refused to create new stream, maxed out active connections");
    return nullptr;
  }

  // In half_close state, TS doesn't create new stream. Because GOAWAY frame is sent to client
  if (session->get_half_close_local_flag()) {
    error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_REFUSED_STREAM,
                       "refused to create new stream, because session is in half_close state");
    return nullptr;
  }

  bool is_client_streamid = http2_is_client_streamid(new_id);

  // 5.1.1 The identifier of a newly established stream MUST be numerically
  // greater than all streams that the initiating endpoint has opened or
  // reserved.  This governs streams that are opened using a HEADERS frame
  // and streams that are reserved using PUSH_PROMISE.  An endpoint that
  // receives an unexpected stream identifier MUST respond with a
  // connection error (Section 5.4.1) of type PROTOCOL_ERROR.
  if (is_client_streamid) {
    if (new_id <= latest_streamid_in) {
      error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                         "recv headers new client id less than latest stream id");
      return nullptr;
    }
  } else {
    if (new_id <= latest_streamid_out) {
      error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                         "recv headers new server id less than latest stream id");
      return nullptr;
    }
  }

  // Endpoints MUST NOT exceed the limit set by their peer.  An endpoint
  // that receives a HEADERS frame that causes their advertised concurrent
  // stream limit to be exceeded MUST treat this as a stream error.
  int check_max_concurrent_limit = 0;
  int check_count                = 0;
  if (is_client_streamid) {
    check_count = peer_streams_count_in;
    // If this is an outbound client stream, must check against the peer's max_concurrent
    if (session->is_outbound()) {
      check_max_concurrent_limit = peer_settings.get(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
    } else { // Inbound client streamm check against our own max_connecurent limits
      check_max_concurrent_limit = acknowledged_local_settings.get(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
    }
  } else { // Not a client stream (i.e. a push)
    check_count = peer_streams_count_out;
    // If this is an outbound non-client stream, must check against the local max_concurrent
    if (session->is_outbound()) {
      check_max_concurrent_limit = acknowledged_local_settings.get(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
    } else { // Inbound non-client streamm check against the peer's max_connecurent limits
      check_max_concurrent_limit = peer_settings.get(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
    }
  }
  // If we haven't got the peers settings yet, just hope for the best
  if (check_max_concurrent_limit >= 0 && check_count >= check_max_concurrent_limit) {
    Metrics::Counter::increment(is_client_streamid ? http2_rsb.max_concurrent_streams_exceeded_in :
                                                     http2_rsb.max_concurrent_streams_exceeded_out);
    error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_REFUSED_STREAM,
                       "recv headers creating stream beyond max_concurrent limit");
    return nullptr;
  }

  ink_assert(dynamic_cast<Http2CommonSession *>(this->session->get_proxy_session()));
  ink_assert(this->session->is_outbound() == false);
  uint32_t initial_stream_window        = this->acknowledged_local_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE);
  uint32_t initial_stream_window_target = initial_stream_window;
  if (is_client_streamid && this->_has_dynamic_stream_window()) {
    // For dynamic stream windows, the peer's idea of what the window size is
    // may be different than what we are configuring. Our calculated server
    // receive window is always maintained at what the peer has acknowledged so
    // far. This prevents us from enforcing window sizes that have been
    // adjusted by SETTINGS frames which the peer has not received yet. So we
    // initialize the receive window to what the peer has acknowledged while in
    // the meantime calculating initial_stream_window_target for the SETTINGS
    // frame which will shrink or enlarge it to our new desired size.
    //
    // The situation of dynamic stream window sizes is described in [RFC 9113]
    // 6.9.3.
    initial_stream_window_target = this->_get_configured_receive_session_window_size() / (peer_streams_count_in.load() + 1);

    Http2ConnectionSettings new_settings = local_settings;
    new_settings.set(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE, initial_stream_window_target);
    error = this->_check_outgoing_settings_frame(new_settings, !SEND_EMPTY);
    if (error.cls != Http2ErrorClass::HTTP2_ERROR_CLASS_NONE) {
      return nullptr;
    }
  }

  Http2Stream *new_stream =
    THREAD_ALLOC_INIT(http2StreamAllocator, this_ethread(), session->get_proxy_session(), new_id,
                      peer_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE), initial_stream_window, STREAM_IS_REGISTERED);

  ink_assert(nullptr != new_stream);
  ink_assert(!stream_list.in(new_stream));

  new_stream->mutex                     = new_ProxyMutex();
  new_stream->is_first_transaction_flag = get_stream_requests() == 0;

  stream_list.enqueue(new_stream);
  if (is_client_streamid) {
    latest_streamid_in = new_id;
    ink_assert(peer_streams_count_in < UINT32_MAX);
    ++peer_streams_count_in;
    if (this->_has_dynamic_stream_window()) {
      Http2ConnectionSettings new_settings = local_settings;
      new_settings.set(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE, initial_stream_window_target);
      Http2Error settings_error = this->send_settings_frame(new_settings, !SEND_EMPTY);
      ink_assert(settings_error.cls == Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
    }
  } else {
    latest_streamid_out = new_id;
    ink_assert(peer_streams_count_out < UINT32_MAX);
    ++peer_streams_count_out;
  }
  ++total_peer_streams_count;

  if (zombie_event != nullptr) {
    zombie_event->cancel();
    zombie_event = nullptr;
  }
  increment_stream_requests();

  // Set incomplete header timeout
  //   Client should send END_HEADERS flag within the http2.incomplete_header_timeout_in.
  //   The active timeout of this stream will be reset by HttpSM with http.transaction_active_timeout_in when a HTTP TXN is started
  new_stream->set_active_timeout(HRTIME_SECONDS(Http2::incomplete_header_timeout_in));

  // Clear the session timeout.  Let the transaction timeouts reign
  session->get_proxy_session()->cancel_inactivity_timeout();
  session->get_proxy_session()->set_session_active();

  return new_stream;
}

Http2Stream *
Http2ConnectionState::find_stream(Http2StreamId id) const
{
  for (Http2Stream *s = stream_list.head; s; s = static_cast<Http2Stream *>(s->link.next)) {
    if (s->get_id() == id) {
      return s;
    }
    ink_assert(s != s->link.next);
  }
  return nullptr;
}

void
Http2ConnectionState::restart_streams()
{
  Http2Stream *s = stream_list.head;
  if (s) {
    Http2Stream *end = s;

    // This is a static variable, so it is shared in Http2ConnectionState instances and will get incremented in subsequent calls.
    // It doesn't need to be initialized with rand() nor time(), and doesn't need to be accessed with a lock, because it doesn't
    // need that randomness and accuracy.
    static uint16_t starting_point = 0;
    // Change the start point randomly
    for (int i = starting_point % total_peer_streams_count; i >= 0; --i) {
      end = static_cast<Http2Stream *>(end->link.next ? end->link.next : stream_list.head);
    }
    s = static_cast<Http2Stream *>(end->link.next ? end->link.next : stream_list.head);

    // Call send_response_body() for each streams
    while (s != end) {
      Http2Stream *next = static_cast<Http2Stream *>(s->link.next ? s->link.next : stream_list.head);
      if (this->get_peer_rwnd() > 0 && s->get_peer_rwnd() > 0) {
        SCOPED_MUTEX_LOCK(lock, s->mutex, this_ethread());
        s->restart_sending();
      }
      ink_assert(s != next);
      s = next;
    }

    // The above stopped at end, so we need to call send_response_body() one
    // last time for the stream pointed to by end.
    if (this->get_peer_rwnd() > 0 && s->get_peer_rwnd() > 0) {
      SCOPED_MUTEX_LOCK(lock, s->mutex, this_ethread());
      s->restart_sending();
    }

    ++starting_point;
  }
}

void
Http2ConnectionState::restart_receiving(Http2Stream *stream)
{
  if (this->session->get_proxy_session()->is_peer_closed()) {
    // Cannot restart a closed connection.
    return;
  }
  // Connection level WINDOW UPDATE
  uint32_t const configured_session_window = this->_get_configured_receive_session_window_size();
  uint32_t const min_session_window =
    std::min(configured_session_window, this->acknowledged_local_settings.get(HTTP2_SETTINGS_MAX_FRAME_SIZE));
  if (this->get_local_rwnd() < min_session_window) {
    Http2WindowSize diff_size = configured_session_window - this->get_local_rwnd();
    if (diff_size > 0) {
      this->increment_local_rwnd(diff_size);
      this->_local_rwnd_is_shrinking = false;
      this->send_window_update_frame(HTTP2_CONNECTION_CONTROL_STREAM, diff_size);
    }
  }

  // Stream level WINDOW UPDATE
  if (stream == nullptr || stream->get_local_rwnd() >= min_session_window) {
    // There's no need to increase the stream window size if it is already big
    // enough to hold what the stream/max frame size can receive.
    return;
  }

  uint32_t const initial_stream_window = this->acknowledged_local_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE);
  int64_t        data_size             = stream->read_vio_read_avail();

  Http2WindowSize diff_size = 0;
  if (stream->get_local_rwnd() < 0) {
    // Receive windows can be negative if we sent a SETTINGS frame that
    // decreased the stream window size mid-stream. This is not a problem: we
    // simply compute a WINDOW_UPDATE value to bring the window up to the
    // target initial_stream_window size.
    diff_size = initial_stream_window - stream->get_local_rwnd();
  } else {
    diff_size = initial_stream_window - std::min(static_cast<int64_t>(stream->get_local_rwnd()), data_size);
  }

  // Dynamic stream window sizes may result in negative values. In this case,
  // we'll just be waiting for the peer to send more data until the receive
  // window decreases to be under the initial window size.
  if (diff_size > 0) {
    stream->increment_local_rwnd(diff_size);
    this->send_window_update_frame(stream->get_id(), diff_size);
  }
}

void
Http2ConnectionState::cleanup_streams()
{
  Http2Stream *s = stream_list.head;
  while (s) {
    Http2Stream *next = static_cast<Http2Stream *>(s->link.next);
    if (this->rx_error_code.cls != ProxyErrorClass::NONE) {
      s->set_rx_error_code(this->rx_error_code);
    }
    if (this->tx_error_code.cls != ProxyErrorClass::NONE) {
      s->set_tx_error_code(this->tx_error_code);
    }
    s->initiating_close();
    ink_assert(s != next);
    s = next;
  }

  if (!is_state_closed()) {
    SCOPED_MUTEX_LOCK(lock, this->session->get_mutex(), this_ethread());

    UnixNetVConnection *vc = static_cast<UnixNetVConnection *>(session->get_netvc());
    if (vc && vc->active_timeout_in == 0) {
      vc->add_to_keep_alive_queue();
    }
  }
}

bool
Http2ConnectionState::delete_stream(Http2Stream *stream)
{
  ink_assert(nullptr != stream);
  SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());

  // If stream has already been removed from the list, just go on
  if (!stream_list.in(stream)) {
    return false;
  }

  Http2StreamDebug(session, stream->get_id(), "Delete stream");
  REMEMBER(NO_EVENT, this->recursion);

  if (Http2::stream_priority_enabled) {
    Http2DependencyTree::Node *node       = stream->priority_node;
    Http2DependencyTree::Node *node_by_id = this->dependency_tree->find(stream->get_id());
    ink_assert(node == node_by_id);
    if (node != nullptr) {
      if (node->active) {
        dependency_tree->deactivate(node, 0);
      }
      if (dbg_ctl_http2_priority.on()) {
        std::stringstream output;
        dependency_tree->dump_tree(output);
        Dbg(dbg_ctl_http2_priority, "[%" PRId64 "] %s", session->get_connection_id(), output.str().c_str());
      }
      dependency_tree->remove(node);
      // ink_release_assert(dependency_tree->find(stream->get_id()) == nullptr);
    }
    stream->priority_node = nullptr;
  }

  if (stream->get_state() != Http2StreamState::HTTP2_STREAM_STATE_CLOSED) {
    send_rst_stream_frame(stream->get_id(), Http2ErrorCode::HTTP2_ERROR_NO_ERROR);
  }

  stream_list.remove(stream);
  if (http2_is_client_streamid(stream->get_id())) {
    ink_release_assert(peer_streams_count_in > 0);
    --peer_streams_count_in;
    // Do not put a session that has already entered local half-close back in
    // the pool. Once `set_half_close_local_flag(true)` has been called (for
    // example because we have started a graceful GOAWAY) every subsequent
    // `create_initiating_stream` on this session will fast-fail with
    // REFUSED_STREAM, so handing it back out via `acquire_session` only
    // causes spurious aborts. The session will be torn down once its
    // remaining in-flight streams finish; until then it must stay out of
    // the pool.
    if (!fini_received && !session->get_half_close_local_flag() && is_peer_concurrent_stream_lb()) {
      session->add_session();
    }
  } else {
    ink_assert(peer_streams_count_out > 0);
    --peer_streams_count_out;
  }
  // total_peer_streams_count will be decremented in release_stream(), because it's a counter include streams in the process of
  // shutting down.

  stream->initiating_close();

  return true;
}

void
Http2ConnectionState::release_stream()
{
  REMEMBER(NO_EVENT, this->recursion)

  SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
  if (this->session) {
    ink_assert(this->mutex == session->get_mutex());

    if (total_peer_streams_count == 0) {
      if (fini_received) {
        session->do_clear_session_active();

        // We were shutting down, go ahead and terminate the session
        // this is a member of Http2ConnectionState and will be freed
        // when session is destroyed
        session->get_proxy_session()->destroy();

        // Can't do this because we just destroyed right here ^,
        // or we can use a local variable to do it.
        // session = nullptr;
      } else if (_peer_goaway_drain) {
        // Every stream left by the origin's GOAWAY is gone. The half-closed
        // session cannot gain streams, so the count stays at zero.
        if (fini_event == nullptr) {
          fini_event = this_ethread()->schedule_imm_local(static_cast<Continuation *>(this), HTTP2_SESSION_EVENT_FINI);
        }
      } else if (session->get_proxy_session()->is_active()) {
        // If the number of clients is 0, HTTP2_SESSION_EVENT_FINI is not received or sent, and session is active,
        // then mark the connection as inactive
        session->do_clear_session_active();
        session->set_no_activity_timeout();
        UnixNetVConnection *vc = static_cast<UnixNetVConnection *>(session->get_netvc());
        if (vc && vc->active_timeout_in == 0) {
          // With heavy traffic, session could be destroyed. Do not touch session after this.
          vc->add_to_keep_alive_queue();
        }
      } else {
        schedule_zombie_event();
      }
    } else if (fini_received) {
      schedule_zombie_event();
    }
  }
}

void
Http2ConnectionState::update_initial_peer_rwnd(Http2WindowSize new_size)
{
  // Update stream level window sizes
  for (Http2Stream *s = stream_list.head; s; s = static_cast<Http2Stream *>(s->link.next)) {
    SCOPED_MUTEX_LOCK(lock, s->mutex, this_ethread());
    // Set the new window size, but take into account the already adjusted
    // window based on previously sent bytes.
    //
    // For example:
    // 1. Client initializes the stream window to 10K bytes.
    // 2. ATS sends 3K bytes to the client. The stream window is now 7K bytes.
    // 3. The client sends a SETTINGS frame to update the initial window size to 20K bytes.
    // 4. ATS should update the stream window to 17K bytes: 20K - (10K - 7K).
    //
    // Note that if the client reduces the stream window, this may result in
    // negative receive window values.
    s->set_peer_rwnd(new_size - (peer_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE) - s->get_peer_rwnd()));
  }
}

void
Http2ConnectionState::update_initial_local_rwnd(Http2WindowSize new_size)
{
  // Update stream level window sizes
  for (Http2Stream *s = stream_list.head; s; s = static_cast<Http2Stream *>(s->link.next)) {
    SCOPED_MUTEX_LOCK(lock, s->mutex, this_ethread());
    // Set the new window size, but take into account the already adjusted
    // window based on previously sent bytes.
    //
    // For example:
    // 1. ATS initializes the stream window to 10K bytes.
    // 2. ATS receives 3K bytes from the client. The stream window is now 7K bytes.
    // 3. ATS sends a SETTINGS frame to the client to update the initial window size to 20K bytes.
    // 4. The stream window should be updated to 17K bytes: 20K - (10K - 7K).
    //
    // Note that if ATS reduces the stream window, this may result in negative
    // receive window values.
    s->set_local_rwnd(new_size - (acknowledged_local_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE) - s->get_local_rwnd()));
  }
}

void
Http2ConnectionState::schedule_stream_to_send_priority_frames(Http2Stream *stream)
{
  Http2StreamDebug(session, stream->get_id(), "Scheduling sending priority frames");

  Http2DependencyTree::Node *node = stream->priority_node;
  ink_release_assert(node != nullptr);

  SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
  dependency_tree->activate(node);

  if (_priority_event == nullptr) {
    SET_HANDLER(&Http2ConnectionState::main_event_handler);
    _priority_event = this_ethread()->schedule_imm_local(static_cast<Continuation *>(this), HTTP2_SESSION_EVENT_PRIO);
  }
}

void
Http2ConnectionState::schedule_stream_to_send_data_frames(Http2Stream *stream)
{
  Http2StreamDebug(session, stream->get_id(), "Scheduling sending data frames");

  SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());

  if (_data_event == nullptr) {
    SET_HANDLER(&Http2ConnectionState::main_event_handler);
    // exponential backoff scheduling event if we are in a retry.
    // assume a slow reader will always be slow so don't reset the backoff
    if (_data_event_retry) {
      _data_event_backoff = std::min(DATA_EVENT_BACKOFF_MAX, _data_event_backoff << 1);
    }
    _data_event = this_ethread()->schedule_in(static_cast<Continuation *>(this), HRTIME_MSECONDS(_data_event_backoff),
                                              HTTP2_SESSION_EVENT_DATA);
  }
}

void
Http2ConnectionState::schedule_retransmit(ink_hrtime t)
{
  Http2StreamDebug(session, 0, "Scheduling retransmitting data frames");
  SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());

  if (retransmit_event == nullptr) {
    SET_HANDLER(&Http2ConnectionState::main_event_handler);
    retransmit_event = this_ethread()->schedule_in(static_cast<Continuation *>(this), t, HTTP2_SESSION_EVENT_XMIT);
  }
}

void
Http2ConnectionState::cancel_retransmit()
{
  Http2StreamDebug(session, 0, "Canceling retransmitting data frames");
  SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
  if (retransmit_event != nullptr) {
    retransmit_event->cancel();
    retransmit_event = nullptr;
  }
}

void
Http2ConnectionState::send_data_frames_depends_on_priority()
{
  Http2DependencyTree::Node *node = dependency_tree->top();

  // No node to send or no connection level window left
  if (node == nullptr || _peer_rwnd <= 0) {
    return;
  }

  Http2Stream *stream = static_cast<Http2Stream *>(node->t);
  ink_release_assert(stream != nullptr);
  ink_release_assert(stream->priority_node == node);
  Http2StreamDebug(session, stream->get_id(), "top node, point=%d", node->point);

  size_t                   len    = 0;
  Http2SendDataFrameResult result = send_a_data_frame(stream, len);
  ink_release_assert(stream->priority_node != nullptr);

  switch (result) {
  case Http2SendDataFrameResult::NO_ERROR: {
    // No response body to send
    if (len == 0 && !stream->is_write_vio_done()) {
      dependency_tree->deactivate(node, len);
    } else {
      dependency_tree->update(node, len);
      SCOPED_MUTEX_LOCK(stream_lock, stream->mutex, this_ethread());
      stream->signal_write_event(stream->is_write_vio_done() ? VC_EVENT_WRITE_COMPLETE : VC_EVENT_WRITE_READY);
    }
    break;
  }
  case Http2SendDataFrameResult::DONE: {
    dependency_tree->deactivate(node, len);
    stream->initiating_close();
    break;
  }
  default:
    // When no stream level window left, deactivate node once and wait window_update frame
    dependency_tree->deactivate(node, len);
    break;
  }

  if (_priority_event == nullptr) {
    _priority_event = this_ethread()->schedule_imm_local(static_cast<Continuation *>(this), HTTP2_SESSION_EVENT_PRIO);
  }

  return;
}

Http2SendDataFrameResult
Http2ConnectionState::send_a_data_frame(Http2Stream *stream, size_t &payload_length)
{
  const ssize_t window_size          = std::min(this->get_peer_rwnd(), stream->get_peer_rwnd());
  const size_t  buf_len              = BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_DATA]);
  const size_t  write_available_size = std::min(buf_len, static_cast<size_t>(window_size));
  payload_length                     = 0;

  uint8_t         flags       = 0x00;
  IOBufferReader *resp_reader = stream->get_data_reader_for_send();
  bool            last_write_vio_payload{false};

  SCOPED_MUTEX_LOCK(stream_lock, stream->mutex, this_ethread());

  if (!resp_reader) {
    Http2StreamDebug(this->session, stream->get_id(), "couldn't get data reader");
    return Http2SendDataFrameResult::ERROR;
  }

  // Select appropriate payload length
  if (resp_reader->is_read_avail_more_than(0)) {
    // We only need to check for window size when there is a payload
    if (window_size <= 0) {
      if (dbg_ctl_http2_con.on()) {
        ip_port_text_buffer ipb;
        const char         *peer_ip = ats_ip_ntop(session->get_proxy_session()->get_remote_addr(), ipb, sizeof(ipb));
        Http2StreamDebug(this->session, stream->get_id(),
                         "Waiting for peer WINDOW_UPDATE peer_ip=%s session_wnd=%zd stream_wnd=%zd peer_initial_window=%u", peer_ip,
                         get_peer_rwnd(), stream->get_peer_rwnd(), this->peer_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE));
      }
      ATS_PROBE5(http2_send_window_blocked, this->session->get_connection_id(), stream->get_id(), this->get_peer_rwnd(),
                 stream->get_peer_rwnd(), resp_reader->read_avail());
      this->session->flush();
      return Http2SendDataFrameResult::NO_WINDOW;
    }

    if (resp_reader->is_read_avail_more_than(write_available_size)) {
      payload_length = write_available_size;
    } else {
      payload_length = resp_reader->read_avail();
    }
    const int64_t remaining_write = stream->write_vio_ntodo();
    if (remaining_write != INT64_MAX) {
      if (remaining_write > 0) {
        last_write_vio_payload = payload_length >= static_cast<size_t>(remaining_write);
        payload_length         = std::min(payload_length, static_cast<size_t>(remaining_write));
      } else {
        last_write_vio_payload = true;
        payload_length         = 0;
      }
    }
  } else {
    payload_length = 0;
  }

  // For HTTP/2 sessions, is_write_high_water() returning true correlates to
  // our write buffer exceeding HTTP2_SETTINGS_MAX_FRAME_SIZE. Thus we will
  // hold off on processing the payload until the write buffer is drained.
  if (payload_length > 0 && this->session->is_write_high_water()) {
    Http2StreamDebug(this->session, stream->get_id(), "Not write avail, payload_length=%zu", payload_length);
    ATS_PROBE4(http2_write_buffer_blocked, this->session->get_connection_id(), stream->get_id(), payload_length,
               this->get_peer_rwnd());
    this->session->flush();
    return Http2SendDataFrameResult::NOT_WRITE_AVAIL;
  }

  stream->update_sent_count(payload_length);

  // Are we at the end?
  // We have no payload to send but might expect data from either trailer or body
  // TODO(KS): does the expect send trailer and empty payload need a flush, or does it
  //           warrant a separate flow with NO_ERROR?
  // If we return here, we never send the END_STREAM in the case of a early terminating OS.
  // OK if there is no body yet. Otherwise continue on to send a DATA frame and delete the stream
  if ((!stream->is_write_vio_done() || stream->expect_send_trailer()) && payload_length == 0) {
    Http2StreamDebug(this->session, stream->get_id(), "No payload");
    this->session->flush();
    return Http2SendDataFrameResult::NO_PAYLOAD;
  }

  if (stream->is_write_vio_done() && (last_write_vio_payload || !resp_reader->is_read_avail_more_than(payload_length)) &&
      !stream->expect_send_trailer()) {
    Http2StreamDebug(this->session, stream->get_id(), "End of Data Frame");
    flags |= HTTP2_FLAGS_DATA_END_STREAM;
  }

  // Update window size
  this->decrement_peer_rwnd(payload_length);
  stream->decrement_peer_rwnd(payload_length);

  // Create frame
  Http2StreamDebug(session, stream->get_id(), "Send a DATA frame - peer window con: %5zd stream: %5zd payload: %5zd flags: 0x%x",
                   _peer_rwnd, stream->get_peer_rwnd(), payload_length, flags);

  Http2DataFrame data(stream->get_id(), flags, resp_reader, payload_length);
  this->session->xmit(data, stream->is_tunneling() || flags & HTTP2_FLAGS_DATA_END_STREAM);
  ATS_PROBE6(http2_data_frame_sent, this->session->get_connection_id(), stream->get_id(), payload_length, this->get_peer_rwnd(),
             stream->get_peer_rwnd(), (flags & HTTP2_FLAGS_DATA_END_STREAM) ? 1 : 0);

  if (flags & HTTP2_FLAGS_DATA_END_STREAM) {
    Http2StreamDebug(session, stream->get_id(), "END_STREAM");
    stream->send_end_stream = true;
    // Setting to the same state shouldn't be erroneous
    stream->change_state(HTTP2_FRAME_TYPE_DATA, flags);

    return Http2SendDataFrameResult::DONE;
  }

  return Http2SendDataFrameResult::NO_ERROR;
}

void
Http2ConnectionState::send_data_frames(Http2Stream *stream)
{
  // To follow RFC 7540 must not send more frames other than priority on
  // a closed stream.  So we return without sending
  if (stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_HALF_CLOSED_LOCAL ||
      stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_CLOSED) {
    Http2StreamDebug(this->session, stream->get_id(), "Shutdown half closed local stream");
    stream->initiating_close();
    return;
  }

  if (zombie_event != nullptr) {
    zombie_event->cancel();
    zombie_event = nullptr;
  }

  size_t                   len         = 0;
  Http2SendDataFrameResult result      = Http2SendDataFrameResult::NO_ERROR;
  bool                     more_data   = true;
  IOBufferReader          *resp_reader = stream->get_data_reader_for_send();
  while (more_data && result == Http2SendDataFrameResult::NO_ERROR) {
    result    = send_a_data_frame(stream, len);
    more_data = resp_reader->is_read_avail_more_than(0);

    if (result == Http2SendDataFrameResult::DONE) {
      if (!stream->is_outbound_connection()) {
        if (stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_CLOSED) {
          // Delete a stream immediately
          Http2StreamDebug(this->session, stream->get_id(), "Shutdown stream");
          stream->signal_write_event(VC_EVENT_WRITE_COMPLETE);
          stream->do_io_close();
        } else {
          // This stream waits for the END_STREAM in half-closed (local) state until `http.transaction_no_activity_timeout_in`.
          // If no frame with END_STREAM is found, ATS actively closes the stream.
          Http2StreamDebug(this->session, stream->get_id(), "waiting END_STREAM");
        }
      } else if (stream->is_outbound_connection() && stream->is_write_vio_done()) {
        stream->signal_write_event(VC_EVENT_WRITE_COMPLETE);
      } else {
        ink_release_assert(!"What case is this?");
      }
    } else if (result == Http2SendDataFrameResult::NOT_WRITE_AVAIL) {
      // Schedule an even to wake up and try to resend the stream.
      schedule_stream_to_send_data_frames(stream);
    }
  }
  if (!more_data && result != Http2SendDataFrameResult::DONE) {
    stream->signal_write_event(VC_EVENT_WRITE_READY);
  }

  return;
}

void
Http2ConnectionState::send_headers_frame(Http2Stream *stream)
{
  uint32_t header_blocks_size = 0;
  int      payload_length     = 0;
  uint8_t  flags              = 0x00;

  // For outbound streams, set the ID if it has not yet already been set
  // Need to defer setting the stream ID to avoid another later created stream
  // sending out first.  This may cause the peer to issue a stream or connection
  // error (new stream less that the greatest we have seen so far)
  this->set_stream_id(stream);

  // Keep this debug below set_stream_id so that the id is correct.
  Http2StreamDebug(session, stream->get_id(), "Send HEADERS frame");

  HTTPHdr *send_hdr = stream->get_send_header();
  if (stream->expect_send_trailer()) {
    // Which is a no-op conversion
  } else {
    http2_convert_header_from_1_1_to_2(send_hdr);
  }

  uint32_t        buf_len = send_hdr->length_get() * 2; // Make it double just in case
  ts::LocalBuffer local_buffer(buf_len);
  uint8_t        *buf = local_buffer.data();

  stream->mark_milestone(Http2StreamMilestone::START_ENCODE_HEADERS);
  Http2ErrorCode result = http2_encode_header_blocks(send_hdr, buf, buf_len, &header_blocks_size, *(this->peer_hpack_handle),
                                                     peer_settings.get(HTTP2_SETTINGS_HEADER_TABLE_SIZE));
  if (result != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
    // The encoder may have mutated the dynamic table for fields written before
    // the failure.  Rolling that back to keep other streams alive would be
    // ideal but is non-trivial; close the connection instead so peer state
    // cannot diverge.
    this->_close_connection(result);
    return;
  }

  // Send a HEADERS frame
  if (header_blocks_size <= static_cast<uint32_t>(BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_HEADERS]))) {
    payload_length  = header_blocks_size;
    flags          |= HTTP2_FLAGS_HEADERS_END_HEADERS;
    if (stream->is_outbound_connection()) { // Will be sending a request_header
      int method = send_hdr->method_get_wksidx();
      stream->set_sent_request_method(method);

      // Set END_STREAM on request headers for POST, etc. methods combined with
      // an explicit length 0. Some origins RST on request headers with
      // explicit zero length and no end stream flag, causing the request to
      // fail. We emulate chromium behaviour here prevent such RSTs. Transfer-encoding
      // implies there’s a body, regardless of whether it is chunked or not.
      bool content_method =
        method == HTTP_WKSIDX_POST || method == HTTP_WKSIDX_PUSH || method == HTTP_WKSIDX_PUT || method == HTTP_WKSIDX_QUERY;
      bool    is_transfer_encoded  = send_hdr->presence(MIME_PRESENCE_TRANSFER_ENCODING);
      bool    has_content_header   = send_hdr->presence(MIME_PRESENCE_CONTENT_LENGTH);
      bool    explicit_zero_length = has_content_header && send_hdr->get_content_length() == 0;
      int64_t content_length       = has_content_header ? send_hdr->get_content_length() : 0L;
      bool is_chunked = is_transfer_encoded && send_hdr->value_get(static_cast<std::string_view>(MIME_FIELD_TRANSFER_ENCODING)) ==
                                                 static_cast<std::string_view>(HTTP_VALUE_CHUNKED);

      bool expect_content_stream =
        is_transfer_encoded ||                                                        // transfer encoded content length is unknown
        (!content_method && has_content_header && !explicit_zero_length) ||           // nonzero content with GET,etc
        (content_method && !explicit_zero_length) ||                                  // content-length >0 or empty with POST etc
        stream->get_sm()->get_ua_txn()->has_request_body(content_length, is_chunked); // request has a body

      // send END_STREAM if we don't expect any content
      if (!expect_content_stream) {
        // TODO deal with the chunked encoding case
        Http2StreamDebug(session, stream->get_id(), "request END_STREAM");
        flags                   |= HTTP2_FLAGS_HEADERS_END_STREAM;
        stream->send_end_stream  = true;
      }
    } else {
      if ((send_hdr->presence(MIME_PRESENCE_CONTENT_LENGTH) && send_hdr->get_content_length() == 0) ||
          (!send_hdr->expect_final_response() && stream->is_write_vio_done())) {
        Http2StreamDebug(session, stream->get_id(), "response END_STREAM");
        flags                   |= HTTP2_FLAGS_HEADERS_END_STREAM;
        stream->send_end_stream  = true;
      }
    }
    stream->mark_milestone(Http2StreamMilestone::START_TX_HEADERS_FRAMES);
  } else {
    payload_length = BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_HEADERS]);
  }

  // Change stream state
  if (!stream->change_state(HTTP2_FRAME_TYPE_HEADERS, flags)) {
    this->_close_connection(Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR);

    return;
  }

  Http2StreamDebug(session, stream->get_id(), "Send HEADERS frame flags: 0x%x length: %d", flags, payload_length);
  Http2HeadersFrame headers(stream->get_id(), flags, buf, payload_length);
  this->session->xmit(headers);
  uint64_t sent = payload_length;

  // Send CONTINUATION frames
  flags = 0;
  while (sent < header_blocks_size) {
    Http2StreamDebug(session, stream->get_id(), "Send CONTINUATION frame");
    payload_length = std::min(static_cast<uint32_t>(BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_CONTINUATION])),
                              static_cast<uint32_t>(header_blocks_size - sent));
    if (sent + payload_length == header_blocks_size) {
      flags |= HTTP2_FLAGS_CONTINUATION_END_HEADERS;
    }
    stream->change_state(HTTP2_FRAME_TYPE_CONTINUATION, flags);

    Http2ContinuationFrame continuation_frame(stream->get_id(), flags, buf + sent, payload_length);
    this->session->xmit(continuation_frame);
    sent += payload_length;
  }
}

bool
Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url, const MIMEField *accept_encoding)
{
  uint32_t header_blocks_size = 0;
  int      payload_length     = 0;
  uint8_t  flags              = 0x00;

  // It makes no sense to send a PUSH_PROMISE toward the server.
  ink_release_assert(!this->session->is_outbound());
  if (peer_settings.get(HTTP2_SETTINGS_ENABLE_PUSH) == 0) {
    return false;
  }

  Http2StreamDebug(session, stream->get_id(), "Send PUSH_PROMISE frame");

  HTTPHdr        hdr;
  ts::PostScript hdr_defer([&]() -> void { hdr.destroy(); });
  hdr.create(HTTPType::REQUEST, HTTP_2_0);
  hdr.url_set(&url);
  hdr.method_set(static_cast<std::string_view>(HTTP_METHOD_GET));

  if (accept_encoding != nullptr) {
    auto       name{accept_encoding->name_get()};
    MIMEField *f = hdr.field_create(name);

    auto value{accept_encoding->value_get()};
    f->value_set(hdr.m_heap, hdr.m_mime, value);

    hdr.field_attach(f);
  }

  http2_convert_header_from_1_1_to_2(&hdr);

  uint32_t        buf_len = hdr.length_get() * 2; // Make it double just in case
  ts::LocalBuffer local_buffer(buf_len);
  uint8_t        *buf = local_buffer.data();

  Http2ErrorCode result = http2_encode_header_blocks(&hdr, buf, buf_len, &header_blocks_size, *(this->peer_hpack_handle),
                                                     peer_settings.get(HTTP2_SETTINGS_HEADER_TABLE_SIZE));
  if (result != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
    // See send_headers_frame: a partial encode can leave the dynamic table
    // out of sync with the peer.  Close the connection rather than risk
    // desync; rollback would be cleaner but is non-trivial.
    this->_close_connection(result);
    return false;
  }

  // Send a PUSH_PROMISE frame
  Http2PushPromise push_promise;
  if (header_blocks_size <=
      BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_PUSH_PROMISE]) - sizeof(push_promise.promised_streamid)) {
    payload_length  = header_blocks_size;
    flags          |= HTTP2_FLAGS_PUSH_PROMISE_END_HEADERS;
  } else {
    payload_length =
      BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_PUSH_PROMISE]) - sizeof(push_promise.promised_streamid);
  }

  Http2StreamId id               = this->get_latest_stream_id_out() + 2;
  push_promise.promised_streamid = id;

  Http2PushPromiseFrame push_promise_frame(stream->get_id(), flags, push_promise, buf, payload_length);
  this->session->xmit(push_promise_frame);
  uint64_t sent = payload_length;

  // Send CONTINUATION frames
  flags = 0;
  while (sent < header_blocks_size) {
    Http2StreamDebug(session, stream->get_id(), "Send CONTINUATION frame");
    payload_length = std::min(static_cast<uint32_t>(BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_CONTINUATION])),
                              static_cast<uint32_t>(header_blocks_size - sent));
    if (sent + payload_length == header_blocks_size) {
      flags |= HTTP2_FLAGS_CONTINUATION_END_HEADERS;
    }

    Http2ContinuationFrame continuation(stream->get_id(), flags, buf + sent, payload_length);
    this->session->xmit(continuation);
    sent += payload_length;
  }

  Http2Error error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
  stream = this->create_stream(id, error);
  if (!stream) {
    return false;
  }

  SCOPED_MUTEX_LOCK(stream_lock, stream->mutex, this_ethread());
  if (Http2::stream_priority_enabled) {
    Http2DependencyTree::Node *node = this->dependency_tree->find(id);
    if (node != nullptr) {
      stream->priority_node = node;
    } else {
      Http2StreamDebug(this->session, id, "PRIORITY - dep: %d, weight: %d, excl: %d, tree size: %d",
                       HTTP2_PRIORITY_DEFAULT_STREAM_DEPENDENCY, HTTP2_PRIORITY_DEFAULT_WEIGHT, false,
                       this->dependency_tree->size());

      stream->priority_node =
        this->dependency_tree->add(HTTP2_PRIORITY_DEFAULT_STREAM_DEPENDENCY, id, HTTP2_PRIORITY_DEFAULT_WEIGHT, false, stream);
    }
  }
  stream->change_state(HTTP2_FRAME_TYPE_PUSH_PROMISE, HTTP2_FLAGS_PUSH_PROMISE_END_HEADERS);
  stream->set_receive_headers(hdr);
  stream->new_transaction();
  stream->receive_end_stream = true; // No more data with the request
  stream->send_headers(*this);

  return true;
}

void
Http2ConnectionState::send_rst_stream_frame(Http2StreamId id, Http2ErrorCode ec)
{
  Http2StreamDebug(session, id, "Send RST_STREAM frame: Error Code: %u", static_cast<uint32_t>(ec));
  ATS_PROBE3(http2_rst_stream_sent, this->session->get_connection_id(), id, static_cast<uint32_t>(ec));

  if (ec != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
    Metrics::Counter::increment(http2_rsb.stream_errors_count);
    ++stream_error_count;
  }

  // change state to closed
  Http2Stream *stream = find_stream(id);
  if (stream != nullptr) {
    stream->set_tx_error_code({ProxyErrorClass::TXN, static_cast<uint32_t>(ec)});
    if (!stream->change_state(HTTP2_FRAME_TYPE_RST_STREAM, 0)) {
      this->_close_connection(Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR);

      return;
    }
  }

  Http2RstStreamFrame rst_stream(id, static_cast<uint32_t>(ec));
  this->session->xmit(rst_stream);
}

Http2Error
Http2ConnectionState::send_settings_frame(const Http2ConnectionSettings &new_settings, bool send_empty)
{
  constexpr Http2StreamId stream_id = HTTP2_CONNECTION_CONTROL_STREAM;

  Http2StreamDebug(session, stream_id, "Send SETTINGS frame");

  if (!this->_settings_have_changes(new_settings) && !send_empty) {
    Http2StreamDebug(session, stream_id, "Skip SETTINGS frame with no changes");
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
  }

  Http2Error error = this->_check_outgoing_settings_frame(new_settings, send_empty);
  if (error.cls != Http2ErrorClass::HTTP2_ERROR_CLASS_NONE) {
    Http2StreamDebug(session, stream_id, "Too many outstanding SETTINGS frames: %zu", this->_outstanding_settings_frames.size());
    return error;
  }

  Http2SettingsParameter params[HTTP2_SETTINGS_MAX];
  size_t                 params_size = 0;

  for (int i = HTTP2_SETTINGS_HEADER_TABLE_SIZE; i < HTTP2_SETTINGS_MAX; ++i) {
    Http2SettingsIdentifier id        = static_cast<Http2SettingsIdentifier>(i);
    unsigned const          old_value = local_settings.get(id);
    unsigned const          new_value = new_settings.get(id);

    // Send only difference
    if (new_value != old_value) {
      Http2StreamDebug(session, stream_id, "  %s : %u -> %u", Http2DebugNames::get_settings_param_name(id), old_value, new_value);

      params[params_size++] = {static_cast<uint16_t>(id), new_value};
    }
  }

  for (size_t i = 0; i < params_size; ++i) {
    local_settings.set(static_cast<Http2SettingsIdentifier>(params[i].id), params[i].value);
  }

  Http2SettingsFrame settings(stream_id, HTTP2_FRAME_NO_FLAG, params, params_size);

  this->_outstanding_settings_frames.emplace(new_settings);
  this->session->xmit(settings, true);

  return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
}

Http2Error
Http2ConnectionState::_process_incoming_settings_ack_frame()
{
  constexpr Http2StreamId stream_id = HTTP2_CONNECTION_CONTROL_STREAM;
  Http2StreamDebug(session, stream_id, "Processing SETTINGS ACK frame with a queue size of %zu",
                   this->_outstanding_settings_frames.size());

  if (this->_outstanding_settings_frames.empty()) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
                      "recv settings ACK with no outstanding SETTINGS frame");
  }

  // Do not update this->acknowledged_local_settings yet as
  // update_initial_local_rwnd relies upon it still pointing to the old value.
  Http2ConnectionSettings const &old_settings = this->acknowledged_local_settings;
  Http2ConnectionSettings const &new_settings = this->_outstanding_settings_frames.front().get_outstanding_settings();

  for (int i = HTTP2_SETTINGS_HEADER_TABLE_SIZE; i < HTTP2_SETTINGS_MAX; ++i) {
    Http2SettingsIdentifier id        = static_cast<Http2SettingsIdentifier>(i);
    unsigned const          old_value = old_settings.get(id);
    unsigned const          new_value = new_settings.get(id);

    if (new_value == old_value) {
      continue;
    }

    Http2StreamDebug(session, stream_id, "SETTINGS ACK %s : %u -> %u", Http2DebugNames::get_settings_param_name(id), old_value,
                     new_value);

    if (id == HTTP2_SETTINGS_INITIAL_WINDOW_SIZE) {
      // Update all the streams for the newly acknowledged window size.
      this->update_initial_local_rwnd(new_value);
    }
  }
  this->acknowledged_local_settings = new_settings;
  this->_outstanding_settings_frames.pop();

  return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
}

bool
Http2ConnectionState::_settings_have_changes(const Http2ConnectionSettings &new_settings) const
{
  for (int i = HTTP2_SETTINGS_HEADER_TABLE_SIZE; i < HTTP2_SETTINGS_MAX; ++i) {
    Http2SettingsIdentifier id = static_cast<Http2SettingsIdentifier>(i);

    if (new_settings.get(id) != local_settings.get(id)) {
      return true;
    }
  }

  return false;
}

Http2Error
Http2ConnectionState::_check_outgoing_settings_frame(const Http2ConnectionSettings &new_settings, bool send_empty) const
{
  bool const send_frame = send_empty || this->_settings_have_changes(new_settings);

  if (send_frame && this->_outstanding_settings_frames.size() >= this->_get_outstanding_settings_frame_limit()) {
    return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_SETTINGS_TIMEOUT,
                      "send settings too many outstanding SETTINGS frames");
  }

  return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
}

size_t
Http2ConnectionState::_get_outstanding_settings_frame_limit() const
{
  uint32_t const stream_limit = this->_get_configured_max_concurrent_streams();

  if (stream_limit == std::numeric_limits<uint32_t>::max()) {
    return stream_limit;
  }
  return std::max<size_t>(1, static_cast<size_t>(stream_limit) + 1);
}

void
Http2ConnectionState::_close_connection(Http2ErrorCode error_code)
{
  // A session draining the origin's GOAWAY is half-closed without having sent one.
  if (!this->session->get_half_close_local_flag() || this->_peer_goaway_drain) {
    this->send_goaway_frame(this->latest_streamid_in, error_code);
    this->session->set_half_close_local_flag(true);
  }
  if (fini_event == nullptr) {
    fini_event = this_ethread()->schedule_imm_local(static_cast<Continuation *>(this), HTTP2_SESSION_EVENT_FINI);
  }
}

void
Http2ConnectionState::send_ping_frame(Http2StreamId id, uint8_t flag, const uint8_t *opaque_data)
{
  Http2StreamDebug(session, id, "Send PING frame");

  Http2PingFrame ping(id, flag, opaque_data);
  this->session->xmit(ping);
}

// As for graceful shutdown, TS should process outstanding stream as long as possible.
// As for signal connection error, TS should close connection immediately.
void
Http2ConnectionState::send_goaway_frame(Http2StreamId id, Http2ErrorCode ec)
{
  ink_assert(this->session != nullptr);

  Http2ConDebug(session, "Send GOAWAY frame: Error Code: %u, Last Stream Id: %d", static_cast<uint32_t>(ec), id);

  if (ec != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
    Metrics::Counter::increment(http2_rsb.connection_errors_count);
  }

  this->tx_error_code = {ProxyErrorClass::SSN, static_cast<uint32_t>(ec)};

  Http2Goaway goaway;
  goaway.last_streamid = id;
  goaway.error_code    = ec;

  Http2GoawayFrame frame(goaway);
  this->session->xmit(frame);
}

void
Http2ConnectionState::send_window_update_frame(Http2StreamId id, uint32_t size)
{
  Http2StreamDebug(session, id, "Send WINDOW_UPDATE frame: size=%" PRIu32, size);

  // By specification, the window update increment must be greater than 0.
  ink_release_assert(size > 0);

  // Create WINDOW_UPDATE frame
  Http2WindowUpdateFrame window_update(id, size);
  this->session->xmit(window_update);
}

void
Http2ConnectionState::increment_received_settings_count(uint32_t count)
{
  this->_received_settings_counter.increment(count);
}

uint32_t
Http2ConnectionState::get_received_settings_count()
{
  return this->_received_settings_counter.get_count();
}

void
Http2ConnectionState::increment_received_settings_frame_count()
{
  this->_received_settings_frame_counter.increment();
}

uint32_t
Http2ConnectionState::get_received_settings_frame_count()
{
  return this->_received_settings_frame_counter.get_count();
}

void
Http2ConnectionState::increment_received_ping_frame_count()
{
  this->_received_ping_frame_counter.increment();
}

uint32_t
Http2ConnectionState::get_received_ping_frame_count()
{
  return this->_received_ping_frame_counter.get_count();
}

void
Http2ConnectionState::increment_received_priority_frame_count()
{
  this->_received_priority_frame_counter.increment();
}

uint32_t
Http2ConnectionState::get_received_priority_frame_count()
{
  return this->_received_priority_frame_counter.get_count();
}

void
Http2ConnectionState::increment_received_rst_stream_frame_count()
{
  this->_received_rst_stream_frame_counter.increment();
}

uint32_t
Http2ConnectionState::get_received_rst_stream_frame_count()
{
  return this->_received_rst_stream_frame_counter.get_count();
}

void
Http2ConnectionState::increment_received_continuation_frame_count()
{
  this->_received_continuation_frame_counter.increment();
}

uint32_t
Http2ConnectionState::get_received_continuation_frame_count()
{
  return this->_received_continuation_frame_counter.get_count();
}

void
Http2ConnectionState::increment_received_empty_frame_count()
{
  this->_received_empty_frame_counter.increment();
}

uint32_t
Http2ConnectionState::get_received_empty_frame_count()
{
  return this->_received_empty_frame_counter.get_count();
}

// Return min_concurrent_streams_in when current client streams number is larger than max_active_streams_in.
// Main purpose of this is preventing DDoS Attacks.
unsigned
Http2ConnectionState::_adjust_concurrent_stream()
{
  uint32_t const max_concurrent_streams = this->_get_configured_max_concurrent_streams();
  uint32_t const max_active_streams     = this->_get_configured_max_active_streams();
  uint32_t const min_concurrent_streams = this->_get_configured_min_concurrent_streams();

  if (max_active_streams == 0) {
    // Throttling down is disabled.
    return max_concurrent_streams;
  }

  if (!this->session->is_outbound() && Http2::max_active_streams_policy_in == 1) {
    // Under hard-enforcement the advertised value is left untouched; new streams
    // are refused at creation instead of throttling down concurrency.
    return max_concurrent_streams;
  }

  int64_t current_client_streams = Metrics::Gauge::load(http2_rsb.current_client_stream_count);

  Http2ConDebug(session, "current client streams: %" PRId64, current_client_streams);

  if (current_client_streams >= max_active_streams) {
    if (!Http2::throttling) {
      Warning("too many streams: %" PRId64 ", reduce SETTINGS_MAX_CONCURRENT_STREAMS to %d", current_client_streams,
              min_concurrent_streams);
      Http2::throttling = true;
    }

    return min_concurrent_streams;
  } else {
    if (Http2::throttling) {
      Note("revert SETTINGS_MAX_CONCURRENT_STREAMS to %d", max_concurrent_streams);
      Http2::throttling = false;
    }
  }

  return max_concurrent_streams;
}

uint32_t
Http2ConnectionState::_get_configured_receive_session_window_size() const
{
  switch (this->_get_configured_flow_control_policy()) {
  case Http2FlowControlPolicy::STATIC_SESSION_AND_STATIC_STREAM:
    return this->_get_configured_initial_window_size();
  case Http2FlowControlPolicy::LARGE_SESSION_AND_STATIC_STREAM:
  case Http2FlowControlPolicy::LARGE_SESSION_AND_DYNAMIC_STREAM:
    return this->_get_configured_initial_window_size() * this->_get_configured_max_concurrent_streams();
  }

  // This is unreachable, but adding a return here quiets a compiler warning.
  return this->_get_configured_initial_window_size();
}

bool
Http2ConnectionState::_has_dynamic_stream_window() const
{
  switch (this->_get_configured_flow_control_policy()) {
  case Http2FlowControlPolicy::STATIC_SESSION_AND_STATIC_STREAM:
  case Http2FlowControlPolicy::LARGE_SESSION_AND_STATIC_STREAM:
    return false;
  case Http2FlowControlPolicy::LARGE_SESSION_AND_DYNAMIC_STREAM:
    return true;
  }

  // This is unreachable, but adding a return here quiets a compiler warning.
  return false;
}

ssize_t
Http2ConnectionState::get_peer_rwnd() const
{
  return this->_peer_rwnd;
}

Http2ErrorCode
Http2ConnectionState::increment_peer_rwnd(size_t amount)
{
  this->_peer_rwnd += amount;

  this->_recent_rwnd_increment[this->_recent_rwnd_increment_index] = amount;
  ++this->_recent_rwnd_increment_index;
  this->_recent_rwnd_increment_index %= this->_recent_rwnd_increment.size();
  double sum = std::accumulate(this->_recent_rwnd_increment.begin(), this->_recent_rwnd_increment.end(), 0.0);
  double avg = sum / this->_recent_rwnd_increment.size();
  if (avg < Http2::min_avg_window_update) {
    Metrics::Counter::increment(http2_rsb.insufficient_avg_window_update);
    return Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM;
  }
  return Http2ErrorCode::HTTP2_ERROR_NO_ERROR;
}

Http2ErrorCode
Http2ConnectionState::decrement_peer_rwnd(size_t amount)
{
  this->_peer_rwnd -= amount;
  return Http2ErrorCode::HTTP2_ERROR_NO_ERROR;
}

ssize_t
Http2ConnectionState::get_local_rwnd() const
{
  return this->_local_rwnd;
}

Http2ErrorCode
Http2ConnectionState::increment_local_rwnd(size_t amount)
{
  this->_local_rwnd += amount;
  return Http2ErrorCode::HTTP2_ERROR_NO_ERROR;
}

Http2ErrorCode
Http2ConnectionState::decrement_local_rwnd(size_t amount)
{
  this->_local_rwnd -= amount;
  return Http2ErrorCode::HTTP2_ERROR_NO_ERROR;
}
