nghttpx: Organize connection related configuration into struct

This commit is contained in:
Tatsuhiro Tsujikawa 2016-01-19 16:56:12 +09:00
parent 35feae3b0c
commit 0402481be4
18 changed files with 389 additions and 292 deletions

View File

@ -299,13 +299,15 @@ void exec_binary(SignalServer *ssv) {
std::string fd, fd6, path, port; 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 = ENV_UNIX_FD "=";
fd += util::utos(ssv->server_fd); fd += util::utos(ssv->server_fd);
envp[envidx++] = &fd[0]; envp[envidx++] = &fd[0];
path = ENV_UNIX_PATH "="; path = ENV_UNIX_PATH "=";
path += get_config()->host.get(); path += listenerconf.host.get();
envp[envidx++] = &path[0]; envp[envidx++] = &path[0];
} else { } else {
if (ssv->server_fd) { if (ssv->server_fd) {
@ -321,7 +323,7 @@ void exec_binary(SignalServer *ssv) {
} }
port = ENV_PORT "="; port = ENV_PORT "=";
port += util::utos(get_config()->port); port += util::utos(listenerconf.port);
envp[envidx++] = &port[0]; envp[envidx++] = &port[0];
} }
@ -430,7 +432,9 @@ void worker_process_child_cb(struct ev_loop *loop, ev_child *w, int revents) {
namespace { namespace {
int create_unix_domain_server_socket() { 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 pathlen = strlen(path);
{ {
auto envfd = getenv(ENV_UNIX_FD); auto envfd = getenv(ENV_UNIX_FD);
@ -490,7 +494,7 @@ int create_unix_domain_server_socket() {
return -1; return -1;
} }
if (listen(fd, get_config()->backlog) != 0) { if (listen(fd, listenerconf.backlog) != 0) {
auto error = errno; auto error = errno;
LOG(FATAL) << "Failed to listen to UNIX domain socket, error=" << error; LOG(FATAL) << "Failed to listen to UNIX domain socket, error=" << error;
close(fd); close(fd);
@ -505,6 +509,8 @@ int create_unix_domain_server_socket() {
namespace { namespace {
int create_tcp_server_socket(int family) { int create_tcp_server_socket(int family) {
auto &listenerconf = get_config()->conn.listener;
{ {
auto envfd = auto envfd =
getenv(family == AF_INET ? ENV_LISTENER4_FD : ENV_LISTENER6_FD); 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. // Only do this iff NGHTTPX_PORT == get_config()->port.
// Otherwise, close fd, and create server socket as usual. // Otherwise, close fd, and create server socket as usual.
if (port == get_config()->port) { if (port == listenerconf.port) {
LOG(NOTICE) << "Listening on port " << get_config()->port; LOG(NOTICE) << "Listening on port " << listenerconf.port;
return fd; return fd;
} }
LOG(WARN) << "Port was changed between old binary (" << port LOG(WARN) << "Port was changed between old binary (" << port
<< ") and new binary (" << get_config()->port << ")"; << ") and new binary (" << listenerconf.port << ")";
close(fd); close(fd);
} }
} }
@ -532,7 +538,7 @@ int create_tcp_server_socket(int family) {
int fd = -1; int fd = -1;
int rv; int rv;
auto service = util::utos(get_config()->port); auto service = util::utos(listenerconf.port);
addrinfo hints{}; addrinfo hints{};
hints.ai_family = family; hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
@ -541,16 +547,16 @@ int create_tcp_server_socket(int family) {
hints.ai_flags |= AI_ADDRCONFIG; hints.ai_flags |= AI_ADDRCONFIG;
#endif // AI_ADDRCONFIG #endif // AI_ADDRCONFIG
auto node = strcmp("*", get_config()->host.get()) == 0 auto node = strcmp("*", listenerconf.host.get()) == 0
? nullptr ? nullptr
: get_config()->host.get(); : listenerconf.host.get();
addrinfo *res, *rp; addrinfo *res, *rp;
rv = getaddrinfo(node, service.c_str(), &hints, &res); rv = getaddrinfo(node, service.c_str(), &hints, &res);
if (rv != 0) { if (rv != 0) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
LOG(INFO) << "Unable to get IPv" << (family == AF_INET ? "4" : "6") 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); << gai_strerror(rv);
} }
return -1; return -1;
@ -619,15 +625,15 @@ int create_tcp_server_socket(int family) {
continue; continue;
} }
if (get_config()->fastopen > 0) { if (listenerconf.fastopen > 0) {
val = get_config()->fastopen; val = listenerconf.fastopen;
if (setsockopt(fd, SOL_TCP, TCP_FASTOPEN, &val, if (setsockopt(fd, SOL_TCP, TCP_FASTOPEN, &val,
static_cast<socklen_t>(sizeof(val))) == -1) { static_cast<socklen_t>(sizeof(val))) == -1) {
LOG(WARN) << "Failed to set TCP_FASTOPEN option to listener socket"; 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; auto error = errno;
LOG(WARN) << "listen() syscall failed, error=" << error; LOG(WARN) << "listen() syscall failed, error=" << error;
close(fd); close(fd);
@ -656,7 +662,7 @@ int create_tcp_server_socket(int family) {
return -1; return -1;
} }
LOG(NOTICE) << "Listening on " << host << ", port " << get_config()->port; LOG(NOTICE) << "Listening on " << host << ", port " << listenerconf.port;
return fd; return fd;
} }
@ -794,12 +800,14 @@ int event_loop() {
util::make_socket_closeonexec(fd); 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}); close_env_fd({ENV_LISTENER4_FD, ENV_LISTENER6_FD});
auto fd = create_unix_domain_server_socket(); auto fd = create_unix_domain_server_socket();
if (fd == -1) { if (fd == -1) {
LOG(FATAL) << "Failed to listen on UNIX domain socket " LOG(FATAL) << "Failed to listen on UNIX domain socket "
<< get_config()->host.get(); << listenerconf.host.get();
return -1; return -1;
} }
@ -808,10 +816,10 @@ int event_loop() {
if (get_config()->uid != 0) { if (get_config()->uid != 0) {
// fd is not associated to inode, so we cannot use fchown(2) // fd is not associated to inode, so we cannot use fchown(2)
// here. https://lkml.org/lkml/2004/11/1/84 // 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; auto error = errno;
LOG(WARN) << "Changing owner of UNIX domain socket " LOG(WARN) << "Changing owner of UNIX domain socket "
<< get_config()->host.get() << " failed: " << strerror(error); << listenerconf.host.get() << " failed: " << strerror(error);
} }
} }
} else { } else {
@ -819,8 +827,8 @@ int event_loop() {
auto fd6 = create_tcp_server_socket(AF_INET6); auto fd6 = create_tcp_server_socket(AF_INET6);
auto fd4 = create_tcp_server_socket(AF_INET); auto fd4 = create_tcp_server_socket(AF_INET);
if (fd6 == -1 && fd4 == -1) { if (fd6 == -1 && fd4 == -1) {
LOG(FATAL) << "Failed to listen on address " << get_config()->host.get() LOG(FATAL) << "Failed to listen on address " << listenerconf.host.get()
<< ", port " << get_config()->port; << ", port " << listenerconf.port;
return -1; return -1;
} }
@ -900,38 +908,8 @@ void fill_default_config() {
mod_config()->verbose = false; mod_config()->verbose = false;
mod_config()->daemon = 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()->num_worker = 1;
mod_config()->conf_path = strcopy("/etc/nghttpx/nghttpx.conf"); mod_config()->conf_path = strcopy("/etc/nghttpx/nghttpx.conf");
// Default accept() backlog
mod_config()->backlog = 512;
mod_config()->http2_proxy = false; mod_config()->http2_proxy = false;
mod_config()->http2_bridge = false; mod_config()->http2_bridge = false;
mod_config()->client_proxy = false; mod_config()->client_proxy = false;
@ -942,29 +920,10 @@ void fill_default_config() {
mod_config()->uid = 0; mod_config()->uid = 0;
mod_config()->gid = 0; mod_config()->gid = 0;
mod_config()->pid = getpid(); 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()->padding = 0;
mod_config()->worker_frontend_connections = 0;
mod_config()->argc = 0; mod_config()->argc = 0;
mod_config()->argv = nullptr; 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; auto &tlsconf = mod_config()->tls;
{ {
@ -1014,6 +973,15 @@ void fill_default_config() {
auto &http2conf = mod_config()->http2; 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; auto &upstreamconf = http2conf.upstream;
// window bits for HTTP/2 and SPDY upstream connection per // window bits for HTTP/2 and SPDY upstream connection per
// stream. 2**16-1 = 64KiB-1, which is HTTP/2 default. Please note // 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; 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 } // namespace
@ -1151,11 +1167,11 @@ Connections:
assumes all addresses including both IPv4 and IPv6. assumes all addresses including both IPv4 and IPv6.
UNIX domain socket can be specified by prefixing path UNIX domain socket can be specified by prefixing path
name with "unix:" (e.g., unix:/var/run/nghttpx.sock) name with "unix:" (e.g., unix:/var/run/nghttpx.sock)
Default: )" << get_config()->host.get() << "," Default: )" << get_config()->conn.listener.host.get() << ","
<< get_config()->port << R"( << get_config()->conn.listener.port << R"(
--backlog=<N> --backlog=<N>
Set listen backlog size. Set listen backlog size.
Default: )" << get_config()->backlog << R"( Default: )" << get_config()->conn.listener.backlog << R"(
--backend-ipv4 --backend-ipv4
Resolve backend hostname to IPv4 address only. Resolve backend hostname to IPv4 address only.
--backend-ipv6 --backend-ipv6
@ -1183,45 +1199,50 @@ Performance:
--read-rate=<SIZE> --read-rate=<SIZE>
Set maximum average read rate on frontend connection. Set maximum average read rate on frontend connection.
Setting 0 to this option means read rate is unlimited. 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=<SIZE> --read-burst=<SIZE>
Set maximum read burst size on frontend connection. Set maximum read burst size on frontend connection.
Setting 0 to this option means read burst size is Setting 0 to this option means read burst size is
unlimited. unlimited.
Default: )" << get_config()->read_burst << R"( Default: )" << get_config()->conn.upstream.ratelimit.read.burst
<< R"(
--write-rate=<SIZE> --write-rate=<SIZE>
Set maximum average write rate on frontend connection. Set maximum average write rate on frontend connection.
Setting 0 to this option means write rate is unlimited. 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=<SIZE> --write-burst=<SIZE>
Set maximum write burst size on frontend connection. Set maximum write burst size on frontend connection.
Setting 0 to this option means write burst size is Setting 0 to this option means write burst size is
unlimited. unlimited.
Default: )" << get_config()->write_burst << R"( Default: )" << get_config()->conn.upstream.ratelimit.write.burst
<< R"(
--worker-read-rate=<SIZE> --worker-read-rate=<SIZE>
Set maximum average read rate on frontend connection per Set maximum average read rate on frontend connection per
worker. Setting 0 to this option means read rate is worker. Setting 0 to this option means read rate is
unlimited. Not implemented yet. unlimited. Not implemented yet.
Default: )" << get_config()->worker_read_rate << R"( Default: 0
--worker-read-burst=<SIZE> --worker-read-burst=<SIZE>
Set maximum read burst size on frontend connection per Set maximum read burst size on frontend connection per
worker. Setting 0 to this option means read burst size worker. Setting 0 to this option means read burst size
is unlimited. Not implemented yet. is unlimited. Not implemented yet.
Default: )" << get_config()->worker_read_burst << R"( Default: 0
--worker-write-rate=<SIZE> --worker-write-rate=<SIZE>
Set maximum average write rate on frontend connection Set maximum average write rate on frontend connection
per worker. Setting 0 to this option means write rate per worker. Setting 0 to this option means write rate
is unlimited. Not implemented yet. is unlimited. Not implemented yet.
Default: )" << get_config()->worker_write_rate << R"( Default: 0
--worker-write-burst=<SIZE> --worker-write-burst=<SIZE>
Set maximum write burst size on frontend connection per Set maximum write burst size on frontend connection per
worker. Setting 0 to this option means write burst size worker. Setting 0 to this option means write burst size
is unlimited. Not implemented yet. is unlimited. Not implemented yet.
Default: )" << get_config()->worker_write_burst << R"( Default: 0
--worker-frontend-connections=<N> --worker-frontend-connections=<N>
Set maximum number of simultaneous connections frontend Set maximum number of simultaneous connections frontend
accepts. Setting 0 means unlimited. 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=<N> --backend-http2-connections-per-worker=<N>
Set maximum number of backend HTTP/2 physical Set maximum number of backend HTTP/2 physical
connections per worker. If pattern is used in -b connections per worker. If pattern is used in -b
@ -1239,7 +1260,7 @@ Performance:
header field for HTTP/2). To limit the number of header field for HTTP/2). To limit the number of
connections per frontend for default mode, use connections per frontend for default mode, use
--backend-http1-connections-per-frontend. --backend-http1-connections-per-frontend.
Default: )" << get_config()->downstream_connections_per_host Default: )" << get_config()->conn.downstream.connections_per_host
<< R"( << R"(
--backend-http1-connections-per-frontend=<N> --backend-http1-connections-per-frontend=<N>
Set maximum number of backend concurrent HTTP/1 Set maximum number of backend concurrent HTTP/1
@ -1247,8 +1268,8 @@ Performance:
default mode. 0 means unlimited. To limit the number default mode. 0 means unlimited. To limit the number
of connections per host for HTTP/2 or SPDY proxy mode of connections per host for HTTP/2 or SPDY proxy mode
(-s option), use --backend-http1-connections-per-host. (-s option), use --backend-http1-connections-per-host.
Default: )" << get_config()->downstream_connections_per_frontend Default: )"
<< R"( << get_config()->conn.downstream.connections_per_frontend << R"(
--rlimit-nofile=<N> --rlimit-nofile=<N>
Set maximum number of open files (RLIMIT_NOFILE) to <N>. Set maximum number of open files (RLIMIT_NOFILE) to <N>.
If 0 is given, nghttpx does not set the limit. If 0 is given, nghttpx does not set the limit.
@ -1256,59 +1277,63 @@ Performance:
--backend-request-buffer=<SIZE> --backend-request-buffer=<SIZE>
Set buffer size used to store backend request. Set buffer size used to store backend request.
Default: )" 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=<SIZE> --backend-response-buffer=<SIZE>
Set buffer size used to store backend response. Set buffer size used to store backend response.
Default: )" Default: )"
<< util::utos_unit(get_config()->downstream_response_buffer_size) << R"( << util::utos_unit(get_config()->conn.downstream.response_buffer_size)
<< R"(
--fastopen=<N> --fastopen=<N>
Enables "TCP Fast Open" for the listening socket and Enables "TCP Fast Open" for the listening socket and
limits the maximum length for the queue of connections limits the maximum length for the queue of connections
that have not yet completed the three-way handshake. If that have not yet completed the three-way handshake. If
value is 0 then fast open is disabled. value is 0 then fast open is disabled.
Default: )" << get_config()->fastopen << R"( Default: )" << get_config()->conn.listener.fastopen << R"(
Timeout: Timeout:
--frontend-http2-read-timeout=<DURATION> --frontend-http2-read-timeout=<DURATION>
Specify read timeout for HTTP/2 and SPDY frontend Specify read timeout for HTTP/2 and SPDY frontend
connection. connection.
Default: )" 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=<DURATION> --frontend-read-timeout=<DURATION>
Specify read timeout for HTTP/1.1 frontend connection. Specify read timeout for HTTP/1.1 frontend connection.
Default: )" Default: )"
<< util::duration_str(get_config()->upstream_read_timeout) << R"( << util::duration_str(get_config()->conn.upstream.timeout.read) << R"(
--frontend-write-timeout=<DURATION> --frontend-write-timeout=<DURATION>
Specify write timeout for all frontend connections. Specify write timeout for all frontend connections.
Default: )" Default: )"
<< util::duration_str(get_config()->upstream_write_timeout) << R"( << util::duration_str(get_config()->conn.upstream.timeout.write) << R"(
--stream-read-timeout=<DURATION> --stream-read-timeout=<DURATION>
Specify read timeout for HTTP/2 and SPDY streams. 0 Specify read timeout for HTTP/2 and SPDY streams. 0
means no timeout. means no timeout.
Default: )" Default: )"
<< util::duration_str(get_config()->stream_read_timeout) << R"( << util::duration_str(get_config()->http2.timeout.stream_read) << R"(
--stream-write-timeout=<DURATION> --stream-write-timeout=<DURATION>
Specify write timeout for HTTP/2 and SPDY streams. 0 Specify write timeout for HTTP/2 and SPDY streams. 0
means no timeout. means no timeout.
Default: )" Default: )"
<< util::duration_str(get_config()->stream_write_timeout) << R"( << util::duration_str(get_config()->http2.timeout.stream_write) << R"(
--backend-read-timeout=<DURATION> --backend-read-timeout=<DURATION>
Specify read timeout for backend connection. Specify read timeout for backend connection.
Default: )" Default: )"
<< util::duration_str(get_config()->downstream_read_timeout) << R"( << util::duration_str(get_config()->conn.downstream.timeout.read) << R"(
--backend-write-timeout=<DURATION> --backend-write-timeout=<DURATION>
Specify write timeout for backend connection. Specify write timeout for backend connection.
Default: )" Default: )"
<< util::duration_str(get_config()->downstream_write_timeout) << R"( << util::duration_str(get_config()->conn.downstream.timeout.write) << R"(
--backend-keep-alive-timeout=<DURATION> --backend-keep-alive-timeout=<DURATION>
Specify keep-alive timeout for backend connection. Specify keep-alive timeout for backend connection.
Default: )" 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=<DURATION> --listener-disable-timeout=<DURATION>
After accepting connection failed, connection listener After accepting connection failed, connection listener
is disabled for a given amount of time. Specifying 0 is disabled for a given amount of time. Specifying 0
disables this feature. disables this feature.
Default: )" Default: )"
<< util::duration_str(get_config()->listener_disable_timeout) << R"( << util::duration_str(get_config()->conn.listener.timeout.sleep) << R"(
SSL/TLS: SSL/TLS:
--ciphers=<SUITE> --ciphers=<SUITE>
@ -1858,15 +1883,18 @@ void process_options(
tlsconf.alpn_prefs = ssl::set_alpn_prefs(tlsconf.npn_list); 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 " LOG(FATAL) << "--backend-ipv4 and --backend-ipv6 cannot be used at the "
<< "same time."; << "same time.";
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (get_config()->worker_frontend_connections == 0) { if (upstreamconf.worker_connections == 0) {
mod_config()->worker_frontend_connections = upstreamconf.worker_connections = std::numeric_limits<size_t>::max();
std::numeric_limits<size_t>::max();
} }
if (get_config()->http2_proxy + get_config()->http2_bridge + if (get_config()->http2_proxy + get_config()->http2_bridge +
@ -1879,23 +1907,23 @@ void process_options(
if (get_config()->client || get_config()->client_proxy) { if (get_config()->client || get_config()->client_proxy) {
mod_config()->client_mode = true; mod_config()->client_mode = true;
mod_config()->upstream_no_tls = true; upstreamconf.no_tls = true;
} }
if (get_config()->client_mode || get_config()->http2_bridge) { if (get_config()->client_mode || get_config()->http2_bridge) {
mod_config()->downstream_proto = PROTO_HTTP2; downstreamconf.proto = PROTO_HTTP2;
} else { } 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)) { (!tlsconf.private_key_file || !tlsconf.cert_file)) {
print_usage(std::cerr); print_usage(std::cerr);
LOG(FATAL) << "Too few arguments"; LOG(FATAL) << "Too few arguments";
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (!get_config()->upstream_no_tls && !tlsconf.ocsp.disabled) { if (!upstreamconf.no_tls && !tlsconf.ocsp.disabled) {
struct stat buf; struct stat buf;
if (stat(tlsconf.ocsp.fetch_ocsp_response_file.get(), &buf) != 0) { if (stat(tlsconf.ocsp.fetch_ocsp_response_file.get(), &buf) != 0) {
tlsconf.ocsp.disabled = true; 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; DownstreamAddr addr;
addr.host = ImmutableString::from_lit(DEFAULT_DOWNSTREAM_HOST); addr.host = ImmutableString::from_lit(DEFAULT_DOWNSTREAM_HOST);
addr.port = DEFAULT_DOWNSTREAM_PORT; addr.port = DEFAULT_DOWNSTREAM_PORT;
DownstreamAddrGroup g("/"); DownstreamAddrGroup g("/");
g.addrs.push_back(std::move(addr)); g.addrs.push_back(std::move(addr));
mod_config()->router.add_route(g.pattern.get(), 1, mod_config()->router.add_route(g.pattern.get(), 1, addr_groups.size());
get_config()->downstream_addr_groups.size()); addr_groups.push_back(std::move(g));
mod_config()->downstream_addr_groups.push_back(std::move(g));
} else if (get_config()->http2_proxy || get_config()->client_proxy) { } else if (get_config()->http2_proxy || get_config()->client_proxy) {
// We don't support host mapping in these cases. Move all // We don't support host mapping in these cases. Move all
// non-catch-all patterns to catch-all pattern. // non-catch-all patterns to catch-all pattern.
DownstreamAddrGroup catch_all("/"); 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::move(std::begin(g.addrs), std::end(g.addrs),
std::back_inserter(catch_all.addrs)); std::back_inserter(catch_all.addrs));
} }
std::vector<DownstreamAddrGroup>().swap( std::vector<DownstreamAddrGroup>().swap(addr_groups);
mod_config()->downstream_addr_groups);
// maybe not necessary? // maybe not necessary?
mod_config()->router = Router(); mod_config()->router = Router();
mod_config()->router.add_route(catch_all.pattern.get(), 1, mod_config()->router.add_route(catch_all.pattern.get(), 1,
get_config()->downstream_addr_groups.size()); addr_groups.size());
mod_config()->downstream_addr_groups.push_back(std::move(catch_all)); addr_groups.push_back(std::move(catch_all));
} }
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
@ -1937,8 +1965,8 @@ void process_options(
} }
ssize_t catch_all_group = -1; ssize_t catch_all_group = -1;
for (size_t i = 0; i < mod_config()->downstream_addr_groups.size(); ++i) { for (size_t i = 0; i < addr_groups.size(); ++i) {
auto &g = mod_config()->downstream_addr_groups[i]; auto &g = addr_groups[i];
if (util::streq(g.pattern.get(), "/")) { if (util::streq(g.pattern.get(), "/")) {
catch_all_group = i; catch_all_group = i;
} }
@ -1956,13 +1984,14 @@ void process_options(
LOG(FATAL) << "-b: No catch-all backend address is configured"; LOG(FATAL) << "-b: No catch-all backend address is configured";
exit(EXIT_FAILURE); 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)) { if (LOG_ENABLED(INFO)) {
LOG(INFO) << "Catch-all pattern is group " << catch_all_group; 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) { for (auto &addr : g.addrs) {
if (addr.host_unix) { if (addr.host_unix) {
@ -1970,7 +1999,7 @@ void process_options(
// hostport. This is used as Host header field to backend and // hostport. This is used as Host header field to backend and
// not going to be passed to any syscalls. // not going to be passed to any syscalls.
addr.hostport = ImmutableString( addr.hostport = ImmutableString(
util::make_hostport("localhost", get_config()->port)); util::make_hostport("localhost", listenerconf.port));
auto path = addr.host.c_str(); auto path = addr.host.c_str();
auto pathlen = addr.host.size(); auto pathlen = addr.host.size();
@ -1997,9 +2026,9 @@ void process_options(
if (resolve_hostname( if (resolve_hostname(
&addr.addr, addr.host.c_str(), addr.port, &addr.addr, addr.host.c_str(), addr.port,
get_config()->backend_ipv4 ? AF_INET : (get_config()->backend_ipv6 downstreamconf.ipv4
? AF_INET6 ? AF_INET
: AF_UNSPEC)) == -1) { : (downstreamconf.ipv6 ? AF_INET6 : AF_UNSPEC)) == -1) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }

View File

@ -371,16 +371,16 @@ int ClientHandler::upstream_http1_connhd_read() {
ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl, ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl,
const char *ipaddr, const char *port) const char *ipaddr, const char *port)
: conn_(worker->get_loop(), fd, ssl, worker->get_mcpool(), : conn_(worker->get_loop(), fd, ssl, worker->get_mcpool(),
get_config()->upstream_write_timeout, get_config()->conn.upstream.timeout.write,
get_config()->upstream_read_timeout, get_config()->write_rate, get_config()->conn.upstream.timeout.read,
get_config()->write_burst, get_config()->read_rate, get_config()->conn.upstream.ratelimit.write,
get_config()->read_burst, writecb, readcb, timeoutcb, this, get_config()->conn.upstream.ratelimit.read, writecb, readcb,
get_config()->tls.dyn_rec.warmup_threshold, timeoutcb, this, get_config()->tls.dyn_rec.warmup_threshold,
get_config()->tls.dyn_rec.idle_timeout), get_config()->tls.dyn_rec.idle_timeout),
pinned_http2sessions_( pinned_http2sessions_(
get_config()->downstream_proto == PROTO_HTTP2 get_config()->conn.downstream.proto == PROTO_HTTP2
? make_unique<std::vector<ssize_t>>( ? make_unique<std::vector<ssize_t>>(
get_config()->downstream_addr_groups.size(), -1) get_config()->conn.downstream.addr_groups.size(), -1)
: nullptr), : nullptr),
ipaddr_(ipaddr), port_(port), worker_(worker), ipaddr_(ipaddr), port_(port), worker_(worker),
left_connhd_len_(NGHTTP2_CLIENT_MAGIC_LEN), left_connhd_len_(NGHTTP2_CLIENT_MAGIC_LEN),
@ -395,7 +395,7 @@ ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl,
conn_.rlimit.startw(); conn_.rlimit.startw();
ev_timer_again(conn_.loop, &conn_.rt); 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; read_ = &ClientHandler::read_clear;
write_ = &ClientHandler::noop; write_ = &ClientHandler::noop;
on_read_ = &ClientHandler::proxy_protocol_read; on_read_ = &ClientHandler::proxy_protocol_read;
@ -647,8 +647,9 @@ void ClientHandler::remove_downstream_connection(DownstreamConnection *dconn) {
std::unique_ptr<DownstreamConnection> std::unique_ptr<DownstreamConnection>
ClientHandler::get_downstream_connection(Downstream *downstream) { ClientHandler::get_downstream_connection(Downstream *downstream) {
size_t group; size_t group;
auto &groups = get_config()->downstream_addr_groups; auto &downstreamconf = get_config()->conn.downstream;
auto catch_all = get_config()->downstream_addr_group_catch_all; auto &groups = downstreamconf.addr_groups;
auto catch_all = downstreamconf.addr_group_catch_all;
const auto &req = downstream->request(); const auto &req = downstream->request();
@ -693,7 +694,7 @@ ClientHandler::get_downstream_connection(Downstream *downstream) {
auto dconn_pool = worker_->get_dconn_pool(); auto dconn_pool = worker_->get_dconn_pool();
if (get_config()->downstream_proto == PROTO_HTTP2) { if (downstreamconf.proto == PROTO_HTTP2) {
Http2Session *http2session; Http2Session *http2session;
auto &pinned = (*pinned_http2sessions_)[group]; auto &pinned = (*pinned_http2sessions_)[group];
if (pinned == -1) { if (pinned == -1) {
@ -857,8 +858,8 @@ void ClientHandler::write_accesslog(Downstream *downstream) {
std::chrono::high_resolution_clock::now(), // request_end_time std::chrono::high_resolution_clock::now(), // request_end_time
req.http_major, req.http_minor, resp.http_status, req.http_major, req.http_minor, resp.http_status,
downstream->response_sent_body_length, port_, get_config()->port, downstream->response_sent_body_length, port_,
get_config()->pid, 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? // there a better value?
highres_now, // request_end_time highres_now, // request_end_time
major, minor, // major, minor 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_ += ':';
} }
local_hostport_ += util::utos(get_config()->port); local_hostport_ += util::utos(get_config()->conn.listener.port);
return local_hostport_; return local_hostport_;
} }

View File

@ -594,6 +594,8 @@ void parse_mapping(const DownstreamAddr &addr, const char *src) {
// will append '/' to all patterns, so it becomes catch-all pattern. // will append '/' to all patterns, so it becomes catch-all pattern.
auto mapping = util::split_config_str_list(src, ':'); auto mapping = util::split_config_str_list(src, ':');
assert(!mapping.empty()); assert(!mapping.empty());
auto &addr_groups = mod_config()->conn.downstream.addr_groups;
for (const auto &raw_pattern : mapping) { for (const auto &raw_pattern : mapping) {
auto done = false; auto done = false;
std::string pattern; std::string pattern;
@ -608,7 +610,7 @@ void parse_mapping(const DownstreamAddr &addr, const char *src) {
util::inp_strlower(pattern); util::inp_strlower(pattern);
pattern += http2::normalize_path(slash, raw_pattern.second); 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) { if (g.pattern.get() == pattern) {
g.addrs.push_back(addr); g.addrs.push_back(addr);
done = true; done = true;
@ -622,9 +624,9 @@ void parse_mapping(const DownstreamAddr &addr, const char *src) {
g.addrs.push_back(addr); g.addrs.push_back(addr);
mod_config()->router.add_route(g.pattern.get(), strlen(g.pattern.get()), 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 } // namespace
@ -1419,11 +1421,13 @@ int parse_config(const char *opt, const char *optarg,
return 0; return 0;
} }
case SHRPX_OPTID_FRONTEND: { case SHRPX_OPTID_FRONTEND: {
auto &listenerconf = mod_config()->conn.listener;
if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) { if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) {
auto path = optarg + str_size(SHRPX_UNIX_PATH_PREFIX); auto path = optarg + str_size(SHRPX_UNIX_PATH_PREFIX);
mod_config()->host = strcopy(path); listenerconf.host = strcopy(path);
mod_config()->port = 0; listenerconf.port = 0;
mod_config()->host_unix = true; listenerconf.host_unix = true;
return 0; return 0;
} }
@ -1433,9 +1437,9 @@ int parse_config(const char *opt, const char *optarg,
return -1; return -1;
} }
mod_config()->host = strcopy(host); listenerconf.host = strcopy(host);
mod_config()->port = port; listenerconf.port = port;
mod_config()->host_unix = false; listenerconf.host_unix = false;
return 0; return 0;
} }
@ -1484,20 +1488,26 @@ int parse_config(const char *opt, const char *optarg,
return 0; return 0;
case SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT: 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); optarg);
case SHRPX_OPTID_FRONTEND_READ_TIMEOUT: 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: 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: 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: 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: 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: 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: case SHRPX_OPTID_ACCESSLOG_FILE:
mod_config()->logging.access.file = strcopy(optarg); mod_config()->logging.access.file = strcopy(optarg);
@ -1529,12 +1539,12 @@ int parse_config(const char *opt, const char *optarg,
return -1; return -1;
} }
mod_config()->fastopen = n; mod_config()->conn.listener.fastopen = n;
return 0; return 0;
} }
case SHRPX_OPTID_BACKEND_KEEP_ALIVE_TIMEOUT: 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); optarg);
case SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS: case SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS:
case SHRPX_OPTID_BACKEND_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; return 0;
} }
case SHRPX_OPTID_FRONTEND_NO_TLS: 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; return 0;
case SHRPX_OPTID_BACKEND_NO_TLS: 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; return 0;
case SHRPX_OPTID_BACKEND_TLS_SNI_FIELD: case SHRPX_OPTID_BACKEND_TLS_SNI_FIELD:
@ -1676,7 +1686,7 @@ int parse_config(const char *opt, const char *optarg,
return -1; return -1;
} }
mod_config()->backlog = n; mod_config()->conn.listener.backlog = n;
return 0; return 0;
} }
@ -1697,11 +1707,11 @@ int parse_config(const char *opt, const char *optarg,
return 0; return 0;
case SHRPX_OPTID_BACKEND_IPV4: case SHRPX_OPTID_BACKEND_IPV4:
mod_config()->backend_ipv4 = util::strieq(optarg, "yes"); mod_config()->conn.downstream.ipv4 = util::strieq(optarg, "yes");
return 0; return 0;
case SHRPX_OPTID_BACKEND_IPV6: case SHRPX_OPTID_BACKEND_IPV6:
mod_config()->backend_ipv6 = util::strieq(optarg, "yes"); mod_config()->conn.downstream.ipv6 = util::strieq(optarg, "yes");
return 0; return 0;
case SHRPX_OPTID_BACKEND_HTTP_PROXY_URI: { case SHRPX_OPTID_BACKEND_HTTP_PROXY_URI: {
@ -1742,25 +1752,29 @@ int parse_config(const char *opt, const char *optarg,
return 0; return 0;
} }
case SHRPX_OPTID_READ_RATE: 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: 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: 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: 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: case SHRPX_OPTID_WORKER_READ_RATE:
LOG(WARN) << opt << ": not implemented yet"; 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: case SHRPX_OPTID_WORKER_READ_BURST:
LOG(WARN) << opt << ": not implemented yet"; 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: case SHRPX_OPTID_WORKER_WRITE_RATE:
LOG(WARN) << opt << ": not implemented yet"; 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: case SHRPX_OPTID_WORKER_WRITE_BURST:
LOG(WARN) << opt << ": not implemented yet"; 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: case SHRPX_OPTID_NPN_LIST:
mod_config()->tls.npn_list = util::parse_config_str_list(optarg); 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; return 0;
} }
case SHRPX_OPTID_WORKER_FRONTEND_CONNECTIONS: 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: case SHRPX_OPTID_NO_LOCATION_REWRITE:
mod_config()->http.no_location_rewrite = util::strieq(optarg, "yes"); 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; return -1;
} }
mod_config()->downstream_connections_per_host = n; mod_config()->conn.downstream.connections_per_host = n;
return 0; return 0;
} }
case SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND: case SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND:
return parse_uint(&mod_config()->downstream_connections_per_frontend, opt, return parse_uint(&mod_config()->conn.downstream.connections_per_frontend,
optarg); opt, optarg);
case SHRPX_OPTID_LISTENER_DISABLE_TIMEOUT: 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: case SHRPX_OPTID_TLS_TICKET_KEY_FILE:
mod_config()->tls.ticket.files.push_back(optarg); mod_config()->tls.ticket.files.push_back(optarg);
return 0; return 0;
@ -1935,9 +1951,9 @@ int parse_config(const char *opt, const char *optarg,
} }
if (optid == SHRPX_OPTID_BACKEND_REQUEST_BUFFER) { if (optid == SHRPX_OPTID_BACKEND_REQUEST_BUFFER) {
mod_config()->downstream_request_buffer_size = n; mod_config()->conn.downstream.request_buffer_size = n;
} else { } else {
mod_config()->downstream_response_buffer_size = n; mod_config()->conn.downstream.response_buffer_size = n;
} }
return 0; return 0;
@ -2065,7 +2081,8 @@ int parse_config(const char *opt, const char *optarg,
#endif // !HAVE_MRUBY #endif // !HAVE_MRUBY
return 0; return 0;
case SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL: 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; return 0;
case SHRPX_OPTID_ADD_FORWARDED: { case SHRPX_OPTID_ADD_FORWARDED: {

View File

@ -429,6 +429,10 @@ struct Http2Config {
size_t connection_window_bits; size_t connection_window_bits;
size_t connections_per_worker; size_t connections_per_worker;
} downstream; } downstream;
struct {
ev_tstamp stream_read;
ev_tstamp stream_write;
} timeout;
size_t max_concurrent_streams; size_t max_concurrent_streams;
bool no_cookie_crumbling; bool no_cookie_crumbling;
bool no_server_push; bool no_server_push;
@ -449,26 +453,77 @@ struct LoggingConfig {
int syslog_facility; 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<char[]> 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<DownstreamAddrGroup> 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 { struct Config {
std::vector<DownstreamAddrGroup> downstream_addr_groups;
Router router; Router router;
HttpProxy downstream_http_proxy; HttpProxy downstream_http_proxy;
HttpConfig http; HttpConfig http;
Http2Config http2; Http2Config http2;
TLSConfig tls; TLSConfig tls;
LoggingConfig logging; LoggingConfig logging;
ev_tstamp http2_upstream_read_timeout; ConnectionConfig conn;
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<char[]> host;
std::unique_ptr<char[]> pid_file; std::unique_ptr<char[]> pid_file;
std::unique_ptr<char[]> conf_path; std::unique_ptr<char[]> conf_path;
std::unique_ptr<char[]> user; std::unique_ptr<char[]> user;
@ -477,49 +532,20 @@ struct Config {
char **argv; char **argv;
char *cwd; char *cwd;
size_t num_worker; 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 padding;
size_t worker_frontend_connections;
size_t rlimit_nofile; 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 argc;
int fastopen;
uid_t uid; uid_t uid;
gid_t gid; gid_t gid;
pid_t pid; 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 verbose;
bool daemon; bool daemon;
bool http2_proxy; bool http2_proxy;
bool http2_bridge; bool http2_bridge;
bool client_proxy; bool client_proxy;
bool upstream_no_tls;
bool downstream_no_tls;
bool client; bool client;
// true if --client or --client-proxy are enabled. // true if --client or --client-proxy are enabled.
bool client_mode; 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(); const Config *get_config();

View File

@ -42,15 +42,17 @@ using namespace nghttp2;
namespace shrpx { namespace shrpx {
Connection::Connection(struct ev_loop *loop, int fd, SSL *ssl, Connection::Connection(struct ev_loop *loop, int fd, SSL *ssl,
MemchunkPool *mcpool, ev_tstamp write_timeout, MemchunkPool *mcpool, ev_tstamp write_timeout,
ev_tstamp read_timeout, size_t write_rate, ev_tstamp read_timeout,
size_t write_burst, size_t read_rate, size_t read_burst, const RateLimitConfig &write_limit,
IOCb writecb, IOCb readcb, TimerCb timeoutcb, void *data, const RateLimitConfig &read_limit, IOCb writecb,
IOCb readcb, TimerCb timeoutcb, void *data,
size_t tls_dyn_rec_warmup_threshold, size_t tls_dyn_rec_warmup_threshold,
ev_tstamp tls_dyn_rec_idle_timeout) ev_tstamp tls_dyn_rec_idle_timeout)
: tls{DefaultMemchunks(mcpool), DefaultPeekMemchunks(mcpool)}, : tls{DefaultMemchunks(mcpool), DefaultPeekMemchunks(mcpool)},
wlimit(loop, &wev, write_rate, write_burst), wlimit(loop, &wev, write_limit.rate, write_limit.burst),
rlimit(loop, &rev, read_rate, read_burst, this), writecb(writecb), rlimit(loop, &rev, read_limit.rate, read_limit.burst, this),
readcb(readcb), timeoutcb(timeoutcb), loop(loop), data(data), fd(fd), 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_warmup_threshold(tls_dyn_rec_warmup_threshold),
tls_dyn_rec_idle_timeout(tls_dyn_rec_idle_timeout) { tls_dyn_rec_idle_timeout(tls_dyn_rec_idle_timeout) {

View File

@ -73,10 +73,10 @@ using TimerCb = EVCb<ev_timer>;
struct Connection { struct Connection {
Connection(struct ev_loop *loop, int fd, SSL *ssl, MemchunkPool *mcpool, Connection(struct ev_loop *loop, int fd, SSL *ssl, MemchunkPool *mcpool,
ev_tstamp write_timeout, ev_tstamp read_timeout, size_t write_rate, ev_tstamp write_timeout, ev_tstamp read_timeout,
size_t write_burst, size_t read_rate, size_t read_burst, const RateLimitConfig &write_limit,
IOCb writecb, IOCb readcb, TimerCb timeoutcb, void *data, const RateLimitConfig &read_limit, IOCb writecb, IOCb readcb,
size_t tls_dyn_rec_warmup_threshold, TimerCb timeoutcb, void *data, size_t tls_dyn_rec_warmup_threshold,
ev_tstamp tls_dyn_rec_idle_timeout); ev_tstamp tls_dyn_rec_idle_timeout);
~Connection(); ~Connection();

View File

@ -300,13 +300,13 @@ int ConnectionHandler::handle_connection(int fd, sockaddr *addr, int addrlen) {
} }
if (get_config()->num_worker == 1) { if (get_config()->num_worker == 1) {
auto &upstreamconf = get_config()->conn.upstream;
if (single_worker_->get_worker_stat()->num_connections >= if (single_worker_->get_worker_stat()->num_connections >=
get_config()->worker_frontend_connections) { upstreamconf.worker_connections) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
LLOG(INFO, this) << "Too many connections >=" LLOG(INFO, this) << "Too many connections >="
<< get_config()->worker_frontend_connections; << upstreamconf.worker_connections;
} }
close(fd); close(fd);

View File

@ -124,14 +124,16 @@ Downstream::Downstream(Upstream *upstream, MemchunkPool *mcpool,
chunked_response_(false), expect_final_response_(false), chunked_response_(false), expect_final_response_(false),
request_pending_(false) { request_pending_(false) {
auto &timeoutconf = get_config()->http2.timeout;
ev_timer_init(&upstream_rtimer_, &upstream_rtimeoutcb, 0., ev_timer_init(&upstream_rtimer_, &upstream_rtimeoutcb, 0.,
get_config()->stream_read_timeout); timeoutconf.stream_read);
ev_timer_init(&upstream_wtimer_, &upstream_wtimeoutcb, 0., ev_timer_init(&upstream_wtimer_, &upstream_wtimeoutcb, 0.,
get_config()->stream_write_timeout); timeoutconf.stream_write);
ev_timer_init(&downstream_rtimer_, &downstream_rtimeoutcb, 0., ev_timer_init(&downstream_rtimer_, &downstream_rtimeoutcb, 0.,
get_config()->stream_read_timeout); timeoutconf.stream_read);
ev_timer_init(&downstream_wtimer_, &downstream_wtimeoutcb, 0., ev_timer_init(&downstream_wtimer_, &downstream_wtimeoutcb, 0.,
get_config()->stream_write_timeout); timeoutconf.stream_write);
upstream_rtimer_.data = this; upstream_rtimer_.data = this;
upstream_wtimer_.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() { bool Downstream::request_buf_full() {
if (dconn_) { if (dconn_) {
return request_buf_.rleft() >= get_config()->downstream_request_buffer_size; return request_buf_.rleft() >=
get_config()->conn.downstream.request_buffer_size;
} else { } else {
return false; return false;
} }
@ -582,7 +585,7 @@ DefaultMemchunks *Downstream::get_response_buf() { return &response_buf_; }
bool Downstream::response_buf_full() { bool Downstream::response_buf_full() {
if (dconn_) { if (dconn_) {
return response_buf_.rleft() >= return response_buf_.rleft() >=
get_config()->downstream_response_buffer_size; get_config()->conn.downstream.response_buffer_size;
} else { } else {
return false; return false;
} }
@ -764,7 +767,7 @@ void disable_timer(struct ev_loop *loop, ev_timer *w) {
} // namespace } // namespace
void Downstream::reset_upstream_rtimer() { void Downstream::reset_upstream_rtimer() {
if (get_config()->stream_read_timeout == 0.) { if (get_config()->http2.timeout.stream_read == 0.) {
return; return;
} }
auto loop = upstream_->get_client_handler()->get_loop(); auto loop = upstream_->get_client_handler()->get_loop();
@ -773,16 +776,18 @@ void Downstream::reset_upstream_rtimer() {
void Downstream::reset_upstream_wtimer() { void Downstream::reset_upstream_wtimer() {
auto loop = upstream_->get_client_handler()->get_loop(); 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_); reset_timer(loop, &upstream_wtimer_);
} }
if (get_config()->stream_read_timeout != 0.) { if (timeoutconf.stream_read != 0.) {
try_reset_timer(loop, &upstream_rtimer_); try_reset_timer(loop, &upstream_rtimer_);
} }
} }
void Downstream::ensure_upstream_wtimer() { void Downstream::ensure_upstream_wtimer() {
if (get_config()->stream_write_timeout == 0.) { if (get_config()->http2.timeout.stream_write == 0.) {
return; return;
} }
auto loop = upstream_->get_client_handler()->get_loop(); auto loop = upstream_->get_client_handler()->get_loop();
@ -790,7 +795,7 @@ void Downstream::ensure_upstream_wtimer() {
} }
void Downstream::disable_upstream_rtimer() { void Downstream::disable_upstream_rtimer() {
if (get_config()->stream_read_timeout == 0.) { if (get_config()->http2.timeout.stream_read == 0.) {
return; return;
} }
auto loop = upstream_->get_client_handler()->get_loop(); auto loop = upstream_->get_client_handler()->get_loop();
@ -798,7 +803,7 @@ void Downstream::disable_upstream_rtimer() {
} }
void Downstream::disable_upstream_wtimer() { void Downstream::disable_upstream_wtimer() {
if (get_config()->stream_write_timeout == 0.) { if (get_config()->http2.timeout.stream_write == 0.) {
return; return;
} }
auto loop = upstream_->get_client_handler()->get_loop(); auto loop = upstream_->get_client_handler()->get_loop();
@ -806,7 +811,7 @@ void Downstream::disable_upstream_wtimer() {
} }
void Downstream::reset_downstream_rtimer() { void Downstream::reset_downstream_rtimer() {
if (get_config()->stream_read_timeout == 0.) { if (get_config()->http2.timeout.stream_read == 0.) {
return; return;
} }
auto loop = upstream_->get_client_handler()->get_loop(); auto loop = upstream_->get_client_handler()->get_loop();
@ -815,16 +820,18 @@ void Downstream::reset_downstream_rtimer() {
void Downstream::reset_downstream_wtimer() { void Downstream::reset_downstream_wtimer() {
auto loop = upstream_->get_client_handler()->get_loop(); 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_); reset_timer(loop, &downstream_wtimer_);
} }
if (get_config()->stream_read_timeout != 0.) { if (timeoutconf.stream_read != 0.) {
try_reset_timer(loop, &downstream_rtimer_); try_reset_timer(loop, &downstream_rtimer_);
} }
} }
void Downstream::ensure_downstream_wtimer() { void Downstream::ensure_downstream_wtimer() {
if (get_config()->stream_write_timeout == 0.) { if (get_config()->http2.timeout.stream_write == 0.) {
return; return;
} }
auto loop = upstream_->get_client_handler()->get_loop(); auto loop = upstream_->get_client_handler()->get_loop();
@ -832,7 +839,7 @@ void Downstream::ensure_downstream_wtimer() {
} }
void Downstream::disable_downstream_rtimer() { void Downstream::disable_downstream_rtimer() {
if (get_config()->stream_read_timeout == 0.) { if (get_config()->http2.timeout.stream_read == 0.) {
return; return;
} }
auto loop = upstream_->get_client_handler()->get_loop(); auto loop = upstream_->get_client_handler()->get_loop();
@ -840,7 +847,7 @@ void Downstream::disable_downstream_rtimer() {
} }
void Downstream::disable_downstream_wtimer() { void Downstream::disable_downstream_wtimer() {
if (get_config()->stream_write_timeout == 0.) { if (get_config()->http2.timeout.stream_write == 0.) {
return; return;
} }
auto loop = upstream_->get_client_handler()->get_loop(); auto loop = upstream_->get_client_handler()->get_loop();

View File

@ -47,7 +47,7 @@ std::string create_error_html(unsigned int status_code) {
const auto &server_name = get_config()->http.server_name; const auto &server_name = get_config()->http.server_name;
res.append(server_name.c_str(), server_name.size()); res.append(server_name.c_str(), server_name.size());
res += " at port "; res += " at port ";
res += util::utos(get_config()->port); res += util::utos(get_config()->conn.listener.port);
res += "</footer></body></html>"; res += "</footer></body></html>";
return res; return res;
} }

View File

@ -268,7 +268,7 @@ int Http2DownstreamConnection::push_request_headers() {
auto addr_idx = http2session_->get_addr_idx(); auto addr_idx = http2session_->get_addr_idx();
auto group = http2session_->get_group(); auto group = http2session_->get_group();
const auto &downstream_hostport = 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 // For HTTP/1.0 request, there is no authority in request. In that
// case, we use backend server's host nonetheless. // case, we use backend server's host nonetheless.

View File

@ -146,8 +146,8 @@ Http2Session::Http2Session(struct ev_loop *loop, SSL_CTX *ssl_ctx,
ConnectBlocker *connect_blocker, Worker *worker, ConnectBlocker *connect_blocker, Worker *worker,
size_t group, size_t idx) size_t group, size_t idx)
: conn_(loop, -1, nullptr, worker->get_mcpool(), : conn_(loop, -1, nullptr, worker->get_mcpool(),
get_config()->downstream_write_timeout, get_config()->conn.downstream.timeout.write,
get_config()->downstream_read_timeout, 0, 0, 0, 0, writecb, readcb, get_config()->conn.downstream.timeout.read, {}, {}, writecb, readcb,
timeoutcb, this, get_config()->tls.dyn_rec.warmup_threshold, timeoutcb, this, get_config()->tls.dyn_rec.warmup_threshold,
get_config()->tls.dyn_rec.idle_timeout), get_config()->tls.dyn_rec.idle_timeout),
worker_(worker), connect_blocker_(connect_blocker), ssl_ctx_(ssl_ctx), worker_(worker), connect_blocker_(connect_blocker), ssl_ctx_(ssl_ctx),
@ -240,13 +240,13 @@ int Http2Session::disconnect(bool hard) {
int Http2Session::check_cert() { int Http2Session::check_cert() {
return ssl::check_cert( return ssl::check_cert(
conn_.tls.ssl, 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 Http2Session::initiate_connection() {
int rv = 0; 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 (state_ == DISCONNECTED) {
if (connect_blocker_->blocked()) { if (connect_blocker_->blocked()) {
@ -509,7 +509,7 @@ int Http2Session::downstream_connect_proxy() {
SSLOG(INFO, this) << "Connected to the proxy"; SSLOG(INFO, this) << "Connected to the proxy";
} }
auto &downstream_addr = 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 "; std::string req = "CONNECT ";
req.append(downstream_addr.hostport.c_str(), downstream_addr.hostport.size()); 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); !nghttp2::ssl::check_http2_requirement(conn_.tls.ssl);
if (must_terminate) { if (must_terminate) {
@ -1719,7 +1719,7 @@ int Http2Session::tls_handshake() {
SSLOG(INFO, this) << "SSL/TLS handshake completed"; 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) { check_cert() != 0) {
return -1; return -1;
} }

View File

@ -852,9 +852,9 @@ nghttp2_session_callbacks *create_http2_upstream_callbacks() {
Http2Upstream::Http2Upstream(ClientHandler *handler) Http2Upstream::Http2Upstream(ClientHandler *handler)
: downstream_queue_( : downstream_queue_(
get_config()->http2_proxy get_config()->http2_proxy
? get_config()->downstream_connections_per_host ? get_config()->conn.downstream.connections_per_host
: get_config()->downstream_proto == PROTO_HTTP : get_config()->conn.downstream.proto == PROTO_HTTP
? get_config()->downstream_connections_per_frontend ? get_config()->conn.downstream.connections_per_frontend
: 0, : 0,
!get_config()->http2_proxy), !get_config()->http2_proxy),
pending_response_buf_(handler->get_worker()->get_mcpool()), pending_response_buf_(handler->get_worker()->get_mcpool()),
@ -914,7 +914,7 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
ev_prepare_start(handler_->get_loop(), &prep_); ev_prepare_start(handler_->get_loop(), &prep_);
handler_->reset_upstream_read_timeout( handler_->reset_upstream_read_timeout(
get_config()->http2_upstream_read_timeout); get_config()->conn.upstream.timeout.http2_read);
handler_->signal_write(); handler_->signal_write();
} }

View File

@ -113,8 +113,9 @@ void connectcb(struct ev_loop *loop, ev_io *w, int revents) {
HttpDownstreamConnection::HttpDownstreamConnection( HttpDownstreamConnection::HttpDownstreamConnection(
DownstreamConnectionPool *dconn_pool, size_t group, struct ev_loop *loop) DownstreamConnectionPool *dconn_pool, size_t group, struct ev_loop *loop)
: DownstreamConnection(dconn_pool), : DownstreamConnection(dconn_pool),
conn_(loop, -1, nullptr, nullptr, get_config()->downstream_write_timeout, conn_(loop, -1, nullptr, nullptr,
get_config()->downstream_read_timeout, 0, 0, 0, 0, connectcb, get_config()->conn.downstream.timeout.write,
get_config()->conn.downstream.timeout.read, {}, {}, connectcb,
readcb, timeoutcb, this, get_config()->tls.dyn_rec.warmup_threshold, readcb, timeoutcb, this, get_config()->tls.dyn_rec.warmup_threshold,
get_config()->tls.dyn_rec.idle_timeout), get_config()->tls.dyn_rec.idle_timeout),
ioctrl_(&conn_.rlimit), response_htp_{0}, group_(group), addr_idx_(0), 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; DCLOG(INFO, this) << "Attaching to DOWNSTREAM:" << downstream;
} }
auto &downstreamconf = get_config()->conn.downstream;
if (conn_.fd == -1) { if (conn_.fd == -1) {
auto connect_blocker = client_handler_->get_connect_blocker(); 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 worker = client_handler_->get_worker();
auto &next_downstream = worker->get_dgrp(group_)->next; auto &next_downstream = worker->get_dgrp(group_)->next;
auto end = next_downstream; auto end = next_downstream;
auto &addrs = get_config()->downstream_addr_groups[group_].addrs; auto &addrs = downstreamconf.addr_groups[group_].addrs;
for (;;) { for (;;) {
auto &addr = addrs[next_downstream]; auto &addr = addrs[next_downstream];
auto i = next_downstream; auto i = next_downstream;
@ -196,7 +199,7 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream) {
ev_timer_again(conn_.loop, &conn_.wt); ev_timer_again(conn_.loop, &conn_.wt);
} else { } else {
// we may set read timer cb to idle_timeoutcb. Reset again. // 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_set_cb(&conn_.rt, timeoutcb);
ev_timer_again(conn_.loop, &conn_.rt); ev_timer_again(conn_.loop, &conn_.rt);
ev_set_cb(&conn_.rev, readcb); ev_set_cb(&conn_.rev, readcb);
@ -211,8 +214,10 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream) {
} }
int HttpDownstreamConnection::push_request_headers() { int HttpDownstreamConnection::push_request_headers() {
const auto &downstream_hostport = const auto &downstream_hostport = get_config()
get_config()->downstream_addr_groups[group_].addrs[addr_idx_].hostport; ->conn.downstream.addr_groups[group_]
.addrs[addr_idx_]
.hostport;
const auto &req = downstream_->request(); const auto &req = downstream_->request();
auto connect_method = req.method == HTTP_CONNECT; auto connect_method = req.method == HTTP_CONNECT;
@ -479,7 +484,7 @@ void HttpDownstreamConnection::detach_downstream(Downstream *downstream) {
ev_set_cb(&conn_.rev, idle_readcb); ev_set_cb(&conn_.rev, idle_readcb);
ioctrl_.force_resume_read(); 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_set_cb(&conn_.rt, idle_timeoutcb);
ev_timer_again(conn_.loop, &conn_.rt); ev_timer_again(conn_.loop, &conn_.rt);
@ -494,7 +499,7 @@ void HttpDownstreamConnection::pause_read(IOCtrlReason reason) {
int HttpDownstreamConnection::resume_read(IOCtrlReason reason, int HttpDownstreamConnection::resume_read(IOCtrlReason reason,
size_t consumed) { size_t consumed) {
if (downstream_->get_response_buf()->rleft() <= 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); ioctrl_.resume_read(reason);
} }

View File

@ -92,7 +92,7 @@ constexpr ev_tstamp read_timeout = 10.;
MemcachedConnection::MemcachedConnection(const Address *addr, MemcachedConnection::MemcachedConnection(const Address *addr,
struct ev_loop *loop) 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.), connectcb, readcb, timeoutcb, this, 0, 0.),
parse_state_{}, addr_(addr), sendsum_(0), connected_(false) {} parse_state_{}, addr_(addr), sendsum_(0), connected_(false) {}

View File

@ -494,9 +494,9 @@ uint32_t infer_upstream_rst_stream_status_code(uint32_t downstream_error_code) {
SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler) SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
: downstream_queue_( : downstream_queue_(
get_config()->http2_proxy get_config()->http2_proxy
? get_config()->downstream_connections_per_host ? get_config()->conn.downstream.connections_per_host
: get_config()->downstream_proto == PROTO_HTTP : get_config()->conn.downstream.proto == PROTO_HTTP
? get_config()->downstream_connections_per_frontend ? get_config()->conn.downstream.connections_per_frontend
: 0, : 0,
!get_config()->http2_proxy), !get_config()->http2_proxy),
handler_(handler), session_(nullptr) { handler_(handler), session_(nullptr) {
@ -558,7 +558,7 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
} }
handler_->reset_upstream_read_timeout( handler_->reset_upstream_read_timeout(
get_config()->http2_upstream_read_timeout); get_config()->conn.upstream.timeout.http2_read);
handler_->signal_write(); handler_->signal_write();
} }

View File

@ -1214,7 +1214,7 @@ SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
neverbleed_t *nb neverbleed_t *nb
#endif // HAVE_NEVERBLEED #endif // HAVE_NEVERBLEED
) { ) {
if (get_config()->upstream_no_tls) { if (get_config()->conn.upstream.no_tls) {
return nullptr; return nullptr;
} }
@ -1266,11 +1266,13 @@ SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
} }
bool downstream_tls_enabled() { bool downstream_tls_enabled() {
auto no_tls = get_config()->conn.downstream.no_tls;
if (get_config()->client_mode) { 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( SSL_CTX *setup_client_ssl_context(
@ -1290,7 +1292,8 @@ SSL_CTX *setup_client_ssl_context(
} }
CertLookupTree *create_cert_lookup_tree() { 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 nullptr;
} }
return new ssl::CertLookupTree(); return new ssl::CertLookupTree();

View File

@ -69,9 +69,10 @@ std::random_device rd;
Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx, Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx,
ssl::CertLookupTree *cert_tree, ssl::CertLookupTree *cert_tree,
const std::shared_ptr<TicketKeys> &ticket_keys) const std::shared_ptr<TicketKeys> &ticket_keys)
: randgen_(rd()), dconn_pool_(get_config()->downstream_addr_groups.size()), : randgen_(rd()),
worker_stat_(get_config()->downstream_addr_groups.size()), dconn_pool_(get_config()->conn.downstream.addr_groups.size()),
dgrps_(get_config()->downstream_addr_groups.size()), loop_(loop), 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), sv_ssl_ctx_(sv_ssl_ctx), cl_ssl_ctx_(cl_ssl_ctx), cert_tree_(cert_tree),
ticket_keys_(ticket_keys), ticket_keys_(ticket_keys),
connect_blocker_(make_unique<ConnectBlocker>(loop_)), connect_blocker_(make_unique<ConnectBlocker>(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); &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; auto n = get_config()->http2.downstream.connections_per_worker;
size_t group = 0; size_t group = 0;
for (auto &dgrp : dgrps_) { for (auto &dgrp : dgrps_) {
auto m = n; auto m = n;
if (m == 0) { 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) { for (size_t idx = 0; idx < m; ++idx) {
dgrp.http2sessions.push_back(make_unique<Http2Session>( dgrp.http2sessions.push_back(make_unique<Http2Session>(
@ -151,6 +154,9 @@ void Worker::process_events() {
std::lock_guard<std::mutex> g(m_); std::lock_guard<std::mutex> g(m_);
q.swap(q_); q.swap(q_);
} }
auto worker_connections = get_config()->conn.upstream.worker_connections;
for (auto &wev : q) { for (auto &wev : q) {
switch (wev.type) { switch (wev.type) {
case NEW_CONNECTION: { case NEW_CONNECTION: {
@ -159,12 +165,10 @@ void Worker::process_events() {
<< ", addrlen=" << wev.client_addrlen; << ", addrlen=" << wev.client_addrlen;
} }
if (worker_stat_.num_connections >= if (worker_stat_.num_connections >= worker_connections) {
get_config()->worker_frontend_connections) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
WLOG(INFO, this) << "Too many connections >= " WLOG(INFO, this) << "Too many connections >= " << worker_connections;
<< get_config()->worker_frontend_connections;
} }
close(wev.client_fd); close(wev.client_fd);

View File

@ -423,8 +423,10 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
#endif // HAVE_NEVERBLEED #endif // HAVE_NEVERBLEED
auto &upstreamconf = get_config()->conn.upstream;
ev_timer renew_ticket_key_timer; ev_timer renew_ticket_key_timer;
if (!get_config()->upstream_no_tls) { if (!upstreamconf.no_tls) {
auto &ticketconf = get_config()->tls.ticket; auto &ticketconf = get_config()->tls.ticket;
if (ticketconf.memcached.host) { if (ticketconf.memcached.host) {
@ -514,7 +516,7 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
ipcev.data = &conn_handler; ipcev.data = &conn_handler;
ev_io_start(loop, &ipcev); 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(); conn_handler.proceed_next_cert_ocsp();
} }