From 0402481be40876532ea63b164db60229d9154ac8 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Tue, 19 Jan 2016 16:56:12 +0900 Subject: [PATCH] nghttpx: Organize connection related configuration into struct --- src/shrpx.cc | 277 +++++++++++++---------- src/shrpx_client_handler.cc | 32 +-- src/shrpx_config.cc | 95 ++++---- src/shrpx_config.h | 110 +++++---- src/shrpx_connection.cc | 14 +- src/shrpx_connection.h | 8 +- src/shrpx_connection_handler.cc | 6 +- src/shrpx_downstream.cc | 43 ++-- src/shrpx_http.cc | 2 +- src/shrpx_http2_downstream_connection.cc | 2 +- src/shrpx_http2_session.cc | 14 +- src/shrpx_http2_upstream.cc | 8 +- src/shrpx_http_downstream_connection.cc | 21 +- src/shrpx_memcached_connection.cc | 2 +- src/shrpx_spdy_upstream.cc | 8 +- src/shrpx_ssl.cc | 11 +- src/shrpx_worker.cc | 22 +- src/shrpx_worker_process.cc | 6 +- 18 files changed, 389 insertions(+), 292 deletions(-) diff --git a/src/shrpx.cc b/src/shrpx.cc index b8c391a2..f1abba0d 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -299,13 +299,15 @@ void exec_binary(SignalServer *ssv) { std::string fd, fd6, path, port; - if (get_config()->host_unix) { + auto &listenerconf = get_config()->conn.listener; + + if (listenerconf.host_unix) { fd = ENV_UNIX_FD "="; fd += util::utos(ssv->server_fd); envp[envidx++] = &fd[0]; path = ENV_UNIX_PATH "="; - path += get_config()->host.get(); + path += listenerconf.host.get(); envp[envidx++] = &path[0]; } else { if (ssv->server_fd) { @@ -321,7 +323,7 @@ void exec_binary(SignalServer *ssv) { } port = ENV_PORT "="; - port += util::utos(get_config()->port); + port += util::utos(listenerconf.port); envp[envidx++] = &port[0]; } @@ -430,7 +432,9 @@ void worker_process_child_cb(struct ev_loop *loop, ev_child *w, int revents) { namespace { int create_unix_domain_server_socket() { - auto path = get_config()->host.get(); + auto &listenerconf = get_config()->conn.listener; + + auto path = listenerconf.host.get(); auto pathlen = strlen(path); { auto envfd = getenv(ENV_UNIX_FD); @@ -490,7 +494,7 @@ int create_unix_domain_server_socket() { return -1; } - if (listen(fd, get_config()->backlog) != 0) { + if (listen(fd, listenerconf.backlog) != 0) { auto error = errno; LOG(FATAL) << "Failed to listen to UNIX domain socket, error=" << error; close(fd); @@ -505,6 +509,8 @@ int create_unix_domain_server_socket() { namespace { int create_tcp_server_socket(int family) { + auto &listenerconf = get_config()->conn.listener; + { auto envfd = getenv(family == AF_INET ? ENV_LISTENER4_FD : ENV_LISTENER6_FD); @@ -517,14 +523,14 @@ int create_tcp_server_socket(int family) { // Only do this iff NGHTTPX_PORT == get_config()->port. // Otherwise, close fd, and create server socket as usual. - if (port == get_config()->port) { - LOG(NOTICE) << "Listening on port " << get_config()->port; + if (port == listenerconf.port) { + LOG(NOTICE) << "Listening on port " << listenerconf.port; return fd; } LOG(WARN) << "Port was changed between old binary (" << port - << ") and new binary (" << get_config()->port << ")"; + << ") and new binary (" << listenerconf.port << ")"; close(fd); } } @@ -532,7 +538,7 @@ int create_tcp_server_socket(int family) { int fd = -1; int rv; - auto service = util::utos(get_config()->port); + auto service = util::utos(listenerconf.port); addrinfo hints{}; hints.ai_family = family; hints.ai_socktype = SOCK_STREAM; @@ -541,16 +547,16 @@ int create_tcp_server_socket(int family) { hints.ai_flags |= AI_ADDRCONFIG; #endif // AI_ADDRCONFIG - auto node = strcmp("*", get_config()->host.get()) == 0 + auto node = strcmp("*", listenerconf.host.get()) == 0 ? nullptr - : get_config()->host.get(); + : listenerconf.host.get(); addrinfo *res, *rp; rv = getaddrinfo(node, service.c_str(), &hints, &res); if (rv != 0) { if (LOG_ENABLED(INFO)) { LOG(INFO) << "Unable to get IPv" << (family == AF_INET ? "4" : "6") - << " address for " << get_config()->host.get() << ": " + << " address for " << listenerconf.host.get() << ": " << gai_strerror(rv); } return -1; @@ -619,15 +625,15 @@ int create_tcp_server_socket(int family) { continue; } - if (get_config()->fastopen > 0) { - val = get_config()->fastopen; + if (listenerconf.fastopen > 0) { + val = listenerconf.fastopen; if (setsockopt(fd, SOL_TCP, TCP_FASTOPEN, &val, static_cast(sizeof(val))) == -1) { LOG(WARN) << "Failed to set TCP_FASTOPEN option to listener socket"; } } - if (listen(fd, get_config()->backlog) == -1) { + if (listen(fd, listenerconf.backlog) == -1) { auto error = errno; LOG(WARN) << "listen() syscall failed, error=" << error; close(fd); @@ -656,7 +662,7 @@ int create_tcp_server_socket(int family) { return -1; } - LOG(NOTICE) << "Listening on " << host << ", port " << get_config()->port; + LOG(NOTICE) << "Listening on " << host << ", port " << listenerconf.port; return fd; } @@ -794,12 +800,14 @@ int event_loop() { util::make_socket_closeonexec(fd); } - if (get_config()->host_unix) { + auto &listenerconf = get_config()->conn.listener; + + if (listenerconf.host_unix) { close_env_fd({ENV_LISTENER4_FD, ENV_LISTENER6_FD}); auto fd = create_unix_domain_server_socket(); if (fd == -1) { LOG(FATAL) << "Failed to listen on UNIX domain socket " - << get_config()->host.get(); + << listenerconf.host.get(); return -1; } @@ -808,10 +816,10 @@ int event_loop() { if (get_config()->uid != 0) { // fd is not associated to inode, so we cannot use fchown(2) // here. https://lkml.org/lkml/2004/11/1/84 - if (chown_to_running_user(get_config()->host.get()) == -1) { + if (chown_to_running_user(listenerconf.host.get()) == -1) { auto error = errno; LOG(WARN) << "Changing owner of UNIX domain socket " - << get_config()->host.get() << " failed: " << strerror(error); + << listenerconf.host.get() << " failed: " << strerror(error); } } } else { @@ -819,8 +827,8 @@ int event_loop() { auto fd6 = create_tcp_server_socket(AF_INET6); auto fd4 = create_tcp_server_socket(AF_INET); if (fd6 == -1 && fd4 == -1) { - LOG(FATAL) << "Failed to listen on address " << get_config()->host.get() - << ", port " << get_config()->port; + LOG(FATAL) << "Failed to listen on address " << listenerconf.host.get() + << ", port " << listenerconf.port; return -1; } @@ -900,38 +908,8 @@ void fill_default_config() { mod_config()->verbose = false; mod_config()->daemon = false; - mod_config()->host = strcopy("*"); - mod_config()->port = 3000; - - // Read timeout for HTTP2 upstream connection - mod_config()->http2_upstream_read_timeout = 3_min; - - // Read timeout for non-HTTP2 upstream connection - mod_config()->upstream_read_timeout = 1_min; - - // Write timeout for HTTP2/non-HTTP2 upstream connection - mod_config()->upstream_write_timeout = 30.; - - // Read/Write timeouts for downstream connection - mod_config()->downstream_read_timeout = 1_min; - mod_config()->downstream_write_timeout = 30.; - - // Read timeout for HTTP/2 stream - mod_config()->stream_read_timeout = 0.; - - // Write timeout for HTTP/2 stream - mod_config()->stream_write_timeout = 0.; - - // Timeout for pooled (idle) connections - mod_config()->downstream_idle_read_timeout = 2.; - - mod_config()->upstream_no_tls = false; - mod_config()->downstream_no_tls = false; - mod_config()->num_worker = 1; mod_config()->conf_path = strcopy("/etc/nghttpx/nghttpx.conf"); - // Default accept() backlog - mod_config()->backlog = 512; mod_config()->http2_proxy = false; mod_config()->http2_bridge = false; mod_config()->client_proxy = false; @@ -942,29 +920,10 @@ void fill_default_config() { mod_config()->uid = 0; mod_config()->gid = 0; mod_config()->pid = getpid(); - mod_config()->backend_ipv4 = false; - mod_config()->backend_ipv6 = false; - mod_config()->read_rate = 0; - mod_config()->read_burst = 0; - mod_config()->write_rate = 0; - mod_config()->write_burst = 0; - mod_config()->worker_read_rate = 0; - mod_config()->worker_read_burst = 0; - mod_config()->worker_write_rate = 0; - mod_config()->worker_write_burst = 0; mod_config()->padding = 0; - mod_config()->worker_frontend_connections = 0; mod_config()->argc = 0; mod_config()->argv = nullptr; - mod_config()->downstream_connections_per_host = 8; - mod_config()->downstream_connections_per_frontend = 0; - mod_config()->listener_disable_timeout = 0.; - mod_config()->downstream_request_buffer_size = 16_k; - mod_config()->downstream_response_buffer_size = 16_k; - mod_config()->host_unix = false; - mod_config()->downstream_addr_group_catch_all = 0; - mod_config()->fastopen = 0; auto &tlsconf = mod_config()->tls; { @@ -1014,6 +973,15 @@ void fill_default_config() { auto &http2conf = mod_config()->http2; { + auto &timeoutconf = http2conf.timeout; + { + // Read timeout for HTTP/2 stream + timeoutconf.stream_read = 0.; + + // Write timeout for HTTP/2 stream + timeoutconf.stream_write = 0.; + } + auto &upstreamconf = http2conf.upstream; // window bits for HTTP/2 and SPDY upstream connection per // stream. 2**16-1 = 64KiB-1, which is HTTP/2 default. Please note @@ -1054,6 +1022,54 @@ void fill_default_config() { } loggingconf.syslog_facility = LOG_DAEMON; + + auto &connconf = mod_config()->conn; + { + auto &listenerconf = connconf.listener; + { + listenerconf.host = strcopy("*"); + listenerconf.port = 3000; + // Default accept() backlog + listenerconf.backlog = 512; + listenerconf.host_unix = false; + } + } + + { + auto &upstreamconf = connconf.upstream; + { + auto &timeoutconf = upstreamconf.timeout; + // Read timeout for HTTP2 upstream connection + timeoutconf.http2_read = 3_min; + + // Read timeout for non-HTTP2 upstream connection + timeoutconf.read = 1_min; + + // Write timeout for HTTP2/non-HTTP2 upstream connection + timeoutconf.write = 30.; + } + + upstreamconf.no_tls = false; + } + + { + auto &downstreamconf = connconf.downstream; + { + auto &timeoutconf = downstreamconf.timeout; + // Read/Write timeouts for downstream connection + timeoutconf.read = 1_min; + timeoutconf.write = 30.; + // Timeout for pooled (idle) connections + timeoutconf.idle_read = 2.; + } + + downstreamconf.no_tls = false; + downstreamconf.ipv4 = false; + downstreamconf.ipv6 = false; + downstreamconf.connections_per_host = 8; + downstreamconf.request_buffer_size = 16_k; + downstreamconf.response_buffer_size = 16_k; + } } } // namespace @@ -1151,11 +1167,11 @@ Connections: assumes all addresses including both IPv4 and IPv6. UNIX domain socket can be specified by prefixing path name with "unix:" (e.g., unix:/var/run/nghttpx.sock) - Default: )" << get_config()->host.get() << "," - << get_config()->port << R"( + Default: )" << get_config()->conn.listener.host.get() << "," + << get_config()->conn.listener.port << R"( --backlog= Set listen backlog size. - Default: )" << get_config()->backlog << R"( + Default: )" << get_config()->conn.listener.backlog << R"( --backend-ipv4 Resolve backend hostname to IPv4 address only. --backend-ipv6 @@ -1183,45 +1199,50 @@ Performance: --read-rate= Set maximum average read rate on frontend connection. Setting 0 to this option means read rate is unlimited. - Default: )" << get_config()->read_rate << R"( + Default: )" << get_config()->conn.upstream.ratelimit.read.rate + << R"( --read-burst= Set maximum read burst size on frontend connection. Setting 0 to this option means read burst size is unlimited. - Default: )" << get_config()->read_burst << R"( + Default: )" << get_config()->conn.upstream.ratelimit.read.burst + << R"( --write-rate= Set maximum average write rate on frontend connection. Setting 0 to this option means write rate is unlimited. - Default: )" << get_config()->write_rate << R"( + Default: )" << get_config()->conn.upstream.ratelimit.write.rate + << R"( --write-burst= Set maximum write burst size on frontend connection. Setting 0 to this option means write burst size is unlimited. - Default: )" << get_config()->write_burst << R"( + Default: )" << get_config()->conn.upstream.ratelimit.write.burst + << R"( --worker-read-rate= Set maximum average read rate on frontend connection per worker. Setting 0 to this option means read rate is unlimited. Not implemented yet. - Default: )" << get_config()->worker_read_rate << R"( + Default: 0 --worker-read-burst= Set maximum read burst size on frontend connection per worker. Setting 0 to this option means read burst size is unlimited. Not implemented yet. - Default: )" << get_config()->worker_read_burst << R"( + Default: 0 --worker-write-rate= Set maximum average write rate on frontend connection per worker. Setting 0 to this option means write rate is unlimited. Not implemented yet. - Default: )" << get_config()->worker_write_rate << R"( + Default: 0 --worker-write-burst= Set maximum write burst size on frontend connection per worker. Setting 0 to this option means write burst size is unlimited. Not implemented yet. - Default: )" << get_config()->worker_write_burst << R"( + Default: 0 --worker-frontend-connections= Set maximum number of simultaneous connections frontend accepts. Setting 0 means unlimited. - Default: )" << get_config()->worker_frontend_connections << R"( + Default: )" << get_config()->conn.upstream.worker_connections + << R"( --backend-http2-connections-per-worker= Set maximum number of backend HTTP/2 physical connections per worker. If pattern is used in -b @@ -1239,7 +1260,7 @@ Performance: header field for HTTP/2). To limit the number of connections per frontend for default mode, use --backend-http1-connections-per-frontend. - Default: )" << get_config()->downstream_connections_per_host + Default: )" << get_config()->conn.downstream.connections_per_host << R"( --backend-http1-connections-per-frontend= Set maximum number of backend concurrent HTTP/1 @@ -1247,8 +1268,8 @@ Performance: default mode. 0 means unlimited. To limit the number of connections per host for HTTP/2 or SPDY proxy mode (-s option), use --backend-http1-connections-per-host. - Default: )" << get_config()->downstream_connections_per_frontend - << R"( + Default: )" + << get_config()->conn.downstream.connections_per_frontend << R"( --rlimit-nofile= Set maximum number of open files (RLIMIT_NOFILE) to . If 0 is given, nghttpx does not set the limit. @@ -1256,59 +1277,63 @@ Performance: --backend-request-buffer= Set buffer size used to store backend request. Default: )" - << util::utos_unit(get_config()->downstream_request_buffer_size) << R"( + << util::utos_unit(get_config()->conn.downstream.request_buffer_size) + << R"( --backend-response-buffer= Set buffer size used to store backend response. Default: )" - << util::utos_unit(get_config()->downstream_response_buffer_size) << R"( + << util::utos_unit(get_config()->conn.downstream.response_buffer_size) + << R"( --fastopen= Enables "TCP Fast Open" for the listening socket and limits the maximum length for the queue of connections that have not yet completed the three-way handshake. If value is 0 then fast open is disabled. - Default: )" << get_config()->fastopen << R"( + Default: )" << get_config()->conn.listener.fastopen << R"( Timeout: --frontend-http2-read-timeout= Specify read timeout for HTTP/2 and SPDY frontend connection. Default: )" - << util::duration_str(get_config()->http2_upstream_read_timeout) << R"( + << util::duration_str(get_config()->conn.upstream.timeout.http2_read) + << R"( --frontend-read-timeout= Specify read timeout for HTTP/1.1 frontend connection. Default: )" - << util::duration_str(get_config()->upstream_read_timeout) << R"( + << util::duration_str(get_config()->conn.upstream.timeout.read) << R"( --frontend-write-timeout= Specify write timeout for all frontend connections. Default: )" - << util::duration_str(get_config()->upstream_write_timeout) << R"( + << util::duration_str(get_config()->conn.upstream.timeout.write) << R"( --stream-read-timeout= Specify read timeout for HTTP/2 and SPDY streams. 0 means no timeout. Default: )" - << util::duration_str(get_config()->stream_read_timeout) << R"( + << util::duration_str(get_config()->http2.timeout.stream_read) << R"( --stream-write-timeout= Specify write timeout for HTTP/2 and SPDY streams. 0 means no timeout. Default: )" - << util::duration_str(get_config()->stream_write_timeout) << R"( + << util::duration_str(get_config()->http2.timeout.stream_write) << R"( --backend-read-timeout= Specify read timeout for backend connection. Default: )" - << util::duration_str(get_config()->downstream_read_timeout) << R"( + << util::duration_str(get_config()->conn.downstream.timeout.read) << R"( --backend-write-timeout= Specify write timeout for backend connection. Default: )" - << util::duration_str(get_config()->downstream_write_timeout) << R"( + << util::duration_str(get_config()->conn.downstream.timeout.write) << R"( --backend-keep-alive-timeout= Specify keep-alive timeout for backend connection. Default: )" - << util::duration_str(get_config()->downstream_idle_read_timeout) << R"( + << util::duration_str(get_config()->conn.downstream.timeout.idle_read) + << R"( --listener-disable-timeout= After accepting connection failed, connection listener is disabled for a given amount of time. Specifying 0 disables this feature. Default: )" - << util::duration_str(get_config()->listener_disable_timeout) << R"( + << util::duration_str(get_config()->conn.listener.timeout.sleep) << R"( SSL/TLS: --ciphers= @@ -1858,15 +1883,18 @@ void process_options( tlsconf.alpn_prefs = ssl::set_alpn_prefs(tlsconf.npn_list); - if (get_config()->backend_ipv4 && get_config()->backend_ipv6) { + auto &listenerconf = mod_config()->conn.listener; + auto &upstreamconf = mod_config()->conn.upstream; + auto &downstreamconf = mod_config()->conn.downstream; + + if (downstreamconf.ipv4 && downstreamconf.ipv6) { LOG(FATAL) << "--backend-ipv4 and --backend-ipv6 cannot be used at the " << "same time."; exit(EXIT_FAILURE); } - if (get_config()->worker_frontend_connections == 0) { - mod_config()->worker_frontend_connections = - std::numeric_limits::max(); + if (upstreamconf.worker_connections == 0) { + upstreamconf.worker_connections = std::numeric_limits::max(); } if (get_config()->http2_proxy + get_config()->http2_bridge + @@ -1879,23 +1907,23 @@ void process_options( if (get_config()->client || get_config()->client_proxy) { mod_config()->client_mode = true; - mod_config()->upstream_no_tls = true; + upstreamconf.no_tls = true; } if (get_config()->client_mode || get_config()->http2_bridge) { - mod_config()->downstream_proto = PROTO_HTTP2; + downstreamconf.proto = PROTO_HTTP2; } else { - mod_config()->downstream_proto = PROTO_HTTP; + downstreamconf.proto = PROTO_HTTP; } - if (!get_config()->upstream_no_tls && + if (!upstreamconf.no_tls && (!tlsconf.private_key_file || !tlsconf.cert_file)) { print_usage(std::cerr); LOG(FATAL) << "Too few arguments"; exit(EXIT_FAILURE); } - if (!get_config()->upstream_no_tls && !tlsconf.ocsp.disabled) { + if (!upstreamconf.no_tls && !tlsconf.ocsp.disabled) { struct stat buf; if (stat(tlsconf.ocsp.fetch_ocsp_response_file.get(), &buf) != 0) { tlsconf.ocsp.disabled = true; @@ -1905,31 +1933,31 @@ void process_options( } } - if (get_config()->downstream_addr_groups.empty()) { + auto &addr_groups = downstreamconf.addr_groups; + + if (addr_groups.empty()) { DownstreamAddr addr; addr.host = ImmutableString::from_lit(DEFAULT_DOWNSTREAM_HOST); addr.port = DEFAULT_DOWNSTREAM_PORT; DownstreamAddrGroup g("/"); g.addrs.push_back(std::move(addr)); - mod_config()->router.add_route(g.pattern.get(), 1, - get_config()->downstream_addr_groups.size()); - mod_config()->downstream_addr_groups.push_back(std::move(g)); + mod_config()->router.add_route(g.pattern.get(), 1, addr_groups.size()); + addr_groups.push_back(std::move(g)); } else if (get_config()->http2_proxy || get_config()->client_proxy) { // We don't support host mapping in these cases. Move all // non-catch-all patterns to catch-all pattern. DownstreamAddrGroup catch_all("/"); - for (auto &g : mod_config()->downstream_addr_groups) { + for (auto &g : addr_groups) { std::move(std::begin(g.addrs), std::end(g.addrs), std::back_inserter(catch_all.addrs)); } - std::vector().swap( - mod_config()->downstream_addr_groups); + std::vector().swap(addr_groups); // maybe not necessary? mod_config()->router = Router(); mod_config()->router.add_route(catch_all.pattern.get(), 1, - get_config()->downstream_addr_groups.size()); - mod_config()->downstream_addr_groups.push_back(std::move(catch_all)); + addr_groups.size()); + addr_groups.push_back(std::move(catch_all)); } if (LOG_ENABLED(INFO)) { @@ -1937,8 +1965,8 @@ void process_options( } ssize_t catch_all_group = -1; - for (size_t i = 0; i < mod_config()->downstream_addr_groups.size(); ++i) { - auto &g = mod_config()->downstream_addr_groups[i]; + for (size_t i = 0; i < addr_groups.size(); ++i) { + auto &g = addr_groups[i]; if (util::streq(g.pattern.get(), "/")) { catch_all_group = i; } @@ -1956,13 +1984,14 @@ void process_options( LOG(FATAL) << "-b: No catch-all backend address is configured"; exit(EXIT_FAILURE); } - mod_config()->downstream_addr_group_catch_all = catch_all_group; + + downstreamconf.addr_group_catch_all = catch_all_group; if (LOG_ENABLED(INFO)) { LOG(INFO) << "Catch-all pattern is group " << catch_all_group; } - for (auto &g : mod_config()->downstream_addr_groups) { + for (auto &g : addr_groups) { for (auto &addr : g.addrs) { if (addr.host_unix) { @@ -1970,7 +1999,7 @@ void process_options( // hostport. This is used as Host header field to backend and // not going to be passed to any syscalls. addr.hostport = ImmutableString( - util::make_hostport("localhost", get_config()->port)); + util::make_hostport("localhost", listenerconf.port)); auto path = addr.host.c_str(); auto pathlen = addr.host.size(); @@ -1997,9 +2026,9 @@ void process_options( if (resolve_hostname( &addr.addr, addr.host.c_str(), addr.port, - get_config()->backend_ipv4 ? AF_INET : (get_config()->backend_ipv6 - ? AF_INET6 - : AF_UNSPEC)) == -1) { + downstreamconf.ipv4 + ? AF_INET + : (downstreamconf.ipv6 ? AF_INET6 : AF_UNSPEC)) == -1) { exit(EXIT_FAILURE); } } diff --git a/src/shrpx_client_handler.cc b/src/shrpx_client_handler.cc index 1a8822de..1bcd9bd1 100644 --- a/src/shrpx_client_handler.cc +++ b/src/shrpx_client_handler.cc @@ -371,16 +371,16 @@ int ClientHandler::upstream_http1_connhd_read() { ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl, const char *ipaddr, const char *port) : conn_(worker->get_loop(), fd, ssl, worker->get_mcpool(), - get_config()->upstream_write_timeout, - get_config()->upstream_read_timeout, get_config()->write_rate, - get_config()->write_burst, get_config()->read_rate, - get_config()->read_burst, writecb, readcb, timeoutcb, this, - get_config()->tls.dyn_rec.warmup_threshold, + get_config()->conn.upstream.timeout.write, + get_config()->conn.upstream.timeout.read, + get_config()->conn.upstream.ratelimit.write, + get_config()->conn.upstream.ratelimit.read, writecb, readcb, + timeoutcb, this, get_config()->tls.dyn_rec.warmup_threshold, get_config()->tls.dyn_rec.idle_timeout), pinned_http2sessions_( - get_config()->downstream_proto == PROTO_HTTP2 + get_config()->conn.downstream.proto == PROTO_HTTP2 ? make_unique>( - get_config()->downstream_addr_groups.size(), -1) + get_config()->conn.downstream.addr_groups.size(), -1) : nullptr), ipaddr_(ipaddr), port_(port), worker_(worker), left_connhd_len_(NGHTTP2_CLIENT_MAGIC_LEN), @@ -395,7 +395,7 @@ ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl, conn_.rlimit.startw(); ev_timer_again(conn_.loop, &conn_.rt); - if (get_config()->accept_proxy_protocol) { + if (get_config()->conn.upstream.accept_proxy_protocol) { read_ = &ClientHandler::read_clear; write_ = &ClientHandler::noop; on_read_ = &ClientHandler::proxy_protocol_read; @@ -647,8 +647,9 @@ void ClientHandler::remove_downstream_connection(DownstreamConnection *dconn) { std::unique_ptr ClientHandler::get_downstream_connection(Downstream *downstream) { size_t group; - auto &groups = get_config()->downstream_addr_groups; - auto catch_all = get_config()->downstream_addr_group_catch_all; + auto &downstreamconf = get_config()->conn.downstream; + auto &groups = downstreamconf.addr_groups; + auto catch_all = downstreamconf.addr_group_catch_all; const auto &req = downstream->request(); @@ -693,7 +694,7 @@ ClientHandler::get_downstream_connection(Downstream *downstream) { auto dconn_pool = worker_->get_dconn_pool(); - if (get_config()->downstream_proto == PROTO_HTTP2) { + if (downstreamconf.proto == PROTO_HTTP2) { Http2Session *http2session; auto &pinned = (*pinned_http2sessions_)[group]; if (pinned == -1) { @@ -857,8 +858,8 @@ void ClientHandler::write_accesslog(Downstream *downstream) { std::chrono::high_resolution_clock::now(), // request_end_time req.http_major, req.http_minor, resp.http_status, - downstream->response_sent_body_length, port_, get_config()->port, - get_config()->pid, + downstream->response_sent_body_length, port_, + get_config()->conn.listener.port, get_config()->pid, }); } @@ -880,7 +881,8 @@ void ClientHandler::write_accesslog(int major, int minor, unsigned int status, // there a better value? highres_now, // request_end_time major, minor, // major, minor - status, body_bytes_sent, port_, get_config()->port, get_config()->pid, + status, body_bytes_sent, port_, get_config()->conn.listener.port, + get_config()->pid, }); } @@ -1156,7 +1158,7 @@ const std::string &ClientHandler::get_forwarded_by() { local_hostport_ += ':'; } - local_hostport_ += util::utos(get_config()->port); + local_hostport_ += util::utos(get_config()->conn.listener.port); return local_hostport_; } diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index 47e8a80c..b22461f9 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -594,6 +594,8 @@ void parse_mapping(const DownstreamAddr &addr, const char *src) { // will append '/' to all patterns, so it becomes catch-all pattern. auto mapping = util::split_config_str_list(src, ':'); assert(!mapping.empty()); + auto &addr_groups = mod_config()->conn.downstream.addr_groups; + for (const auto &raw_pattern : mapping) { auto done = false; std::string pattern; @@ -608,7 +610,7 @@ void parse_mapping(const DownstreamAddr &addr, const char *src) { util::inp_strlower(pattern); pattern += http2::normalize_path(slash, raw_pattern.second); } - for (auto &g : mod_config()->downstream_addr_groups) { + for (auto &g : addr_groups) { if (g.pattern.get() == pattern) { g.addrs.push_back(addr); done = true; @@ -622,9 +624,9 @@ void parse_mapping(const DownstreamAddr &addr, const char *src) { g.addrs.push_back(addr); mod_config()->router.add_route(g.pattern.get(), strlen(g.pattern.get()), - get_config()->downstream_addr_groups.size()); + addr_groups.size()); - mod_config()->downstream_addr_groups.push_back(std::move(g)); + addr_groups.push_back(std::move(g)); } } } // namespace @@ -1419,11 +1421,13 @@ int parse_config(const char *opt, const char *optarg, return 0; } case SHRPX_OPTID_FRONTEND: { + auto &listenerconf = mod_config()->conn.listener; + if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) { auto path = optarg + str_size(SHRPX_UNIX_PATH_PREFIX); - mod_config()->host = strcopy(path); - mod_config()->port = 0; - mod_config()->host_unix = true; + listenerconf.host = strcopy(path); + listenerconf.port = 0; + listenerconf.host_unix = true; return 0; } @@ -1433,9 +1437,9 @@ int parse_config(const char *opt, const char *optarg, return -1; } - mod_config()->host = strcopy(host); - mod_config()->port = port; - mod_config()->host_unix = false; + listenerconf.host = strcopy(host); + listenerconf.port = port; + listenerconf.host_unix = false; return 0; } @@ -1484,20 +1488,26 @@ int parse_config(const char *opt, const char *optarg, return 0; case SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT: - return parse_duration(&mod_config()->http2_upstream_read_timeout, opt, + return parse_duration(&mod_config()->conn.upstream.timeout.http2_read, opt, optarg); case SHRPX_OPTID_FRONTEND_READ_TIMEOUT: - return parse_duration(&mod_config()->upstream_read_timeout, opt, optarg); + return parse_duration(&mod_config()->conn.upstream.timeout.read, opt, + optarg); case SHRPX_OPTID_FRONTEND_WRITE_TIMEOUT: - return parse_duration(&mod_config()->upstream_write_timeout, opt, optarg); + return parse_duration(&mod_config()->conn.upstream.timeout.write, opt, + optarg); case SHRPX_OPTID_BACKEND_READ_TIMEOUT: - return parse_duration(&mod_config()->downstream_read_timeout, opt, optarg); + return parse_duration(&mod_config()->conn.downstream.timeout.read, opt, + optarg); case SHRPX_OPTID_BACKEND_WRITE_TIMEOUT: - return parse_duration(&mod_config()->downstream_write_timeout, opt, optarg); + return parse_duration(&mod_config()->conn.downstream.timeout.write, opt, + optarg); case SHRPX_OPTID_STREAM_READ_TIMEOUT: - return parse_duration(&mod_config()->stream_read_timeout, opt, optarg); + return parse_duration(&mod_config()->http2.timeout.stream_read, opt, + optarg); case SHRPX_OPTID_STREAM_WRITE_TIMEOUT: - return parse_duration(&mod_config()->stream_write_timeout, opt, optarg); + return parse_duration(&mod_config()->http2.timeout.stream_write, opt, + optarg); case SHRPX_OPTID_ACCESSLOG_FILE: mod_config()->logging.access.file = strcopy(optarg); @@ -1529,12 +1539,12 @@ int parse_config(const char *opt, const char *optarg, return -1; } - mod_config()->fastopen = n; + mod_config()->conn.listener.fastopen = n; return 0; } case SHRPX_OPTID_BACKEND_KEEP_ALIVE_TIMEOUT: - return parse_duration(&mod_config()->downstream_idle_read_timeout, opt, + return parse_duration(&mod_config()->conn.downstream.timeout.idle_read, opt, optarg); case SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS: case SHRPX_OPTID_BACKEND_HTTP2_WINDOW_BITS: { @@ -1593,11 +1603,11 @@ int parse_config(const char *opt, const char *optarg, return 0; } case SHRPX_OPTID_FRONTEND_NO_TLS: - mod_config()->upstream_no_tls = util::strieq(optarg, "yes"); + mod_config()->conn.upstream.no_tls = util::strieq(optarg, "yes"); return 0; case SHRPX_OPTID_BACKEND_NO_TLS: - mod_config()->downstream_no_tls = util::strieq(optarg, "yes"); + mod_config()->conn.downstream.no_tls = util::strieq(optarg, "yes"); return 0; case SHRPX_OPTID_BACKEND_TLS_SNI_FIELD: @@ -1676,7 +1686,7 @@ int parse_config(const char *opt, const char *optarg, return -1; } - mod_config()->backlog = n; + mod_config()->conn.listener.backlog = n; return 0; } @@ -1697,11 +1707,11 @@ int parse_config(const char *opt, const char *optarg, return 0; case SHRPX_OPTID_BACKEND_IPV4: - mod_config()->backend_ipv4 = util::strieq(optarg, "yes"); + mod_config()->conn.downstream.ipv4 = util::strieq(optarg, "yes"); return 0; case SHRPX_OPTID_BACKEND_IPV6: - mod_config()->backend_ipv6 = util::strieq(optarg, "yes"); + mod_config()->conn.downstream.ipv6 = util::strieq(optarg, "yes"); return 0; case SHRPX_OPTID_BACKEND_HTTP_PROXY_URI: { @@ -1742,25 +1752,29 @@ int parse_config(const char *opt, const char *optarg, return 0; } case SHRPX_OPTID_READ_RATE: - return parse_uint_with_unit(&mod_config()->read_rate, opt, optarg); + return parse_uint_with_unit( + &mod_config()->conn.upstream.ratelimit.read.rate, opt, optarg); case SHRPX_OPTID_READ_BURST: - return parse_uint_with_unit(&mod_config()->read_burst, opt, optarg); + return parse_uint_with_unit( + &mod_config()->conn.upstream.ratelimit.read.burst, opt, optarg); case SHRPX_OPTID_WRITE_RATE: - return parse_uint_with_unit(&mod_config()->write_rate, opt, optarg); + return parse_uint_with_unit( + &mod_config()->conn.upstream.ratelimit.write.rate, opt, optarg); case SHRPX_OPTID_WRITE_BURST: - return parse_uint_with_unit(&mod_config()->write_burst, opt, optarg); + return parse_uint_with_unit( + &mod_config()->conn.upstream.ratelimit.write.burst, opt, optarg); case SHRPX_OPTID_WORKER_READ_RATE: LOG(WARN) << opt << ": not implemented yet"; - return parse_uint_with_unit(&mod_config()->worker_read_rate, opt, optarg); + return 0; case SHRPX_OPTID_WORKER_READ_BURST: LOG(WARN) << opt << ": not implemented yet"; - return parse_uint_with_unit(&mod_config()->worker_read_burst, opt, optarg); + return 0; case SHRPX_OPTID_WORKER_WRITE_RATE: LOG(WARN) << opt << ": not implemented yet"; - return parse_uint_with_unit(&mod_config()->worker_write_rate, opt, optarg); + return 0; case SHRPX_OPTID_WORKER_WRITE_BURST: LOG(WARN) << opt << ": not implemented yet"; - return parse_uint_with_unit(&mod_config()->worker_write_burst, opt, optarg); + return 0; case SHRPX_OPTID_NPN_LIST: mod_config()->tls.npn_list = util::parse_config_str_list(optarg); @@ -1867,7 +1881,8 @@ int parse_config(const char *opt, const char *optarg, return 0; } case SHRPX_OPTID_WORKER_FRONTEND_CONNECTIONS: - return parse_uint(&mod_config()->worker_frontend_connections, opt, optarg); + return parse_uint(&mod_config()->conn.upstream.worker_connections, opt, + optarg); case SHRPX_OPTID_NO_LOCATION_REWRITE: mod_config()->http.no_location_rewrite = util::strieq(optarg, "yes"); @@ -1892,15 +1907,16 @@ int parse_config(const char *opt, const char *optarg, return -1; } - mod_config()->downstream_connections_per_host = n; + mod_config()->conn.downstream.connections_per_host = n; return 0; } case SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND: - return parse_uint(&mod_config()->downstream_connections_per_frontend, opt, - optarg); + return parse_uint(&mod_config()->conn.downstream.connections_per_frontend, + opt, optarg); case SHRPX_OPTID_LISTENER_DISABLE_TIMEOUT: - return parse_duration(&mod_config()->listener_disable_timeout, opt, optarg); + return parse_duration(&mod_config()->conn.listener.timeout.sleep, opt, + optarg); case SHRPX_OPTID_TLS_TICKET_KEY_FILE: mod_config()->tls.ticket.files.push_back(optarg); return 0; @@ -1935,9 +1951,9 @@ int parse_config(const char *opt, const char *optarg, } if (optid == SHRPX_OPTID_BACKEND_REQUEST_BUFFER) { - mod_config()->downstream_request_buffer_size = n; + mod_config()->conn.downstream.request_buffer_size = n; } else { - mod_config()->downstream_response_buffer_size = n; + mod_config()->conn.downstream.response_buffer_size = n; } return 0; @@ -2065,7 +2081,8 @@ int parse_config(const char *opt, const char *optarg, #endif // !HAVE_MRUBY return 0; case SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL: - mod_config()->accept_proxy_protocol = util::strieq(optarg, "yes"); + mod_config()->conn.upstream.accept_proxy_protocol = + util::strieq(optarg, "yes"); return 0; case SHRPX_OPTID_ADD_FORWARDED: { diff --git a/src/shrpx_config.h b/src/shrpx_config.h index 4620227b..7963828f 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -429,6 +429,10 @@ struct Http2Config { size_t connection_window_bits; size_t connections_per_worker; } downstream; + struct { + ev_tstamp stream_read; + ev_tstamp stream_write; + } timeout; size_t max_concurrent_streams; bool no_cookie_crumbling; bool no_server_push; @@ -449,26 +453,77 @@ struct LoggingConfig { int syslog_facility; }; +struct RateLimitConfig { + size_t rate; + size_t burst; +}; + +struct ConnectionConfig { + struct { + struct { + ev_tstamp sleep; + } timeout; + // address of frontend connection. This could be a path to UNIX + // domain socket. In this case, |host_unix| must be true. + std::unique_ptr host; + // frontend listening port. 0 if frontend listens on UNIX domain + // socket, in this case |host_unix| must be true. + uint16_t port; + // true if host contains UNIX domain socket path + bool host_unix; + int backlog; + // TCP fastopen. If this is positive, it is passed to + // setsockopt() along with TCP_FASTOPEN. + int fastopen; + } listener; + + struct { + struct { + ev_tstamp http2_read; + ev_tstamp read; + ev_tstamp write; + } timeout; + struct { + RateLimitConfig read; + RateLimitConfig write; + } ratelimit; + size_t worker_connections; + bool no_tls; + bool accept_proxy_protocol; + } upstream; + + struct { + struct { + ev_tstamp read; + ev_tstamp write; + ev_tstamp idle_read; + } timeout; + std::vector addr_groups; + // The index of catch-all group in downstream_addr_groups. + size_t addr_group_catch_all; + size_t connections_per_host; + size_t connections_per_frontend; + size_t request_buffer_size; + size_t response_buffer_size; + // downstream protocol; this will be determined by given options. + shrpx_proto proto; + bool no_tls; + // true if IPv4 only; ipv4 and ipv6 are mutually exclusive; and + // (ipv4 && ipv6) must be false. + bool ipv4; + // true if IPv6 only + bool ipv6; + } downstream; +}; + struct Config { - std::vector downstream_addr_groups; Router router; HttpProxy downstream_http_proxy; HttpConfig http; Http2Config http2; TLSConfig tls; LoggingConfig logging; - ev_tstamp http2_upstream_read_timeout; - ev_tstamp upstream_read_timeout; - ev_tstamp upstream_write_timeout; - ev_tstamp downstream_read_timeout; - ev_tstamp downstream_write_timeout; - ev_tstamp stream_read_timeout; - ev_tstamp stream_write_timeout; - ev_tstamp downstream_idle_read_timeout; - ev_tstamp listener_disable_timeout; - // address of frontend connection. This could be a path to UNIX - // domain socket. In this case, |host_unix| must be true. - std::unique_ptr host; + ConnectionConfig conn; std::unique_ptr pid_file; std::unique_ptr conf_path; std::unique_ptr user; @@ -477,49 +532,20 @@ struct Config { char **argv; char *cwd; size_t num_worker; - size_t downstream_connections_per_host; - size_t downstream_connections_per_frontend; - size_t read_rate; - size_t read_burst; - size_t write_rate; - size_t write_burst; - size_t worker_read_rate; - size_t worker_read_burst; - size_t worker_write_rate; - size_t worker_write_burst; size_t padding; - size_t worker_frontend_connections; size_t rlimit_nofile; - size_t downstream_request_buffer_size; - size_t downstream_response_buffer_size; - // The index of catch-all group in downstream_addr_groups. - size_t downstream_addr_group_catch_all; - // downstream protocol; this will be determined by given options. - shrpx_proto downstream_proto; - int backlog; int argc; - int fastopen; uid_t uid; gid_t gid; pid_t pid; - // frontend listening port. 0 if frontend listens on UNIX domain - // socket, in this case |host_unix| must be true. - uint16_t port; bool verbose; bool daemon; bool http2_proxy; bool http2_bridge; bool client_proxy; - bool upstream_no_tls; - bool downstream_no_tls; bool client; // true if --client or --client-proxy are enabled. bool client_mode; - bool backend_ipv4; - bool backend_ipv6; - // true if host contains UNIX domain socket path - bool host_unix; - bool accept_proxy_protocol; }; const Config *get_config(); diff --git a/src/shrpx_connection.cc b/src/shrpx_connection.cc index 97d1e0af..5d27d110 100644 --- a/src/shrpx_connection.cc +++ b/src/shrpx_connection.cc @@ -42,15 +42,17 @@ using namespace nghttp2; namespace shrpx { Connection::Connection(struct ev_loop *loop, int fd, SSL *ssl, MemchunkPool *mcpool, ev_tstamp write_timeout, - ev_tstamp read_timeout, size_t write_rate, - size_t write_burst, size_t read_rate, size_t read_burst, - IOCb writecb, IOCb readcb, TimerCb timeoutcb, void *data, + ev_tstamp read_timeout, + const RateLimitConfig &write_limit, + const RateLimitConfig &read_limit, IOCb writecb, + IOCb readcb, TimerCb timeoutcb, void *data, size_t tls_dyn_rec_warmup_threshold, ev_tstamp tls_dyn_rec_idle_timeout) : tls{DefaultMemchunks(mcpool), DefaultPeekMemchunks(mcpool)}, - wlimit(loop, &wev, write_rate, write_burst), - rlimit(loop, &rev, read_rate, read_burst, this), writecb(writecb), - readcb(readcb), timeoutcb(timeoutcb), loop(loop), data(data), fd(fd), + wlimit(loop, &wev, write_limit.rate, write_limit.burst), + rlimit(loop, &rev, read_limit.rate, read_limit.burst, this), + writecb(writecb), readcb(readcb), timeoutcb(timeoutcb), loop(loop), + data(data), fd(fd), tls_dyn_rec_warmup_threshold(tls_dyn_rec_warmup_threshold), tls_dyn_rec_idle_timeout(tls_dyn_rec_idle_timeout) { diff --git a/src/shrpx_connection.h b/src/shrpx_connection.h index 4906a19a..30ff448d 100644 --- a/src/shrpx_connection.h +++ b/src/shrpx_connection.h @@ -73,10 +73,10 @@ using TimerCb = EVCb; struct Connection { Connection(struct ev_loop *loop, int fd, SSL *ssl, MemchunkPool *mcpool, - ev_tstamp write_timeout, ev_tstamp read_timeout, size_t write_rate, - size_t write_burst, size_t read_rate, size_t read_burst, - IOCb writecb, IOCb readcb, TimerCb timeoutcb, void *data, - size_t tls_dyn_rec_warmup_threshold, + ev_tstamp write_timeout, ev_tstamp read_timeout, + const RateLimitConfig &write_limit, + const RateLimitConfig &read_limit, IOCb writecb, IOCb readcb, + TimerCb timeoutcb, void *data, size_t tls_dyn_rec_warmup_threshold, ev_tstamp tls_dyn_rec_idle_timeout); ~Connection(); diff --git a/src/shrpx_connection_handler.cc b/src/shrpx_connection_handler.cc index ee97437b..34b10996 100644 --- a/src/shrpx_connection_handler.cc +++ b/src/shrpx_connection_handler.cc @@ -300,13 +300,13 @@ int ConnectionHandler::handle_connection(int fd, sockaddr *addr, int addrlen) { } if (get_config()->num_worker == 1) { - + auto &upstreamconf = get_config()->conn.upstream; if (single_worker_->get_worker_stat()->num_connections >= - get_config()->worker_frontend_connections) { + upstreamconf.worker_connections) { if (LOG_ENABLED(INFO)) { LLOG(INFO, this) << "Too many connections >=" - << get_config()->worker_frontend_connections; + << upstreamconf.worker_connections; } close(fd); diff --git a/src/shrpx_downstream.cc b/src/shrpx_downstream.cc index be97814d..20bc9f67 100644 --- a/src/shrpx_downstream.cc +++ b/src/shrpx_downstream.cc @@ -124,14 +124,16 @@ Downstream::Downstream(Upstream *upstream, MemchunkPool *mcpool, chunked_response_(false), expect_final_response_(false), request_pending_(false) { + auto &timeoutconf = get_config()->http2.timeout; + ev_timer_init(&upstream_rtimer_, &upstream_rtimeoutcb, 0., - get_config()->stream_read_timeout); + timeoutconf.stream_read); ev_timer_init(&upstream_wtimer_, &upstream_wtimeoutcb, 0., - get_config()->stream_write_timeout); + timeoutconf.stream_write); ev_timer_init(&downstream_rtimer_, &downstream_rtimeoutcb, 0., - get_config()->stream_read_timeout); + timeoutconf.stream_read); ev_timer_init(&downstream_wtimer_, &downstream_wtimeoutcb, 0., - get_config()->stream_write_timeout); + timeoutconf.stream_write); upstream_rtimer_.data = this; upstream_wtimer_.data = this; @@ -491,7 +493,8 @@ void Downstream::set_chunked_request(bool f) { chunked_request_ = f; } bool Downstream::request_buf_full() { if (dconn_) { - return request_buf_.rleft() >= get_config()->downstream_request_buffer_size; + return request_buf_.rleft() >= + get_config()->conn.downstream.request_buffer_size; } else { return false; } @@ -582,7 +585,7 @@ DefaultMemchunks *Downstream::get_response_buf() { return &response_buf_; } bool Downstream::response_buf_full() { if (dconn_) { return response_buf_.rleft() >= - get_config()->downstream_response_buffer_size; + get_config()->conn.downstream.response_buffer_size; } else { return false; } @@ -764,7 +767,7 @@ void disable_timer(struct ev_loop *loop, ev_timer *w) { } // namespace void Downstream::reset_upstream_rtimer() { - if (get_config()->stream_read_timeout == 0.) { + if (get_config()->http2.timeout.stream_read == 0.) { return; } auto loop = upstream_->get_client_handler()->get_loop(); @@ -773,16 +776,18 @@ void Downstream::reset_upstream_rtimer() { void Downstream::reset_upstream_wtimer() { auto loop = upstream_->get_client_handler()->get_loop(); - if (get_config()->stream_write_timeout != 0.) { + auto &timeoutconf = get_config()->http2.timeout; + + if (timeoutconf.stream_write != 0.) { reset_timer(loop, &upstream_wtimer_); } - if (get_config()->stream_read_timeout != 0.) { + if (timeoutconf.stream_read != 0.) { try_reset_timer(loop, &upstream_rtimer_); } } void Downstream::ensure_upstream_wtimer() { - if (get_config()->stream_write_timeout == 0.) { + if (get_config()->http2.timeout.stream_write == 0.) { return; } auto loop = upstream_->get_client_handler()->get_loop(); @@ -790,7 +795,7 @@ void Downstream::ensure_upstream_wtimer() { } void Downstream::disable_upstream_rtimer() { - if (get_config()->stream_read_timeout == 0.) { + if (get_config()->http2.timeout.stream_read == 0.) { return; } auto loop = upstream_->get_client_handler()->get_loop(); @@ -798,7 +803,7 @@ void Downstream::disable_upstream_rtimer() { } void Downstream::disable_upstream_wtimer() { - if (get_config()->stream_write_timeout == 0.) { + if (get_config()->http2.timeout.stream_write == 0.) { return; } auto loop = upstream_->get_client_handler()->get_loop(); @@ -806,7 +811,7 @@ void Downstream::disable_upstream_wtimer() { } void Downstream::reset_downstream_rtimer() { - if (get_config()->stream_read_timeout == 0.) { + if (get_config()->http2.timeout.stream_read == 0.) { return; } auto loop = upstream_->get_client_handler()->get_loop(); @@ -815,16 +820,18 @@ void Downstream::reset_downstream_rtimer() { void Downstream::reset_downstream_wtimer() { auto loop = upstream_->get_client_handler()->get_loop(); - if (get_config()->stream_write_timeout != 0.) { + auto &timeoutconf = get_config()->http2.timeout; + + if (timeoutconf.stream_write != 0.) { reset_timer(loop, &downstream_wtimer_); } - if (get_config()->stream_read_timeout != 0.) { + if (timeoutconf.stream_read != 0.) { try_reset_timer(loop, &downstream_rtimer_); } } void Downstream::ensure_downstream_wtimer() { - if (get_config()->stream_write_timeout == 0.) { + if (get_config()->http2.timeout.stream_write == 0.) { return; } auto loop = upstream_->get_client_handler()->get_loop(); @@ -832,7 +839,7 @@ void Downstream::ensure_downstream_wtimer() { } void Downstream::disable_downstream_rtimer() { - if (get_config()->stream_read_timeout == 0.) { + if (get_config()->http2.timeout.stream_read == 0.) { return; } auto loop = upstream_->get_client_handler()->get_loop(); @@ -840,7 +847,7 @@ void Downstream::disable_downstream_rtimer() { } void Downstream::disable_downstream_wtimer() { - if (get_config()->stream_write_timeout == 0.) { + if (get_config()->http2.timeout.stream_write == 0.) { return; } auto loop = upstream_->get_client_handler()->get_loop(); diff --git a/src/shrpx_http.cc b/src/shrpx_http.cc index 0a67247b..faf83afb 100644 --- a/src/shrpx_http.cc +++ b/src/shrpx_http.cc @@ -47,7 +47,7 @@ std::string create_error_html(unsigned int status_code) { const auto &server_name = get_config()->http.server_name; res.append(server_name.c_str(), server_name.size()); res += " at port "; - res += util::utos(get_config()->port); + res += util::utos(get_config()->conn.listener.port); res += ""; return res; } diff --git a/src/shrpx_http2_downstream_connection.cc b/src/shrpx_http2_downstream_connection.cc index c39a722c..4cf0f538 100644 --- a/src/shrpx_http2_downstream_connection.cc +++ b/src/shrpx_http2_downstream_connection.cc @@ -268,7 +268,7 @@ int Http2DownstreamConnection::push_request_headers() { auto addr_idx = http2session_->get_addr_idx(); auto group = http2session_->get_group(); const auto &downstream_hostport = - get_config()->downstream_addr_groups[group].addrs[addr_idx].hostport; + get_config()->conn.downstream.addr_groups[group].addrs[addr_idx].hostport; // For HTTP/1.0 request, there is no authority in request. In that // case, we use backend server's host nonetheless. diff --git a/src/shrpx_http2_session.cc b/src/shrpx_http2_session.cc index 24cb4ce1..0e732677 100644 --- a/src/shrpx_http2_session.cc +++ b/src/shrpx_http2_session.cc @@ -146,8 +146,8 @@ Http2Session::Http2Session(struct ev_loop *loop, SSL_CTX *ssl_ctx, ConnectBlocker *connect_blocker, Worker *worker, size_t group, size_t idx) : conn_(loop, -1, nullptr, worker->get_mcpool(), - get_config()->downstream_write_timeout, - get_config()->downstream_read_timeout, 0, 0, 0, 0, writecb, readcb, + get_config()->conn.downstream.timeout.write, + get_config()->conn.downstream.timeout.read, {}, {}, writecb, readcb, timeoutcb, this, get_config()->tls.dyn_rec.warmup_threshold, get_config()->tls.dyn_rec.idle_timeout), worker_(worker), connect_blocker_(connect_blocker), ssl_ctx_(ssl_ctx), @@ -240,13 +240,13 @@ int Http2Session::disconnect(bool hard) { int Http2Session::check_cert() { return ssl::check_cert( conn_.tls.ssl, - &get_config()->downstream_addr_groups[group_].addrs[addr_idx_]); + &get_config()->conn.downstream.addr_groups[group_].addrs[addr_idx_]); } int Http2Session::initiate_connection() { int rv = 0; - auto &addrs = get_config()->downstream_addr_groups[group_].addrs; + auto &addrs = get_config()->conn.downstream.addr_groups[group_].addrs; if (state_ == DISCONNECTED) { if (connect_blocker_->blocked()) { @@ -509,7 +509,7 @@ int Http2Session::downstream_connect_proxy() { SSLOG(INFO, this) << "Connected to the proxy"; } auto &downstream_addr = - get_config()->downstream_addr_groups[group_].addrs[addr_idx_]; + get_config()->conn.downstream.addr_groups[group_].addrs[addr_idx_]; std::string req = "CONNECT "; req.append(downstream_addr.hostport.c_str(), downstream_addr.hostport.size()); @@ -1351,7 +1351,7 @@ int Http2Session::connection_made() { } } - auto must_terminate = !get_config()->downstream_no_tls && + auto must_terminate = !get_config()->conn.downstream.no_tls && !nghttp2::ssl::check_http2_requirement(conn_.tls.ssl); if (must_terminate) { @@ -1719,7 +1719,7 @@ int Http2Session::tls_handshake() { SSLOG(INFO, this) << "SSL/TLS handshake completed"; } - if (!get_config()->downstream_no_tls && !get_config()->tls.insecure && + if (!get_config()->conn.downstream.no_tls && !get_config()->tls.insecure && check_cert() != 0) { return -1; } diff --git a/src/shrpx_http2_upstream.cc b/src/shrpx_http2_upstream.cc index f152434a..309100cd 100644 --- a/src/shrpx_http2_upstream.cc +++ b/src/shrpx_http2_upstream.cc @@ -852,9 +852,9 @@ nghttp2_session_callbacks *create_http2_upstream_callbacks() { Http2Upstream::Http2Upstream(ClientHandler *handler) : downstream_queue_( get_config()->http2_proxy - ? get_config()->downstream_connections_per_host - : get_config()->downstream_proto == PROTO_HTTP - ? get_config()->downstream_connections_per_frontend + ? get_config()->conn.downstream.connections_per_host + : get_config()->conn.downstream.proto == PROTO_HTTP + ? get_config()->conn.downstream.connections_per_frontend : 0, !get_config()->http2_proxy), pending_response_buf_(handler->get_worker()->get_mcpool()), @@ -914,7 +914,7 @@ Http2Upstream::Http2Upstream(ClientHandler *handler) ev_prepare_start(handler_->get_loop(), &prep_); handler_->reset_upstream_read_timeout( - get_config()->http2_upstream_read_timeout); + get_config()->conn.upstream.timeout.http2_read); handler_->signal_write(); } diff --git a/src/shrpx_http_downstream_connection.cc b/src/shrpx_http_downstream_connection.cc index 3f86ad6c..46d9a058 100644 --- a/src/shrpx_http_downstream_connection.cc +++ b/src/shrpx_http_downstream_connection.cc @@ -113,8 +113,9 @@ void connectcb(struct ev_loop *loop, ev_io *w, int revents) { HttpDownstreamConnection::HttpDownstreamConnection( DownstreamConnectionPool *dconn_pool, size_t group, struct ev_loop *loop) : DownstreamConnection(dconn_pool), - conn_(loop, -1, nullptr, nullptr, get_config()->downstream_write_timeout, - get_config()->downstream_read_timeout, 0, 0, 0, 0, connectcb, + conn_(loop, -1, nullptr, nullptr, + get_config()->conn.downstream.timeout.write, + get_config()->conn.downstream.timeout.read, {}, {}, connectcb, readcb, timeoutcb, this, get_config()->tls.dyn_rec.warmup_threshold, get_config()->tls.dyn_rec.idle_timeout), ioctrl_(&conn_.rlimit), response_htp_{0}, group_(group), addr_idx_(0), @@ -127,6 +128,8 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream) { DCLOG(INFO, this) << "Attaching to DOWNSTREAM:" << downstream; } + auto &downstreamconf = get_config()->conn.downstream; + if (conn_.fd == -1) { auto connect_blocker = client_handler_->get_connect_blocker(); @@ -141,7 +144,7 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream) { auto worker = client_handler_->get_worker(); auto &next_downstream = worker->get_dgrp(group_)->next; auto end = next_downstream; - auto &addrs = get_config()->downstream_addr_groups[group_].addrs; + auto &addrs = downstreamconf.addr_groups[group_].addrs; for (;;) { auto &addr = addrs[next_downstream]; auto i = next_downstream; @@ -196,7 +199,7 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream) { ev_timer_again(conn_.loop, &conn_.wt); } else { // we may set read timer cb to idle_timeoutcb. Reset again. - conn_.rt.repeat = get_config()->downstream_read_timeout; + conn_.rt.repeat = downstreamconf.timeout.read; ev_set_cb(&conn_.rt, timeoutcb); ev_timer_again(conn_.loop, &conn_.rt); ev_set_cb(&conn_.rev, readcb); @@ -211,8 +214,10 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream) { } int HttpDownstreamConnection::push_request_headers() { - const auto &downstream_hostport = - get_config()->downstream_addr_groups[group_].addrs[addr_idx_].hostport; + const auto &downstream_hostport = get_config() + ->conn.downstream.addr_groups[group_] + .addrs[addr_idx_] + .hostport; const auto &req = downstream_->request(); auto connect_method = req.method == HTTP_CONNECT; @@ -479,7 +484,7 @@ void HttpDownstreamConnection::detach_downstream(Downstream *downstream) { ev_set_cb(&conn_.rev, idle_readcb); ioctrl_.force_resume_read(); - conn_.rt.repeat = get_config()->downstream_idle_read_timeout; + conn_.rt.repeat = get_config()->conn.downstream.timeout.idle_read; ev_set_cb(&conn_.rt, idle_timeoutcb); ev_timer_again(conn_.loop, &conn_.rt); @@ -494,7 +499,7 @@ void HttpDownstreamConnection::pause_read(IOCtrlReason reason) { int HttpDownstreamConnection::resume_read(IOCtrlReason reason, size_t consumed) { if (downstream_->get_response_buf()->rleft() <= - get_config()->downstream_request_buffer_size / 2) { + get_config()->conn.downstream.request_buffer_size / 2) { ioctrl_.resume_read(reason); } diff --git a/src/shrpx_memcached_connection.cc b/src/shrpx_memcached_connection.cc index e5e831ec..8bb01aab 100644 --- a/src/shrpx_memcached_connection.cc +++ b/src/shrpx_memcached_connection.cc @@ -92,7 +92,7 @@ constexpr ev_tstamp read_timeout = 10.; MemcachedConnection::MemcachedConnection(const Address *addr, struct ev_loop *loop) - : conn_(loop, -1, nullptr, nullptr, write_timeout, read_timeout, 0, 0, 0, 0, + : conn_(loop, -1, nullptr, nullptr, write_timeout, read_timeout, {}, {}, connectcb, readcb, timeoutcb, this, 0, 0.), parse_state_{}, addr_(addr), sendsum_(0), connected_(false) {} diff --git a/src/shrpx_spdy_upstream.cc b/src/shrpx_spdy_upstream.cc index 4d9cfa56..7fcdeba9 100644 --- a/src/shrpx_spdy_upstream.cc +++ b/src/shrpx_spdy_upstream.cc @@ -494,9 +494,9 @@ uint32_t infer_upstream_rst_stream_status_code(uint32_t downstream_error_code) { SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler) : downstream_queue_( get_config()->http2_proxy - ? get_config()->downstream_connections_per_host - : get_config()->downstream_proto == PROTO_HTTP - ? get_config()->downstream_connections_per_frontend + ? get_config()->conn.downstream.connections_per_host + : get_config()->conn.downstream.proto == PROTO_HTTP + ? get_config()->conn.downstream.connections_per_frontend : 0, !get_config()->http2_proxy), handler_(handler), session_(nullptr) { @@ -558,7 +558,7 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler) } handler_->reset_upstream_read_timeout( - get_config()->http2_upstream_read_timeout); + get_config()->conn.upstream.timeout.http2_read); handler_->signal_write(); } diff --git a/src/shrpx_ssl.cc b/src/shrpx_ssl.cc index 412071fd..b35f31cc 100644 --- a/src/shrpx_ssl.cc +++ b/src/shrpx_ssl.cc @@ -1214,7 +1214,7 @@ SSL_CTX *setup_server_ssl_context(std::vector &all_ssl_ctx, neverbleed_t *nb #endif // HAVE_NEVERBLEED ) { - if (get_config()->upstream_no_tls) { + if (get_config()->conn.upstream.no_tls) { return nullptr; } @@ -1266,11 +1266,13 @@ SSL_CTX *setup_server_ssl_context(std::vector &all_ssl_ctx, } bool downstream_tls_enabled() { + auto no_tls = get_config()->conn.downstream.no_tls; + if (get_config()->client_mode) { - return !get_config()->downstream_no_tls; + return !no_tls; } - return get_config()->http2_bridge && !get_config()->downstream_no_tls; + return get_config()->http2_bridge && !no_tls; } SSL_CTX *setup_client_ssl_context( @@ -1290,7 +1292,8 @@ SSL_CTX *setup_client_ssl_context( } CertLookupTree *create_cert_lookup_tree() { - if (get_config()->upstream_no_tls || get_config()->tls.subcerts.empty()) { + if (get_config()->conn.upstream.no_tls || + get_config()->tls.subcerts.empty()) { return nullptr; } return new ssl::CertLookupTree(); diff --git a/src/shrpx_worker.cc b/src/shrpx_worker.cc index 65103c92..d6282d37 100644 --- a/src/shrpx_worker.cc +++ b/src/shrpx_worker.cc @@ -69,9 +69,10 @@ std::random_device rd; Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx, ssl::CertLookupTree *cert_tree, const std::shared_ptr &ticket_keys) - : randgen_(rd()), dconn_pool_(get_config()->downstream_addr_groups.size()), - worker_stat_(get_config()->downstream_addr_groups.size()), - dgrps_(get_config()->downstream_addr_groups.size()), loop_(loop), + : randgen_(rd()), + dconn_pool_(get_config()->conn.downstream.addr_groups.size()), + worker_stat_(get_config()->conn.downstream.addr_groups.size()), + dgrps_(get_config()->conn.downstream.addr_groups.size()), loop_(loop), sv_ssl_ctx_(sv_ssl_ctx), cl_ssl_ctx_(cl_ssl_ctx), cert_tree_(cert_tree), ticket_keys_(ticket_keys), connect_blocker_(make_unique(loop_)), @@ -90,13 +91,15 @@ Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx, &session_cacheconf.memcached.addr, loop); } - if (get_config()->downstream_proto == PROTO_HTTP2) { + auto &downstreamconf = get_config()->conn.downstream; + + if (downstreamconf.proto == PROTO_HTTP2) { auto n = get_config()->http2.downstream.connections_per_worker; size_t group = 0; for (auto &dgrp : dgrps_) { auto m = n; if (m == 0) { - m = get_config()->downstream_addr_groups[group].addrs.size(); + m = downstreamconf.addr_groups[group].addrs.size(); } for (size_t idx = 0; idx < m; ++idx) { dgrp.http2sessions.push_back(make_unique( @@ -151,6 +154,9 @@ void Worker::process_events() { std::lock_guard g(m_); q.swap(q_); } + + auto worker_connections = get_config()->conn.upstream.worker_connections; + for (auto &wev : q) { switch (wev.type) { case NEW_CONNECTION: { @@ -159,12 +165,10 @@ void Worker::process_events() { << ", addrlen=" << wev.client_addrlen; } - if (worker_stat_.num_connections >= - get_config()->worker_frontend_connections) { + if (worker_stat_.num_connections >= worker_connections) { if (LOG_ENABLED(INFO)) { - WLOG(INFO, this) << "Too many connections >= " - << get_config()->worker_frontend_connections; + WLOG(INFO, this) << "Too many connections >= " << worker_connections; } close(wev.client_fd); diff --git a/src/shrpx_worker_process.cc b/src/shrpx_worker_process.cc index 181e4c96..61e44cb0 100644 --- a/src/shrpx_worker_process.cc +++ b/src/shrpx_worker_process.cc @@ -423,8 +423,10 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) { #endif // HAVE_NEVERBLEED + auto &upstreamconf = get_config()->conn.upstream; + ev_timer renew_ticket_key_timer; - if (!get_config()->upstream_no_tls) { + if (!upstreamconf.no_tls) { auto &ticketconf = get_config()->tls.ticket; if (ticketconf.memcached.host) { @@ -514,7 +516,7 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) { ipcev.data = &conn_handler; ev_io_start(loop, &ipcev); - if (!get_config()->upstream_no_tls && !get_config()->tls.ocsp.disabled) { + if (!upstreamconf.no_tls && !get_config()->tls.ocsp.disabled) { conn_handler.proceed_next_cert_ocsp(); }