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