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;
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<socklen_t>(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=<N>
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=<SIZE>
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=<SIZE>
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=<SIZE>
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=<SIZE>
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=<SIZE>
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=<SIZE>
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=<SIZE>
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=<SIZE>
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=<N>
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=<N>
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=<N>
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=<N>
Set maximum number of open files (RLIMIT_NOFILE) to <N>.
If 0 is given, nghttpx does not set the limit.
@ -1256,59 +1277,63 @@ Performance:
--backend-request-buffer=<SIZE>
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=<SIZE>
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=<N>
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=<DURATION>
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=<DURATION>
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=<DURATION>
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=<DURATION>
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=<DURATION>
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=<DURATION>
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=<DURATION>
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=<DURATION>
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=<DURATION>
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=<SUITE>
@ -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<size_t>::max();
if (upstreamconf.worker_connections == 0) {
upstreamconf.worker_connections = std::numeric_limits<size_t>::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<DownstreamAddrGroup>().swap(
mod_config()->downstream_addr_groups);
std::vector<DownstreamAddrGroup>().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);
}
}

View File

@ -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<std::vector<ssize_t>>(
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<DownstreamConnection>
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_;
}

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.
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: {

View File

@ -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<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 {
std::vector<DownstreamAddrGroup> 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<char[]> host;
ConnectionConfig conn;
std::unique_ptr<char[]> pid_file;
std::unique_ptr<char[]> conf_path;
std::unique_ptr<char[]> 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();

View File

@ -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) {

View File

@ -73,10 +73,10 @@ using TimerCb = EVCb<ev_timer>;
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();

View File

@ -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);

View File

@ -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();

View File

@ -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 += "</footer></body></html>";
return res;
}

View File

@ -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.

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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) {}

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)
: 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();
}

View File

@ -1214,7 +1214,7 @@ SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &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<SSL_CTX *> &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();

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,
ssl::CertLookupTree *cert_tree,
const std::shared_ptr<TicketKeys> &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<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);
}
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<Http2Session>(
@ -151,6 +154,9 @@ void Worker::process_events() {
std::lock_guard<std::mutex> 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);

View File

@ -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();
}