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_connection_handler.h"
262c593315Sopenharmony_ci
272c593315Sopenharmony_ci#ifdef HAVE_UNISTD_H
282c593315Sopenharmony_ci#  include <unistd.h>
292c593315Sopenharmony_ci#endif // HAVE_UNISTD_H
302c593315Sopenharmony_ci#include <sys/types.h>
312c593315Sopenharmony_ci#include <sys/wait.h>
322c593315Sopenharmony_ci
332c593315Sopenharmony_ci#include <cerrno>
342c593315Sopenharmony_ci#include <thread>
352c593315Sopenharmony_ci#include <random>
362c593315Sopenharmony_ci
372c593315Sopenharmony_ci#include "shrpx_client_handler.h"
382c593315Sopenharmony_ci#include "shrpx_tls.h"
392c593315Sopenharmony_ci#include "shrpx_worker.h"
402c593315Sopenharmony_ci#include "shrpx_config.h"
412c593315Sopenharmony_ci#include "shrpx_http2_session.h"
422c593315Sopenharmony_ci#include "shrpx_connect_blocker.h"
432c593315Sopenharmony_ci#include "shrpx_downstream_connection.h"
442c593315Sopenharmony_ci#include "shrpx_accept_handler.h"
452c593315Sopenharmony_ci#include "shrpx_memcached_dispatcher.h"
462c593315Sopenharmony_ci#include "shrpx_signal.h"
472c593315Sopenharmony_ci#include "shrpx_log.h"
482c593315Sopenharmony_ci#include "xsi_strerror.h"
492c593315Sopenharmony_ci#include "util.h"
502c593315Sopenharmony_ci#include "template.h"
512c593315Sopenharmony_ci
522c593315Sopenharmony_ciusing namespace nghttp2;
532c593315Sopenharmony_ci
542c593315Sopenharmony_cinamespace shrpx {
552c593315Sopenharmony_ci
562c593315Sopenharmony_cinamespace {
572c593315Sopenharmony_civoid acceptor_disable_cb(struct ev_loop *loop, ev_timer *w, int revent) {
582c593315Sopenharmony_ci  auto h = static_cast<ConnectionHandler *>(w->data);
592c593315Sopenharmony_ci
602c593315Sopenharmony_ci  // If we are in graceful shutdown period, we must not enable
612c593315Sopenharmony_ci  // acceptors again.
622c593315Sopenharmony_ci  if (h->get_graceful_shutdown()) {
632c593315Sopenharmony_ci    return;
642c593315Sopenharmony_ci  }
652c593315Sopenharmony_ci
662c593315Sopenharmony_ci  h->enable_acceptor();
672c593315Sopenharmony_ci}
682c593315Sopenharmony_ci} // namespace
692c593315Sopenharmony_ci
702c593315Sopenharmony_cinamespace {
712c593315Sopenharmony_civoid ocsp_cb(struct ev_loop *loop, ev_timer *w, int revent) {
722c593315Sopenharmony_ci  auto h = static_cast<ConnectionHandler *>(w->data);
732c593315Sopenharmony_ci
742c593315Sopenharmony_ci  // If we are in graceful shutdown period, we won't do ocsp query.
752c593315Sopenharmony_ci  if (h->get_graceful_shutdown()) {
762c593315Sopenharmony_ci    return;
772c593315Sopenharmony_ci  }
782c593315Sopenharmony_ci
792c593315Sopenharmony_ci  LOG(NOTICE) << "Start ocsp update";
802c593315Sopenharmony_ci
812c593315Sopenharmony_ci  h->proceed_next_cert_ocsp();
822c593315Sopenharmony_ci}
832c593315Sopenharmony_ci} // namespace
842c593315Sopenharmony_ci
852c593315Sopenharmony_cinamespace {
862c593315Sopenharmony_civoid ocsp_read_cb(struct ev_loop *loop, ev_io *w, int revent) {
872c593315Sopenharmony_ci  auto h = static_cast<ConnectionHandler *>(w->data);
882c593315Sopenharmony_ci
892c593315Sopenharmony_ci  h->read_ocsp_chunk();
902c593315Sopenharmony_ci}
912c593315Sopenharmony_ci} // namespace
922c593315Sopenharmony_ci
932c593315Sopenharmony_cinamespace {
942c593315Sopenharmony_civoid ocsp_chld_cb(struct ev_loop *loop, ev_child *w, int revent) {
952c593315Sopenharmony_ci  auto h = static_cast<ConnectionHandler *>(w->data);
962c593315Sopenharmony_ci
972c593315Sopenharmony_ci  h->handle_ocsp_complete();
982c593315Sopenharmony_ci}
992c593315Sopenharmony_ci} // namespace
1002c593315Sopenharmony_ci
1012c593315Sopenharmony_cinamespace {
1022c593315Sopenharmony_civoid thread_join_async_cb(struct ev_loop *loop, ev_async *w, int revent) {
1032c593315Sopenharmony_ci  ev_break(loop);
1042c593315Sopenharmony_ci}
1052c593315Sopenharmony_ci} // namespace
1062c593315Sopenharmony_ci
1072c593315Sopenharmony_cinamespace {
1082c593315Sopenharmony_civoid serial_event_async_cb(struct ev_loop *loop, ev_async *w, int revent) {
1092c593315Sopenharmony_ci  auto h = static_cast<ConnectionHandler *>(w->data);
1102c593315Sopenharmony_ci
1112c593315Sopenharmony_ci  h->handle_serial_event();
1122c593315Sopenharmony_ci}
1132c593315Sopenharmony_ci} // namespace
1142c593315Sopenharmony_ci
1152c593315Sopenharmony_ciConnectionHandler::ConnectionHandler(struct ev_loop *loop, std::mt19937 &gen)
1162c593315Sopenharmony_ci    :
1172c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
1182c593315Sopenharmony_ci      quic_ipc_fd_(-1),
1192c593315Sopenharmony_ci#endif // ENABLE_HTTP3
1202c593315Sopenharmony_ci      gen_(gen),
1212c593315Sopenharmony_ci      single_worker_(nullptr),
1222c593315Sopenharmony_ci      loop_(loop),
1232c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED
1242c593315Sopenharmony_ci      nb_(nullptr),
1252c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED
1262c593315Sopenharmony_ci      tls_ticket_key_memcached_get_retry_count_(0),
1272c593315Sopenharmony_ci      tls_ticket_key_memcached_fail_count_(0),
1282c593315Sopenharmony_ci      worker_round_robin_cnt_(get_config()->api.enabled ? 1 : 0),
1292c593315Sopenharmony_ci      graceful_shutdown_(false),
1302c593315Sopenharmony_ci      enable_acceptor_on_ocsp_completion_(false) {
1312c593315Sopenharmony_ci  ev_timer_init(&disable_acceptor_timer_, acceptor_disable_cb, 0., 0.);
1322c593315Sopenharmony_ci  disable_acceptor_timer_.data = this;
1332c593315Sopenharmony_ci
1342c593315Sopenharmony_ci  ev_timer_init(&ocsp_timer_, ocsp_cb, 0., 0.);
1352c593315Sopenharmony_ci  ocsp_timer_.data = this;
1362c593315Sopenharmony_ci
1372c593315Sopenharmony_ci  ev_io_init(&ocsp_.rev, ocsp_read_cb, -1, EV_READ);
1382c593315Sopenharmony_ci  ocsp_.rev.data = this;
1392c593315Sopenharmony_ci
1402c593315Sopenharmony_ci  ev_async_init(&thread_join_asyncev_, thread_join_async_cb);
1412c593315Sopenharmony_ci
1422c593315Sopenharmony_ci  ev_async_init(&serial_event_asyncev_, serial_event_async_cb);
1432c593315Sopenharmony_ci  serial_event_asyncev_.data = this;
1442c593315Sopenharmony_ci
1452c593315Sopenharmony_ci  ev_async_start(loop_, &serial_event_asyncev_);
1462c593315Sopenharmony_ci
1472c593315Sopenharmony_ci  ev_child_init(&ocsp_.chldev, ocsp_chld_cb, 0, 0);
1482c593315Sopenharmony_ci  ocsp_.chldev.data = this;
1492c593315Sopenharmony_ci
1502c593315Sopenharmony_ci  ocsp_.next = 0;
1512c593315Sopenharmony_ci  ocsp_.proc.rfd = -1;
1522c593315Sopenharmony_ci
1532c593315Sopenharmony_ci  reset_ocsp();
1542c593315Sopenharmony_ci}
1552c593315Sopenharmony_ci
1562c593315Sopenharmony_ciConnectionHandler::~ConnectionHandler() {
1572c593315Sopenharmony_ci  ev_child_stop(loop_, &ocsp_.chldev);
1582c593315Sopenharmony_ci  ev_async_stop(loop_, &serial_event_asyncev_);
1592c593315Sopenharmony_ci  ev_async_stop(loop_, &thread_join_asyncev_);
1602c593315Sopenharmony_ci  ev_io_stop(loop_, &ocsp_.rev);
1612c593315Sopenharmony_ci  ev_timer_stop(loop_, &ocsp_timer_);
1622c593315Sopenharmony_ci  ev_timer_stop(loop_, &disable_acceptor_timer_);
1632c593315Sopenharmony_ci
1642c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
1652c593315Sopenharmony_ci  for (auto ssl_ctx : quic_all_ssl_ctx_) {
1662c593315Sopenharmony_ci    if (ssl_ctx == nullptr) {
1672c593315Sopenharmony_ci      continue;
1682c593315Sopenharmony_ci    }
1692c593315Sopenharmony_ci
1702c593315Sopenharmony_ci    auto tls_ctx_data =
1712c593315Sopenharmony_ci        static_cast<tls::TLSContextData *>(SSL_CTX_get_app_data(ssl_ctx));
1722c593315Sopenharmony_ci    delete tls_ctx_data;
1732c593315Sopenharmony_ci    SSL_CTX_free(ssl_ctx);
1742c593315Sopenharmony_ci  }
1752c593315Sopenharmony_ci#endif // ENABLE_HTTP3
1762c593315Sopenharmony_ci
1772c593315Sopenharmony_ci  for (auto ssl_ctx : all_ssl_ctx_) {
1782c593315Sopenharmony_ci    auto tls_ctx_data =
1792c593315Sopenharmony_ci        static_cast<tls::TLSContextData *>(SSL_CTX_get_app_data(ssl_ctx));
1802c593315Sopenharmony_ci    delete tls_ctx_data;
1812c593315Sopenharmony_ci    SSL_CTX_free(ssl_ctx);
1822c593315Sopenharmony_ci  }
1832c593315Sopenharmony_ci
1842c593315Sopenharmony_ci  // Free workers before destroying ev_loop
1852c593315Sopenharmony_ci  workers_.clear();
1862c593315Sopenharmony_ci
1872c593315Sopenharmony_ci  for (auto loop : worker_loops_) {
1882c593315Sopenharmony_ci    ev_loop_destroy(loop);
1892c593315Sopenharmony_ci  }
1902c593315Sopenharmony_ci}
1912c593315Sopenharmony_ci
1922c593315Sopenharmony_civoid ConnectionHandler::set_ticket_keys_to_worker(
1932c593315Sopenharmony_ci    const std::shared_ptr<TicketKeys> &ticket_keys) {
1942c593315Sopenharmony_ci  for (auto &worker : workers_) {
1952c593315Sopenharmony_ci    worker->set_ticket_keys(ticket_keys);
1962c593315Sopenharmony_ci  }
1972c593315Sopenharmony_ci}
1982c593315Sopenharmony_ci
1992c593315Sopenharmony_civoid ConnectionHandler::worker_reopen_log_files() {
2002c593315Sopenharmony_ci  for (auto &worker : workers_) {
2012c593315Sopenharmony_ci    WorkerEvent wev{};
2022c593315Sopenharmony_ci
2032c593315Sopenharmony_ci    wev.type = WorkerEventType::REOPEN_LOG;
2042c593315Sopenharmony_ci
2052c593315Sopenharmony_ci    worker->send(std::move(wev));
2062c593315Sopenharmony_ci  }
2072c593315Sopenharmony_ci}
2082c593315Sopenharmony_ci
2092c593315Sopenharmony_civoid ConnectionHandler::worker_replace_downstream(
2102c593315Sopenharmony_ci    std::shared_ptr<DownstreamConfig> downstreamconf) {
2112c593315Sopenharmony_ci  for (auto &worker : workers_) {
2122c593315Sopenharmony_ci    WorkerEvent wev{};
2132c593315Sopenharmony_ci
2142c593315Sopenharmony_ci    wev.type = WorkerEventType::REPLACE_DOWNSTREAM;
2152c593315Sopenharmony_ci    wev.downstreamconf = downstreamconf;
2162c593315Sopenharmony_ci
2172c593315Sopenharmony_ci    worker->send(std::move(wev));
2182c593315Sopenharmony_ci  }
2192c593315Sopenharmony_ci}
2202c593315Sopenharmony_ci
2212c593315Sopenharmony_ciint ConnectionHandler::create_single_worker() {
2222c593315Sopenharmony_ci  cert_tree_ = tls::create_cert_lookup_tree();
2232c593315Sopenharmony_ci  auto sv_ssl_ctx = tls::setup_server_ssl_context(
2242c593315Sopenharmony_ci      all_ssl_ctx_, indexed_ssl_ctx_, cert_tree_.get()
2252c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED
2262c593315Sopenharmony_ci                                          ,
2272c593315Sopenharmony_ci      nb_
2282c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED
2292c593315Sopenharmony_ci  );
2302c593315Sopenharmony_ci
2312c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
2322c593315Sopenharmony_ci  quic_cert_tree_ = tls::create_cert_lookup_tree();
2332c593315Sopenharmony_ci  auto quic_sv_ssl_ctx = tls::setup_quic_server_ssl_context(
2342c593315Sopenharmony_ci      quic_all_ssl_ctx_, quic_indexed_ssl_ctx_, quic_cert_tree_.get()
2352c593315Sopenharmony_ci#  ifdef HAVE_NEVERBLEED
2362c593315Sopenharmony_ci                                                    ,
2372c593315Sopenharmony_ci      nb_
2382c593315Sopenharmony_ci#  endif // HAVE_NEVERBLEED
2392c593315Sopenharmony_ci  );
2402c593315Sopenharmony_ci#endif // ENABLE_HTTP3
2412c593315Sopenharmony_ci
2422c593315Sopenharmony_ci  auto cl_ssl_ctx = tls::setup_downstream_client_ssl_context(
2432c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED
2442c593315Sopenharmony_ci      nb_
2452c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED
2462c593315Sopenharmony_ci  );
2472c593315Sopenharmony_ci
2482c593315Sopenharmony_ci  if (cl_ssl_ctx) {
2492c593315Sopenharmony_ci    all_ssl_ctx_.push_back(cl_ssl_ctx);
2502c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
2512c593315Sopenharmony_ci    quic_all_ssl_ctx_.push_back(nullptr);
2522c593315Sopenharmony_ci#endif // ENABLE_HTTP3
2532c593315Sopenharmony_ci  }
2542c593315Sopenharmony_ci
2552c593315Sopenharmony_ci  auto config = get_config();
2562c593315Sopenharmony_ci  auto &tlsconf = config->tls;
2572c593315Sopenharmony_ci
2582c593315Sopenharmony_ci  SSL_CTX *session_cache_ssl_ctx = nullptr;
2592c593315Sopenharmony_ci  {
2602c593315Sopenharmony_ci    auto &memcachedconf = config->tls.session_cache.memcached;
2612c593315Sopenharmony_ci    if (memcachedconf.tls) {
2622c593315Sopenharmony_ci      session_cache_ssl_ctx = tls::create_ssl_client_context(
2632c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED
2642c593315Sopenharmony_ci          nb_,
2652c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED
2662c593315Sopenharmony_ci          tlsconf.cacert, memcachedconf.cert_file,
2672c593315Sopenharmony_ci          memcachedconf.private_key_file, nullptr);
2682c593315Sopenharmony_ci      all_ssl_ctx_.push_back(session_cache_ssl_ctx);
2692c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
2702c593315Sopenharmony_ci      quic_all_ssl_ctx_.push_back(nullptr);
2712c593315Sopenharmony_ci#endif // ENABLE_HTTP3
2722c593315Sopenharmony_ci    }
2732c593315Sopenharmony_ci  }
2742c593315Sopenharmony_ci
2752c593315Sopenharmony_ci#if defined(ENABLE_HTTP3) && defined(HAVE_LIBBPF)
2762c593315Sopenharmony_ci  quic_bpf_refs_.resize(config->conn.quic_listener.addrs.size());
2772c593315Sopenharmony_ci#endif // ENABLE_HTTP3 && HAVE_LIBBPF
2782c593315Sopenharmony_ci
2792c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
2802c593315Sopenharmony_ci  assert(cid_prefixes_.size() == 1);
2812c593315Sopenharmony_ci  const auto &cid_prefix = cid_prefixes_[0];
2822c593315Sopenharmony_ci#endif // ENABLE_HTTP3
2832c593315Sopenharmony_ci
2842c593315Sopenharmony_ci  single_worker_ = std::make_unique<Worker>(
2852c593315Sopenharmony_ci      loop_, sv_ssl_ctx, cl_ssl_ctx, session_cache_ssl_ctx, cert_tree_.get(),
2862c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
2872c593315Sopenharmony_ci      quic_sv_ssl_ctx, quic_cert_tree_.get(), cid_prefix.data(),
2882c593315Sopenharmony_ci      cid_prefix.size(),
2892c593315Sopenharmony_ci#  ifdef HAVE_LIBBPF
2902c593315Sopenharmony_ci      /* index = */ 0,
2912c593315Sopenharmony_ci#  endif // HAVE_LIBBPF
2922c593315Sopenharmony_ci#endif   // ENABLE_HTTP3
2932c593315Sopenharmony_ci      ticket_keys_, this, config->conn.downstream);
2942c593315Sopenharmony_ci#ifdef HAVE_MRUBY
2952c593315Sopenharmony_ci  if (single_worker_->create_mruby_context() != 0) {
2962c593315Sopenharmony_ci    return -1;
2972c593315Sopenharmony_ci  }
2982c593315Sopenharmony_ci#endif // HAVE_MRUBY
2992c593315Sopenharmony_ci
3002c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
3012c593315Sopenharmony_ci  if (single_worker_->setup_quic_server_socket() != 0) {
3022c593315Sopenharmony_ci    return -1;
3032c593315Sopenharmony_ci  }
3042c593315Sopenharmony_ci#endif // ENABLE_HTTP3
3052c593315Sopenharmony_ci
3062c593315Sopenharmony_ci  return 0;
3072c593315Sopenharmony_ci}
3082c593315Sopenharmony_ci
3092c593315Sopenharmony_ciint ConnectionHandler::create_worker_thread(size_t num) {
3102c593315Sopenharmony_ci#ifndef NOTHREADS
3112c593315Sopenharmony_ci  assert(workers_.size() == 0);
3122c593315Sopenharmony_ci
3132c593315Sopenharmony_ci  cert_tree_ = tls::create_cert_lookup_tree();
3142c593315Sopenharmony_ci  auto sv_ssl_ctx = tls::setup_server_ssl_context(
3152c593315Sopenharmony_ci      all_ssl_ctx_, indexed_ssl_ctx_, cert_tree_.get()
3162c593315Sopenharmony_ci#  ifdef HAVE_NEVERBLEED
3172c593315Sopenharmony_ci                                          ,
3182c593315Sopenharmony_ci      nb_
3192c593315Sopenharmony_ci#  endif // HAVE_NEVERBLEED
3202c593315Sopenharmony_ci  );
3212c593315Sopenharmony_ci
3222c593315Sopenharmony_ci#  ifdef ENABLE_HTTP3
3232c593315Sopenharmony_ci  quic_cert_tree_ = tls::create_cert_lookup_tree();
3242c593315Sopenharmony_ci  auto quic_sv_ssl_ctx = tls::setup_quic_server_ssl_context(
3252c593315Sopenharmony_ci      quic_all_ssl_ctx_, quic_indexed_ssl_ctx_, quic_cert_tree_.get()
3262c593315Sopenharmony_ci#    ifdef HAVE_NEVERBLEED
3272c593315Sopenharmony_ci                                                    ,
3282c593315Sopenharmony_ci      nb_
3292c593315Sopenharmony_ci#    endif // HAVE_NEVERBLEED
3302c593315Sopenharmony_ci  );
3312c593315Sopenharmony_ci#  endif // ENABLE_HTTP3
3322c593315Sopenharmony_ci
3332c593315Sopenharmony_ci  auto cl_ssl_ctx = tls::setup_downstream_client_ssl_context(
3342c593315Sopenharmony_ci#  ifdef HAVE_NEVERBLEED
3352c593315Sopenharmony_ci      nb_
3362c593315Sopenharmony_ci#  endif // HAVE_NEVERBLEED
3372c593315Sopenharmony_ci  );
3382c593315Sopenharmony_ci
3392c593315Sopenharmony_ci  if (cl_ssl_ctx) {
3402c593315Sopenharmony_ci    all_ssl_ctx_.push_back(cl_ssl_ctx);
3412c593315Sopenharmony_ci#  ifdef ENABLE_HTTP3
3422c593315Sopenharmony_ci    quic_all_ssl_ctx_.push_back(nullptr);
3432c593315Sopenharmony_ci#  endif // ENABLE_HTTP3
3442c593315Sopenharmony_ci  }
3452c593315Sopenharmony_ci
3462c593315Sopenharmony_ci  auto config = get_config();
3472c593315Sopenharmony_ci  auto &tlsconf = config->tls;
3482c593315Sopenharmony_ci  auto &apiconf = config->api;
3492c593315Sopenharmony_ci
3502c593315Sopenharmony_ci#  if defined(ENABLE_HTTP3) && defined(HAVE_LIBBPF)
3512c593315Sopenharmony_ci  quic_bpf_refs_.resize(config->conn.quic_listener.addrs.size());
3522c593315Sopenharmony_ci#  endif // ENABLE_HTTP3 && HAVE_LIBBPF
3532c593315Sopenharmony_ci
3542c593315Sopenharmony_ci  // We have dedicated worker for API request processing.
3552c593315Sopenharmony_ci  if (apiconf.enabled) {
3562c593315Sopenharmony_ci    ++num;
3572c593315Sopenharmony_ci  }
3582c593315Sopenharmony_ci
3592c593315Sopenharmony_ci  SSL_CTX *session_cache_ssl_ctx = nullptr;
3602c593315Sopenharmony_ci  {
3612c593315Sopenharmony_ci    auto &memcachedconf = config->tls.session_cache.memcached;
3622c593315Sopenharmony_ci
3632c593315Sopenharmony_ci    if (memcachedconf.tls) {
3642c593315Sopenharmony_ci      session_cache_ssl_ctx = tls::create_ssl_client_context(
3652c593315Sopenharmony_ci#  ifdef HAVE_NEVERBLEED
3662c593315Sopenharmony_ci          nb_,
3672c593315Sopenharmony_ci#  endif // HAVE_NEVERBLEED
3682c593315Sopenharmony_ci          tlsconf.cacert, memcachedconf.cert_file,
3692c593315Sopenharmony_ci          memcachedconf.private_key_file, nullptr);
3702c593315Sopenharmony_ci      all_ssl_ctx_.push_back(session_cache_ssl_ctx);
3712c593315Sopenharmony_ci#  ifdef ENABLE_HTTP3
3722c593315Sopenharmony_ci      quic_all_ssl_ctx_.push_back(nullptr);
3732c593315Sopenharmony_ci#  endif // ENABLE_HTTP3
3742c593315Sopenharmony_ci    }
3752c593315Sopenharmony_ci  }
3762c593315Sopenharmony_ci
3772c593315Sopenharmony_ci#  ifdef ENABLE_HTTP3
3782c593315Sopenharmony_ci  assert(cid_prefixes_.size() == num);
3792c593315Sopenharmony_ci#  endif // ENABLE_HTTP3
3802c593315Sopenharmony_ci
3812c593315Sopenharmony_ci  for (size_t i = 0; i < num; ++i) {
3822c593315Sopenharmony_ci    auto loop = ev_loop_new(config->ev_loop_flags);
3832c593315Sopenharmony_ci
3842c593315Sopenharmony_ci#  ifdef ENABLE_HTTP3
3852c593315Sopenharmony_ci    const auto &cid_prefix = cid_prefixes_[i];
3862c593315Sopenharmony_ci#  endif // ENABLE_HTTP3
3872c593315Sopenharmony_ci
3882c593315Sopenharmony_ci    auto worker = std::make_unique<Worker>(
3892c593315Sopenharmony_ci        loop, sv_ssl_ctx, cl_ssl_ctx, session_cache_ssl_ctx, cert_tree_.get(),
3902c593315Sopenharmony_ci#  ifdef ENABLE_HTTP3
3912c593315Sopenharmony_ci        quic_sv_ssl_ctx, quic_cert_tree_.get(), cid_prefix.data(),
3922c593315Sopenharmony_ci        cid_prefix.size(),
3932c593315Sopenharmony_ci#    ifdef HAVE_LIBBPF
3942c593315Sopenharmony_ci        i,
3952c593315Sopenharmony_ci#    endif // HAVE_LIBBPF
3962c593315Sopenharmony_ci#  endif   // ENABLE_HTTP3
3972c593315Sopenharmony_ci        ticket_keys_, this, config->conn.downstream);
3982c593315Sopenharmony_ci#  ifdef HAVE_MRUBY
3992c593315Sopenharmony_ci    if (worker->create_mruby_context() != 0) {
4002c593315Sopenharmony_ci      return -1;
4012c593315Sopenharmony_ci    }
4022c593315Sopenharmony_ci#  endif // HAVE_MRUBY
4032c593315Sopenharmony_ci
4042c593315Sopenharmony_ci#  ifdef ENABLE_HTTP3
4052c593315Sopenharmony_ci    if ((!apiconf.enabled || i != 0) &&
4062c593315Sopenharmony_ci        worker->setup_quic_server_socket() != 0) {
4072c593315Sopenharmony_ci      return -1;
4082c593315Sopenharmony_ci    }
4092c593315Sopenharmony_ci#  endif // ENABLE_HTTP3
4102c593315Sopenharmony_ci
4112c593315Sopenharmony_ci    workers_.push_back(std::move(worker));
4122c593315Sopenharmony_ci    worker_loops_.push_back(loop);
4132c593315Sopenharmony_ci
4142c593315Sopenharmony_ci    LLOG(NOTICE, this) << "Created worker thread #" << workers_.size() - 1;
4152c593315Sopenharmony_ci  }
4162c593315Sopenharmony_ci
4172c593315Sopenharmony_ci  for (auto &worker : workers_) {
4182c593315Sopenharmony_ci    worker->run_async();
4192c593315Sopenharmony_ci  }
4202c593315Sopenharmony_ci
4212c593315Sopenharmony_ci#endif // NOTHREADS
4222c593315Sopenharmony_ci
4232c593315Sopenharmony_ci  return 0;
4242c593315Sopenharmony_ci}
4252c593315Sopenharmony_ci
4262c593315Sopenharmony_civoid ConnectionHandler::join_worker() {
4272c593315Sopenharmony_ci#ifndef NOTHREADS
4282c593315Sopenharmony_ci  int n = 0;
4292c593315Sopenharmony_ci
4302c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
4312c593315Sopenharmony_ci    LLOG(INFO, this) << "Waiting for worker thread to join: n="
4322c593315Sopenharmony_ci                     << workers_.size();
4332c593315Sopenharmony_ci  }
4342c593315Sopenharmony_ci
4352c593315Sopenharmony_ci  for (auto &worker : workers_) {
4362c593315Sopenharmony_ci    worker->wait();
4372c593315Sopenharmony_ci    if (LOG_ENABLED(INFO)) {
4382c593315Sopenharmony_ci      LLOG(INFO, this) << "Thread #" << n << " joined";
4392c593315Sopenharmony_ci    }
4402c593315Sopenharmony_ci    ++n;
4412c593315Sopenharmony_ci  }
4422c593315Sopenharmony_ci#endif // NOTHREADS
4432c593315Sopenharmony_ci}
4442c593315Sopenharmony_ci
4452c593315Sopenharmony_civoid ConnectionHandler::graceful_shutdown_worker() {
4462c593315Sopenharmony_ci  if (single_worker_) {
4472c593315Sopenharmony_ci    return;
4482c593315Sopenharmony_ci  }
4492c593315Sopenharmony_ci
4502c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
4512c593315Sopenharmony_ci    LLOG(INFO, this) << "Sending graceful shutdown signal to worker";
4522c593315Sopenharmony_ci  }
4532c593315Sopenharmony_ci
4542c593315Sopenharmony_ci  for (auto &worker : workers_) {
4552c593315Sopenharmony_ci    WorkerEvent wev{};
4562c593315Sopenharmony_ci    wev.type = WorkerEventType::GRACEFUL_SHUTDOWN;
4572c593315Sopenharmony_ci
4582c593315Sopenharmony_ci    worker->send(std::move(wev));
4592c593315Sopenharmony_ci  }
4602c593315Sopenharmony_ci
4612c593315Sopenharmony_ci#ifndef NOTHREADS
4622c593315Sopenharmony_ci  ev_async_start(loop_, &thread_join_asyncev_);
4632c593315Sopenharmony_ci
4642c593315Sopenharmony_ci  thread_join_fut_ = std::async(std::launch::async, [this]() {
4652c593315Sopenharmony_ci    (void)reopen_log_files(get_config()->logging);
4662c593315Sopenharmony_ci    join_worker();
4672c593315Sopenharmony_ci    ev_async_send(get_loop(), &thread_join_asyncev_);
4682c593315Sopenharmony_ci    delete_log_config();
4692c593315Sopenharmony_ci  });
4702c593315Sopenharmony_ci#endif // NOTHREADS
4712c593315Sopenharmony_ci}
4722c593315Sopenharmony_ci
4732c593315Sopenharmony_ciint ConnectionHandler::handle_connection(int fd, sockaddr *addr, int addrlen,
4742c593315Sopenharmony_ci                                         const UpstreamAddr *faddr) {
4752c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
4762c593315Sopenharmony_ci    LLOG(INFO, this) << "Accepted connection from "
4772c593315Sopenharmony_ci                     << util::numeric_name(addr, addrlen) << ", fd=" << fd;
4782c593315Sopenharmony_ci  }
4792c593315Sopenharmony_ci
4802c593315Sopenharmony_ci  auto config = get_config();
4812c593315Sopenharmony_ci
4822c593315Sopenharmony_ci  if (single_worker_) {
4832c593315Sopenharmony_ci    auto &upstreamconf = config->conn.upstream;
4842c593315Sopenharmony_ci    if (single_worker_->get_worker_stat()->num_connections >=
4852c593315Sopenharmony_ci        upstreamconf.worker_connections) {
4862c593315Sopenharmony_ci
4872c593315Sopenharmony_ci      if (LOG_ENABLED(INFO)) {
4882c593315Sopenharmony_ci        LLOG(INFO, this) << "Too many connections >="
4892c593315Sopenharmony_ci                         << upstreamconf.worker_connections;
4902c593315Sopenharmony_ci      }
4912c593315Sopenharmony_ci
4922c593315Sopenharmony_ci      close(fd);
4932c593315Sopenharmony_ci      return -1;
4942c593315Sopenharmony_ci    }
4952c593315Sopenharmony_ci
4962c593315Sopenharmony_ci    auto client =
4972c593315Sopenharmony_ci        tls::accept_connection(single_worker_.get(), fd, addr, addrlen, faddr);
4982c593315Sopenharmony_ci    if (!client) {
4992c593315Sopenharmony_ci      LLOG(ERROR, this) << "ClientHandler creation failed";
5002c593315Sopenharmony_ci
5012c593315Sopenharmony_ci      close(fd);
5022c593315Sopenharmony_ci      return -1;
5032c593315Sopenharmony_ci    }
5042c593315Sopenharmony_ci
5052c593315Sopenharmony_ci    return 0;
5062c593315Sopenharmony_ci  }
5072c593315Sopenharmony_ci
5082c593315Sopenharmony_ci  Worker *worker;
5092c593315Sopenharmony_ci
5102c593315Sopenharmony_ci  if (faddr->alt_mode == UpstreamAltMode::API) {
5112c593315Sopenharmony_ci    worker = workers_[0].get();
5122c593315Sopenharmony_ci
5132c593315Sopenharmony_ci    if (LOG_ENABLED(INFO)) {
5142c593315Sopenharmony_ci      LOG(INFO) << "Dispatch connection to API worker #0";
5152c593315Sopenharmony_ci    }
5162c593315Sopenharmony_ci  } else {
5172c593315Sopenharmony_ci    worker = workers_[worker_round_robin_cnt_].get();
5182c593315Sopenharmony_ci
5192c593315Sopenharmony_ci    if (LOG_ENABLED(INFO)) {
5202c593315Sopenharmony_ci      LOG(INFO) << "Dispatch connection to worker #" << worker_round_robin_cnt_;
5212c593315Sopenharmony_ci    }
5222c593315Sopenharmony_ci
5232c593315Sopenharmony_ci    if (++worker_round_robin_cnt_ == workers_.size()) {
5242c593315Sopenharmony_ci      auto &apiconf = config->api;
5252c593315Sopenharmony_ci
5262c593315Sopenharmony_ci      if (apiconf.enabled) {
5272c593315Sopenharmony_ci        worker_round_robin_cnt_ = 1;
5282c593315Sopenharmony_ci      } else {
5292c593315Sopenharmony_ci        worker_round_robin_cnt_ = 0;
5302c593315Sopenharmony_ci      }
5312c593315Sopenharmony_ci    }
5322c593315Sopenharmony_ci  }
5332c593315Sopenharmony_ci
5342c593315Sopenharmony_ci  WorkerEvent wev{};
5352c593315Sopenharmony_ci  wev.type = WorkerEventType::NEW_CONNECTION;
5362c593315Sopenharmony_ci  wev.client_fd = fd;
5372c593315Sopenharmony_ci  memcpy(&wev.client_addr, addr, addrlen);
5382c593315Sopenharmony_ci  wev.client_addrlen = addrlen;
5392c593315Sopenharmony_ci  wev.faddr = faddr;
5402c593315Sopenharmony_ci
5412c593315Sopenharmony_ci  worker->send(std::move(wev));
5422c593315Sopenharmony_ci
5432c593315Sopenharmony_ci  return 0;
5442c593315Sopenharmony_ci}
5452c593315Sopenharmony_ci
5462c593315Sopenharmony_cistruct ev_loop *ConnectionHandler::get_loop() const {
5472c593315Sopenharmony_ci  return loop_;
5482c593315Sopenharmony_ci}
5492c593315Sopenharmony_ci
5502c593315Sopenharmony_ciWorker *ConnectionHandler::get_single_worker() const {
5512c593315Sopenharmony_ci  return single_worker_.get();
5522c593315Sopenharmony_ci}
5532c593315Sopenharmony_ci
5542c593315Sopenharmony_civoid ConnectionHandler::add_acceptor(std::unique_ptr<AcceptHandler> h) {
5552c593315Sopenharmony_ci  acceptors_.push_back(std::move(h));
5562c593315Sopenharmony_ci}
5572c593315Sopenharmony_ci
5582c593315Sopenharmony_civoid ConnectionHandler::delete_acceptor() { acceptors_.clear(); }
5592c593315Sopenharmony_ci
5602c593315Sopenharmony_civoid ConnectionHandler::enable_acceptor() {
5612c593315Sopenharmony_ci  for (auto &a : acceptors_) {
5622c593315Sopenharmony_ci    a->enable();
5632c593315Sopenharmony_ci  }
5642c593315Sopenharmony_ci}
5652c593315Sopenharmony_ci
5662c593315Sopenharmony_civoid ConnectionHandler::disable_acceptor() {
5672c593315Sopenharmony_ci  for (auto &a : acceptors_) {
5682c593315Sopenharmony_ci    a->disable();
5692c593315Sopenharmony_ci  }
5702c593315Sopenharmony_ci}
5712c593315Sopenharmony_ci
5722c593315Sopenharmony_civoid ConnectionHandler::sleep_acceptor(ev_tstamp t) {
5732c593315Sopenharmony_ci  if (t == 0. || ev_is_active(&disable_acceptor_timer_)) {
5742c593315Sopenharmony_ci    return;
5752c593315Sopenharmony_ci  }
5762c593315Sopenharmony_ci
5772c593315Sopenharmony_ci  disable_acceptor();
5782c593315Sopenharmony_ci
5792c593315Sopenharmony_ci  ev_timer_set(&disable_acceptor_timer_, t, 0.);
5802c593315Sopenharmony_ci  ev_timer_start(loop_, &disable_acceptor_timer_);
5812c593315Sopenharmony_ci}
5822c593315Sopenharmony_ci
5832c593315Sopenharmony_civoid ConnectionHandler::accept_pending_connection() {
5842c593315Sopenharmony_ci  for (auto &a : acceptors_) {
5852c593315Sopenharmony_ci    a->accept_connection();
5862c593315Sopenharmony_ci  }
5872c593315Sopenharmony_ci}
5882c593315Sopenharmony_ci
5892c593315Sopenharmony_civoid ConnectionHandler::set_ticket_keys(
5902c593315Sopenharmony_ci    std::shared_ptr<TicketKeys> ticket_keys) {
5912c593315Sopenharmony_ci  ticket_keys_ = std::move(ticket_keys);
5922c593315Sopenharmony_ci  if (single_worker_) {
5932c593315Sopenharmony_ci    single_worker_->set_ticket_keys(ticket_keys_);
5942c593315Sopenharmony_ci  }
5952c593315Sopenharmony_ci}
5962c593315Sopenharmony_ci
5972c593315Sopenharmony_ciconst std::shared_ptr<TicketKeys> &ConnectionHandler::get_ticket_keys() const {
5982c593315Sopenharmony_ci  return ticket_keys_;
5992c593315Sopenharmony_ci}
6002c593315Sopenharmony_ci
6012c593315Sopenharmony_civoid ConnectionHandler::set_graceful_shutdown(bool f) {
6022c593315Sopenharmony_ci  graceful_shutdown_ = f;
6032c593315Sopenharmony_ci  if (single_worker_) {
6042c593315Sopenharmony_ci    single_worker_->set_graceful_shutdown(f);
6052c593315Sopenharmony_ci  }
6062c593315Sopenharmony_ci}
6072c593315Sopenharmony_ci
6082c593315Sopenharmony_cibool ConnectionHandler::get_graceful_shutdown() const {
6092c593315Sopenharmony_ci  return graceful_shutdown_;
6102c593315Sopenharmony_ci}
6112c593315Sopenharmony_ci
6122c593315Sopenharmony_civoid ConnectionHandler::cancel_ocsp_update() {
6132c593315Sopenharmony_ci  enable_acceptor_on_ocsp_completion_ = false;
6142c593315Sopenharmony_ci  ev_timer_stop(loop_, &ocsp_timer_);
6152c593315Sopenharmony_ci
6162c593315Sopenharmony_ci  if (ocsp_.proc.pid == 0) {
6172c593315Sopenharmony_ci    return;
6182c593315Sopenharmony_ci  }
6192c593315Sopenharmony_ci
6202c593315Sopenharmony_ci  int rv;
6212c593315Sopenharmony_ci
6222c593315Sopenharmony_ci  rv = kill(ocsp_.proc.pid, SIGTERM);
6232c593315Sopenharmony_ci  if (rv != 0) {
6242c593315Sopenharmony_ci    auto error = errno;
6252c593315Sopenharmony_ci    LOG(ERROR) << "Could not send signal to OCSP query process: errno="
6262c593315Sopenharmony_ci               << error;
6272c593315Sopenharmony_ci  }
6282c593315Sopenharmony_ci
6292c593315Sopenharmony_ci  while ((rv = waitpid(ocsp_.proc.pid, nullptr, 0)) == -1 && errno == EINTR)
6302c593315Sopenharmony_ci    ;
6312c593315Sopenharmony_ci  if (rv == -1) {
6322c593315Sopenharmony_ci    auto error = errno;
6332c593315Sopenharmony_ci    LOG(ERROR) << "Error occurred while we were waiting for the completion of "
6342c593315Sopenharmony_ci                  "OCSP query process: errno="
6352c593315Sopenharmony_ci               << error;
6362c593315Sopenharmony_ci  }
6372c593315Sopenharmony_ci}
6382c593315Sopenharmony_ci
6392c593315Sopenharmony_ci// inspired by h2o_read_command function from h2o project:
6402c593315Sopenharmony_ci// https://github.com/h2o/h2o
6412c593315Sopenharmony_ciint ConnectionHandler::start_ocsp_update(const char *cert_file) {
6422c593315Sopenharmony_ci  int rv;
6432c593315Sopenharmony_ci
6442c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
6452c593315Sopenharmony_ci    LOG(INFO) << "Start ocsp update for " << cert_file;
6462c593315Sopenharmony_ci  }
6472c593315Sopenharmony_ci
6482c593315Sopenharmony_ci  assert(!ev_is_active(&ocsp_.rev));
6492c593315Sopenharmony_ci  assert(!ev_is_active(&ocsp_.chldev));
6502c593315Sopenharmony_ci
6512c593315Sopenharmony_ci  char *const argv[] = {
6522c593315Sopenharmony_ci      const_cast<char *>(
6532c593315Sopenharmony_ci          get_config()->tls.ocsp.fetch_ocsp_response_file.c_str()),
6542c593315Sopenharmony_ci      const_cast<char *>(cert_file), nullptr};
6552c593315Sopenharmony_ci
6562c593315Sopenharmony_ci  Process proc;
6572c593315Sopenharmony_ci  rv = exec_read_command(proc, argv);
6582c593315Sopenharmony_ci  if (rv != 0) {
6592c593315Sopenharmony_ci    return -1;
6602c593315Sopenharmony_ci  }
6612c593315Sopenharmony_ci
6622c593315Sopenharmony_ci  ocsp_.proc = proc;
6632c593315Sopenharmony_ci
6642c593315Sopenharmony_ci  ev_io_set(&ocsp_.rev, ocsp_.proc.rfd, EV_READ);
6652c593315Sopenharmony_ci  ev_io_start(loop_, &ocsp_.rev);
6662c593315Sopenharmony_ci
6672c593315Sopenharmony_ci  ev_child_set(&ocsp_.chldev, ocsp_.proc.pid, 0);
6682c593315Sopenharmony_ci  ev_child_start(loop_, &ocsp_.chldev);
6692c593315Sopenharmony_ci
6702c593315Sopenharmony_ci  return 0;
6712c593315Sopenharmony_ci}
6722c593315Sopenharmony_ci
6732c593315Sopenharmony_civoid ConnectionHandler::read_ocsp_chunk() {
6742c593315Sopenharmony_ci  std::array<uint8_t, 4_k> buf;
6752c593315Sopenharmony_ci  for (;;) {
6762c593315Sopenharmony_ci    ssize_t n;
6772c593315Sopenharmony_ci    while ((n = read(ocsp_.proc.rfd, buf.data(), buf.size())) == -1 &&
6782c593315Sopenharmony_ci           errno == EINTR)
6792c593315Sopenharmony_ci      ;
6802c593315Sopenharmony_ci
6812c593315Sopenharmony_ci    if (n == -1) {
6822c593315Sopenharmony_ci      if (errno == EAGAIN || errno == EWOULDBLOCK) {
6832c593315Sopenharmony_ci        return;
6842c593315Sopenharmony_ci      }
6852c593315Sopenharmony_ci      auto error = errno;
6862c593315Sopenharmony_ci      LOG(WARN) << "Reading from ocsp query command failed: errno=" << error;
6872c593315Sopenharmony_ci      ocsp_.error = error;
6882c593315Sopenharmony_ci
6892c593315Sopenharmony_ci      break;
6902c593315Sopenharmony_ci    }
6912c593315Sopenharmony_ci
6922c593315Sopenharmony_ci    if (n == 0) {
6932c593315Sopenharmony_ci      break;
6942c593315Sopenharmony_ci    }
6952c593315Sopenharmony_ci
6962c593315Sopenharmony_ci    std::copy_n(std::begin(buf), n, std::back_inserter(ocsp_.resp));
6972c593315Sopenharmony_ci  }
6982c593315Sopenharmony_ci
6992c593315Sopenharmony_ci  ev_io_stop(loop_, &ocsp_.rev);
7002c593315Sopenharmony_ci}
7012c593315Sopenharmony_ci
7022c593315Sopenharmony_civoid ConnectionHandler::handle_ocsp_complete() {
7032c593315Sopenharmony_ci  ev_io_stop(loop_, &ocsp_.rev);
7042c593315Sopenharmony_ci  ev_child_stop(loop_, &ocsp_.chldev);
7052c593315Sopenharmony_ci
7062c593315Sopenharmony_ci  assert(ocsp_.next < all_ssl_ctx_.size());
7072c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
7082c593315Sopenharmony_ci  assert(all_ssl_ctx_.size() == quic_all_ssl_ctx_.size());
7092c593315Sopenharmony_ci#endif // ENABLE_HTTP3
7102c593315Sopenharmony_ci
7112c593315Sopenharmony_ci  auto ssl_ctx = all_ssl_ctx_[ocsp_.next];
7122c593315Sopenharmony_ci  auto tls_ctx_data =
7132c593315Sopenharmony_ci      static_cast<tls::TLSContextData *>(SSL_CTX_get_app_data(ssl_ctx));
7142c593315Sopenharmony_ci
7152c593315Sopenharmony_ci  auto rstatus = ocsp_.chldev.rstatus;
7162c593315Sopenharmony_ci  auto status = WEXITSTATUS(rstatus);
7172c593315Sopenharmony_ci  if (ocsp_.error || !WIFEXITED(rstatus) || status != 0) {
7182c593315Sopenharmony_ci    LOG(WARN) << "ocsp query command for " << tls_ctx_data->cert_file
7192c593315Sopenharmony_ci              << " failed: error=" << ocsp_.error << ", rstatus=" << log::hex
7202c593315Sopenharmony_ci              << rstatus << log::dec << ", status=" << status;
7212c593315Sopenharmony_ci    ++ocsp_.next;
7222c593315Sopenharmony_ci    proceed_next_cert_ocsp();
7232c593315Sopenharmony_ci    return;
7242c593315Sopenharmony_ci  }
7252c593315Sopenharmony_ci
7262c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
7272c593315Sopenharmony_ci    LOG(INFO) << "ocsp update for " << tls_ctx_data->cert_file
7282c593315Sopenharmony_ci              << " finished successfully";
7292c593315Sopenharmony_ci  }
7302c593315Sopenharmony_ci
7312c593315Sopenharmony_ci  auto config = get_config();
7322c593315Sopenharmony_ci  auto &tlsconf = config->tls;
7332c593315Sopenharmony_ci
7342c593315Sopenharmony_ci  if (tlsconf.ocsp.no_verify ||
7352c593315Sopenharmony_ci      tls::verify_ocsp_response(ssl_ctx, ocsp_.resp.data(),
7362c593315Sopenharmony_ci                                ocsp_.resp.size()) == 0) {
7372c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
7382c593315Sopenharmony_ci    // We have list of SSL_CTX with the same certificate in
7392c593315Sopenharmony_ci    // quic_all_ssl_ctx_ as well.  Some SSL_CTXs are missing there in
7402c593315Sopenharmony_ci    // that case we get nullptr.
7412c593315Sopenharmony_ci    auto quic_ssl_ctx = quic_all_ssl_ctx_[ocsp_.next];
7422c593315Sopenharmony_ci    if (quic_ssl_ctx) {
7432c593315Sopenharmony_ci#  ifndef OPENSSL_IS_BORINGSSL
7442c593315Sopenharmony_ci      auto quic_tls_ctx_data = static_cast<tls::TLSContextData *>(
7452c593315Sopenharmony_ci          SSL_CTX_get_app_data(quic_ssl_ctx));
7462c593315Sopenharmony_ci#    ifdef HAVE_ATOMIC_STD_SHARED_PTR
7472c593315Sopenharmony_ci      std::atomic_store_explicit(
7482c593315Sopenharmony_ci          &quic_tls_ctx_data->ocsp_data,
7492c593315Sopenharmony_ci          std::make_shared<std::vector<uint8_t>>(ocsp_.resp),
7502c593315Sopenharmony_ci          std::memory_order_release);
7512c593315Sopenharmony_ci#    else  // !HAVE_ATOMIC_STD_SHARED_PTR
7522c593315Sopenharmony_ci      std::lock_guard<std::mutex> g(quic_tls_ctx_data->mu);
7532c593315Sopenharmony_ci      quic_tls_ctx_data->ocsp_data =
7542c593315Sopenharmony_ci          std::make_shared<std::vector<uint8_t>>(ocsp_.resp);
7552c593315Sopenharmony_ci#    endif // !HAVE_ATOMIC_STD_SHARED_PTR
7562c593315Sopenharmony_ci#  else    // OPENSSL_IS_BORINGSSL
7572c593315Sopenharmony_ci      SSL_CTX_set_ocsp_response(quic_ssl_ctx, ocsp_.resp.data(),
7582c593315Sopenharmony_ci                                ocsp_.resp.size());
7592c593315Sopenharmony_ci#  endif   // OPENSSL_IS_BORINGSSL
7602c593315Sopenharmony_ci    }
7612c593315Sopenharmony_ci#endif // ENABLE_HTTP3
7622c593315Sopenharmony_ci
7632c593315Sopenharmony_ci#ifndef OPENSSL_IS_BORINGSSL
7642c593315Sopenharmony_ci#  ifdef HAVE_ATOMIC_STD_SHARED_PTR
7652c593315Sopenharmony_ci    std::atomic_store_explicit(
7662c593315Sopenharmony_ci        &tls_ctx_data->ocsp_data,
7672c593315Sopenharmony_ci        std::make_shared<std::vector<uint8_t>>(std::move(ocsp_.resp)),
7682c593315Sopenharmony_ci        std::memory_order_release);
7692c593315Sopenharmony_ci#  else  // !HAVE_ATOMIC_STD_SHARED_PTR
7702c593315Sopenharmony_ci    std::lock_guard<std::mutex> g(tls_ctx_data->mu);
7712c593315Sopenharmony_ci    tls_ctx_data->ocsp_data =
7722c593315Sopenharmony_ci        std::make_shared<std::vector<uint8_t>>(std::move(ocsp_.resp));
7732c593315Sopenharmony_ci#  endif // !HAVE_ATOMIC_STD_SHARED_PTR
7742c593315Sopenharmony_ci#else    // OPENSSL_IS_BORINGSSL
7752c593315Sopenharmony_ci    SSL_CTX_set_ocsp_response(ssl_ctx, ocsp_.resp.data(), ocsp_.resp.size());
7762c593315Sopenharmony_ci#endif   // OPENSSL_IS_BORINGSSL
7772c593315Sopenharmony_ci  }
7782c593315Sopenharmony_ci
7792c593315Sopenharmony_ci  ++ocsp_.next;
7802c593315Sopenharmony_ci  proceed_next_cert_ocsp();
7812c593315Sopenharmony_ci}
7822c593315Sopenharmony_ci
7832c593315Sopenharmony_civoid ConnectionHandler::reset_ocsp() {
7842c593315Sopenharmony_ci  if (ocsp_.proc.rfd != -1) {
7852c593315Sopenharmony_ci    close(ocsp_.proc.rfd);
7862c593315Sopenharmony_ci  }
7872c593315Sopenharmony_ci
7882c593315Sopenharmony_ci  ocsp_.proc.rfd = -1;
7892c593315Sopenharmony_ci  ocsp_.proc.pid = 0;
7902c593315Sopenharmony_ci  ocsp_.error = 0;
7912c593315Sopenharmony_ci  ocsp_.resp = std::vector<uint8_t>();
7922c593315Sopenharmony_ci}
7932c593315Sopenharmony_ci
7942c593315Sopenharmony_civoid ConnectionHandler::proceed_next_cert_ocsp() {
7952c593315Sopenharmony_ci  for (;;) {
7962c593315Sopenharmony_ci    reset_ocsp();
7972c593315Sopenharmony_ci    if (ocsp_.next == all_ssl_ctx_.size()) {
7982c593315Sopenharmony_ci      ocsp_.next = 0;
7992c593315Sopenharmony_ci      // We have updated all ocsp response, and schedule next update.
8002c593315Sopenharmony_ci      ev_timer_set(&ocsp_timer_, get_config()->tls.ocsp.update_interval, 0.);
8012c593315Sopenharmony_ci      ev_timer_start(loop_, &ocsp_timer_);
8022c593315Sopenharmony_ci
8032c593315Sopenharmony_ci      if (enable_acceptor_on_ocsp_completion_) {
8042c593315Sopenharmony_ci        enable_acceptor_on_ocsp_completion_ = false;
8052c593315Sopenharmony_ci        enable_acceptor();
8062c593315Sopenharmony_ci      }
8072c593315Sopenharmony_ci
8082c593315Sopenharmony_ci      return;
8092c593315Sopenharmony_ci    }
8102c593315Sopenharmony_ci
8112c593315Sopenharmony_ci    auto ssl_ctx = all_ssl_ctx_[ocsp_.next];
8122c593315Sopenharmony_ci    auto tls_ctx_data =
8132c593315Sopenharmony_ci        static_cast<tls::TLSContextData *>(SSL_CTX_get_app_data(ssl_ctx));
8142c593315Sopenharmony_ci
8152c593315Sopenharmony_ci    // client SSL_CTX is also included in all_ssl_ctx_, but has no
8162c593315Sopenharmony_ci    // tls_ctx_data.
8172c593315Sopenharmony_ci    if (!tls_ctx_data) {
8182c593315Sopenharmony_ci      ++ocsp_.next;
8192c593315Sopenharmony_ci      continue;
8202c593315Sopenharmony_ci    }
8212c593315Sopenharmony_ci
8222c593315Sopenharmony_ci    auto cert_file = tls_ctx_data->cert_file;
8232c593315Sopenharmony_ci
8242c593315Sopenharmony_ci    if (start_ocsp_update(cert_file) != 0) {
8252c593315Sopenharmony_ci      ++ocsp_.next;
8262c593315Sopenharmony_ci      continue;
8272c593315Sopenharmony_ci    }
8282c593315Sopenharmony_ci
8292c593315Sopenharmony_ci    break;
8302c593315Sopenharmony_ci  }
8312c593315Sopenharmony_ci}
8322c593315Sopenharmony_ci
8332c593315Sopenharmony_civoid ConnectionHandler::set_tls_ticket_key_memcached_dispatcher(
8342c593315Sopenharmony_ci    std::unique_ptr<MemcachedDispatcher> dispatcher) {
8352c593315Sopenharmony_ci  tls_ticket_key_memcached_dispatcher_ = std::move(dispatcher);
8362c593315Sopenharmony_ci}
8372c593315Sopenharmony_ci
8382c593315Sopenharmony_ciMemcachedDispatcher *
8392c593315Sopenharmony_ciConnectionHandler::get_tls_ticket_key_memcached_dispatcher() const {
8402c593315Sopenharmony_ci  return tls_ticket_key_memcached_dispatcher_.get();
8412c593315Sopenharmony_ci}
8422c593315Sopenharmony_ci
8432c593315Sopenharmony_ci// Use the similar backoff algorithm described in
8442c593315Sopenharmony_ci// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md
8452c593315Sopenharmony_cinamespace {
8462c593315Sopenharmony_ciconstexpr size_t MAX_BACKOFF_EXP = 10;
8472c593315Sopenharmony_ciconstexpr auto MULTIPLIER = 3.2;
8482c593315Sopenharmony_ciconstexpr auto JITTER = 0.2;
8492c593315Sopenharmony_ci} // namespace
8502c593315Sopenharmony_ci
8512c593315Sopenharmony_civoid ConnectionHandler::on_tls_ticket_key_network_error(ev_timer *w) {
8522c593315Sopenharmony_ci  if (++tls_ticket_key_memcached_get_retry_count_ >=
8532c593315Sopenharmony_ci      get_config()->tls.ticket.memcached.max_retry) {
8542c593315Sopenharmony_ci    LOG(WARN) << "Memcached: tls ticket get retry all failed "
8552c593315Sopenharmony_ci              << tls_ticket_key_memcached_get_retry_count_ << " times.";
8562c593315Sopenharmony_ci
8572c593315Sopenharmony_ci    on_tls_ticket_key_not_found(w);
8582c593315Sopenharmony_ci    return;
8592c593315Sopenharmony_ci  }
8602c593315Sopenharmony_ci
8612c593315Sopenharmony_ci  auto base_backoff = util::int_pow(
8622c593315Sopenharmony_ci      MULTIPLIER,
8632c593315Sopenharmony_ci      std::min(MAX_BACKOFF_EXP, tls_ticket_key_memcached_get_retry_count_));
8642c593315Sopenharmony_ci  auto dist = std::uniform_real_distribution<>(-JITTER * base_backoff,
8652c593315Sopenharmony_ci                                               JITTER * base_backoff);
8662c593315Sopenharmony_ci
8672c593315Sopenharmony_ci  auto backoff = base_backoff + dist(gen_);
8682c593315Sopenharmony_ci
8692c593315Sopenharmony_ci  LOG(WARN)
8702c593315Sopenharmony_ci      << "Memcached: tls ticket get failed due to network error, retrying in "
8712c593315Sopenharmony_ci      << backoff << " seconds";
8722c593315Sopenharmony_ci
8732c593315Sopenharmony_ci  ev_timer_set(w, backoff, 0.);
8742c593315Sopenharmony_ci  ev_timer_start(loop_, w);
8752c593315Sopenharmony_ci}
8762c593315Sopenharmony_ci
8772c593315Sopenharmony_civoid ConnectionHandler::on_tls_ticket_key_not_found(ev_timer *w) {
8782c593315Sopenharmony_ci  tls_ticket_key_memcached_get_retry_count_ = 0;
8792c593315Sopenharmony_ci
8802c593315Sopenharmony_ci  if (++tls_ticket_key_memcached_fail_count_ >=
8812c593315Sopenharmony_ci      get_config()->tls.ticket.memcached.max_fail) {
8822c593315Sopenharmony_ci    LOG(WARN) << "Memcached: could not get tls ticket; disable tls ticket";
8832c593315Sopenharmony_ci
8842c593315Sopenharmony_ci    tls_ticket_key_memcached_fail_count_ = 0;
8852c593315Sopenharmony_ci
8862c593315Sopenharmony_ci    set_ticket_keys(nullptr);
8872c593315Sopenharmony_ci    set_ticket_keys_to_worker(nullptr);
8882c593315Sopenharmony_ci  }
8892c593315Sopenharmony_ci
8902c593315Sopenharmony_ci  LOG(WARN) << "Memcached: tls ticket get failed, schedule next";
8912c593315Sopenharmony_ci  schedule_next_tls_ticket_key_memcached_get(w);
8922c593315Sopenharmony_ci}
8932c593315Sopenharmony_ci
8942c593315Sopenharmony_civoid ConnectionHandler::on_tls_ticket_key_get_success(
8952c593315Sopenharmony_ci    const std::shared_ptr<TicketKeys> &ticket_keys, ev_timer *w) {
8962c593315Sopenharmony_ci  LOG(NOTICE) << "Memcached: tls ticket get success";
8972c593315Sopenharmony_ci
8982c593315Sopenharmony_ci  tls_ticket_key_memcached_get_retry_count_ = 0;
8992c593315Sopenharmony_ci  tls_ticket_key_memcached_fail_count_ = 0;
9002c593315Sopenharmony_ci
9012c593315Sopenharmony_ci  schedule_next_tls_ticket_key_memcached_get(w);
9022c593315Sopenharmony_ci
9032c593315Sopenharmony_ci  if (!ticket_keys || ticket_keys->keys.empty()) {
9042c593315Sopenharmony_ci    LOG(WARN) << "Memcached: tls ticket keys are empty; tls ticket disabled";
9052c593315Sopenharmony_ci    set_ticket_keys(nullptr);
9062c593315Sopenharmony_ci    set_ticket_keys_to_worker(nullptr);
9072c593315Sopenharmony_ci    return;
9082c593315Sopenharmony_ci  }
9092c593315Sopenharmony_ci
9102c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
9112c593315Sopenharmony_ci    LOG(INFO) << "ticket keys get done";
9122c593315Sopenharmony_ci    LOG(INFO) << 0 << " enc+dec: "
9132c593315Sopenharmony_ci              << util::format_hex(ticket_keys->keys[0].data.name);
9142c593315Sopenharmony_ci    for (size_t i = 1; i < ticket_keys->keys.size(); ++i) {
9152c593315Sopenharmony_ci      auto &key = ticket_keys->keys[i];
9162c593315Sopenharmony_ci      LOG(INFO) << i << " dec: " << util::format_hex(key.data.name);
9172c593315Sopenharmony_ci    }
9182c593315Sopenharmony_ci  }
9192c593315Sopenharmony_ci
9202c593315Sopenharmony_ci  set_ticket_keys(ticket_keys);
9212c593315Sopenharmony_ci  set_ticket_keys_to_worker(ticket_keys);
9222c593315Sopenharmony_ci}
9232c593315Sopenharmony_ci
9242c593315Sopenharmony_civoid ConnectionHandler::schedule_next_tls_ticket_key_memcached_get(
9252c593315Sopenharmony_ci    ev_timer *w) {
9262c593315Sopenharmony_ci  ev_timer_set(w, get_config()->tls.ticket.memcached.interval, 0.);
9272c593315Sopenharmony_ci  ev_timer_start(loop_, w);
9282c593315Sopenharmony_ci}
9292c593315Sopenharmony_ci
9302c593315Sopenharmony_ciSSL_CTX *ConnectionHandler::create_tls_ticket_key_memcached_ssl_ctx() {
9312c593315Sopenharmony_ci  auto config = get_config();
9322c593315Sopenharmony_ci  auto &tlsconf = config->tls;
9332c593315Sopenharmony_ci  auto &memcachedconf = config->tls.ticket.memcached;
9342c593315Sopenharmony_ci
9352c593315Sopenharmony_ci  auto ssl_ctx = tls::create_ssl_client_context(
9362c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED
9372c593315Sopenharmony_ci      nb_,
9382c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED
9392c593315Sopenharmony_ci      tlsconf.cacert, memcachedconf.cert_file, memcachedconf.private_key_file,
9402c593315Sopenharmony_ci      nullptr);
9412c593315Sopenharmony_ci
9422c593315Sopenharmony_ci  all_ssl_ctx_.push_back(ssl_ctx);
9432c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
9442c593315Sopenharmony_ci  quic_all_ssl_ctx_.push_back(nullptr);
9452c593315Sopenharmony_ci#endif // ENABLE_HTTP3
9462c593315Sopenharmony_ci
9472c593315Sopenharmony_ci  return ssl_ctx;
9482c593315Sopenharmony_ci}
9492c593315Sopenharmony_ci
9502c593315Sopenharmony_ci#ifdef HAVE_NEVERBLEED
9512c593315Sopenharmony_civoid ConnectionHandler::set_neverbleed(neverbleed_t *nb) { nb_ = nb; }
9522c593315Sopenharmony_ci#endif // HAVE_NEVERBLEED
9532c593315Sopenharmony_ci
9542c593315Sopenharmony_civoid ConnectionHandler::handle_serial_event() {
9552c593315Sopenharmony_ci  std::vector<SerialEvent> q;
9562c593315Sopenharmony_ci  {
9572c593315Sopenharmony_ci    std::lock_guard<std::mutex> g(serial_event_mu_);
9582c593315Sopenharmony_ci    q.swap(serial_events_);
9592c593315Sopenharmony_ci  }
9602c593315Sopenharmony_ci
9612c593315Sopenharmony_ci  for (auto &sev : q) {
9622c593315Sopenharmony_ci    switch (sev.type) {
9632c593315Sopenharmony_ci    case SerialEventType::REPLACE_DOWNSTREAM:
9642c593315Sopenharmony_ci      // Mmake sure that none of worker uses
9652c593315Sopenharmony_ci      // get_config()->conn.downstream
9662c593315Sopenharmony_ci      mod_config()->conn.downstream = sev.downstreamconf;
9672c593315Sopenharmony_ci
9682c593315Sopenharmony_ci      if (single_worker_) {
9692c593315Sopenharmony_ci        single_worker_->replace_downstream_config(sev.downstreamconf);
9702c593315Sopenharmony_ci
9712c593315Sopenharmony_ci        break;
9722c593315Sopenharmony_ci      }
9732c593315Sopenharmony_ci
9742c593315Sopenharmony_ci      worker_replace_downstream(sev.downstreamconf);
9752c593315Sopenharmony_ci
9762c593315Sopenharmony_ci      break;
9772c593315Sopenharmony_ci    default:
9782c593315Sopenharmony_ci      break;
9792c593315Sopenharmony_ci    }
9802c593315Sopenharmony_ci  }
9812c593315Sopenharmony_ci}
9822c593315Sopenharmony_ci
9832c593315Sopenharmony_civoid ConnectionHandler::send_replace_downstream(
9842c593315Sopenharmony_ci    const std::shared_ptr<DownstreamConfig> &downstreamconf) {
9852c593315Sopenharmony_ci  send_serial_event(
9862c593315Sopenharmony_ci      SerialEvent(SerialEventType::REPLACE_DOWNSTREAM, downstreamconf));
9872c593315Sopenharmony_ci}
9882c593315Sopenharmony_ci
9892c593315Sopenharmony_civoid ConnectionHandler::send_serial_event(SerialEvent ev) {
9902c593315Sopenharmony_ci  {
9912c593315Sopenharmony_ci    std::lock_guard<std::mutex> g(serial_event_mu_);
9922c593315Sopenharmony_ci
9932c593315Sopenharmony_ci    serial_events_.push_back(std::move(ev));
9942c593315Sopenharmony_ci  }
9952c593315Sopenharmony_ci
9962c593315Sopenharmony_ci  ev_async_send(loop_, &serial_event_asyncev_);
9972c593315Sopenharmony_ci}
9982c593315Sopenharmony_ci
9992c593315Sopenharmony_ciSSL_CTX *ConnectionHandler::get_ssl_ctx(size_t idx) const {
10002c593315Sopenharmony_ci  return all_ssl_ctx_[idx];
10012c593315Sopenharmony_ci}
10022c593315Sopenharmony_ci
10032c593315Sopenharmony_ciconst std::vector<SSL_CTX *> &
10042c593315Sopenharmony_ciConnectionHandler::get_indexed_ssl_ctx(size_t idx) const {
10052c593315Sopenharmony_ci  return indexed_ssl_ctx_[idx];
10062c593315Sopenharmony_ci}
10072c593315Sopenharmony_ci
10082c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
10092c593315Sopenharmony_ciconst std::vector<SSL_CTX *> &
10102c593315Sopenharmony_ciConnectionHandler::get_quic_indexed_ssl_ctx(size_t idx) const {
10112c593315Sopenharmony_ci  return quic_indexed_ssl_ctx_[idx];
10122c593315Sopenharmony_ci}
10132c593315Sopenharmony_ci#endif // ENABLE_HTTP3
10142c593315Sopenharmony_ci
10152c593315Sopenharmony_civoid ConnectionHandler::set_enable_acceptor_on_ocsp_completion(bool f) {
10162c593315Sopenharmony_ci  enable_acceptor_on_ocsp_completion_ = f;
10172c593315Sopenharmony_ci}
10182c593315Sopenharmony_ci
10192c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
10202c593315Sopenharmony_ciint ConnectionHandler::forward_quic_packet(
10212c593315Sopenharmony_ci    const UpstreamAddr *faddr, const Address &remote_addr,
10222c593315Sopenharmony_ci    const Address &local_addr, const ngtcp2_pkt_info &pi,
10232c593315Sopenharmony_ci    const uint8_t *cid_prefix, const uint8_t *data, size_t datalen) {
10242c593315Sopenharmony_ci  assert(!get_config()->single_thread);
10252c593315Sopenharmony_ci
10262c593315Sopenharmony_ci  for (auto &worker : workers_) {
10272c593315Sopenharmony_ci    if (!std::equal(cid_prefix, cid_prefix + SHRPX_QUIC_CID_PREFIXLEN,
10282c593315Sopenharmony_ci                    worker->get_cid_prefix())) {
10292c593315Sopenharmony_ci      continue;
10302c593315Sopenharmony_ci    }
10312c593315Sopenharmony_ci
10322c593315Sopenharmony_ci    WorkerEvent wev{};
10332c593315Sopenharmony_ci    wev.type = WorkerEventType::QUIC_PKT_FORWARD;
10342c593315Sopenharmony_ci    wev.quic_pkt = std::make_unique<QUICPacket>(faddr->index, remote_addr,
10352c593315Sopenharmony_ci                                                local_addr, pi, data, datalen);
10362c593315Sopenharmony_ci
10372c593315Sopenharmony_ci    worker->send(std::move(wev));
10382c593315Sopenharmony_ci
10392c593315Sopenharmony_ci    return 0;
10402c593315Sopenharmony_ci  }
10412c593315Sopenharmony_ci
10422c593315Sopenharmony_ci  return -1;
10432c593315Sopenharmony_ci}
10442c593315Sopenharmony_ci
10452c593315Sopenharmony_civoid ConnectionHandler::set_quic_keying_materials(
10462c593315Sopenharmony_ci    std::shared_ptr<QUICKeyingMaterials> qkms) {
10472c593315Sopenharmony_ci  quic_keying_materials_ = std::move(qkms);
10482c593315Sopenharmony_ci}
10492c593315Sopenharmony_ci
10502c593315Sopenharmony_ciconst std::shared_ptr<QUICKeyingMaterials> &
10512c593315Sopenharmony_ciConnectionHandler::get_quic_keying_materials() const {
10522c593315Sopenharmony_ci  return quic_keying_materials_;
10532c593315Sopenharmony_ci}
10542c593315Sopenharmony_ci
10552c593315Sopenharmony_civoid ConnectionHandler::set_cid_prefixes(
10562c593315Sopenharmony_ci    const std::vector<std::array<uint8_t, SHRPX_QUIC_CID_PREFIXLEN>>
10572c593315Sopenharmony_ci        &cid_prefixes) {
10582c593315Sopenharmony_ci  cid_prefixes_ = cid_prefixes;
10592c593315Sopenharmony_ci}
10602c593315Sopenharmony_ci
10612c593315Sopenharmony_ciQUICLingeringWorkerProcess *
10622c593315Sopenharmony_ciConnectionHandler::match_quic_lingering_worker_process_cid_prefix(
10632c593315Sopenharmony_ci    const uint8_t *dcid, size_t dcidlen) {
10642c593315Sopenharmony_ci  assert(dcidlen >= SHRPX_QUIC_CID_PREFIXLEN);
10652c593315Sopenharmony_ci
10662c593315Sopenharmony_ci  for (auto &lwps : quic_lingering_worker_processes_) {
10672c593315Sopenharmony_ci    for (auto &cid_prefix : lwps.cid_prefixes) {
10682c593315Sopenharmony_ci      if (std::equal(std::begin(cid_prefix), std::end(cid_prefix), dcid)) {
10692c593315Sopenharmony_ci        return &lwps;
10702c593315Sopenharmony_ci      }
10712c593315Sopenharmony_ci    }
10722c593315Sopenharmony_ci  }
10732c593315Sopenharmony_ci
10742c593315Sopenharmony_ci  return nullptr;
10752c593315Sopenharmony_ci}
10762c593315Sopenharmony_ci
10772c593315Sopenharmony_ci#  ifdef HAVE_LIBBPF
10782c593315Sopenharmony_cistd::vector<BPFRef> &ConnectionHandler::get_quic_bpf_refs() {
10792c593315Sopenharmony_ci  return quic_bpf_refs_;
10802c593315Sopenharmony_ci}
10812c593315Sopenharmony_ci
10822c593315Sopenharmony_civoid ConnectionHandler::unload_bpf_objects() {
10832c593315Sopenharmony_ci  LOG(NOTICE) << "Unloading BPF objects";
10842c593315Sopenharmony_ci
10852c593315Sopenharmony_ci  for (auto &ref : quic_bpf_refs_) {
10862c593315Sopenharmony_ci    if (ref.obj == nullptr) {
10872c593315Sopenharmony_ci      continue;
10882c593315Sopenharmony_ci    }
10892c593315Sopenharmony_ci
10902c593315Sopenharmony_ci    bpf_object__close(ref.obj);
10912c593315Sopenharmony_ci
10922c593315Sopenharmony_ci    ref.obj = nullptr;
10932c593315Sopenharmony_ci  }
10942c593315Sopenharmony_ci}
10952c593315Sopenharmony_ci#  endif // HAVE_LIBBPF
10962c593315Sopenharmony_ci
10972c593315Sopenharmony_civoid ConnectionHandler::set_quic_ipc_fd(int fd) { quic_ipc_fd_ = fd; }
10982c593315Sopenharmony_ci
10992c593315Sopenharmony_civoid ConnectionHandler::set_quic_lingering_worker_processes(
11002c593315Sopenharmony_ci    const std::vector<QUICLingeringWorkerProcess> &quic_lwps) {
11012c593315Sopenharmony_ci  quic_lingering_worker_processes_ = quic_lwps;
11022c593315Sopenharmony_ci}
11032c593315Sopenharmony_ci
11042c593315Sopenharmony_ciint ConnectionHandler::forward_quic_packet_to_lingering_worker_process(
11052c593315Sopenharmony_ci    QUICLingeringWorkerProcess *quic_lwp, const Address &remote_addr,
11062c593315Sopenharmony_ci    const Address &local_addr, const ngtcp2_pkt_info &pi, const uint8_t *data,
11072c593315Sopenharmony_ci    size_t datalen) {
11082c593315Sopenharmony_ci  std::array<uint8_t, 512> header;
11092c593315Sopenharmony_ci
11102c593315Sopenharmony_ci  assert(header.size() >= 1 + 1 + 1 + 1 + sizeof(sockaddr_storage) * 2);
11112c593315Sopenharmony_ci  assert(remote_addr.len > 0);
11122c593315Sopenharmony_ci  assert(local_addr.len > 0);
11132c593315Sopenharmony_ci
11142c593315Sopenharmony_ci  auto p = header.data();
11152c593315Sopenharmony_ci
11162c593315Sopenharmony_ci  *p++ = static_cast<uint8_t>(QUICIPCType::DGRAM_FORWARD);
11172c593315Sopenharmony_ci  *p++ = static_cast<uint8_t>(remote_addr.len - 1);
11182c593315Sopenharmony_ci  p = std::copy_n(reinterpret_cast<const uint8_t *>(&remote_addr.su),
11192c593315Sopenharmony_ci                  remote_addr.len, p);
11202c593315Sopenharmony_ci  *p++ = static_cast<uint8_t>(local_addr.len - 1);
11212c593315Sopenharmony_ci  p = std::copy_n(reinterpret_cast<const uint8_t *>(&local_addr.su),
11222c593315Sopenharmony_ci                  local_addr.len, p);
11232c593315Sopenharmony_ci  *p++ = pi.ecn;
11242c593315Sopenharmony_ci
11252c593315Sopenharmony_ci  iovec msg_iov[] = {
11262c593315Sopenharmony_ci      {
11272c593315Sopenharmony_ci          .iov_base = header.data(),
11282c593315Sopenharmony_ci          .iov_len = static_cast<size_t>(p - header.data()),
11292c593315Sopenharmony_ci      },
11302c593315Sopenharmony_ci      {
11312c593315Sopenharmony_ci          .iov_base = const_cast<uint8_t *>(data),
11322c593315Sopenharmony_ci          .iov_len = datalen,
11332c593315Sopenharmony_ci      },
11342c593315Sopenharmony_ci  };
11352c593315Sopenharmony_ci
11362c593315Sopenharmony_ci  msghdr msg{};
11372c593315Sopenharmony_ci  msg.msg_iov = msg_iov;
11382c593315Sopenharmony_ci  msg.msg_iovlen = array_size(msg_iov);
11392c593315Sopenharmony_ci
11402c593315Sopenharmony_ci  ssize_t nwrite;
11412c593315Sopenharmony_ci
11422c593315Sopenharmony_ci  while ((nwrite = sendmsg(quic_lwp->quic_ipc_fd, &msg, 0)) == -1 &&
11432c593315Sopenharmony_ci         errno == EINTR)
11442c593315Sopenharmony_ci    ;
11452c593315Sopenharmony_ci
11462c593315Sopenharmony_ci  if (nwrite == -1) {
11472c593315Sopenharmony_ci    std::array<char, STRERROR_BUFSIZE> errbuf;
11482c593315Sopenharmony_ci
11492c593315Sopenharmony_ci    auto error = errno;
11502c593315Sopenharmony_ci    LOG(ERROR) << "Failed to send QUIC IPC message: "
11512c593315Sopenharmony_ci               << xsi_strerror(error, errbuf.data(), errbuf.size());
11522c593315Sopenharmony_ci
11532c593315Sopenharmony_ci    return -1;
11542c593315Sopenharmony_ci  }
11552c593315Sopenharmony_ci
11562c593315Sopenharmony_ci  return 0;
11572c593315Sopenharmony_ci}
11582c593315Sopenharmony_ci
11592c593315Sopenharmony_ciint ConnectionHandler::quic_ipc_read() {
11602c593315Sopenharmony_ci  std::array<uint8_t, 65536> buf;
11612c593315Sopenharmony_ci
11622c593315Sopenharmony_ci  ssize_t nread;
11632c593315Sopenharmony_ci
11642c593315Sopenharmony_ci  while ((nread = recv(quic_ipc_fd_, buf.data(), buf.size(), 0)) == -1 &&
11652c593315Sopenharmony_ci         errno == EINTR)
11662c593315Sopenharmony_ci    ;
11672c593315Sopenharmony_ci
11682c593315Sopenharmony_ci  if (nread == -1) {
11692c593315Sopenharmony_ci    std::array<char, STRERROR_BUFSIZE> errbuf;
11702c593315Sopenharmony_ci
11712c593315Sopenharmony_ci    auto error = errno;
11722c593315Sopenharmony_ci    LOG(ERROR) << "Failed to read data from QUIC IPC channel: "
11732c593315Sopenharmony_ci               << xsi_strerror(error, errbuf.data(), errbuf.size());
11742c593315Sopenharmony_ci
11752c593315Sopenharmony_ci    return -1;
11762c593315Sopenharmony_ci  }
11772c593315Sopenharmony_ci
11782c593315Sopenharmony_ci  if (nread == 0) {
11792c593315Sopenharmony_ci    return 0;
11802c593315Sopenharmony_ci  }
11812c593315Sopenharmony_ci
11822c593315Sopenharmony_ci  size_t len = 1 + 1 + 1 + 1;
11832c593315Sopenharmony_ci
11842c593315Sopenharmony_ci  // Wire format:
11852c593315Sopenharmony_ci  // TYPE(1) REMOTE_ADDRLEN(1) REMOTE_ADDR(N) LOCAL_ADDRLEN(1) LOCAL_ADDR(N)
11862c593315Sopenharmony_ci  // ECN(1) DGRAM_PAYLOAD(N)
11872c593315Sopenharmony_ci  //
11882c593315Sopenharmony_ci  // When encoding, REMOTE_ADDRLEN and LOCAL_ADDRLEN are decremented
11892c593315Sopenharmony_ci  // by 1.
11902c593315Sopenharmony_ci  if (static_cast<size_t>(nread) < len) {
11912c593315Sopenharmony_ci    return 0;
11922c593315Sopenharmony_ci  }
11932c593315Sopenharmony_ci
11942c593315Sopenharmony_ci  auto p = buf.data();
11952c593315Sopenharmony_ci  if (*p != static_cast<uint8_t>(QUICIPCType::DGRAM_FORWARD)) {
11962c593315Sopenharmony_ci    LOG(ERROR) << "Unknown QUICIPCType: " << static_cast<uint32_t>(*p);
11972c593315Sopenharmony_ci
11982c593315Sopenharmony_ci    return -1;
11992c593315Sopenharmony_ci  }
12002c593315Sopenharmony_ci
12012c593315Sopenharmony_ci  ++p;
12022c593315Sopenharmony_ci
12032c593315Sopenharmony_ci  auto pkt = std::make_unique<QUICPacket>();
12042c593315Sopenharmony_ci
12052c593315Sopenharmony_ci  auto remote_addrlen = static_cast<size_t>(*p++) + 1;
12062c593315Sopenharmony_ci  if (remote_addrlen > sizeof(sockaddr_storage)) {
12072c593315Sopenharmony_ci    LOG(ERROR) << "The length of remote address is too large: "
12082c593315Sopenharmony_ci               << remote_addrlen;
12092c593315Sopenharmony_ci
12102c593315Sopenharmony_ci    return -1;
12112c593315Sopenharmony_ci  }
12122c593315Sopenharmony_ci
12132c593315Sopenharmony_ci  len += remote_addrlen;
12142c593315Sopenharmony_ci
12152c593315Sopenharmony_ci  if (static_cast<size_t>(nread) < len) {
12162c593315Sopenharmony_ci    LOG(ERROR) << "Insufficient QUIC IPC message length";
12172c593315Sopenharmony_ci
12182c593315Sopenharmony_ci    return -1;
12192c593315Sopenharmony_ci  }
12202c593315Sopenharmony_ci
12212c593315Sopenharmony_ci  pkt->remote_addr.len = remote_addrlen;
12222c593315Sopenharmony_ci  memcpy(&pkt->remote_addr.su, p, remote_addrlen);
12232c593315Sopenharmony_ci
12242c593315Sopenharmony_ci  p += remote_addrlen;
12252c593315Sopenharmony_ci
12262c593315Sopenharmony_ci  auto local_addrlen = static_cast<size_t>(*p++) + 1;
12272c593315Sopenharmony_ci  if (local_addrlen > sizeof(sockaddr_storage)) {
12282c593315Sopenharmony_ci    LOG(ERROR) << "The length of local address is too large: " << local_addrlen;
12292c593315Sopenharmony_ci
12302c593315Sopenharmony_ci    return -1;
12312c593315Sopenharmony_ci  }
12322c593315Sopenharmony_ci
12332c593315Sopenharmony_ci  len += local_addrlen;
12342c593315Sopenharmony_ci
12352c593315Sopenharmony_ci  if (static_cast<size_t>(nread) < len) {
12362c593315Sopenharmony_ci    LOG(ERROR) << "Insufficient QUIC IPC message length";
12372c593315Sopenharmony_ci
12382c593315Sopenharmony_ci    return -1;
12392c593315Sopenharmony_ci  }
12402c593315Sopenharmony_ci
12412c593315Sopenharmony_ci  pkt->local_addr.len = local_addrlen;
12422c593315Sopenharmony_ci  memcpy(&pkt->local_addr.su, p, local_addrlen);
12432c593315Sopenharmony_ci
12442c593315Sopenharmony_ci  p += local_addrlen;
12452c593315Sopenharmony_ci
12462c593315Sopenharmony_ci  pkt->pi.ecn = *p++;
12472c593315Sopenharmony_ci
12482c593315Sopenharmony_ci  auto datalen = nread - (p - buf.data());
12492c593315Sopenharmony_ci
12502c593315Sopenharmony_ci  pkt->data.assign(p, p + datalen);
12512c593315Sopenharmony_ci
12522c593315Sopenharmony_ci  // At the moment, UpstreamAddr index is unknown.
12532c593315Sopenharmony_ci  pkt->upstream_addr_index = static_cast<size_t>(-1);
12542c593315Sopenharmony_ci
12552c593315Sopenharmony_ci  ngtcp2_version_cid vc;
12562c593315Sopenharmony_ci
12572c593315Sopenharmony_ci  auto rv = ngtcp2_pkt_decode_version_cid(&vc, p, datalen, SHRPX_QUIC_SCIDLEN);
12582c593315Sopenharmony_ci  if (rv < 0) {
12592c593315Sopenharmony_ci    LOG(ERROR) << "ngtcp2_pkt_decode_version_cid: " << ngtcp2_strerror(rv);
12602c593315Sopenharmony_ci
12612c593315Sopenharmony_ci    return -1;
12622c593315Sopenharmony_ci  }
12632c593315Sopenharmony_ci
12642c593315Sopenharmony_ci  if (vc.dcidlen != SHRPX_QUIC_SCIDLEN) {
12652c593315Sopenharmony_ci    LOG(ERROR) << "DCID length is invalid";
12662c593315Sopenharmony_ci    return -1;
12672c593315Sopenharmony_ci  }
12682c593315Sopenharmony_ci
12692c593315Sopenharmony_ci  if (single_worker_) {
12702c593315Sopenharmony_ci    auto faddr = single_worker_->find_quic_upstream_addr(pkt->local_addr);
12712c593315Sopenharmony_ci    if (faddr == nullptr) {
12722c593315Sopenharmony_ci      LOG(ERROR) << "No suitable upstream address found";
12732c593315Sopenharmony_ci
12742c593315Sopenharmony_ci      return 0;
12752c593315Sopenharmony_ci    }
12762c593315Sopenharmony_ci
12772c593315Sopenharmony_ci    auto quic_conn_handler = single_worker_->get_quic_connection_handler();
12782c593315Sopenharmony_ci
12792c593315Sopenharmony_ci    // Ignore return value
12802c593315Sopenharmony_ci    quic_conn_handler->handle_packet(faddr, pkt->remote_addr, pkt->local_addr,
12812c593315Sopenharmony_ci                                     pkt->pi, pkt->data.data(),
12822c593315Sopenharmony_ci                                     pkt->data.size());
12832c593315Sopenharmony_ci
12842c593315Sopenharmony_ci    return 0;
12852c593315Sopenharmony_ci  }
12862c593315Sopenharmony_ci
12872c593315Sopenharmony_ci  auto &qkm = quic_keying_materials_->keying_materials.front();
12882c593315Sopenharmony_ci
12892c593315Sopenharmony_ci  std::array<uint8_t, SHRPX_QUIC_DECRYPTED_DCIDLEN> decrypted_dcid;
12902c593315Sopenharmony_ci
12912c593315Sopenharmony_ci  if (decrypt_quic_connection_id(decrypted_dcid.data(),
12922c593315Sopenharmony_ci                                 vc.dcid + SHRPX_QUIC_CID_PREFIX_OFFSET,
12932c593315Sopenharmony_ci                                 qkm.cid_encryption_key.data()) != 0) {
12942c593315Sopenharmony_ci    return -1;
12952c593315Sopenharmony_ci  }
12962c593315Sopenharmony_ci
12972c593315Sopenharmony_ci  for (auto &worker : workers_) {
12982c593315Sopenharmony_ci    if (!std::equal(std::begin(decrypted_dcid),
12992c593315Sopenharmony_ci                    std::begin(decrypted_dcid) + SHRPX_QUIC_CID_PREFIXLEN,
13002c593315Sopenharmony_ci                    worker->get_cid_prefix())) {
13012c593315Sopenharmony_ci      continue;
13022c593315Sopenharmony_ci    }
13032c593315Sopenharmony_ci
13042c593315Sopenharmony_ci    WorkerEvent wev{
13052c593315Sopenharmony_ci        .type = WorkerEventType::QUIC_PKT_FORWARD,
13062c593315Sopenharmony_ci        .quic_pkt = std::move(pkt),
13072c593315Sopenharmony_ci    };
13082c593315Sopenharmony_ci    worker->send(std::move(wev));
13092c593315Sopenharmony_ci
13102c593315Sopenharmony_ci    return 0;
13112c593315Sopenharmony_ci  }
13122c593315Sopenharmony_ci
13132c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
13142c593315Sopenharmony_ci    LOG(INFO) << "No worker to match CID prefix";
13152c593315Sopenharmony_ci  }
13162c593315Sopenharmony_ci
13172c593315Sopenharmony_ci  return 0;
13182c593315Sopenharmony_ci}
13192c593315Sopenharmony_ci#endif // ENABLE_HTTP3
13202c593315Sopenharmony_ci
13212c593315Sopenharmony_ci} // namespace shrpx
1322