12c593315Sopenharmony_ci/*
22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library
32c593315Sopenharmony_ci *
42c593315Sopenharmony_ci * Copyright (c) 2012 Tatsuhiro Tsujikawa
52c593315Sopenharmony_ci *
62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining
72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the
82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to
112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
122c593315Sopenharmony_ci * the following conditions:
132c593315Sopenharmony_ci *
142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be
152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software.
162c593315Sopenharmony_ci *
172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
242c593315Sopenharmony_ci */
252c593315Sopenharmony_ci#include "shrpx_downstream.h"
262c593315Sopenharmony_ci
272c593315Sopenharmony_ci#include <cassert>
282c593315Sopenharmony_ci
292c593315Sopenharmony_ci#include "url-parser/url_parser.h"
302c593315Sopenharmony_ci
312c593315Sopenharmony_ci#include "shrpx_upstream.h"
322c593315Sopenharmony_ci#include "shrpx_client_handler.h"
332c593315Sopenharmony_ci#include "shrpx_config.h"
342c593315Sopenharmony_ci#include "shrpx_error.h"
352c593315Sopenharmony_ci#include "shrpx_downstream_connection.h"
362c593315Sopenharmony_ci#include "shrpx_downstream_queue.h"
372c593315Sopenharmony_ci#include "shrpx_worker.h"
382c593315Sopenharmony_ci#include "shrpx_http2_session.h"
392c593315Sopenharmony_ci#include "shrpx_log.h"
402c593315Sopenharmony_ci#ifdef HAVE_MRUBY
412c593315Sopenharmony_ci#  include "shrpx_mruby.h"
422c593315Sopenharmony_ci#endif // HAVE_MRUBY
432c593315Sopenharmony_ci#include "util.h"
442c593315Sopenharmony_ci#include "http2.h"
452c593315Sopenharmony_ci
462c593315Sopenharmony_cinamespace shrpx {
472c593315Sopenharmony_ci
482c593315Sopenharmony_cinamespace {
492c593315Sopenharmony_civoid upstream_timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
502c593315Sopenharmony_ci  auto downstream = static_cast<Downstream *>(w->data);
512c593315Sopenharmony_ci  auto upstream = downstream->get_upstream();
522c593315Sopenharmony_ci
532c593315Sopenharmony_ci  auto which = revents == EV_READ ? "read" : "write";
542c593315Sopenharmony_ci
552c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
562c593315Sopenharmony_ci    DLOG(INFO, downstream) << "upstream timeout stream_id="
572c593315Sopenharmony_ci                           << downstream->get_stream_id() << " event=" << which;
582c593315Sopenharmony_ci  }
592c593315Sopenharmony_ci
602c593315Sopenharmony_ci  downstream->disable_upstream_rtimer();
612c593315Sopenharmony_ci  downstream->disable_upstream_wtimer();
622c593315Sopenharmony_ci
632c593315Sopenharmony_ci  upstream->on_timeout(downstream);
642c593315Sopenharmony_ci}
652c593315Sopenharmony_ci} // namespace
662c593315Sopenharmony_ci
672c593315Sopenharmony_cinamespace {
682c593315Sopenharmony_civoid upstream_rtimeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
692c593315Sopenharmony_ci  upstream_timeoutcb(loop, w, EV_READ);
702c593315Sopenharmony_ci}
712c593315Sopenharmony_ci} // namespace
722c593315Sopenharmony_ci
732c593315Sopenharmony_cinamespace {
742c593315Sopenharmony_civoid upstream_wtimeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
752c593315Sopenharmony_ci  upstream_timeoutcb(loop, w, EV_WRITE);
762c593315Sopenharmony_ci}
772c593315Sopenharmony_ci} // namespace
782c593315Sopenharmony_ci
792c593315Sopenharmony_cinamespace {
802c593315Sopenharmony_civoid downstream_timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
812c593315Sopenharmony_ci  auto downstream = static_cast<Downstream *>(w->data);
822c593315Sopenharmony_ci
832c593315Sopenharmony_ci  auto which = revents == EV_READ ? "read" : "write";
842c593315Sopenharmony_ci
852c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
862c593315Sopenharmony_ci    DLOG(INFO, downstream) << "downstream timeout stream_id="
872c593315Sopenharmony_ci                           << downstream->get_downstream_stream_id()
882c593315Sopenharmony_ci                           << " event=" << which;
892c593315Sopenharmony_ci  }
902c593315Sopenharmony_ci
912c593315Sopenharmony_ci  downstream->disable_downstream_rtimer();
922c593315Sopenharmony_ci  downstream->disable_downstream_wtimer();
932c593315Sopenharmony_ci
942c593315Sopenharmony_ci  auto dconn = downstream->get_downstream_connection();
952c593315Sopenharmony_ci
962c593315Sopenharmony_ci  if (dconn) {
972c593315Sopenharmony_ci    dconn->on_timeout();
982c593315Sopenharmony_ci  }
992c593315Sopenharmony_ci}
1002c593315Sopenharmony_ci} // namespace
1012c593315Sopenharmony_ci
1022c593315Sopenharmony_cinamespace {
1032c593315Sopenharmony_civoid downstream_rtimeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
1042c593315Sopenharmony_ci  downstream_timeoutcb(loop, w, EV_READ);
1052c593315Sopenharmony_ci}
1062c593315Sopenharmony_ci} // namespace
1072c593315Sopenharmony_ci
1082c593315Sopenharmony_cinamespace {
1092c593315Sopenharmony_civoid downstream_wtimeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
1102c593315Sopenharmony_ci  downstream_timeoutcb(loop, w, EV_WRITE);
1112c593315Sopenharmony_ci}
1122c593315Sopenharmony_ci} // namespace
1132c593315Sopenharmony_ci
1142c593315Sopenharmony_ci// upstream could be nullptr for unittests
1152c593315Sopenharmony_ciDownstream::Downstream(Upstream *upstream, MemchunkPool *mcpool,
1162c593315Sopenharmony_ci                       int64_t stream_id)
1172c593315Sopenharmony_ci    : dlnext(nullptr),
1182c593315Sopenharmony_ci      dlprev(nullptr),
1192c593315Sopenharmony_ci      response_sent_body_length(0),
1202c593315Sopenharmony_ci      balloc_(1024, 1024),
1212c593315Sopenharmony_ci      req_(balloc_),
1222c593315Sopenharmony_ci      resp_(balloc_),
1232c593315Sopenharmony_ci      request_start_time_(std::chrono::high_resolution_clock::now()),
1242c593315Sopenharmony_ci      blocked_request_buf_(mcpool),
1252c593315Sopenharmony_ci      request_buf_(mcpool),
1262c593315Sopenharmony_ci      response_buf_(mcpool),
1272c593315Sopenharmony_ci      upstream_(upstream),
1282c593315Sopenharmony_ci      blocked_link_(nullptr),
1292c593315Sopenharmony_ci      addr_(nullptr),
1302c593315Sopenharmony_ci      num_retry_(0),
1312c593315Sopenharmony_ci      stream_id_(stream_id),
1322c593315Sopenharmony_ci      assoc_stream_id_(-1),
1332c593315Sopenharmony_ci      downstream_stream_id_(-1),
1342c593315Sopenharmony_ci      response_rst_stream_error_code_(NGHTTP2_NO_ERROR),
1352c593315Sopenharmony_ci      affinity_cookie_(0),
1362c593315Sopenharmony_ci      request_state_(DownstreamState::INITIAL),
1372c593315Sopenharmony_ci      response_state_(DownstreamState::INITIAL),
1382c593315Sopenharmony_ci      dispatch_state_(DispatchState::NONE),
1392c593315Sopenharmony_ci      upgraded_(false),
1402c593315Sopenharmony_ci      chunked_request_(false),
1412c593315Sopenharmony_ci      chunked_response_(false),
1422c593315Sopenharmony_ci      expect_final_response_(false),
1432c593315Sopenharmony_ci      request_pending_(false),
1442c593315Sopenharmony_ci      request_header_sent_(false),
1452c593315Sopenharmony_ci      accesslog_written_(false),
1462c593315Sopenharmony_ci      new_affinity_cookie_(false),
1472c593315Sopenharmony_ci      blocked_request_data_eof_(false),
1482c593315Sopenharmony_ci      expect_100_continue_(false),
1492c593315Sopenharmony_ci      stop_reading_(false) {
1502c593315Sopenharmony_ci
1512c593315Sopenharmony_ci  auto &timeoutconf = get_config()->http2.timeout;
1522c593315Sopenharmony_ci
1532c593315Sopenharmony_ci  ev_timer_init(&upstream_rtimer_, &upstream_rtimeoutcb, 0.,
1542c593315Sopenharmony_ci                timeoutconf.stream_read);
1552c593315Sopenharmony_ci  ev_timer_init(&upstream_wtimer_, &upstream_wtimeoutcb, 0.,
1562c593315Sopenharmony_ci                timeoutconf.stream_write);
1572c593315Sopenharmony_ci  ev_timer_init(&downstream_rtimer_, &downstream_rtimeoutcb, 0.,
1582c593315Sopenharmony_ci                timeoutconf.stream_read);
1592c593315Sopenharmony_ci  ev_timer_init(&downstream_wtimer_, &downstream_wtimeoutcb, 0.,
1602c593315Sopenharmony_ci                timeoutconf.stream_write);
1612c593315Sopenharmony_ci
1622c593315Sopenharmony_ci  upstream_rtimer_.data = this;
1632c593315Sopenharmony_ci  upstream_wtimer_.data = this;
1642c593315Sopenharmony_ci  downstream_rtimer_.data = this;
1652c593315Sopenharmony_ci  downstream_wtimer_.data = this;
1662c593315Sopenharmony_ci
1672c593315Sopenharmony_ci  rcbufs_.reserve(32);
1682c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
1692c593315Sopenharmony_ci  rcbufs3_.reserve(32);
1702c593315Sopenharmony_ci#endif // ENABLE_HTTP3
1712c593315Sopenharmony_ci}
1722c593315Sopenharmony_ci
1732c593315Sopenharmony_ciDownstream::~Downstream() {
1742c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
1752c593315Sopenharmony_ci    DLOG(INFO, this) << "Deleting";
1762c593315Sopenharmony_ci  }
1772c593315Sopenharmony_ci
1782c593315Sopenharmony_ci  // check nullptr for unittest
1792c593315Sopenharmony_ci  if (upstream_) {
1802c593315Sopenharmony_ci    auto loop = upstream_->get_client_handler()->get_loop();
1812c593315Sopenharmony_ci
1822c593315Sopenharmony_ci    ev_timer_stop(loop, &upstream_rtimer_);
1832c593315Sopenharmony_ci    ev_timer_stop(loop, &upstream_wtimer_);
1842c593315Sopenharmony_ci    ev_timer_stop(loop, &downstream_rtimer_);
1852c593315Sopenharmony_ci    ev_timer_stop(loop, &downstream_wtimer_);
1862c593315Sopenharmony_ci
1872c593315Sopenharmony_ci#ifdef HAVE_MRUBY
1882c593315Sopenharmony_ci    auto handler = upstream_->get_client_handler();
1892c593315Sopenharmony_ci    auto worker = handler->get_worker();
1902c593315Sopenharmony_ci    auto mruby_ctx = worker->get_mruby_context();
1912c593315Sopenharmony_ci
1922c593315Sopenharmony_ci    mruby_ctx->delete_downstream(this);
1932c593315Sopenharmony_ci#endif // HAVE_MRUBY
1942c593315Sopenharmony_ci  }
1952c593315Sopenharmony_ci
1962c593315Sopenharmony_ci#ifdef HAVE_MRUBY
1972c593315Sopenharmony_ci  if (dconn_) {
1982c593315Sopenharmony_ci    const auto &group = dconn_->get_downstream_addr_group();
1992c593315Sopenharmony_ci    if (group) {
2002c593315Sopenharmony_ci      const auto &mruby_ctx = group->shared_addr->mruby_ctx;
2012c593315Sopenharmony_ci      mruby_ctx->delete_downstream(this);
2022c593315Sopenharmony_ci    }
2032c593315Sopenharmony_ci  }
2042c593315Sopenharmony_ci#endif // HAVE_MRUBY
2052c593315Sopenharmony_ci
2062c593315Sopenharmony_ci  // DownstreamConnection may refer to this object.  Delete it now
2072c593315Sopenharmony_ci  // explicitly.
2082c593315Sopenharmony_ci  dconn_.reset();
2092c593315Sopenharmony_ci
2102c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
2112c593315Sopenharmony_ci  for (auto rcbuf : rcbufs3_) {
2122c593315Sopenharmony_ci    nghttp3_rcbuf_decref(rcbuf);
2132c593315Sopenharmony_ci  }
2142c593315Sopenharmony_ci#endif // ENABLE_HTTP3
2152c593315Sopenharmony_ci
2162c593315Sopenharmony_ci  for (auto rcbuf : rcbufs_) {
2172c593315Sopenharmony_ci    nghttp2_rcbuf_decref(rcbuf);
2182c593315Sopenharmony_ci  }
2192c593315Sopenharmony_ci
2202c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
2212c593315Sopenharmony_ci    DLOG(INFO, this) << "Deleted";
2222c593315Sopenharmony_ci  }
2232c593315Sopenharmony_ci}
2242c593315Sopenharmony_ci
2252c593315Sopenharmony_ciint Downstream::attach_downstream_connection(
2262c593315Sopenharmony_ci    std::unique_ptr<DownstreamConnection> dconn) {
2272c593315Sopenharmony_ci  if (dconn->attach_downstream(this) != 0) {
2282c593315Sopenharmony_ci    return -1;
2292c593315Sopenharmony_ci  }
2302c593315Sopenharmony_ci
2312c593315Sopenharmony_ci  dconn_ = std::move(dconn);
2322c593315Sopenharmony_ci
2332c593315Sopenharmony_ci  return 0;
2342c593315Sopenharmony_ci}
2352c593315Sopenharmony_ci
2362c593315Sopenharmony_civoid Downstream::detach_downstream_connection() {
2372c593315Sopenharmony_ci  if (!dconn_) {
2382c593315Sopenharmony_ci    return;
2392c593315Sopenharmony_ci  }
2402c593315Sopenharmony_ci
2412c593315Sopenharmony_ci#ifdef HAVE_MRUBY
2422c593315Sopenharmony_ci  const auto &group = dconn_->get_downstream_addr_group();
2432c593315Sopenharmony_ci  if (group) {
2442c593315Sopenharmony_ci    const auto &mruby_ctx = group->shared_addr->mruby_ctx;
2452c593315Sopenharmony_ci    mruby_ctx->delete_downstream(this);
2462c593315Sopenharmony_ci  }
2472c593315Sopenharmony_ci#endif // HAVE_MRUBY
2482c593315Sopenharmony_ci
2492c593315Sopenharmony_ci  dconn_->detach_downstream(this);
2502c593315Sopenharmony_ci
2512c593315Sopenharmony_ci  auto handler = dconn_->get_client_handler();
2522c593315Sopenharmony_ci
2532c593315Sopenharmony_ci  handler->pool_downstream_connection(
2542c593315Sopenharmony_ci      std::unique_ptr<DownstreamConnection>(dconn_.release()));
2552c593315Sopenharmony_ci}
2562c593315Sopenharmony_ci
2572c593315Sopenharmony_ciDownstreamConnection *Downstream::get_downstream_connection() {
2582c593315Sopenharmony_ci  return dconn_.get();
2592c593315Sopenharmony_ci}
2602c593315Sopenharmony_ci
2612c593315Sopenharmony_cistd::unique_ptr<DownstreamConnection> Downstream::pop_downstream_connection() {
2622c593315Sopenharmony_ci#ifdef HAVE_MRUBY
2632c593315Sopenharmony_ci  if (!dconn_) {
2642c593315Sopenharmony_ci    return nullptr;
2652c593315Sopenharmony_ci  }
2662c593315Sopenharmony_ci
2672c593315Sopenharmony_ci  const auto &group = dconn_->get_downstream_addr_group();
2682c593315Sopenharmony_ci  if (group) {
2692c593315Sopenharmony_ci    const auto &mruby_ctx = group->shared_addr->mruby_ctx;
2702c593315Sopenharmony_ci    mruby_ctx->delete_downstream(this);
2712c593315Sopenharmony_ci  }
2722c593315Sopenharmony_ci#endif // HAVE_MRUBY
2732c593315Sopenharmony_ci
2742c593315Sopenharmony_ci  return std::unique_ptr<DownstreamConnection>(dconn_.release());
2752c593315Sopenharmony_ci}
2762c593315Sopenharmony_ci
2772c593315Sopenharmony_civoid Downstream::pause_read(IOCtrlReason reason) {
2782c593315Sopenharmony_ci  if (dconn_) {
2792c593315Sopenharmony_ci    dconn_->pause_read(reason);
2802c593315Sopenharmony_ci  }
2812c593315Sopenharmony_ci}
2822c593315Sopenharmony_ci
2832c593315Sopenharmony_ciint Downstream::resume_read(IOCtrlReason reason, size_t consumed) {
2842c593315Sopenharmony_ci  if (dconn_) {
2852c593315Sopenharmony_ci    return dconn_->resume_read(reason, consumed);
2862c593315Sopenharmony_ci  }
2872c593315Sopenharmony_ci
2882c593315Sopenharmony_ci  return 0;
2892c593315Sopenharmony_ci}
2902c593315Sopenharmony_ci
2912c593315Sopenharmony_civoid Downstream::force_resume_read() {
2922c593315Sopenharmony_ci  if (dconn_) {
2932c593315Sopenharmony_ci    dconn_->force_resume_read();
2942c593315Sopenharmony_ci  }
2952c593315Sopenharmony_ci}
2962c593315Sopenharmony_ci
2972c593315Sopenharmony_cinamespace {
2982c593315Sopenharmony_ciconst HeaderRefs::value_type *
2992c593315Sopenharmony_cisearch_header_linear_backwards(const HeaderRefs &headers,
3002c593315Sopenharmony_ci                               const StringRef &name) {
3012c593315Sopenharmony_ci  for (auto it = headers.rbegin(); it != headers.rend(); ++it) {
3022c593315Sopenharmony_ci    auto &kv = *it;
3032c593315Sopenharmony_ci    if (kv.name == name) {
3042c593315Sopenharmony_ci      return &kv;
3052c593315Sopenharmony_ci    }
3062c593315Sopenharmony_ci  }
3072c593315Sopenharmony_ci  return nullptr;
3082c593315Sopenharmony_ci}
3092c593315Sopenharmony_ci} // namespace
3102c593315Sopenharmony_ci
3112c593315Sopenharmony_ciStringRef Downstream::assemble_request_cookie() {
3122c593315Sopenharmony_ci  size_t len = 0;
3132c593315Sopenharmony_ci
3142c593315Sopenharmony_ci  for (auto &kv : req_.fs.headers()) {
3152c593315Sopenharmony_ci    if (kv.token != http2::HD_COOKIE || kv.value.empty()) {
3162c593315Sopenharmony_ci      continue;
3172c593315Sopenharmony_ci    }
3182c593315Sopenharmony_ci
3192c593315Sopenharmony_ci    len += kv.value.size() + str_size("; ");
3202c593315Sopenharmony_ci  }
3212c593315Sopenharmony_ci
3222c593315Sopenharmony_ci  auto iov = make_byte_ref(balloc_, len + 1);
3232c593315Sopenharmony_ci  auto p = iov.base;
3242c593315Sopenharmony_ci
3252c593315Sopenharmony_ci  for (auto &kv : req_.fs.headers()) {
3262c593315Sopenharmony_ci    if (kv.token != http2::HD_COOKIE || kv.value.empty()) {
3272c593315Sopenharmony_ci      continue;
3282c593315Sopenharmony_ci    }
3292c593315Sopenharmony_ci
3302c593315Sopenharmony_ci    auto end = std::end(kv.value);
3312c593315Sopenharmony_ci    for (auto it = std::begin(kv.value) + kv.value.size();
3322c593315Sopenharmony_ci         it != std::begin(kv.value); --it) {
3332c593315Sopenharmony_ci      auto c = *(it - 1);
3342c593315Sopenharmony_ci      if (c == ' ' || c == ';') {
3352c593315Sopenharmony_ci        continue;
3362c593315Sopenharmony_ci      }
3372c593315Sopenharmony_ci      end = it;
3382c593315Sopenharmony_ci      break;
3392c593315Sopenharmony_ci    }
3402c593315Sopenharmony_ci
3412c593315Sopenharmony_ci    p = std::copy(std::begin(kv.value), end, p);
3422c593315Sopenharmony_ci    p = util::copy_lit(p, "; ");
3432c593315Sopenharmony_ci  }
3442c593315Sopenharmony_ci
3452c593315Sopenharmony_ci  // cut trailing "; "
3462c593315Sopenharmony_ci  if (p - iov.base >= 2) {
3472c593315Sopenharmony_ci    p -= 2;
3482c593315Sopenharmony_ci  }
3492c593315Sopenharmony_ci
3502c593315Sopenharmony_ci  return StringRef{iov.base, p};
3512c593315Sopenharmony_ci}
3522c593315Sopenharmony_ci
3532c593315Sopenharmony_ciuint32_t Downstream::find_affinity_cookie(const StringRef &name) {
3542c593315Sopenharmony_ci  for (auto &kv : req_.fs.headers()) {
3552c593315Sopenharmony_ci    if (kv.token != http2::HD_COOKIE) {
3562c593315Sopenharmony_ci      continue;
3572c593315Sopenharmony_ci    }
3582c593315Sopenharmony_ci
3592c593315Sopenharmony_ci    for (auto it = std::begin(kv.value); it != std::end(kv.value);) {
3602c593315Sopenharmony_ci      if (*it == '\t' || *it == ' ' || *it == ';') {
3612c593315Sopenharmony_ci        ++it;
3622c593315Sopenharmony_ci        continue;
3632c593315Sopenharmony_ci      }
3642c593315Sopenharmony_ci
3652c593315Sopenharmony_ci      auto end = std::find(it, std::end(kv.value), '=');
3662c593315Sopenharmony_ci      if (end == std::end(kv.value)) {
3672c593315Sopenharmony_ci        return 0;
3682c593315Sopenharmony_ci      }
3692c593315Sopenharmony_ci
3702c593315Sopenharmony_ci      if (!util::streq(name, StringRef{it, end})) {
3712c593315Sopenharmony_ci        it = std::find(it, std::end(kv.value), ';');
3722c593315Sopenharmony_ci        continue;
3732c593315Sopenharmony_ci      }
3742c593315Sopenharmony_ci
3752c593315Sopenharmony_ci      it = std::find(end + 1, std::end(kv.value), ';');
3762c593315Sopenharmony_ci      auto val = StringRef{end + 1, it};
3772c593315Sopenharmony_ci      if (val.size() != 8) {
3782c593315Sopenharmony_ci        return 0;
3792c593315Sopenharmony_ci      }
3802c593315Sopenharmony_ci      uint32_t h = 0;
3812c593315Sopenharmony_ci      for (auto c : val) {
3822c593315Sopenharmony_ci        auto n = util::hex_to_uint(c);
3832c593315Sopenharmony_ci        if (n == 256) {
3842c593315Sopenharmony_ci          return 0;
3852c593315Sopenharmony_ci        }
3862c593315Sopenharmony_ci        h <<= 4;
3872c593315Sopenharmony_ci        h += n;
3882c593315Sopenharmony_ci      }
3892c593315Sopenharmony_ci      affinity_cookie_ = h;
3902c593315Sopenharmony_ci      return h;
3912c593315Sopenharmony_ci    }
3922c593315Sopenharmony_ci  }
3932c593315Sopenharmony_ci  return 0;
3942c593315Sopenharmony_ci}
3952c593315Sopenharmony_ci
3962c593315Sopenharmony_cisize_t Downstream::count_crumble_request_cookie() {
3972c593315Sopenharmony_ci  size_t n = 0;
3982c593315Sopenharmony_ci  for (auto &kv : req_.fs.headers()) {
3992c593315Sopenharmony_ci    if (kv.token != http2::HD_COOKIE) {
4002c593315Sopenharmony_ci      continue;
4012c593315Sopenharmony_ci    }
4022c593315Sopenharmony_ci
4032c593315Sopenharmony_ci    for (auto it = std::begin(kv.value); it != std::end(kv.value);) {
4042c593315Sopenharmony_ci      if (*it == '\t' || *it == ' ' || *it == ';') {
4052c593315Sopenharmony_ci        ++it;
4062c593315Sopenharmony_ci        continue;
4072c593315Sopenharmony_ci      }
4082c593315Sopenharmony_ci
4092c593315Sopenharmony_ci      it = std::find(it, std::end(kv.value), ';');
4102c593315Sopenharmony_ci
4112c593315Sopenharmony_ci      ++n;
4122c593315Sopenharmony_ci    }
4132c593315Sopenharmony_ci  }
4142c593315Sopenharmony_ci  return n;
4152c593315Sopenharmony_ci}
4162c593315Sopenharmony_ci
4172c593315Sopenharmony_civoid Downstream::crumble_request_cookie(std::vector<nghttp2_nv> &nva) {
4182c593315Sopenharmony_ci  for (auto &kv : req_.fs.headers()) {
4192c593315Sopenharmony_ci    if (kv.token != http2::HD_COOKIE) {
4202c593315Sopenharmony_ci      continue;
4212c593315Sopenharmony_ci    }
4222c593315Sopenharmony_ci
4232c593315Sopenharmony_ci    for (auto it = std::begin(kv.value); it != std::end(kv.value);) {
4242c593315Sopenharmony_ci      if (*it == '\t' || *it == ' ' || *it == ';') {
4252c593315Sopenharmony_ci        ++it;
4262c593315Sopenharmony_ci        continue;
4272c593315Sopenharmony_ci      }
4282c593315Sopenharmony_ci
4292c593315Sopenharmony_ci      auto first = it;
4302c593315Sopenharmony_ci
4312c593315Sopenharmony_ci      it = std::find(it, std::end(kv.value), ';');
4322c593315Sopenharmony_ci
4332c593315Sopenharmony_ci      nva.push_back({(uint8_t *)"cookie", (uint8_t *)first, str_size("cookie"),
4342c593315Sopenharmony_ci                     (size_t)(it - first),
4352c593315Sopenharmony_ci                     (uint8_t)(NGHTTP2_NV_FLAG_NO_COPY_NAME |
4362c593315Sopenharmony_ci                               NGHTTP2_NV_FLAG_NO_COPY_VALUE |
4372c593315Sopenharmony_ci                               (kv.no_index ? NGHTTP2_NV_FLAG_NO_INDEX : 0))});
4382c593315Sopenharmony_ci    }
4392c593315Sopenharmony_ci  }
4402c593315Sopenharmony_ci}
4412c593315Sopenharmony_ci
4422c593315Sopenharmony_cinamespace {
4432c593315Sopenharmony_civoid add_header(size_t &sum, HeaderRefs &headers, const StringRef &name,
4442c593315Sopenharmony_ci                const StringRef &value, bool no_index, int32_t token) {
4452c593315Sopenharmony_ci  sum += name.size() + value.size();
4462c593315Sopenharmony_ci  headers.emplace_back(name, value, no_index, token);
4472c593315Sopenharmony_ci}
4482c593315Sopenharmony_ci} // namespace
4492c593315Sopenharmony_ci
4502c593315Sopenharmony_cinamespace {
4512c593315Sopenharmony_ciStringRef alloc_header_name(BlockAllocator &balloc, const StringRef &name) {
4522c593315Sopenharmony_ci  auto iov = make_byte_ref(balloc, name.size() + 1);
4532c593315Sopenharmony_ci  auto p = iov.base;
4542c593315Sopenharmony_ci  p = std::copy(std::begin(name), std::end(name), p);
4552c593315Sopenharmony_ci  util::inp_strlower(iov.base, p);
4562c593315Sopenharmony_ci  *p = '\0';
4572c593315Sopenharmony_ci
4582c593315Sopenharmony_ci  return StringRef{iov.base, p};
4592c593315Sopenharmony_ci}
4602c593315Sopenharmony_ci} // namespace
4612c593315Sopenharmony_ci
4622c593315Sopenharmony_cinamespace {
4632c593315Sopenharmony_civoid append_last_header_key(BlockAllocator &balloc, bool &key_prev, size_t &sum,
4642c593315Sopenharmony_ci                            HeaderRefs &headers, const char *data, size_t len) {
4652c593315Sopenharmony_ci  assert(key_prev);
4662c593315Sopenharmony_ci  sum += len;
4672c593315Sopenharmony_ci  auto &item = headers.back();
4682c593315Sopenharmony_ci  auto name =
4692c593315Sopenharmony_ci      realloc_concat_string_ref(balloc, item.name, StringRef{data, len});
4702c593315Sopenharmony_ci
4712c593315Sopenharmony_ci  auto p = const_cast<uint8_t *>(name.byte());
4722c593315Sopenharmony_ci  util::inp_strlower(p + name.size() - len, p + name.size());
4732c593315Sopenharmony_ci
4742c593315Sopenharmony_ci  item.name = name;
4752c593315Sopenharmony_ci  item.token = http2::lookup_token(item.name);
4762c593315Sopenharmony_ci}
4772c593315Sopenharmony_ci} // namespace
4782c593315Sopenharmony_ci
4792c593315Sopenharmony_cinamespace {
4802c593315Sopenharmony_civoid append_last_header_value(BlockAllocator &balloc, bool &key_prev,
4812c593315Sopenharmony_ci                              size_t &sum, HeaderRefs &headers,
4822c593315Sopenharmony_ci                              const char *data, size_t len) {
4832c593315Sopenharmony_ci  key_prev = false;
4842c593315Sopenharmony_ci  sum += len;
4852c593315Sopenharmony_ci  auto &item = headers.back();
4862c593315Sopenharmony_ci  item.value =
4872c593315Sopenharmony_ci      realloc_concat_string_ref(balloc, item.value, StringRef{data, len});
4882c593315Sopenharmony_ci}
4892c593315Sopenharmony_ci} // namespace
4902c593315Sopenharmony_ci
4912c593315Sopenharmony_ciint FieldStore::parse_content_length() {
4922c593315Sopenharmony_ci  content_length = -1;
4932c593315Sopenharmony_ci
4942c593315Sopenharmony_ci  for (auto &kv : headers_) {
4952c593315Sopenharmony_ci    if (kv.token != http2::HD_CONTENT_LENGTH) {
4962c593315Sopenharmony_ci      continue;
4972c593315Sopenharmony_ci    }
4982c593315Sopenharmony_ci
4992c593315Sopenharmony_ci    auto len = util::parse_uint(kv.value);
5002c593315Sopenharmony_ci    if (len == -1) {
5012c593315Sopenharmony_ci      return -1;
5022c593315Sopenharmony_ci    }
5032c593315Sopenharmony_ci    if (content_length != -1) {
5042c593315Sopenharmony_ci      return -1;
5052c593315Sopenharmony_ci    }
5062c593315Sopenharmony_ci    content_length = len;
5072c593315Sopenharmony_ci  }
5082c593315Sopenharmony_ci  return 0;
5092c593315Sopenharmony_ci}
5102c593315Sopenharmony_ci
5112c593315Sopenharmony_ciconst HeaderRefs::value_type *FieldStore::header(int32_t token) const {
5122c593315Sopenharmony_ci  for (auto it = headers_.rbegin(); it != headers_.rend(); ++it) {
5132c593315Sopenharmony_ci    auto &kv = *it;
5142c593315Sopenharmony_ci    if (kv.token == token) {
5152c593315Sopenharmony_ci      return &kv;
5162c593315Sopenharmony_ci    }
5172c593315Sopenharmony_ci  }
5182c593315Sopenharmony_ci  return nullptr;
5192c593315Sopenharmony_ci}
5202c593315Sopenharmony_ci
5212c593315Sopenharmony_ciHeaderRefs::value_type *FieldStore::header(int32_t token) {
5222c593315Sopenharmony_ci  for (auto it = headers_.rbegin(); it != headers_.rend(); ++it) {
5232c593315Sopenharmony_ci    auto &kv = *it;
5242c593315Sopenharmony_ci    if (kv.token == token) {
5252c593315Sopenharmony_ci      return &kv;
5262c593315Sopenharmony_ci    }
5272c593315Sopenharmony_ci  }
5282c593315Sopenharmony_ci  return nullptr;
5292c593315Sopenharmony_ci}
5302c593315Sopenharmony_ci
5312c593315Sopenharmony_ciconst HeaderRefs::value_type *FieldStore::header(const StringRef &name) const {
5322c593315Sopenharmony_ci  return search_header_linear_backwards(headers_, name);
5332c593315Sopenharmony_ci}
5342c593315Sopenharmony_ci
5352c593315Sopenharmony_civoid FieldStore::add_header_token(const StringRef &name, const StringRef &value,
5362c593315Sopenharmony_ci                                  bool no_index, int32_t token) {
5372c593315Sopenharmony_ci  shrpx::add_header(buffer_size_, headers_, name, value, no_index, token);
5382c593315Sopenharmony_ci}
5392c593315Sopenharmony_ci
5402c593315Sopenharmony_civoid FieldStore::alloc_add_header_name(const StringRef &name) {
5412c593315Sopenharmony_ci  auto name_ref = alloc_header_name(balloc_, name);
5422c593315Sopenharmony_ci  auto token = http2::lookup_token(name_ref);
5432c593315Sopenharmony_ci  add_header_token(name_ref, StringRef{}, false, token);
5442c593315Sopenharmony_ci  header_key_prev_ = true;
5452c593315Sopenharmony_ci}
5462c593315Sopenharmony_ci
5472c593315Sopenharmony_civoid FieldStore::append_last_header_key(const char *data, size_t len) {
5482c593315Sopenharmony_ci  shrpx::append_last_header_key(balloc_, header_key_prev_, buffer_size_,
5492c593315Sopenharmony_ci                                headers_, data, len);
5502c593315Sopenharmony_ci}
5512c593315Sopenharmony_ci
5522c593315Sopenharmony_civoid FieldStore::append_last_header_value(const char *data, size_t len) {
5532c593315Sopenharmony_ci  shrpx::append_last_header_value(balloc_, header_key_prev_, buffer_size_,
5542c593315Sopenharmony_ci                                  headers_, data, len);
5552c593315Sopenharmony_ci}
5562c593315Sopenharmony_ci
5572c593315Sopenharmony_civoid FieldStore::clear_headers() {
5582c593315Sopenharmony_ci  headers_.clear();
5592c593315Sopenharmony_ci  header_key_prev_ = false;
5602c593315Sopenharmony_ci}
5612c593315Sopenharmony_ci
5622c593315Sopenharmony_civoid FieldStore::add_trailer_token(const StringRef &name,
5632c593315Sopenharmony_ci                                   const StringRef &value, bool no_index,
5642c593315Sopenharmony_ci                                   int32_t token) {
5652c593315Sopenharmony_ci  // Header size limit should be applied to all header and trailer
5662c593315Sopenharmony_ci  // fields combined.
5672c593315Sopenharmony_ci  shrpx::add_header(buffer_size_, trailers_, name, value, no_index, token);
5682c593315Sopenharmony_ci}
5692c593315Sopenharmony_ci
5702c593315Sopenharmony_civoid FieldStore::alloc_add_trailer_name(const StringRef &name) {
5712c593315Sopenharmony_ci  auto name_ref = alloc_header_name(balloc_, name);
5722c593315Sopenharmony_ci  auto token = http2::lookup_token(name_ref);
5732c593315Sopenharmony_ci  add_trailer_token(name_ref, StringRef{}, false, token);
5742c593315Sopenharmony_ci  trailer_key_prev_ = true;
5752c593315Sopenharmony_ci}
5762c593315Sopenharmony_ci
5772c593315Sopenharmony_civoid FieldStore::append_last_trailer_key(const char *data, size_t len) {
5782c593315Sopenharmony_ci  shrpx::append_last_header_key(balloc_, trailer_key_prev_, buffer_size_,
5792c593315Sopenharmony_ci                                trailers_, data, len);
5802c593315Sopenharmony_ci}
5812c593315Sopenharmony_ci
5822c593315Sopenharmony_civoid FieldStore::append_last_trailer_value(const char *data, size_t len) {
5832c593315Sopenharmony_ci  shrpx::append_last_header_value(balloc_, trailer_key_prev_, buffer_size_,
5842c593315Sopenharmony_ci                                  trailers_, data, len);
5852c593315Sopenharmony_ci}
5862c593315Sopenharmony_ci
5872c593315Sopenharmony_civoid FieldStore::erase_content_length_and_transfer_encoding() {
5882c593315Sopenharmony_ci  for (auto &kv : headers_) {
5892c593315Sopenharmony_ci    switch (kv.token) {
5902c593315Sopenharmony_ci    case http2::HD_CONTENT_LENGTH:
5912c593315Sopenharmony_ci    case http2::HD_TRANSFER_ENCODING:
5922c593315Sopenharmony_ci      kv.name = StringRef{};
5932c593315Sopenharmony_ci      kv.token = -1;
5942c593315Sopenharmony_ci      break;
5952c593315Sopenharmony_ci    }
5962c593315Sopenharmony_ci  }
5972c593315Sopenharmony_ci}
5982c593315Sopenharmony_ci
5992c593315Sopenharmony_civoid Downstream::set_request_start_time(
6002c593315Sopenharmony_ci    std::chrono::high_resolution_clock::time_point time) {
6012c593315Sopenharmony_ci  request_start_time_ = std::move(time);
6022c593315Sopenharmony_ci}
6032c593315Sopenharmony_ci
6042c593315Sopenharmony_ciconst std::chrono::high_resolution_clock::time_point &
6052c593315Sopenharmony_ciDownstream::get_request_start_time() const {
6062c593315Sopenharmony_ci  return request_start_time_;
6072c593315Sopenharmony_ci}
6082c593315Sopenharmony_ci
6092c593315Sopenharmony_civoid Downstream::reset_upstream(Upstream *upstream) {
6102c593315Sopenharmony_ci  upstream_ = upstream;
6112c593315Sopenharmony_ci  if (dconn_) {
6122c593315Sopenharmony_ci    dconn_->on_upstream_change(upstream);
6132c593315Sopenharmony_ci  }
6142c593315Sopenharmony_ci}
6152c593315Sopenharmony_ci
6162c593315Sopenharmony_ciUpstream *Downstream::get_upstream() const { return upstream_; }
6172c593315Sopenharmony_ci
6182c593315Sopenharmony_civoid Downstream::set_stream_id(int64_t stream_id) { stream_id_ = stream_id; }
6192c593315Sopenharmony_ci
6202c593315Sopenharmony_ciint64_t Downstream::get_stream_id() const { return stream_id_; }
6212c593315Sopenharmony_ci
6222c593315Sopenharmony_civoid Downstream::set_request_state(DownstreamState state) {
6232c593315Sopenharmony_ci  request_state_ = state;
6242c593315Sopenharmony_ci}
6252c593315Sopenharmony_ci
6262c593315Sopenharmony_ciDownstreamState Downstream::get_request_state() const { return request_state_; }
6272c593315Sopenharmony_ci
6282c593315Sopenharmony_cibool Downstream::get_chunked_request() const { return chunked_request_; }
6292c593315Sopenharmony_ci
6302c593315Sopenharmony_civoid Downstream::set_chunked_request(bool f) { chunked_request_ = f; }
6312c593315Sopenharmony_ci
6322c593315Sopenharmony_cibool Downstream::request_buf_full() {
6332c593315Sopenharmony_ci  auto handler = upstream_->get_client_handler();
6342c593315Sopenharmony_ci  auto faddr = handler->get_upstream_addr();
6352c593315Sopenharmony_ci  auto worker = handler->get_worker();
6362c593315Sopenharmony_ci
6372c593315Sopenharmony_ci  // We don't check buffer size here for API endpoint.
6382c593315Sopenharmony_ci  if (faddr->alt_mode == UpstreamAltMode::API) {
6392c593315Sopenharmony_ci    return false;
6402c593315Sopenharmony_ci  }
6412c593315Sopenharmony_ci
6422c593315Sopenharmony_ci  if (dconn_) {
6432c593315Sopenharmony_ci    auto &downstreamconf = *worker->get_downstream_config();
6442c593315Sopenharmony_ci    return blocked_request_buf_.rleft() + request_buf_.rleft() >=
6452c593315Sopenharmony_ci           downstreamconf.request_buffer_size;
6462c593315Sopenharmony_ci  }
6472c593315Sopenharmony_ci
6482c593315Sopenharmony_ci  return false;
6492c593315Sopenharmony_ci}
6502c593315Sopenharmony_ci
6512c593315Sopenharmony_ciDefaultMemchunks *Downstream::get_request_buf() { return &request_buf_; }
6522c593315Sopenharmony_ci
6532c593315Sopenharmony_ci// Call this function after this object is attached to
6542c593315Sopenharmony_ci// Downstream. Otherwise, the program will crash.
6552c593315Sopenharmony_ciint Downstream::push_request_headers() {
6562c593315Sopenharmony_ci  if (!dconn_) {
6572c593315Sopenharmony_ci    DLOG(INFO, this) << "dconn_ is NULL";
6582c593315Sopenharmony_ci    return -1;
6592c593315Sopenharmony_ci  }
6602c593315Sopenharmony_ci  return dconn_->push_request_headers();
6612c593315Sopenharmony_ci}
6622c593315Sopenharmony_ci
6632c593315Sopenharmony_ciint Downstream::push_upload_data_chunk(const uint8_t *data, size_t datalen) {
6642c593315Sopenharmony_ci  req_.recv_body_length += datalen;
6652c593315Sopenharmony_ci
6662c593315Sopenharmony_ci  if (!dconn_ && !request_header_sent_) {
6672c593315Sopenharmony_ci    blocked_request_buf_.append(data, datalen);
6682c593315Sopenharmony_ci    req_.unconsumed_body_length += datalen;
6692c593315Sopenharmony_ci    return 0;
6702c593315Sopenharmony_ci  }
6712c593315Sopenharmony_ci
6722c593315Sopenharmony_ci  // Assumes that request headers have already been pushed to output
6732c593315Sopenharmony_ci  // buffer using push_request_headers().
6742c593315Sopenharmony_ci  if (!dconn_) {
6752c593315Sopenharmony_ci    DLOG(INFO, this) << "dconn_ is NULL";
6762c593315Sopenharmony_ci    return -1;
6772c593315Sopenharmony_ci  }
6782c593315Sopenharmony_ci  if (dconn_->push_upload_data_chunk(data, datalen) != 0) {
6792c593315Sopenharmony_ci    return -1;
6802c593315Sopenharmony_ci  }
6812c593315Sopenharmony_ci
6822c593315Sopenharmony_ci  req_.unconsumed_body_length += datalen;
6832c593315Sopenharmony_ci
6842c593315Sopenharmony_ci  return 0;
6852c593315Sopenharmony_ci}
6862c593315Sopenharmony_ci
6872c593315Sopenharmony_ciint Downstream::end_upload_data() {
6882c593315Sopenharmony_ci  if (!dconn_ && !request_header_sent_) {
6892c593315Sopenharmony_ci    blocked_request_data_eof_ = true;
6902c593315Sopenharmony_ci    return 0;
6912c593315Sopenharmony_ci  }
6922c593315Sopenharmony_ci  if (!dconn_) {
6932c593315Sopenharmony_ci    DLOG(INFO, this) << "dconn_ is NULL";
6942c593315Sopenharmony_ci    return -1;
6952c593315Sopenharmony_ci  }
6962c593315Sopenharmony_ci  return dconn_->end_upload_data();
6972c593315Sopenharmony_ci}
6982c593315Sopenharmony_ci
6992c593315Sopenharmony_civoid Downstream::rewrite_location_response_header(
7002c593315Sopenharmony_ci    const StringRef &upstream_scheme) {
7012c593315Sopenharmony_ci  auto hd = resp_.fs.header(http2::HD_LOCATION);
7022c593315Sopenharmony_ci  if (!hd) {
7032c593315Sopenharmony_ci    return;
7042c593315Sopenharmony_ci  }
7052c593315Sopenharmony_ci
7062c593315Sopenharmony_ci  if (request_downstream_host_.empty() || req_.authority.empty()) {
7072c593315Sopenharmony_ci    return;
7082c593315Sopenharmony_ci  }
7092c593315Sopenharmony_ci
7102c593315Sopenharmony_ci  http_parser_url u{};
7112c593315Sopenharmony_ci  auto rv = http_parser_parse_url(hd->value.c_str(), hd->value.size(), 0, &u);
7122c593315Sopenharmony_ci  if (rv != 0) {
7132c593315Sopenharmony_ci    return;
7142c593315Sopenharmony_ci  }
7152c593315Sopenharmony_ci
7162c593315Sopenharmony_ci  auto new_uri = http2::rewrite_location_uri(balloc_, hd->value, u,
7172c593315Sopenharmony_ci                                             request_downstream_host_,
7182c593315Sopenharmony_ci                                             req_.authority, upstream_scheme);
7192c593315Sopenharmony_ci
7202c593315Sopenharmony_ci  if (new_uri.empty()) {
7212c593315Sopenharmony_ci    return;
7222c593315Sopenharmony_ci  }
7232c593315Sopenharmony_ci
7242c593315Sopenharmony_ci  hd->value = new_uri;
7252c593315Sopenharmony_ci}
7262c593315Sopenharmony_ci
7272c593315Sopenharmony_cibool Downstream::get_chunked_response() const { return chunked_response_; }
7282c593315Sopenharmony_ci
7292c593315Sopenharmony_civoid Downstream::set_chunked_response(bool f) { chunked_response_ = f; }
7302c593315Sopenharmony_ci
7312c593315Sopenharmony_ciint Downstream::on_read() {
7322c593315Sopenharmony_ci  if (!dconn_) {
7332c593315Sopenharmony_ci    DLOG(INFO, this) << "dconn_ is NULL";
7342c593315Sopenharmony_ci    return -1;
7352c593315Sopenharmony_ci  }
7362c593315Sopenharmony_ci  return dconn_->on_read();
7372c593315Sopenharmony_ci}
7382c593315Sopenharmony_ci
7392c593315Sopenharmony_civoid Downstream::set_response_state(DownstreamState state) {
7402c593315Sopenharmony_ci  response_state_ = state;
7412c593315Sopenharmony_ci}
7422c593315Sopenharmony_ci
7432c593315Sopenharmony_ciDownstreamState Downstream::get_response_state() const {
7442c593315Sopenharmony_ci  return response_state_;
7452c593315Sopenharmony_ci}
7462c593315Sopenharmony_ci
7472c593315Sopenharmony_ciDefaultMemchunks *Downstream::get_response_buf() { return &response_buf_; }
7482c593315Sopenharmony_ci
7492c593315Sopenharmony_cibool Downstream::response_buf_full() {
7502c593315Sopenharmony_ci  if (dconn_) {
7512c593315Sopenharmony_ci    auto handler = upstream_->get_client_handler();
7522c593315Sopenharmony_ci    auto worker = handler->get_worker();
7532c593315Sopenharmony_ci    auto &downstreamconf = *worker->get_downstream_config();
7542c593315Sopenharmony_ci
7552c593315Sopenharmony_ci    return response_buf_.rleft() >= downstreamconf.response_buffer_size;
7562c593315Sopenharmony_ci  }
7572c593315Sopenharmony_ci
7582c593315Sopenharmony_ci  return false;
7592c593315Sopenharmony_ci}
7602c593315Sopenharmony_ci
7612c593315Sopenharmony_cibool Downstream::validate_request_recv_body_length() const {
7622c593315Sopenharmony_ci  if (req_.fs.content_length == -1) {
7632c593315Sopenharmony_ci    return true;
7642c593315Sopenharmony_ci  }
7652c593315Sopenharmony_ci
7662c593315Sopenharmony_ci  if (req_.fs.content_length != req_.recv_body_length) {
7672c593315Sopenharmony_ci    if (LOG_ENABLED(INFO)) {
7682c593315Sopenharmony_ci      DLOG(INFO, this) << "request invalid bodylen: content-length="
7692c593315Sopenharmony_ci                       << req_.fs.content_length
7702c593315Sopenharmony_ci                       << ", received=" << req_.recv_body_length;
7712c593315Sopenharmony_ci    }
7722c593315Sopenharmony_ci    return false;
7732c593315Sopenharmony_ci  }
7742c593315Sopenharmony_ci
7752c593315Sopenharmony_ci  return true;
7762c593315Sopenharmony_ci}
7772c593315Sopenharmony_ci
7782c593315Sopenharmony_cibool Downstream::validate_response_recv_body_length() const {
7792c593315Sopenharmony_ci  if (!expect_response_body() || resp_.fs.content_length == -1) {
7802c593315Sopenharmony_ci    return true;
7812c593315Sopenharmony_ci  }
7822c593315Sopenharmony_ci
7832c593315Sopenharmony_ci  if (resp_.fs.content_length != resp_.recv_body_length) {
7842c593315Sopenharmony_ci    if (LOG_ENABLED(INFO)) {
7852c593315Sopenharmony_ci      DLOG(INFO, this) << "response invalid bodylen: content-length="
7862c593315Sopenharmony_ci                       << resp_.fs.content_length
7872c593315Sopenharmony_ci                       << ", received=" << resp_.recv_body_length;
7882c593315Sopenharmony_ci    }
7892c593315Sopenharmony_ci    return false;
7902c593315Sopenharmony_ci  }
7912c593315Sopenharmony_ci
7922c593315Sopenharmony_ci  return true;
7932c593315Sopenharmony_ci}
7942c593315Sopenharmony_ci
7952c593315Sopenharmony_civoid Downstream::check_upgrade_fulfilled_http2() {
7962c593315Sopenharmony_ci  // This handles nonzero req_.connect_proto and h1 frontend requests
7972c593315Sopenharmony_ci  // WebSocket upgrade.
7982c593315Sopenharmony_ci  upgraded_ = (req_.method == HTTP_CONNECT ||
7992c593315Sopenharmony_ci               req_.connect_proto == ConnectProto::WEBSOCKET) &&
8002c593315Sopenharmony_ci              resp_.http_status / 100 == 2;
8012c593315Sopenharmony_ci}
8022c593315Sopenharmony_ci
8032c593315Sopenharmony_civoid Downstream::check_upgrade_fulfilled_http1() {
8042c593315Sopenharmony_ci  if (req_.method == HTTP_CONNECT) {
8052c593315Sopenharmony_ci    if (req_.connect_proto == ConnectProto::WEBSOCKET) {
8062c593315Sopenharmony_ci      if (resp_.http_status != 101) {
8072c593315Sopenharmony_ci        return;
8082c593315Sopenharmony_ci      }
8092c593315Sopenharmony_ci
8102c593315Sopenharmony_ci      // This is done for HTTP/2 frontend only.
8112c593315Sopenharmony_ci      auto accept = resp_.fs.header(http2::HD_SEC_WEBSOCKET_ACCEPT);
8122c593315Sopenharmony_ci      if (!accept) {
8132c593315Sopenharmony_ci        return;
8142c593315Sopenharmony_ci      }
8152c593315Sopenharmony_ci
8162c593315Sopenharmony_ci      std::array<uint8_t, base64::encode_length(20)> accept_buf;
8172c593315Sopenharmony_ci      auto expected =
8182c593315Sopenharmony_ci          http2::make_websocket_accept_token(accept_buf.data(), ws_key_);
8192c593315Sopenharmony_ci
8202c593315Sopenharmony_ci      upgraded_ = expected != "" && expected == accept->value;
8212c593315Sopenharmony_ci    } else {
8222c593315Sopenharmony_ci      upgraded_ = resp_.http_status / 100 == 2;
8232c593315Sopenharmony_ci    }
8242c593315Sopenharmony_ci
8252c593315Sopenharmony_ci    return;
8262c593315Sopenharmony_ci  }
8272c593315Sopenharmony_ci
8282c593315Sopenharmony_ci  if (resp_.http_status == 101) {
8292c593315Sopenharmony_ci    // TODO Do more strict checking for upgrade headers
8302c593315Sopenharmony_ci    upgraded_ = req_.upgrade_request;
8312c593315Sopenharmony_ci
8322c593315Sopenharmony_ci    return;
8332c593315Sopenharmony_ci  }
8342c593315Sopenharmony_ci}
8352c593315Sopenharmony_ci
8362c593315Sopenharmony_civoid Downstream::inspect_http2_request() {
8372c593315Sopenharmony_ci  if (req_.method == HTTP_CONNECT) {
8382c593315Sopenharmony_ci    req_.upgrade_request = true;
8392c593315Sopenharmony_ci  }
8402c593315Sopenharmony_ci}
8412c593315Sopenharmony_ci
8422c593315Sopenharmony_civoid Downstream::inspect_http1_request() {
8432c593315Sopenharmony_ci  if (req_.method == HTTP_CONNECT) {
8442c593315Sopenharmony_ci    req_.upgrade_request = true;
8452c593315Sopenharmony_ci  } else if (req_.http_minor > 0) {
8462c593315Sopenharmony_ci    auto upgrade = req_.fs.header(http2::HD_UPGRADE);
8472c593315Sopenharmony_ci    if (upgrade) {
8482c593315Sopenharmony_ci      const auto &val = upgrade->value;
8492c593315Sopenharmony_ci      // TODO Perform more strict checking for upgrade headers
8502c593315Sopenharmony_ci      if (util::streq_l(NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, val.c_str(),
8512c593315Sopenharmony_ci                        val.size())) {
8522c593315Sopenharmony_ci        req_.http2_upgrade_seen = true;
8532c593315Sopenharmony_ci      } else {
8542c593315Sopenharmony_ci        req_.upgrade_request = true;
8552c593315Sopenharmony_ci
8562c593315Sopenharmony_ci        // TODO Should we check Sec-WebSocket-Key, and
8572c593315Sopenharmony_ci        // Sec-WebSocket-Version as well?
8582c593315Sopenharmony_ci        if (util::strieq_l("websocket", val)) {
8592c593315Sopenharmony_ci          req_.connect_proto = ConnectProto::WEBSOCKET;
8602c593315Sopenharmony_ci        }
8612c593315Sopenharmony_ci      }
8622c593315Sopenharmony_ci    }
8632c593315Sopenharmony_ci  }
8642c593315Sopenharmony_ci  auto transfer_encoding = req_.fs.header(http2::HD_TRANSFER_ENCODING);
8652c593315Sopenharmony_ci  if (transfer_encoding) {
8662c593315Sopenharmony_ci    req_.fs.content_length = -1;
8672c593315Sopenharmony_ci  }
8682c593315Sopenharmony_ci
8692c593315Sopenharmony_ci  auto expect = req_.fs.header(http2::HD_EXPECT);
8702c593315Sopenharmony_ci  expect_100_continue_ =
8712c593315Sopenharmony_ci      expect &&
8722c593315Sopenharmony_ci      util::strieq(expect->value, StringRef::from_lit("100-continue"));
8732c593315Sopenharmony_ci}
8742c593315Sopenharmony_ci
8752c593315Sopenharmony_civoid Downstream::inspect_http1_response() {
8762c593315Sopenharmony_ci  auto transfer_encoding = resp_.fs.header(http2::HD_TRANSFER_ENCODING);
8772c593315Sopenharmony_ci  if (transfer_encoding) {
8782c593315Sopenharmony_ci    resp_.fs.content_length = -1;
8792c593315Sopenharmony_ci  }
8802c593315Sopenharmony_ci}
8812c593315Sopenharmony_ci
8822c593315Sopenharmony_civoid Downstream::reset_response() {
8832c593315Sopenharmony_ci  resp_.http_status = 0;
8842c593315Sopenharmony_ci  resp_.http_major = 1;
8852c593315Sopenharmony_ci  resp_.http_minor = 1;
8862c593315Sopenharmony_ci}
8872c593315Sopenharmony_ci
8882c593315Sopenharmony_cibool Downstream::get_non_final_response() const {
8892c593315Sopenharmony_ci  return !upgraded_ && resp_.http_status / 100 == 1;
8902c593315Sopenharmony_ci}
8912c593315Sopenharmony_ci
8922c593315Sopenharmony_cibool Downstream::supports_non_final_response() const {
8932c593315Sopenharmony_ci  return req_.http_major == 3 || req_.http_major == 2 ||
8942c593315Sopenharmony_ci         (req_.http_major == 1 && req_.http_minor == 1);
8952c593315Sopenharmony_ci}
8962c593315Sopenharmony_ci
8972c593315Sopenharmony_cibool Downstream::get_upgraded() const { return upgraded_; }
8982c593315Sopenharmony_ci
8992c593315Sopenharmony_cibool Downstream::get_http2_upgrade_request() const {
9002c593315Sopenharmony_ci  return req_.http2_upgrade_seen && req_.fs.header(http2::HD_HTTP2_SETTINGS) &&
9012c593315Sopenharmony_ci         response_state_ == DownstreamState::INITIAL;
9022c593315Sopenharmony_ci}
9032c593315Sopenharmony_ci
9042c593315Sopenharmony_ciStringRef Downstream::get_http2_settings() const {
9052c593315Sopenharmony_ci  auto http2_settings = req_.fs.header(http2::HD_HTTP2_SETTINGS);
9062c593315Sopenharmony_ci  if (!http2_settings) {
9072c593315Sopenharmony_ci    return StringRef{};
9082c593315Sopenharmony_ci  }
9092c593315Sopenharmony_ci  return http2_settings->value;
9102c593315Sopenharmony_ci}
9112c593315Sopenharmony_ci
9122c593315Sopenharmony_civoid Downstream::set_downstream_stream_id(int64_t stream_id) {
9132c593315Sopenharmony_ci  downstream_stream_id_ = stream_id;
9142c593315Sopenharmony_ci}
9152c593315Sopenharmony_ci
9162c593315Sopenharmony_ciint64_t Downstream::get_downstream_stream_id() const {
9172c593315Sopenharmony_ci  return downstream_stream_id_;
9182c593315Sopenharmony_ci}
9192c593315Sopenharmony_ci
9202c593315Sopenharmony_ciuint32_t Downstream::get_response_rst_stream_error_code() const {
9212c593315Sopenharmony_ci  return response_rst_stream_error_code_;
9222c593315Sopenharmony_ci}
9232c593315Sopenharmony_ci
9242c593315Sopenharmony_civoid Downstream::set_response_rst_stream_error_code(uint32_t error_code) {
9252c593315Sopenharmony_ci  response_rst_stream_error_code_ = error_code;
9262c593315Sopenharmony_ci}
9272c593315Sopenharmony_ci
9282c593315Sopenharmony_civoid Downstream::set_expect_final_response(bool f) {
9292c593315Sopenharmony_ci  expect_final_response_ = f;
9302c593315Sopenharmony_ci}
9312c593315Sopenharmony_ci
9322c593315Sopenharmony_cibool Downstream::get_expect_final_response() const {
9332c593315Sopenharmony_ci  return expect_final_response_;
9342c593315Sopenharmony_ci}
9352c593315Sopenharmony_ci
9362c593315Sopenharmony_cibool Downstream::expect_response_body() const {
9372c593315Sopenharmony_ci  return !resp_.headers_only &&
9382c593315Sopenharmony_ci         http2::expect_response_body(req_.method, resp_.http_status);
9392c593315Sopenharmony_ci}
9402c593315Sopenharmony_ci
9412c593315Sopenharmony_cibool Downstream::expect_response_trailer() const {
9422c593315Sopenharmony_ci  // In HTTP/2, if final response HEADERS does not bear END_STREAM it
9432c593315Sopenharmony_ci  // is possible trailer fields might come, regardless of request
9442c593315Sopenharmony_ci  // method or status code.
9452c593315Sopenharmony_ci  return !resp_.headers_only &&
9462c593315Sopenharmony_ci         (resp_.http_major == 3 || resp_.http_major == 2);
9472c593315Sopenharmony_ci}
9482c593315Sopenharmony_ci
9492c593315Sopenharmony_cinamespace {
9502c593315Sopenharmony_civoid reset_timer(struct ev_loop *loop, ev_timer *w) { ev_timer_again(loop, w); }
9512c593315Sopenharmony_ci} // namespace
9522c593315Sopenharmony_ci
9532c593315Sopenharmony_cinamespace {
9542c593315Sopenharmony_civoid try_reset_timer(struct ev_loop *loop, ev_timer *w) {
9552c593315Sopenharmony_ci  if (!ev_is_active(w)) {
9562c593315Sopenharmony_ci    return;
9572c593315Sopenharmony_ci  }
9582c593315Sopenharmony_ci  ev_timer_again(loop, w);
9592c593315Sopenharmony_ci}
9602c593315Sopenharmony_ci} // namespace
9612c593315Sopenharmony_ci
9622c593315Sopenharmony_cinamespace {
9632c593315Sopenharmony_civoid ensure_timer(struct ev_loop *loop, ev_timer *w) {
9642c593315Sopenharmony_ci  if (ev_is_active(w)) {
9652c593315Sopenharmony_ci    return;
9662c593315Sopenharmony_ci  }
9672c593315Sopenharmony_ci  ev_timer_again(loop, w);
9682c593315Sopenharmony_ci}
9692c593315Sopenharmony_ci} // namespace
9702c593315Sopenharmony_ci
9712c593315Sopenharmony_cinamespace {
9722c593315Sopenharmony_civoid disable_timer(struct ev_loop *loop, ev_timer *w) {
9732c593315Sopenharmony_ci  ev_timer_stop(loop, w);
9742c593315Sopenharmony_ci}
9752c593315Sopenharmony_ci} // namespace
9762c593315Sopenharmony_ci
9772c593315Sopenharmony_civoid Downstream::reset_upstream_rtimer() {
9782c593315Sopenharmony_ci  if (get_config()->http2.timeout.stream_read == 0.) {
9792c593315Sopenharmony_ci    return;
9802c593315Sopenharmony_ci  }
9812c593315Sopenharmony_ci  auto loop = upstream_->get_client_handler()->get_loop();
9822c593315Sopenharmony_ci  reset_timer(loop, &upstream_rtimer_);
9832c593315Sopenharmony_ci}
9842c593315Sopenharmony_ci
9852c593315Sopenharmony_civoid Downstream::reset_upstream_wtimer() {
9862c593315Sopenharmony_ci  auto loop = upstream_->get_client_handler()->get_loop();
9872c593315Sopenharmony_ci  auto &timeoutconf = get_config()->http2.timeout;
9882c593315Sopenharmony_ci
9892c593315Sopenharmony_ci  if (timeoutconf.stream_write != 0.) {
9902c593315Sopenharmony_ci    reset_timer(loop, &upstream_wtimer_);
9912c593315Sopenharmony_ci  }
9922c593315Sopenharmony_ci  if (timeoutconf.stream_read != 0.) {
9932c593315Sopenharmony_ci    try_reset_timer(loop, &upstream_rtimer_);
9942c593315Sopenharmony_ci  }
9952c593315Sopenharmony_ci}
9962c593315Sopenharmony_ci
9972c593315Sopenharmony_civoid Downstream::ensure_upstream_wtimer() {
9982c593315Sopenharmony_ci  if (get_config()->http2.timeout.stream_write == 0.) {
9992c593315Sopenharmony_ci    return;
10002c593315Sopenharmony_ci  }
10012c593315Sopenharmony_ci  auto loop = upstream_->get_client_handler()->get_loop();
10022c593315Sopenharmony_ci  ensure_timer(loop, &upstream_wtimer_);
10032c593315Sopenharmony_ci}
10042c593315Sopenharmony_ci
10052c593315Sopenharmony_civoid Downstream::disable_upstream_rtimer() {
10062c593315Sopenharmony_ci  if (get_config()->http2.timeout.stream_read == 0.) {
10072c593315Sopenharmony_ci    return;
10082c593315Sopenharmony_ci  }
10092c593315Sopenharmony_ci  auto loop = upstream_->get_client_handler()->get_loop();
10102c593315Sopenharmony_ci  disable_timer(loop, &upstream_rtimer_);
10112c593315Sopenharmony_ci}
10122c593315Sopenharmony_ci
10132c593315Sopenharmony_civoid Downstream::disable_upstream_wtimer() {
10142c593315Sopenharmony_ci  if (get_config()->http2.timeout.stream_write == 0.) {
10152c593315Sopenharmony_ci    return;
10162c593315Sopenharmony_ci  }
10172c593315Sopenharmony_ci  auto loop = upstream_->get_client_handler()->get_loop();
10182c593315Sopenharmony_ci  disable_timer(loop, &upstream_wtimer_);
10192c593315Sopenharmony_ci}
10202c593315Sopenharmony_ci
10212c593315Sopenharmony_civoid Downstream::reset_downstream_rtimer() {
10222c593315Sopenharmony_ci  if (get_config()->http2.timeout.stream_read == 0.) {
10232c593315Sopenharmony_ci    return;
10242c593315Sopenharmony_ci  }
10252c593315Sopenharmony_ci  auto loop = upstream_->get_client_handler()->get_loop();
10262c593315Sopenharmony_ci  reset_timer(loop, &downstream_rtimer_);
10272c593315Sopenharmony_ci}
10282c593315Sopenharmony_ci
10292c593315Sopenharmony_civoid Downstream::reset_downstream_wtimer() {
10302c593315Sopenharmony_ci  auto loop = upstream_->get_client_handler()->get_loop();
10312c593315Sopenharmony_ci  auto &timeoutconf = get_config()->http2.timeout;
10322c593315Sopenharmony_ci
10332c593315Sopenharmony_ci  if (timeoutconf.stream_write != 0.) {
10342c593315Sopenharmony_ci    reset_timer(loop, &downstream_wtimer_);
10352c593315Sopenharmony_ci  }
10362c593315Sopenharmony_ci  if (timeoutconf.stream_read != 0.) {
10372c593315Sopenharmony_ci    try_reset_timer(loop, &downstream_rtimer_);
10382c593315Sopenharmony_ci  }
10392c593315Sopenharmony_ci}
10402c593315Sopenharmony_ci
10412c593315Sopenharmony_civoid Downstream::ensure_downstream_wtimer() {
10422c593315Sopenharmony_ci  if (get_config()->http2.timeout.stream_write == 0.) {
10432c593315Sopenharmony_ci    return;
10442c593315Sopenharmony_ci  }
10452c593315Sopenharmony_ci  auto loop = upstream_->get_client_handler()->get_loop();
10462c593315Sopenharmony_ci  ensure_timer(loop, &downstream_wtimer_);
10472c593315Sopenharmony_ci}
10482c593315Sopenharmony_ci
10492c593315Sopenharmony_civoid Downstream::disable_downstream_rtimer() {
10502c593315Sopenharmony_ci  if (get_config()->http2.timeout.stream_read == 0.) {
10512c593315Sopenharmony_ci    return;
10522c593315Sopenharmony_ci  }
10532c593315Sopenharmony_ci  auto loop = upstream_->get_client_handler()->get_loop();
10542c593315Sopenharmony_ci  disable_timer(loop, &downstream_rtimer_);
10552c593315Sopenharmony_ci}
10562c593315Sopenharmony_ci
10572c593315Sopenharmony_civoid Downstream::disable_downstream_wtimer() {
10582c593315Sopenharmony_ci  if (get_config()->http2.timeout.stream_write == 0.) {
10592c593315Sopenharmony_ci    return;
10602c593315Sopenharmony_ci  }
10612c593315Sopenharmony_ci  auto loop = upstream_->get_client_handler()->get_loop();
10622c593315Sopenharmony_ci  disable_timer(loop, &downstream_wtimer_);
10632c593315Sopenharmony_ci}
10642c593315Sopenharmony_ci
10652c593315Sopenharmony_cibool Downstream::accesslog_ready() const {
10662c593315Sopenharmony_ci  return !accesslog_written_ && resp_.http_status > 0;
10672c593315Sopenharmony_ci}
10682c593315Sopenharmony_ci
10692c593315Sopenharmony_civoid Downstream::add_retry() { ++num_retry_; }
10702c593315Sopenharmony_ci
10712c593315Sopenharmony_cibool Downstream::no_more_retry() const { return num_retry_ > 50; }
10722c593315Sopenharmony_ci
10732c593315Sopenharmony_civoid Downstream::set_request_downstream_host(const StringRef &host) {
10742c593315Sopenharmony_ci  request_downstream_host_ = host;
10752c593315Sopenharmony_ci}
10762c593315Sopenharmony_ci
10772c593315Sopenharmony_civoid Downstream::set_request_pending(bool f) { request_pending_ = f; }
10782c593315Sopenharmony_ci
10792c593315Sopenharmony_cibool Downstream::get_request_pending() const { return request_pending_; }
10802c593315Sopenharmony_ci
10812c593315Sopenharmony_civoid Downstream::set_request_header_sent(bool f) { request_header_sent_ = f; }
10822c593315Sopenharmony_ci
10832c593315Sopenharmony_cibool Downstream::get_request_header_sent() const {
10842c593315Sopenharmony_ci  return request_header_sent_;
10852c593315Sopenharmony_ci}
10862c593315Sopenharmony_ci
10872c593315Sopenharmony_cibool Downstream::request_submission_ready() const {
10882c593315Sopenharmony_ci  return (request_state_ == DownstreamState::HEADER_COMPLETE ||
10892c593315Sopenharmony_ci          request_state_ == DownstreamState::MSG_COMPLETE) &&
10902c593315Sopenharmony_ci         (request_pending_ || !request_header_sent_) &&
10912c593315Sopenharmony_ci         response_state_ == DownstreamState::INITIAL;
10922c593315Sopenharmony_ci}
10932c593315Sopenharmony_ci
10942c593315Sopenharmony_ciDispatchState Downstream::get_dispatch_state() const { return dispatch_state_; }
10952c593315Sopenharmony_ci
10962c593315Sopenharmony_civoid Downstream::set_dispatch_state(DispatchState s) { dispatch_state_ = s; }
10972c593315Sopenharmony_ci
10982c593315Sopenharmony_civoid Downstream::attach_blocked_link(BlockedLink *l) {
10992c593315Sopenharmony_ci  assert(!blocked_link_);
11002c593315Sopenharmony_ci
11012c593315Sopenharmony_ci  l->downstream = this;
11022c593315Sopenharmony_ci  blocked_link_ = l;
11032c593315Sopenharmony_ci}
11042c593315Sopenharmony_ci
11052c593315Sopenharmony_ciBlockedLink *Downstream::detach_blocked_link() {
11062c593315Sopenharmony_ci  auto link = blocked_link_;
11072c593315Sopenharmony_ci  blocked_link_ = nullptr;
11082c593315Sopenharmony_ci  return link;
11092c593315Sopenharmony_ci}
11102c593315Sopenharmony_ci
11112c593315Sopenharmony_cibool Downstream::can_detach_downstream_connection() const {
11122c593315Sopenharmony_ci  // We should check request and response buffer.  If request buffer
11132c593315Sopenharmony_ci  // is not empty, then we might leave downstream connection in weird
11142c593315Sopenharmony_ci  // state, especially for HTTP/1.1
11152c593315Sopenharmony_ci  return dconn_ && response_state_ == DownstreamState::MSG_COMPLETE &&
11162c593315Sopenharmony_ci         request_state_ == DownstreamState::MSG_COMPLETE && !upgraded_ &&
11172c593315Sopenharmony_ci         !resp_.connection_close && request_buf_.rleft() == 0;
11182c593315Sopenharmony_ci}
11192c593315Sopenharmony_ci
11202c593315Sopenharmony_ciDefaultMemchunks Downstream::pop_response_buf() {
11212c593315Sopenharmony_ci  return std::move(response_buf_);
11222c593315Sopenharmony_ci}
11232c593315Sopenharmony_ci
11242c593315Sopenharmony_civoid Downstream::set_assoc_stream_id(int64_t stream_id) {
11252c593315Sopenharmony_ci  assoc_stream_id_ = stream_id;
11262c593315Sopenharmony_ci}
11272c593315Sopenharmony_ci
11282c593315Sopenharmony_ciint64_t Downstream::get_assoc_stream_id() const { return assoc_stream_id_; }
11292c593315Sopenharmony_ci
11302c593315Sopenharmony_ciBlockAllocator &Downstream::get_block_allocator() { return balloc_; }
11312c593315Sopenharmony_ci
11322c593315Sopenharmony_civoid Downstream::add_rcbuf(nghttp2_rcbuf *rcbuf) {
11332c593315Sopenharmony_ci  nghttp2_rcbuf_incref(rcbuf);
11342c593315Sopenharmony_ci  rcbufs_.push_back(rcbuf);
11352c593315Sopenharmony_ci}
11362c593315Sopenharmony_ci
11372c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
11382c593315Sopenharmony_civoid Downstream::add_rcbuf(nghttp3_rcbuf *rcbuf) {
11392c593315Sopenharmony_ci  nghttp3_rcbuf_incref(rcbuf);
11402c593315Sopenharmony_ci  rcbufs3_.push_back(rcbuf);
11412c593315Sopenharmony_ci}
11422c593315Sopenharmony_ci#endif // ENABLE_HTTP3
11432c593315Sopenharmony_ci
11442c593315Sopenharmony_civoid Downstream::set_downstream_addr_group(
11452c593315Sopenharmony_ci    const std::shared_ptr<DownstreamAddrGroup> &group) {
11462c593315Sopenharmony_ci  group_ = group;
11472c593315Sopenharmony_ci}
11482c593315Sopenharmony_ci
11492c593315Sopenharmony_civoid Downstream::set_addr(const DownstreamAddr *addr) { addr_ = addr; }
11502c593315Sopenharmony_ci
11512c593315Sopenharmony_ciconst DownstreamAddr *Downstream::get_addr() const { return addr_; }
11522c593315Sopenharmony_ci
11532c593315Sopenharmony_civoid Downstream::set_accesslog_written(bool f) { accesslog_written_ = f; }
11542c593315Sopenharmony_ci
11552c593315Sopenharmony_civoid Downstream::renew_affinity_cookie(uint32_t h) {
11562c593315Sopenharmony_ci  affinity_cookie_ = h;
11572c593315Sopenharmony_ci  new_affinity_cookie_ = true;
11582c593315Sopenharmony_ci}
11592c593315Sopenharmony_ci
11602c593315Sopenharmony_ciuint32_t Downstream::get_affinity_cookie_to_send() const {
11612c593315Sopenharmony_ci  if (new_affinity_cookie_) {
11622c593315Sopenharmony_ci    return affinity_cookie_;
11632c593315Sopenharmony_ci  }
11642c593315Sopenharmony_ci  return 0;
11652c593315Sopenharmony_ci}
11662c593315Sopenharmony_ci
11672c593315Sopenharmony_ciDefaultMemchunks *Downstream::get_blocked_request_buf() {
11682c593315Sopenharmony_ci  return &blocked_request_buf_;
11692c593315Sopenharmony_ci}
11702c593315Sopenharmony_ci
11712c593315Sopenharmony_cibool Downstream::get_blocked_request_data_eof() const {
11722c593315Sopenharmony_ci  return blocked_request_data_eof_;
11732c593315Sopenharmony_ci}
11742c593315Sopenharmony_ci
11752c593315Sopenharmony_civoid Downstream::set_blocked_request_data_eof(bool f) {
11762c593315Sopenharmony_ci  blocked_request_data_eof_ = f;
11772c593315Sopenharmony_ci}
11782c593315Sopenharmony_ci
11792c593315Sopenharmony_civoid Downstream::set_ws_key(const StringRef &key) { ws_key_ = key; }
11802c593315Sopenharmony_ci
11812c593315Sopenharmony_cibool Downstream::get_expect_100_continue() const {
11822c593315Sopenharmony_ci  return expect_100_continue_;
11832c593315Sopenharmony_ci}
11842c593315Sopenharmony_ci
11852c593315Sopenharmony_cibool Downstream::get_stop_reading() const { return stop_reading_; }
11862c593315Sopenharmony_ci
11872c593315Sopenharmony_civoid Downstream::set_stop_reading(bool f) { stop_reading_ = f; }
11882c593315Sopenharmony_ci
11892c593315Sopenharmony_ci} // namespace shrpx
1190