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