Merge branch 'nghttpx-reorganize-config'

This commit is contained in:
Tatsuhiro Tsujikawa 2016-01-19 18:21:18 +09:00
commit dc0f0123e9
23 changed files with 1273 additions and 1063 deletions

File diff suppressed because it is too large Load Diff

View File

@ -87,7 +87,7 @@ void AcceptHandler::accept_connection() {
case ENFILE:
LOG(WARN) << "acceptor: running out file descriptor; disable acceptor "
"temporarily";
conn_hnr_->disable_acceptor_temporary(30.);
conn_hnr_->sleep_acceptor(get_config()->conn.listener.timeout.sleep);
break;
}

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()->tls_dyn_rec_idle_timeout),
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;
@ -404,14 +404,16 @@ ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl,
setup_upstream_io_callback();
}
if ((get_config()->forwarded_params & FORWARDED_FOR) &&
get_config()->forwarded_for_node_type == FORWARDED_NODE_OBFUSCATED) {
if (get_config()->forwarded_for_obfuscated.empty()) {
auto &fwdconf = get_config()->http.forwarded;
if ((fwdconf.params & FORWARDED_FOR) &&
fwdconf.for_node_type == FORWARDED_NODE_OBFUSCATED) {
if (fwdconf.for_obfuscated.empty()) {
forwarded_for_obfuscated_ = "_";
forwarded_for_obfuscated_ += util::random_alpha_digit(
worker_->get_randgen(), SHRPX_OBFUSCATED_NODE_LENGTH);
} else {
forwarded_for_obfuscated_ = get_config()->forwarded_for_obfuscated;
forwarded_for_obfuscated_ = fwdconf.for_obfuscated;
}
}
}
@ -521,7 +523,8 @@ int ClientHandler::validate_next_proto() {
CLOG(INFO, this) << "The negotiated next protocol: " << proto;
}
if (!ssl::in_proto_list(get_config()->npn_list, next_proto, next_proto_len)) {
if (!ssl::in_proto_list(get_config()->tls.npn_list, next_proto,
next_proto_len)) {
if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "The negotiated protocol is not supported";
}
@ -644,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();
@ -690,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) {
@ -833,7 +837,7 @@ void ClientHandler::write_accesslog(Downstream *downstream) {
const auto &resp = downstream->response();
upstream_accesslog(
get_config()->accesslog_format,
get_config()->logging.access.format,
LogSpec{
downstream, ipaddr_, http2::to_method_string(req.method),
@ -854,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,
});
}
@ -866,7 +870,7 @@ void ClientHandler::write_accesslog(int major, int minor, unsigned int status,
nghttp2::ssl::TLSSessionInfo tls_info;
upstream_accesslog(
get_config()->accesslog_format,
get_config()->logging.access.format,
LogSpec{
nullptr, ipaddr_,
StringRef::from_lit("-"), // method
@ -877,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,
});
}
@ -1119,8 +1124,10 @@ int ClientHandler::proxy_protocol_read() {
}
const std::string &ClientHandler::get_forwarded_by() {
if (get_config()->forwarded_by_node_type == FORWARDED_NODE_OBFUSCATED) {
return get_config()->forwarded_by_obfuscated;
auto &fwdconf = get_config()->http.forwarded;
if (fwdconf.by_node_type == FORWARDED_NODE_OBFUSCATED) {
return fwdconf.by_obfuscated;
}
if (!local_hostport_.empty()) {
return local_hostport_;
@ -1151,13 +1158,13 @@ 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_;
}
const std::string &ClientHandler::get_forwarded_for() const {
if (get_config()->forwarded_for_node_type == FORWARDED_NODE_OBFUSCATED) {
if (get_config()->http.forwarded.for_node_type == FORWARDED_NODE_OBFUSCATED) {
return forwarded_for_obfuscated_;
}

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;
}
@ -1447,7 +1451,7 @@ int parse_config(const char *opt, const char *optarg,
return parse_uint(&mod_config()->num_worker, opt, optarg);
#endif // !NOTHREADS
case SHRPX_OPTID_HTTP2_MAX_CONCURRENT_STREAMS:
return parse_uint(&mod_config()->http2_max_concurrent_streams, opt, optarg);
return parse_uint(&mod_config()->http2.max_concurrent_streams, opt, optarg);
case SHRPX_OPTID_LOG_LEVEL:
if (Log::set_severity_level_by_name(optarg) == -1) {
LOG(ERROR) << opt << ": Invalid severity level: " << optarg;
@ -1472,50 +1476,56 @@ int parse_config(const char *opt, const char *optarg,
return 0;
case SHRPX_OPTID_ADD_X_FORWARDED_FOR:
mod_config()->add_x_forwarded_for = util::strieq(optarg, "yes");
mod_config()->http.xff.add = util::strieq(optarg, "yes");
return 0;
case SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR:
mod_config()->strip_incoming_x_forwarded_for = util::strieq(optarg, "yes");
mod_config()->http.xff.strip_incoming = util::strieq(optarg, "yes");
return 0;
case SHRPX_OPTID_NO_VIA:
mod_config()->no_via = util::strieq(optarg, "yes");
mod_config()->http.no_via = util::strieq(optarg, "yes");
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()->accesslog_file = strcopy(optarg);
mod_config()->logging.access.file = strcopy(optarg);
return 0;
case SHRPX_OPTID_ACCESSLOG_SYSLOG:
mod_config()->accesslog_syslog = util::strieq(optarg, "yes");
mod_config()->logging.access.syslog = util::strieq(optarg, "yes");
return 0;
case SHRPX_OPTID_ACCESSLOG_FORMAT:
mod_config()->accesslog_format = parse_log_format(optarg);
mod_config()->logging.access.format = parse_log_format(optarg);
return 0;
case SHRPX_OPTID_ERRORLOG_FILE:
mod_config()->errorlog_file = strcopy(optarg);
mod_config()->logging.error.file = strcopy(optarg);
return 0;
case SHRPX_OPTID_ERRORLOG_SYSLOG:
mod_config()->errorlog_syslog = util::strieq(optarg, "yes");
mod_config()->logging.error.syslog = util::strieq(optarg, "yes");
return 0;
case SHRPX_OPTID_FASTOPEN: {
@ -1529,21 +1539,21 @@ 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: {
size_t *resp;
if (optid == SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS) {
resp = &mod_config()->http2_upstream_window_bits;
resp = &mod_config()->http2.upstream.window_bits;
} else {
resp = &mod_config()->http2_downstream_window_bits;
resp = &mod_config()->http2.downstream.window_bits;
}
errno = 0;
@ -1569,9 +1579,9 @@ int parse_config(const char *opt, const char *optarg,
size_t *resp;
if (optid == SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS) {
resp = &mod_config()->http2_upstream_connection_window_bits;
resp = &mod_config()->http2.upstream.connection_window_bits;
} else {
resp = &mod_config()->http2_downstream_connection_window_bits;
resp = &mod_config()->http2.downstream.connection_window_bits;
}
errno = 0;
@ -1593,15 +1603,15 @@ 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:
mod_config()->backend_tls_sni_name = optarg;
mod_config()->tls.backend_sni_name = optarg;
return 0;
case SHRPX_OPTID_PID_FILE:
@ -1622,7 +1632,7 @@ int parse_config(const char *opt, const char *optarg,
return 0;
}
case SHRPX_OPTID_PRIVATE_KEY_FILE:
mod_config()->private_key_file = strcopy(optarg);
mod_config()->tls.private_key_file = strcopy(optarg);
return 0;
case SHRPX_OPTID_PRIVATE_KEY_PASSWD_FILE: {
@ -1631,16 +1641,16 @@ int parse_config(const char *opt, const char *optarg,
LOG(ERROR) << opt << ": Couldn't read key file's passwd from " << optarg;
return -1;
}
mod_config()->private_key_passwd = strcopy(passwd);
mod_config()->tls.private_key_passwd = strcopy(passwd);
return 0;
}
case SHRPX_OPTID_CERTIFICATE_FILE:
mod_config()->cert_file = strcopy(optarg);
mod_config()->tls.cert_file = strcopy(optarg);
return 0;
case SHRPX_OPTID_DH_PARAM_FILE:
mod_config()->dh_param_file = strcopy(optarg);
mod_config()->tls.dh_param_file = strcopy(optarg);
return 0;
case SHRPX_OPTID_SUBCERT: {
@ -1649,7 +1659,7 @@ int parse_config(const char *opt, const char *optarg,
if (sp) {
std::string keyfile(optarg, sp);
// TODO Do we need private key for subcert?
mod_config()->subcerts.emplace_back(keyfile, sp + 1);
mod_config()->tls.subcerts.emplace_back(keyfile, sp + 1);
}
return 0;
@ -1660,7 +1670,7 @@ int parse_config(const char *opt, const char *optarg,
LOG(ERROR) << opt << ": Unknown syslog facility: " << optarg;
return -1;
}
mod_config()->syslog_facility = facility;
mod_config()->logging.syslog_facility = facility;
return 0;
}
@ -1676,12 +1686,12 @@ int parse_config(const char *opt, const char *optarg,
return -1;
}
mod_config()->backlog = n;
mod_config()->conn.listener.backlog = n;
return 0;
}
case SHRPX_OPTID_CIPHERS:
mod_config()->ciphers = strcopy(optarg);
mod_config()->tls.ciphers = strcopy(optarg);
return 0;
case SHRPX_OPTID_CLIENT:
@ -1689,19 +1699,19 @@ int parse_config(const char *opt, const char *optarg,
return 0;
case SHRPX_OPTID_INSECURE:
mod_config()->insecure = util::strieq(optarg, "yes");
mod_config()->tls.insecure = util::strieq(optarg, "yes");
return 0;
case SHRPX_OPTID_CACERT:
mod_config()->cacert = strcopy(optarg);
mod_config()->tls.cacert = strcopy(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,63 +1752,70 @@ 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()->npn_list = util::parse_config_str_list(optarg);
mod_config()->tls.npn_list = util::parse_config_str_list(optarg);
return 0;
case SHRPX_OPTID_TLS_PROTO_LIST:
mod_config()->tls_proto_list = util::parse_config_str_list(optarg);
mod_config()->tls.tls_proto_list = util::parse_config_str_list(optarg);
return 0;
case SHRPX_OPTID_VERIFY_CLIENT:
mod_config()->verify_client = util::strieq(optarg, "yes");
mod_config()->tls.client_verify.enabled = util::strieq(optarg, "yes");
return 0;
case SHRPX_OPTID_VERIFY_CLIENT_CACERT:
mod_config()->verify_client_cacert = strcopy(optarg);
mod_config()->tls.client_verify.cacert = strcopy(optarg);
return 0;
case SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE:
mod_config()->client_private_key_file = strcopy(optarg);
mod_config()->tls.client.private_key_file = strcopy(optarg);
return 0;
case SHRPX_OPTID_CLIENT_CERT_FILE:
mod_config()->client_cert_file = strcopy(optarg);
mod_config()->tls.client.cert_file = strcopy(optarg);
return 0;
case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER:
mod_config()->http2_upstream_dump_request_header_file = strcopy(optarg);
mod_config()->http2.upstream.debug.dump.request_header_file =
strcopy(optarg);
return 0;
case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER:
mod_config()->http2_upstream_dump_response_header_file = strcopy(optarg);
mod_config()->http2.upstream.debug.dump.response_header_file =
strcopy(optarg);
return 0;
case SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING:
mod_config()->http2_no_cookie_crumbling = util::strieq(optarg, "yes");
mod_config()->http2.no_cookie_crumbling = util::strieq(optarg, "yes");
return 0;
case SHRPX_OPTID_FRONTEND_FRAME_DEBUG:
mod_config()->upstream_frame_debug = util::strieq(optarg, "yes");
mod_config()->http2.upstream.debug.frame_debug =
util::strieq(optarg, "yes");
return 0;
case SHRPX_OPTID_PADDING:
@ -1845,7 +1862,7 @@ int parse_config(const char *opt, const char *optarg,
}
}
mod_config()->altsvcs.push_back(std::move(altsvc));
mod_config()->http.altsvcs.push_back(std::move(altsvc));
return 0;
}
@ -1857,16 +1874,17 @@ int parse_config(const char *opt, const char *optarg,
return -1;
}
if (optid == SHRPX_OPTID_ADD_REQUEST_HEADER) {
mod_config()->add_request_headers.push_back(std::move(p));
mod_config()->http.add_request_headers.push_back(std::move(p));
} else {
mod_config()->add_response_headers.push_back(std::move(p));
mod_config()->http.add_response_headers.push_back(std::move(p));
}
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()->no_location_rewrite = util::strieq(optarg, "yes");
mod_config()->http.no_location_rewrite = util::strieq(optarg, "yes");
return 0;
case SHRPX_OPTID_NO_HOST_REWRITE:
@ -1889,17 +1907,18 @@ 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_key_files.push_back(optarg);
mod_config()->tls.ticket.files.push_back(optarg);
return 0;
case SHRPX_OPTID_RLIMIT_NOFILE: {
int n;
@ -1932,36 +1951,36 @@ 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;
}
case SHRPX_OPTID_NO_SERVER_PUSH:
mod_config()->no_server_push = util::strieq(optarg, "yes");
mod_config()->http2.no_server_push = util::strieq(optarg, "yes");
return 0;
case SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER:
return parse_uint(&mod_config()->http2_downstream_connections_per_worker,
return parse_uint(&mod_config()->http2.downstream.connections_per_worker,
opt, optarg);
case SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE:
mod_config()->fetch_ocsp_response_file = strcopy(optarg);
mod_config()->tls.ocsp.fetch_ocsp_response_file = strcopy(optarg);
return 0;
case SHRPX_OPTID_OCSP_UPDATE_INTERVAL:
return parse_duration(&mod_config()->ocsp_update_interval, opt, optarg);
return parse_duration(&mod_config()->tls.ocsp.update_interval, opt, optarg);
case SHRPX_OPTID_NO_OCSP:
mod_config()->no_ocsp = util::strieq(optarg, "yes");
mod_config()->tls.ocsp.disabled = util::strieq(optarg, "yes");
return 0;
case SHRPX_OPTID_HEADER_FIELD_BUFFER:
return parse_uint_with_unit(&mod_config()->header_field_buffer, opt,
return parse_uint_with_unit(&mod_config()->http.header_field_buffer, opt,
optarg);
case SHRPX_OPTID_MAX_HEADER_FIELDS:
return parse_uint(&mod_config()->max_header_fields, opt, optarg);
return parse_uint(&mod_config()->http.max_header_fields, opt, optarg);
case SHRPX_OPTID_INCLUDE: {
if (included_set.count(optarg)) {
LOG(ERROR) << opt << ": " << optarg << " has already been included";
@ -1980,19 +1999,19 @@ int parse_config(const char *opt, const char *optarg,
}
case SHRPX_OPTID_TLS_TICKET_KEY_CIPHER:
if (util::strieq(optarg, "aes-128-cbc")) {
mod_config()->tls_ticket_key_cipher = EVP_aes_128_cbc();
mod_config()->tls.ticket.cipher = EVP_aes_128_cbc();
} else if (util::strieq(optarg, "aes-256-cbc")) {
mod_config()->tls_ticket_key_cipher = EVP_aes_256_cbc();
mod_config()->tls.ticket.cipher = EVP_aes_256_cbc();
} else {
LOG(ERROR) << opt
<< ": unsupported cipher for ticket encryption: " << optarg;
return -1;
}
mod_config()->tls_ticket_key_cipher_given = true;
mod_config()->tls.ticket.cipher_given = true;
return 0;
case SHRPX_OPTID_HOST_REWRITE:
mod_config()->no_host_rewrite = !util::strieq(optarg, "yes");
mod_config()->http.no_host_rewrite = !util::strieq(optarg, "yes");
return 0;
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED: {
@ -2001,8 +2020,9 @@ int parse_config(const char *opt, const char *optarg,
return -1;
}
mod_config()->session_cache_memcached_host = strcopy(host);
mod_config()->session_cache_memcached_port = port;
auto &memcachedconf = mod_config()->tls.session_cache.memcached;
memcachedconf.host = strcopy(host);
memcachedconf.port = port;
return 0;
}
@ -2012,13 +2032,14 @@ int parse_config(const char *opt, const char *optarg,
return -1;
}
mod_config()->tls_ticket_key_memcached_host = strcopy(host);
mod_config()->tls_ticket_key_memcached_port = port;
auto &memcachedconf = mod_config()->tls.ticket.memcached;
memcachedconf.host = strcopy(host);
memcachedconf.port = port;
return 0;
}
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_INTERVAL:
return parse_duration(&mod_config()->tls_ticket_key_memcached_interval, opt,
return parse_duration(&mod_config()->tls.ticket.memcached.interval, opt,
optarg);
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY: {
int n;
@ -2031,11 +2052,11 @@ int parse_config(const char *opt, const char *optarg,
return -1;
}
mod_config()->tls_ticket_key_memcached_max_retry = n;
mod_config()->tls.ticket.memcached.max_retry = n;
return 0;
}
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL:
return parse_uint(&mod_config()->tls_ticket_key_memcached_max_fail, opt,
return parse_uint(&mod_config()->tls.ticket.memcached.max_fail, opt,
optarg);
case SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD: {
size_t n;
@ -2043,13 +2064,13 @@ int parse_config(const char *opt, const char *optarg,
return -1;
}
mod_config()->tls_dyn_rec_warmup_threshold = n;
mod_config()->tls.dyn_rec.warmup_threshold = n;
return 0;
}
case SHRPX_OPTID_TLS_DYN_REC_IDLE_TIMEOUT:
return parse_duration(&mod_config()->tls_dyn_rec_idle_timeout, opt, optarg);
return parse_duration(&mod_config()->tls.dyn_rec.idle_timeout, opt, optarg);
case SHRPX_OPTID_MRUBY_FILE:
#ifdef HAVE_MRUBY
@ -2060,26 +2081,28 @@ 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:
mod_config()->forwarded_params = FORWARDED_NONE;
case SHRPX_OPTID_ADD_FORWARDED: {
auto &fwdconf = mod_config()->http.forwarded;
fwdconf.params = FORWARDED_NONE;
for (const auto &param : util::parse_config_str_list(optarg)) {
if (util::strieq(param, "by")) {
mod_config()->forwarded_params |= FORWARDED_BY;
fwdconf.params |= FORWARDED_BY;
continue;
}
if (util::strieq(param, "for")) {
mod_config()->forwarded_params |= FORWARDED_FOR;
fwdconf.params |= FORWARDED_FOR;
continue;
}
if (util::strieq(param, "host")) {
mod_config()->forwarded_params |= FORWARDED_HOST;
fwdconf.params |= FORWARDED_HOST;
continue;
}
if (util::strieq(param, "proto")) {
mod_config()->forwarded_params |= FORWARDED_PROTO;
fwdconf.params |= FORWARDED_PROTO;
continue;
}
@ -2089,8 +2112,9 @@ int parse_config(const char *opt, const char *optarg,
}
return 0;
}
case SHRPX_OPTID_STRIP_INCOMING_FORWARDED:
mod_config()->strip_incoming_forwarded = util::strieq(optarg, "yes");
mod_config()->http.forwarded.strip_incoming = util::strieq(optarg, "yes");
return 0;
case SHRPX_OPTID_FORWARDED_BY:
@ -2103,23 +2127,23 @@ int parse_config(const char *opt, const char *optarg,
return -1;
}
auto &fwdconf = mod_config()->http.forwarded;
switch (optid) {
case SHRPX_OPTID_FORWARDED_BY:
mod_config()->forwarded_by_node_type =
static_cast<shrpx_forwarded_node_type>(type);
fwdconf.by_node_type = static_cast<shrpx_forwarded_node_type>(type);
if (optarg[0] == '_') {
mod_config()->forwarded_by_obfuscated = optarg;
fwdconf.by_obfuscated = optarg;
} else {
mod_config()->forwarded_by_obfuscated = "";
fwdconf.by_obfuscated = "";
}
break;
case SHRPX_OPTID_FORWARDED_FOR:
mod_config()->forwarded_for_node_type =
static_cast<shrpx_forwarded_node_type>(type);
fwdconf.for_node_type = static_cast<shrpx_forwarded_node_type>(type);
if (optarg[0] == '_') {
mod_config()->forwarded_for_obfuscated = optarg;
fwdconf.for_obfuscated = optarg;
} else {
mod_config()->forwarded_for_obfuscated = "";
fwdconf.for_obfuscated = "";
}
break;
}

View File

@ -289,178 +289,263 @@ struct HttpProxy {
std::string host;
// userinfo in http proxy URI, not percent-encoded form
std::string userinfo;
// port in http proxy URI
uint16_t port;
};
struct Config {
struct TLSConfig {
// RFC 5077 Session ticket related configurations
struct {
struct {
Address addr;
uint16_t port;
std::unique_ptr<char[]> host;
ev_tstamp interval;
// Maximum number of retries when getting TLS ticket key from
// mamcached, due to network error.
size_t max_retry;
// Maximum number of consecutive error from memcached, when this
// limit reached, TLS ticket is disabled.
size_t max_fail;
} memcached;
std::vector<std::string> files;
const EVP_CIPHER *cipher;
// true if --tls-ticket-key-cipher is used
bool cipher_given;
} ticket;
// Session cache related configurations
struct {
struct {
Address addr;
uint16_t port;
std::unique_ptr<char[]> host;
} memcached;
} session_cache;
// Dynamic record sizing configurations
struct {
size_t warmup_threshold;
ev_tstamp idle_timeout;
} dyn_rec;
// OCSP realted configurations
struct {
ev_tstamp update_interval;
std::unique_ptr<char[]> fetch_ocsp_response_file;
bool disabled;
} ocsp;
// Client verification configurations
struct {
// Path to file containing CA certificate solely used for client
// certificate validation
std::unique_ptr<char[]> cacert;
bool enabled;
} client_verify;
// Client private key and certificate used in backend connections.
struct {
std::unique_ptr<char[]> private_key_file;
std::unique_ptr<char[]> cert_file;
} client;
// The list of (private key file, certificate file) pair
std::vector<std::pair<std::string, std::string>> subcerts;
std::vector<AltSvc> altsvcs;
std::vector<std::pair<std::string, std::string>> add_request_headers;
std::vector<std::pair<std::string, std::string>> add_response_headers;
std::vector<unsigned char> alpn_prefs;
std::vector<LogFragment> accesslog_format;
std::vector<DownstreamAddrGroup> downstream_addr_groups;
std::vector<std::string> tls_ticket_key_files;
// list of supported NPN/ALPN protocol strings in the order of
// preference.
std::vector<std::string> npn_list;
// list of supported SSL/TLS protocol strings.
std::vector<std::string> tls_proto_list;
Address session_cache_memcached_addr;
Address tls_ticket_key_memcached_addr;
Router router;
HttpProxy downstream_http_proxy;
// obfuscated value used in "by" parameter of Forwarded header
// field.
std::string forwarded_by_obfuscated;
// obfuscated value used in "for" parameter of Forwarded header
// field. This is only used when user defined static obfuscated
// string is provided.
std::string forwarded_for_obfuscated;
std::string backend_tls_sni_name;
StringRef server_name;
std::chrono::seconds tls_session_timeout;
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;
ev_tstamp ocsp_update_interval;
ev_tstamp tls_ticket_key_memcached_interval;
// 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;
// Bit mask to disable SSL/TLS protocol versions. This will be
// passed to SSL_CTX_set_options().
long int tls_proto_mask;
std::string backend_sni_name;
std::chrono::seconds session_timeout;
std::unique_ptr<char[]> private_key_file;
std::unique_ptr<char[]> private_key_passwd;
std::unique_ptr<char[]> cert_file;
std::unique_ptr<char[]> dh_param_file;
std::unique_ptr<char[]> pid_file;
std::unique_ptr<char[]> conf_path;
std::unique_ptr<char[]> ciphers;
std::unique_ptr<char[]> cacert;
std::unique_ptr<char[]> http2_upstream_dump_request_header_file;
std::unique_ptr<char[]> http2_upstream_dump_response_header_file;
// Path to file containing CA certificate solely used for client
// certificate validation
std::unique_ptr<char[]> verify_client_cacert;
std::unique_ptr<char[]> client_private_key_file;
std::unique_ptr<char[]> client_cert_file;
std::unique_ptr<char[]> accesslog_file;
std::unique_ptr<char[]> errorlog_file;
std::unique_ptr<char[]> fetch_ocsp_response_file;
bool insecure;
};
struct HttpConfig {
struct {
// obfuscated value used in "by" parameter of Forwarded header
// field.
std::string by_obfuscated;
// obfuscated value used in "for" parameter of Forwarded header
// field. This is only used when user defined static obfuscated
// string is provided.
std::string for_obfuscated;
// bitwise-OR of one or more of shrpx_forwarded_param values.
uint32_t params;
// type of value recorded in "by" parameter of Forwarded header
// field.
shrpx_forwarded_node_type by_node_type;
// type of value recorded in "for" parameter of Forwarded header
// field.
shrpx_forwarded_node_type for_node_type;
bool strip_incoming;
} forwarded;
struct {
bool add;
bool strip_incoming;
} xff;
std::vector<AltSvc> altsvcs;
std::vector<std::pair<std::string, std::string>> add_request_headers;
std::vector<std::pair<std::string, std::string>> add_response_headers;
StringRef server_name;
size_t header_field_buffer;
size_t max_header_fields;
bool no_via;
bool no_location_rewrite;
bool no_host_rewrite;
};
struct Http2Config {
struct {
struct {
struct {
std::unique_ptr<char[]> request_header_file;
std::unique_ptr<char[]> response_header_file;
FILE *request_header;
FILE *response_header;
} dump;
bool frame_debug;
} debug;
nghttp2_option *option;
nghttp2_session_callbacks *callbacks;
size_t window_bits;
size_t connection_window_bits;
} upstream;
struct {
nghttp2_option *option;
nghttp2_session_callbacks *callbacks;
size_t window_bits;
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;
};
struct LoggingConfig {
struct {
std::vector<LogFragment> format;
std::unique_ptr<char[]> file;
// Send accesslog to syslog, ignoring accesslog_file.
bool syslog;
} access;
struct {
std::unique_ptr<char[]> file;
// Send errorlog to syslog, ignoring errorlog_file.
bool syslog;
} error;
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 {
Router router;
HttpProxy downstream_http_proxy;
HttpConfig http;
Http2Config http2;
TLSConfig tls;
LoggingConfig logging;
ConnectionConfig conn;
std::unique_ptr<char[]> pid_file;
std::unique_ptr<char[]> conf_path;
std::unique_ptr<char[]> user;
std::unique_ptr<char[]> session_cache_memcached_host;
std::unique_ptr<char[]> tls_ticket_key_memcached_host;
std::unique_ptr<char[]> mruby_file;
FILE *http2_upstream_dump_request_header;
FILE *http2_upstream_dump_response_header;
nghttp2_session_callbacks *http2_upstream_callbacks;
nghttp2_session_callbacks *http2_downstream_callbacks;
nghttp2_option *http2_option;
nghttp2_option *http2_client_option;
const EVP_CIPHER *tls_ticket_key_cipher;
char **original_argv;
char **argv;
char *cwd;
size_t num_worker;
size_t http2_max_concurrent_streams;
size_t http2_upstream_window_bits;
size_t http2_downstream_window_bits;
size_t http2_upstream_connection_window_bits;
size_t http2_downstream_connection_window_bits;
size_t http2_downstream_connections_per_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;
size_t header_field_buffer;
size_t max_header_fields;
// The index of catch-all group in downstream_addr_groups.
size_t downstream_addr_group_catch_all;
// Maximum number of retries when getting TLS ticket key from
// mamcached, due to network error.
size_t tls_ticket_key_memcached_max_retry;
// Maximum number of consecutive error from memcached, when this
// limit reached, TLS ticket is disabled.
size_t tls_ticket_key_memcached_max_fail;
// Bit mask to disable SSL/TLS protocol versions. This will be
// passed to SSL_CTX_set_options().
long int tls_proto_mask;
// downstream protocol; this will be determined by given options.
shrpx_proto downstream_proto;
// bitwise-OR of one or more of shrpx_forwarded_param values.
uint32_t forwarded_params;
// type of value recorded in "by" parameter of Forwarded header
// field.
shrpx_forwarded_node_type forwarded_by_node_type;
// type of value recorded in "for" parameter of Forwarded header
// field.
shrpx_forwarded_node_type forwarded_for_node_type;
int syslog_facility;
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;
// port in http proxy URI
uint16_t downstream_http_proxy_port;
uint16_t session_cache_memcached_port;
uint16_t tls_ticket_key_memcached_port;
bool verbose;
bool daemon;
bool verify_client;
bool http2_proxy;
bool http2_bridge;
bool client_proxy;
bool add_x_forwarded_for;
bool strip_incoming_x_forwarded_for;
bool strip_incoming_forwarded;
bool no_via;
bool upstream_no_tls;
bool downstream_no_tls;
// Send accesslog to syslog, ignoring accesslog_file.
bool accesslog_syslog;
// Send errorlog to syslog, ignoring errorlog_file.
bool errorlog_syslog;
bool client;
// true if --client or --client-proxy are enabled.
bool client_mode;
bool insecure;
bool backend_ipv4;
bool backend_ipv6;
bool http2_no_cookie_crumbling;
bool upstream_frame_debug;
bool no_location_rewrite;
bool no_host_rewrite;
bool no_server_push;
// true if host contains UNIX domain socket path
bool host_unix;
bool no_ocsp;
// true if --tls-ticket-key-cipher is used
bool tls_ticket_key_cipher_given;
bool accept_proxy_protocol;
size_t tls_dyn_rec_warmup_threshold;
ev_tstamp tls_dyn_rec_idle_timeout;
};
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);
@ -385,7 +385,7 @@ void ConnectionHandler::disable_acceptor() {
}
}
void ConnectionHandler::disable_acceptor_temporary(ev_tstamp t) {
void ConnectionHandler::sleep_acceptor(ev_tstamp t) {
if (t == 0. || ev_is_active(&disable_acceptor_timer_)) {
return;
}
@ -450,7 +450,7 @@ int ConnectionHandler::start_ocsp_update(const char *cert_file) {
assert(!ev_is_active(&ocsp_.chldev));
char *const argv[] = {
const_cast<char *>(get_config()->fetch_ocsp_response_file.get()),
const_cast<char *>(get_config()->tls.ocsp.fetch_ocsp_response_file.get()),
const_cast<char *>(cert_file), nullptr};
char *const envp[] = {nullptr};
@ -634,7 +634,7 @@ void ConnectionHandler::proceed_next_cert_ocsp() {
if (ocsp_.next == all_ssl_ctx_.size()) {
ocsp_.next = 0;
// We have updated all ocsp response, and schedule next update.
ev_timer_set(&ocsp_timer_, get_config()->ocsp_update_interval, 0.);
ev_timer_set(&ocsp_timer_, get_config()->tls.ocsp.update_interval, 0.);
ev_timer_start(loop_, &ocsp_timer_);
return;
}
@ -673,7 +673,7 @@ ConnectionHandler::get_tls_ticket_key_memcached_dispatcher() const {
void ConnectionHandler::on_tls_ticket_key_network_error(ev_timer *w) {
if (++tls_ticket_key_memcached_get_retry_count_ >=
get_config()->tls_ticket_key_memcached_max_retry) {
get_config()->tls.ticket.memcached.max_retry) {
LOG(WARN) << "Memcached: tls ticket get retry all failed "
<< tls_ticket_key_memcached_get_retry_count_ << " times.";
@ -697,7 +697,7 @@ void ConnectionHandler::on_tls_ticket_key_not_found(ev_timer *w) {
tls_ticket_key_memcached_get_retry_count_ = 0;
if (++tls_ticket_key_memcached_fail_count_ >=
get_config()->tls_ticket_key_memcached_max_fail) {
get_config()->tls.ticket.memcached.max_fail) {
LOG(WARN) << "Memcached: could not get tls ticket; disable tls ticket";
tls_ticket_key_memcached_fail_count_ = 0;
@ -742,7 +742,7 @@ void ConnectionHandler::on_tls_ticket_key_get_success(
void ConnectionHandler::schedule_next_tls_ticket_key_memcached_get(
ev_timer *w) {
ev_timer_set(w, get_config()->tls_ticket_key_memcached_interval, 0.);
ev_timer_set(w, get_config()->tls.ticket.memcached.interval, 0.);
ev_timer_start(loop_, w);
}

View File

@ -98,7 +98,7 @@ public:
AcceptHandler *get_acceptor6() const;
void enable_acceptor();
void disable_acceptor();
void disable_acceptor_temporary(ev_tstamp t);
void sleep_acceptor(ev_tstamp t);
void accept_pending_connection();
void graceful_shutdown_worker();
void set_graceful_shutdown(bool f);

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

@ -44,10 +44,10 @@ std::string create_error_html(unsigned int status_code) {
res += "</title><body><h1>";
res += status;
res += "</h1><footer>";
const auto &server_name = get_config()->server_name;
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

@ -256,8 +256,11 @@ int Http2DownstreamConnection::push_request_headers() {
const auto &req = downstream_->request();
auto &httpconf = get_config()->http;
auto &http2conf = get_config()->http2;
auto no_host_rewrite =
get_config()->no_host_rewrite || get_config()->http2_proxy ||
httpconf.no_host_rewrite || get_config()->http2_proxy ||
get_config()->client_proxy || req.method == HTTP_CONNECT;
// http2session_ has already in CONNECTED state, so we can get
@ -265,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.
@ -278,7 +281,7 @@ int Http2DownstreamConnection::push_request_headers() {
downstream_->set_request_downstream_host(authority.str());
size_t num_cookies = 0;
if (!get_config()->http2_no_cookie_crumbling) {
if (!http2conf.no_cookie_crumbling) {
num_cookies = downstream_->count_crumble_request_cookie();
}
@ -294,7 +297,7 @@ int Http2DownstreamConnection::push_request_headers() {
// 9. forwarded (optional)
auto nva = std::vector<nghttp2_nv>();
nva.reserve(req.fs.headers().size() + 9 + num_cookies +
get_config()->add_request_headers.size());
httpconf.add_request_headers.size());
nva.push_back(
http2::make_nv_lc_nocopy(":method", http2::to_method_string(req.method)));
@ -328,7 +331,7 @@ int Http2DownstreamConnection::push_request_headers() {
chunked_encoding = true;
}
if (!get_config()->http2_no_cookie_crumbling) {
if (!http2conf.no_cookie_crumbling) {
downstream_->crumble_request_cookie(nva);
}
@ -337,12 +340,13 @@ int Http2DownstreamConnection::push_request_headers() {
std::string forwarded_value;
auto fwd = get_config()->strip_incoming_forwarded
? nullptr
: req.fs.header(http2::HD_FORWARDED);
auto &fwdconf = httpconf.forwarded;
if (get_config()->forwarded_params) {
auto params = get_config()->forwarded_params;
auto fwd =
fwdconf.strip_incoming ? nullptr : req.fs.header(http2::HD_FORWARDED);
if (fwdconf.params) {
auto params = fwdconf.params;
if (get_config()->http2_proxy || get_config()->client_proxy ||
req.method == HTTP_CONNECT) {
@ -370,12 +374,14 @@ int Http2DownstreamConnection::push_request_headers() {
forwarded_value = fwd->value;
}
std::string xff_value;
auto xff = get_config()->strip_incoming_x_forwarded_for
? nullptr
: req.fs.header(http2::HD_X_FORWARDED_FOR);
auto &xffconf = httpconf.xff;
if (get_config()->add_x_forwarded_for) {
auto xff = xffconf.strip_incoming ? nullptr
: req.fs.header(http2::HD_X_FORWARDED_FOR);
std::string xff_value;
if (xffconf.add) {
if (xff) {
xff_value = (*xff).value;
xff_value += ", ";
@ -394,7 +400,7 @@ int Http2DownstreamConnection::push_request_headers() {
std::string via_value;
auto via = req.fs.header(http2::HD_VIA);
if (get_config()->no_via) {
if (httpconf.no_via) {
if (via) {
nva.push_back(http2::make_nv_ls_nocopy("via", (*via).value));
}
@ -415,7 +421,7 @@ int Http2DownstreamConnection::push_request_headers() {
nva.push_back(http2::make_nv_ll("te", "trailers"));
}
for (auto &p : get_config()->add_request_headers) {
for (auto &p : httpconf.add_request_headers) {
nva.push_back(http2::make_nv_nocopy(p.first, p.second));
}

View File

@ -146,10 +146,10 @@ 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,
timeoutcb, this, get_config()->tls_dyn_rec_warmup_threshold,
get_config()->tls_dyn_rec_idle_timeout),
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),
session_(nullptr), data_pending_(nullptr), data_pendinglen_(0),
addr_idx_(0), group_(group), index_(idx), state_(DISCONNECTED),
@ -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()) {
@ -331,8 +331,8 @@ int Http2Session::initiate_connection() {
conn_.set_ssl(ssl);
}
StringRef sni_name = !get_config()->backend_tls_sni_name.empty()
? get_config()->backend_tls_sni_name
StringRef sni_name = !get_config()->tls.backend_sni_name.empty()
? get_config()->tls.backend_sni_name
: downstream_addr.host;
if (!util::numeric_host(sni_name.c_str())) {
@ -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());
@ -1309,9 +1309,10 @@ int Http2Session::connection_made() {
}
}
rv = nghttp2_session_client_new2(&session_,
get_config()->http2_downstream_callbacks,
this, get_config()->http2_client_option);
auto &http2conf = get_config()->http2;
rv = nghttp2_session_client_new2(&session_, http2conf.downstream.callbacks,
this, http2conf.downstream.option);
if (rv != 0) {
return -1;
@ -1322,12 +1323,12 @@ int Http2Session::connection_made() {
std::array<nghttp2_settings_entry, 3> entry;
size_t nentry = 2;
entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
entry[0].value = get_config()->http2_max_concurrent_streams;
entry[0].value = http2conf.max_concurrent_streams;
entry[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
entry[1].value = (1 << get_config()->http2_downstream_window_bits) - 1;
entry[1].value = (1 << http2conf.downstream.window_bits) - 1;
if (get_config()->no_server_push || get_config()->http2_proxy ||
if (http2conf.no_server_push || get_config()->http2_proxy ||
get_config()->client_proxy) {
entry[nentry].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
entry[nentry].value = 0;
@ -1340,17 +1341,17 @@ int Http2Session::connection_made() {
return -1;
}
if (get_config()->http2_downstream_connection_window_bits > 16) {
int32_t delta =
(1 << get_config()->http2_downstream_connection_window_bits) - 1 -
NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
auto connection_window_bits = http2conf.downstream.connection_window_bits;
if (connection_window_bits > 16) {
int32_t delta = (1 << connection_window_bits) - 1 -
NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0, delta);
if (rv != 0) {
return -1;
}
}
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) {
@ -1718,7 +1719,7 @@ int Http2Session::tls_handshake() {
SSLOG(INFO, this) << "SSL/TLS handshake completed";
}
if (!get_config()->downstream_no_tls && !get_config()->insecure &&
if (!get_config()->conn.downstream.no_tls && !get_config()->tls.insecure &&
check_cert() != 0) {
return -1;
}

View File

@ -154,7 +154,7 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen, uint8_t flags,
void *user_data) {
if (get_config()->upstream_frame_debug) {
if (get_config()->http2.upstream.debug.frame_debug) {
verbose_on_header_callback(session, frame, name, namelen, value, valuelen,
flags, user_data);
}
@ -170,9 +170,11 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
auto &req = downstream->request();
auto &httpconf = get_config()->http;
if (req.fs.buffer_size() + namelen + valuelen >
get_config()->header_field_buffer ||
req.fs.num_fields() >= get_config()->max_header_fields) {
httpconf.header_field_buffer ||
req.fs.num_fields() >= httpconf.max_header_fields) {
if (downstream->get_response_state() == Downstream::MSG_COMPLETE) {
return 0;
}
@ -263,8 +265,10 @@ int Http2Upstream::on_request_headers(Downstream *downstream,
<< downstream->get_stream_id() << "\n" << ss.str();
}
if (get_config()->http2_upstream_dump_request_header) {
http2::dump_nv(get_config()->http2_upstream_dump_request_header, nva);
auto &dump = get_config()->http2.upstream.debug.dump;
if (dump.request_header) {
http2::dump_nv(dump.request_header, nva);
}
auto content_length = req.fs.header(http2::HD_CONTENT_LENGTH);
@ -398,7 +402,7 @@ void Http2Upstream::initiate_downstream(Downstream *downstream) {
namespace {
int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame,
void *user_data) {
if (get_config()->upstream_frame_debug) {
if (get_config()->http2.upstream.debug.frame_debug) {
verbose_on_frame_recv_callback(session, frame, user_data);
}
auto upstream = static_cast<Http2Upstream *>(user_data);
@ -500,7 +504,7 @@ int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
namespace {
int on_frame_send_callback(nghttp2_session *session, const nghttp2_frame *frame,
void *user_data) {
if (get_config()->upstream_frame_debug) {
if (get_config()->http2.upstream.debug.frame_debug) {
verbose_on_frame_send_callback(session, frame, user_data);
}
auto upstream = static_cast<Http2Upstream *>(user_data);
@ -848,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()),
@ -860,9 +864,10 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
int rv;
rv = nghttp2_session_server_new2(&session_,
get_config()->http2_upstream_callbacks, this,
get_config()->http2_option);
auto &http2conf = get_config()->http2;
rv = nghttp2_session_server_new2(&session_, http2conf.upstream.callbacks,
this, http2conf.upstream.option);
assert(rv == 0);
@ -871,10 +876,10 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
// TODO Maybe call from outside?
std::array<nghttp2_settings_entry, 2> entry;
entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
entry[0].value = get_config()->http2_max_concurrent_streams;
entry[0].value = http2conf.max_concurrent_streams;
entry[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
entry[1].value = (1 << get_config()->http2_upstream_window_bits) - 1;
entry[1].value = (1 << http2conf.upstream.window_bits) - 1;
rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry.data(),
entry.size());
@ -883,9 +888,9 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
<< nghttp2_strerror(rv);
}
if (get_config()->http2_upstream_connection_window_bits > 16) {
int32_t delta = (1 << get_config()->http2_upstream_connection_window_bits) -
1 - NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
if (http2conf.upstream.connection_window_bits > 16) {
int32_t delta = (1 << http2conf.upstream.connection_window_bits) - 1 -
NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0, delta);
if (rv != 0) {
@ -909,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();
}
@ -1337,7 +1342,7 @@ int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body,
if (!resp.fs.header(http2::HD_SERVER)) {
nva.push_back(
http2::make_nv_ls_nocopy("server", get_config()->server_name));
http2::make_nv_ls_nocopy("server", get_config()->http.server_name));
}
rv = nghttp2_submit_response(session_, downstream->get_stream_id(),
@ -1386,7 +1391,7 @@ int Http2Upstream::error_reply(Downstream *downstream,
: http2::make_nv_ls(":status",
(status_code_str = util::utos(status_code))),
http2::make_nv_ll("content-type", "text/html; charset=UTF-8"),
http2::make_nv_ls_nocopy("server", get_config()->server_name),
http2::make_nv_ls_nocopy("server", get_config()->http.server_name),
http2::make_nv_ls("content-length", content_length),
http2::make_nv_ls("date", lgconf->time_http_str));
@ -1442,8 +1447,10 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
}
}
auto &httpconf = get_config()->http;
if (!get_config()->http2_proxy && !get_config()->client_proxy &&
!get_config()->no_location_rewrite) {
!httpconf.no_location_rewrite) {
downstream->rewrite_location_response_header(req.scheme);
}
@ -1470,7 +1477,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
// 4 means :status and possible server, via and x-http2-push header
// field.
nva.reserve(resp.fs.headers().size() + 4 +
get_config()->add_response_headers.size());
httpconf.add_response_headers.size());
std::string via_value;
std::string response_status;
@ -1506,8 +1513,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
http2::copy_headers_to_nva_nocopy(nva, resp.fs.headers());
if (!get_config()->http2_proxy && !get_config()->client_proxy) {
nva.push_back(
http2::make_nv_ls_nocopy("server", get_config()->server_name));
nva.push_back(http2::make_nv_ls_nocopy("server", httpconf.server_name));
} else {
auto server = resp.fs.header(http2::HD_SERVER);
if (server) {
@ -1516,7 +1522,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
}
auto via = resp.fs.header(http2::HD_VIA);
if (get_config()->no_via) {
if (httpconf.no_via) {
if (via) {
nva.push_back(http2::make_nv_ls_nocopy("via", (*via).value));
}
@ -1530,7 +1536,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
nva.push_back(http2::make_nv_ls("via", via_value));
}
for (auto &p : get_config()->add_response_headers) {
for (auto &p : httpconf.add_response_headers) {
nva.push_back(http2::make_nv_nocopy(p.first, p.second));
}
@ -1544,9 +1550,11 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
log_response_headers(downstream, nva);
}
if (get_config()->http2_upstream_dump_response_header) {
http2::dump_nv(get_config()->http2_upstream_dump_response_header,
nva.data(), nva.size());
auto &http2conf = get_config()->http2;
if (http2conf.upstream.debug.dump.response_header) {
http2::dump_nv(http2conf.upstream.debug.dump.response_header, nva.data(),
nva.size());
}
nghttp2_data_provider data_prd;
@ -1574,7 +1582,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
// * We requires GET or POST for associated resource. Probably we
// don't want to push for HEAD request. Not sure other methods
// are also eligible for push.
if (!get_config()->no_server_push &&
if (!http2conf.no_server_push &&
nghttp2_session_get_remote_settings(session_,
NGHTTP2_SETTINGS_ENABLE_PUSH) == 1 &&
!get_config()->http2_proxy && !get_config()->client_proxy &&
@ -1875,7 +1883,7 @@ int Http2Upstream::submit_push_promise(const std::string &scheme,
}
bool Http2Upstream::push_enabled() const {
return !(get_config()->no_server_push ||
return !(get_config()->http2.no_server_push ||
nghttp2_session_get_remote_settings(
session_, NGHTTP2_SETTINGS_ENABLE_PUSH) == 0 ||
get_config()->http2_proxy || get_config()->client_proxy);

View File

@ -113,10 +113,11 @@ 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,
readcb, timeoutcb, this, get_config()->tls_dyn_rec_warmup_threshold,
get_config()->tls_dyn_rec_idle_timeout),
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),
connected_(false) {}
@ -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,16 +214,20 @@ 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;
auto &httpconf = get_config()->http;
// For HTTP/1.0 request, there is no authority in request. In that
// case, we use backend server's host nonetheless.
auto authority = StringRef(downstream_hostport);
auto no_host_rewrite = get_config()->no_host_rewrite ||
auto no_host_rewrite = httpconf.no_host_rewrite ||
get_config()->http2_proxy ||
get_config()->client_proxy || connect_method;
@ -296,11 +303,13 @@ int HttpDownstreamConnection::push_request_headers() {
auto upstream = downstream_->get_upstream();
auto handler = upstream->get_client_handler();
auto fwd = get_config()->strip_incoming_forwarded
? nullptr
: req.fs.header(http2::HD_FORWARDED);
if (get_config()->forwarded_params) {
auto params = get_config()->forwarded_params;
auto &fwdconf = httpconf.forwarded;
auto fwd =
fwdconf.strip_incoming ? nullptr : req.fs.header(http2::HD_FORWARDED);
if (fwdconf.params) {
auto params = fwdconf.params;
if (get_config()->http2_proxy || get_config()->client_proxy ||
connect_method) {
@ -328,11 +337,12 @@ int HttpDownstreamConnection::push_request_headers() {
buf->append("\r\n");
}
auto xff = get_config()->strip_incoming_x_forwarded_for
? nullptr
: req.fs.header(http2::HD_X_FORWARDED_FOR);
auto &xffconf = httpconf.xff;
if (get_config()->add_x_forwarded_for) {
auto xff = xffconf.strip_incoming ? nullptr
: req.fs.header(http2::HD_X_FORWARDED_FOR);
if (xffconf.add) {
buf->append("X-Forwarded-For: ");
if (xff) {
buf->append((*xff).value);
@ -353,7 +363,7 @@ int HttpDownstreamConnection::push_request_headers() {
buf->append("\r\n");
}
auto via = req.fs.header(http2::HD_VIA);
if (get_config()->no_via) {
if (httpconf.no_via) {
if (via) {
buf->append("Via: ");
buf->append((*via).value);
@ -369,7 +379,7 @@ int HttpDownstreamConnection::push_request_headers() {
buf->append("\r\n");
}
for (auto &p : get_config()->add_request_headers) {
for (auto &p : httpconf.add_request_headers) {
buf->append(p.first);
buf->append(": ");
buf->append(p.second);
@ -474,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);
@ -489,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

@ -88,7 +88,7 @@ int htp_uricb(http_parser *htp, const char *data, size_t len) {
// We happen to have the same value for method token.
req.method = htp->method;
if (req.fs.buffer_size() + len > get_config()->header_field_buffer) {
if (req.fs.buffer_size() + len > get_config()->http.header_field_buffer) {
if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream) << "Too large URI size="
<< req.fs.buffer_size() + len;
@ -115,8 +115,9 @@ int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) {
auto upstream = static_cast<HttpsUpstream *>(htp->data);
auto downstream = upstream->get_downstream();
auto &req = downstream->request();
auto &httpconf = get_config()->http;
if (req.fs.buffer_size() + len > get_config()->header_field_buffer) {
if (req.fs.buffer_size() + len > httpconf.header_field_buffer) {
if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream) << "Too large header block size="
<< req.fs.buffer_size() + len;
@ -130,7 +131,7 @@ int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) {
if (req.fs.header_key_prev()) {
req.fs.append_last_header_key(data, len);
} else {
if (req.fs.num_fields() >= get_config()->max_header_fields) {
if (req.fs.num_fields() >= httpconf.max_header_fields) {
if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream)
<< "Too many header field num=" << req.fs.num_fields() + 1;
@ -146,7 +147,7 @@ int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) {
if (req.fs.trailer_key_prev()) {
req.fs.append_last_trailer_key(data, len);
} else {
if (req.fs.num_fields() >= get_config()->max_header_fields) {
if (req.fs.num_fields() >= httpconf.max_header_fields) {
if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream)
<< "Too many header field num=" << req.fs.num_fields() + 1;
@ -166,7 +167,7 @@ int htp_hdr_valcb(http_parser *htp, const char *data, size_t len) {
auto downstream = upstream->get_downstream();
auto &req = downstream->request();
if (req.fs.buffer_size() + len > get_config()->header_field_buffer) {
if (req.fs.buffer_size() + len > get_config()->http.header_field_buffer) {
if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream) << "Too large header block size="
<< req.fs.buffer_size() + len;
@ -802,7 +803,7 @@ int HttpsUpstream::send_reply(Downstream *downstream, const uint8_t *body,
if (!resp.fs.header(http2::HD_SERVER)) {
output->append("Server: ");
output->append(get_config()->server_name);
output->append(get_config()->http.server_name);
output->append("\r\n");
}
@ -839,8 +840,7 @@ void HttpsUpstream::error_reply(unsigned int status_code) {
auto status_str = http2::get_status_string(status_code);
output->append(status_str);
output->append("\r\nServer: ");
const auto &server_name = get_config()->server_name;
output->append(server_name);
output->append(get_config()->http.server_name);
output->append("\r\nContent-Length: ");
auto cl = util::utos(html.size());
output->append(cl);
@ -927,8 +927,10 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
buf->append(http2::get_status_string(resp.http_status));
buf->append("\r\n");
auto &httpconf = get_config()->http;
if (!get_config()->http2_proxy && !get_config()->client_proxy &&
!get_config()->no_location_rewrite) {
!httpconf.no_location_rewrite) {
downstream->rewrite_location_response_header(
get_client_handler()->get_upstream_scheme());
}
@ -984,10 +986,10 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
if (!resp.fs.header(http2::HD_ALT_SVC)) {
// We won't change or alter alt-svc from backend for now
if (!get_config()->altsvcs.empty()) {
if (!httpconf.altsvcs.empty()) {
buf->append("Alt-Svc: ");
auto &altsvcs = get_config()->altsvcs;
auto &altsvcs = httpconf.altsvcs;
write_altsvc(buf, altsvcs[0]);
for (size_t i = 1; i < altsvcs.size(); ++i) {
buf->append(", ");
@ -999,7 +1001,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
if (!get_config()->http2_proxy && !get_config()->client_proxy) {
buf->append("Server: ");
buf->append(get_config()->server_name);
buf->append(httpconf.server_name);
buf->append("\r\n");
} else {
auto server = resp.fs.header(http2::HD_SERVER);
@ -1011,7 +1013,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
}
auto via = resp.fs.header(http2::HD_VIA);
if (get_config()->no_via) {
if (httpconf.no_via) {
if (via) {
buf->append("Via: ");
buf->append((*via).value);
@ -1028,7 +1030,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
buf->append("\r\n");
}
for (auto &p : get_config()->add_response_headers) {
for (auto &p : httpconf.add_response_headers) {
buf->append(p.first);
buf->append(": ");
buf->append(p.second);

View File

@ -109,12 +109,14 @@ Log::~Log() {
auto lgconf = log_config();
auto &errorconf = get_config()->logging.error;
if (!log_enabled(severity_) ||
(lgconf->errorlog_fd == -1 && !get_config()->errorlog_syslog)) {
(lgconf->errorlog_fd == -1 && !errorconf.syslog)) {
return;
}
if (get_config()->errorlog_syslog) {
if (errorconf.syslog) {
if (severity_ == NOTICE) {
syslog(severity_to_syslog_level(severity_), "[%s] %s",
SEVERITY_STR[severity_], stream_.str().c_str());
@ -219,8 +221,9 @@ std::pair<OutputIterator, size_t> copy_hex_low(const uint8_t *src,
void upstream_accesslog(const std::vector<LogFragment> &lfv,
const LogSpec &lgsp) {
auto lgconf = log_config();
auto &accessconf = get_config()->logging.access;
if (lgconf->accesslog_fd == -1 && !get_config()->accesslog_syslog) {
if (lgconf->accesslog_fd == -1 && !accessconf.syslog) {
return;
}
@ -360,7 +363,7 @@ void upstream_accesslog(const std::vector<LogFragment> &lfv,
*p = '\0';
if (get_config()->accesslog_syslog) {
if (accessconf.syslog) {
syslog(LOG_INFO, "%s", buf);
return;
@ -379,29 +382,27 @@ int reopen_log_files() {
int new_errorlog_fd = -1;
auto lgconf = log_config();
auto &accessconf = get_config()->logging.access;
auto &errorconf = get_config()->logging.error;
if (!get_config()->accesslog_syslog && get_config()->accesslog_file) {
new_accesslog_fd = util::open_log_file(get_config()->accesslog_file.get());
if (!accessconf.syslog && accessconf.file) {
new_accesslog_fd = util::open_log_file(accessconf.file.get());
if (new_accesslog_fd == -1) {
LOG(ERROR) << "Failed to open accesslog file "
<< get_config()->accesslog_file.get();
LOG(ERROR) << "Failed to open accesslog file " << accessconf.file.get();
res = -1;
}
}
if (!get_config()->errorlog_syslog && get_config()->errorlog_file) {
new_errorlog_fd = util::open_log_file(get_config()->errorlog_file.get());
if (!errorconf.syslog && errorconf.file) {
new_errorlog_fd = util::open_log_file(errorconf.file.get());
if (new_errorlog_fd == -1) {
if (lgconf->errorlog_fd != -1) {
LOG(ERROR) << "Failed to open errorlog file "
<< get_config()->errorlog_file.get();
LOG(ERROR) << "Failed to open errorlog file " << errorconf.file.get();
} else {
std::cerr << "Failed to open errorlog file "
<< get_config()->errorlog_file.get() << std::endl;
std::cerr << "Failed to open errorlog file " << errorconf.file.get()
<< std::endl;
}
res = -1;
@ -444,8 +445,9 @@ void log_chld(pid_t pid, int rstatus, const char *msg) {
void redirect_stderr_to_errorlog() {
auto lgconf = log_config();
auto &errorconf = get_config()->logging.error;
if (get_config()->errorlog_syslog || lgconf->errorlog_fd == -1) {
if (errorconf.syslog || lgconf->errorlog_fd == -1) {
return;
}

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

@ -173,10 +173,12 @@ void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type,
header_buffer += strlen(nv[i]) + strlen(nv[i + 1]);
}
auto &httpconf = get_config()->http;
// spdy does not define usage of trailer fields, and we ignores
// them.
if (header_buffer > get_config()->header_field_buffer ||
num_headers > get_config()->max_header_fields) {
if (header_buffer > httpconf.header_field_buffer ||
num_headers > httpconf.max_header_fields) {
upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR);
return;
}
@ -370,31 +372,33 @@ void on_data_chunk_recv_callback(spdylay_session *session, uint8_t flags,
return;
}
auto &http2conf = get_config()->http2;
// If connection-level window control is not enabled (e.g,
// spdy/3), spdylay_session_get_recv_data_length() is always
// returns 0.
if (spdylay_session_get_recv_data_length(session) >
std::max(SPDYLAY_INITIAL_WINDOW_SIZE,
1 << get_config()->http2_upstream_connection_window_bits)) {
1 << http2conf.upstream.connection_window_bits)) {
if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream)
<< "Flow control error on connection: "
<< "recv_window_size="
<< spdylay_session_get_recv_data_length(session) << ", window_size="
<< (1 << get_config()->http2_upstream_connection_window_bits);
ULOG(INFO, upstream) << "Flow control error on connection: "
<< "recv_window_size="
<< spdylay_session_get_recv_data_length(session)
<< ", window_size="
<< (1 << http2conf.upstream.connection_window_bits);
}
spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
return;
}
if (spdylay_session_get_stream_recv_data_length(session, stream_id) >
std::max(SPDYLAY_INITIAL_WINDOW_SIZE,
1 << get_config()->http2_upstream_window_bits)) {
1 << http2conf.upstream.window_bits)) {
if (LOG_ENABLED(INFO)) {
ULOG(INFO, upstream) << "Flow control error: recv_window_size="
<< spdylay_session_get_stream_recv_data_length(
session, stream_id)
<< ", initial_window_size="
<< (1 << get_config()->http2_upstream_window_bits);
<< (1 << http2conf.upstream.window_bits);
}
upstream->rst_stream(downstream, SPDYLAY_FLOW_CONTROL_ERROR);
return;
@ -490,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) {
@ -518,10 +522,12 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
&max_buffer, sizeof(max_buffer));
assert(rv == 0);
auto &http2conf = get_config()->http2;
if (version >= SPDYLAY_PROTO_SPDY3) {
int val = 1;
flow_control_ = true;
initial_window_size_ = 1 << get_config()->http2_upstream_window_bits;
initial_window_size_ = 1 << http2conf.upstream.window_bits;
rv = spdylay_session_set_option(
session_, SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE2, &val, sizeof(val));
assert(rv == 0);
@ -532,7 +538,7 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
// TODO Maybe call from outside?
std::array<spdylay_settings_entry, 2> entry;
entry[0].settings_id = SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS;
entry[0].value = get_config()->http2_max_concurrent_streams;
entry[0].value = http2conf.max_concurrent_streams;
entry[0].flags = SPDYLAY_ID_FLAG_SETTINGS_NONE;
entry[1].settings_id = SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE;
@ -544,15 +550,15 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
assert(rv == 0);
if (version >= SPDYLAY_PROTO_SPDY3_1 &&
get_config()->http2_upstream_connection_window_bits > 16) {
int32_t delta = (1 << get_config()->http2_upstream_connection_window_bits) -
http2conf.upstream.connection_window_bits > 16) {
int32_t delta = (1 << http2conf.upstream.connection_window_bits) -
SPDYLAY_INITIAL_WINDOW_SIZE;
rv = spdylay_submit_window_update(session_, 0, delta);
assert(rv == 0);
}
handler_->reset_upstream_read_timeout(
get_config()->http2_upstream_read_timeout);
get_config()->conn.upstream.timeout.http2_read);
handler_->signal_write();
}
@ -875,7 +881,7 @@ int SpdyUpstream::send_reply(Downstream *downstream, const uint8_t *body,
if (!resp.fs.header(http2::HD_SERVER)) {
nva.push_back("server");
nva.push_back(get_config()->server_name.c_str());
nva.push_back(get_config()->http.server_name.c_str());
}
nva.push_back(nullptr);
@ -919,7 +925,7 @@ int SpdyUpstream::error_reply(Downstream *downstream,
std::string status_string = http2::get_status_string(status_code);
const char *nv[] = {":status", status_string.c_str(), ":version", "http/1.1",
"content-type", "text/html; charset=UTF-8", "server",
get_config()->server_name.c_str(), "content-length",
get_config()->http.server_name.c_str(), "content-length",
content_length.c_str(), "date",
lgconf->time_http_str.c_str(), nullptr};
@ -997,15 +1003,17 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
DLOG(INFO, downstream) << "HTTP response header completed";
}
auto &httpconf = get_config()->http;
if (!get_config()->http2_proxy && !get_config()->client_proxy &&
!get_config()->no_location_rewrite) {
!httpconf.no_location_rewrite) {
downstream->rewrite_location_response_header(req.scheme);
}
// 8 means server, :status, :version and possible via header field.
auto nv = make_unique<const char *[]>(
resp.fs.headers().size() * 2 + 8 +
get_config()->add_response_headers.size() * 2 + 1);
auto nv =
make_unique<const char *[]>(resp.fs.headers().size() * 2 + 8 +
httpconf.add_response_headers.size() * 2 + 1);
size_t hdidx = 0;
std::string via_value;
@ -1034,7 +1042,7 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
if (!get_config()->http2_proxy && !get_config()->client_proxy) {
nv[hdidx++] = "server";
nv[hdidx++] = get_config()->server_name.c_str();
nv[hdidx++] = httpconf.server_name.c_str();
} else {
auto server = resp.fs.header(http2::HD_SERVER);
if (server) {
@ -1044,7 +1052,7 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
}
auto via = resp.fs.header(http2::HD_VIA);
if (get_config()->no_via) {
if (httpconf.no_via) {
if (via) {
nv[hdidx++] = "via";
nv[hdidx++] = via->value.c_str();
@ -1060,7 +1068,7 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
nv[hdidx++] = via_value.c_str();
}
for (auto &p : get_config()->add_response_headers) {
for (auto &p : httpconf.add_response_headers) {
nv[hdidx++] = p.first.c_str();
nv[hdidx++] = p.second.c_str();
}

View File

@ -70,7 +70,7 @@ namespace ssl {
namespace {
int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
void *arg) {
auto &prefs = get_config()->alpn_prefs;
auto &prefs = get_config()->tls.alpn_prefs;
*data = prefs.data();
*len = prefs.size();
return SSL_TLSEXT_ERR_OK;
@ -124,13 +124,13 @@ set_alpn_prefs(const std::vector<std::string> &protos) {
namespace {
int ssl_pem_passwd_cb(char *buf, int size, int rwflag, void *user_data) {
auto config = static_cast<Config *>(user_data);
int len = (int)strlen(config->private_key_passwd.get());
int len = (int)strlen(config->tls.private_key_passwd.get());
if (size < len + 1) {
LOG(ERROR) << "ssl_pem_passwd_cb: buf is too small " << size;
return 0;
}
// Copy string including last '\0'.
memcpy(buf, config->private_key_passwd.get(), len + 1);
memcpy(buf, config->tls.private_key_passwd.get(), len + 1);
return len;
}
} // namespace
@ -346,7 +346,7 @@ int ticket_key_cb(SSL *ssl, unsigned char *key_name, unsigned char *iv,
std::copy(std::begin(key.data.name), std::end(key.data.name), key_name);
EVP_EncryptInit_ex(ctx, get_config()->tls_ticket_key_cipher, nullptr,
EVP_EncryptInit_ex(ctx, get_config()->tls.ticket.cipher, nullptr,
key.data.enc_key.data(), iv);
HMAC_Init_ex(hctx, key.data.hmac_key.data(), key.hmac_keylen, key.hmac,
nullptr);
@ -411,7 +411,7 @@ int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
// We assume that get_config()->npn_list contains ALPN protocol
// identifier sorted by preference order. So we just break when we
// found the first overlap.
for (const auto &target_proto_id : get_config()->npn_list) {
for (const auto &target_proto_id : get_config()->tls.npn_list) {
for (auto p = in, end = in + inlen; p < end;) {
auto proto_id = p + 1;
auto proto_len = *p;
@ -477,22 +477,24 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_SINGLE_ECDH_USE |
SSL_OP_SINGLE_DH_USE | SSL_OP_CIPHER_SERVER_PREFERENCE;
SSL_CTX_set_options(ssl_ctx, ssl_opts | get_config()->tls_proto_mask);
auto &tlsconf = get_config()->tls;
SSL_CTX_set_options(ssl_ctx, ssl_opts | tlsconf.tls_proto_mask);
const unsigned char sid_ctx[] = "shrpx";
SSL_CTX_set_session_id_context(ssl_ctx, sid_ctx, sizeof(sid_ctx) - 1);
SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_SERVER);
if (get_config()->session_cache_memcached_host) {
if (tlsconf.session_cache.memcached.host) {
SSL_CTX_sess_set_new_cb(ssl_ctx, tls_session_new_cb);
SSL_CTX_sess_set_get_cb(ssl_ctx, tls_session_get_cb);
}
SSL_CTX_set_timeout(ssl_ctx, get_config()->tls_session_timeout.count());
SSL_CTX_set_timeout(ssl_ctx, tlsconf.session_timeout.count());
const char *ciphers;
if (get_config()->ciphers) {
ciphers = get_config()->ciphers.get();
if (tlsconf.ciphers) {
ciphers = tlsconf.ciphers.get();
} else {
ciphers = nghttp2::ssl::DEFAULT_CIPHER_LIST;
}
@ -525,9 +527,9 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file
#endif // OPENSSL_NO_EC
if (get_config()->dh_param_file) {
if (tlsconf.dh_param_file) {
// Read DH parameters from file
auto bio = BIO_new_file(get_config()->dh_param_file.get(), "r");
auto bio = BIO_new_file(tlsconf.dh_param_file.get(), "r");
if (bio == nullptr) {
LOG(FATAL) << "BIO_new_file() failed: "
<< ERR_error_string(ERR_get_error(), nullptr);
@ -546,7 +548,7 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
if (get_config()->private_key_passwd) {
if (tlsconf.private_key_passwd) {
SSL_CTX_set_default_passwd_cb(ssl_ctx, ssl_pem_passwd_cb);
SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, (void *)get_config());
}
@ -576,14 +578,13 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file
<< ERR_error_string(ERR_get_error(), nullptr);
DIE();
}
if (get_config()->verify_client) {
if (get_config()->verify_client_cacert) {
if (tlsconf.client_verify.enabled) {
if (tlsconf.client_verify.cacert) {
if (SSL_CTX_load_verify_locations(
ssl_ctx, get_config()->verify_client_cacert.get(), nullptr) !=
1) {
ssl_ctx, tlsconf.client_verify.cacert.get(), nullptr) != 1) {
LOG(FATAL) << "Could not load trusted ca certificates from "
<< get_config()->verify_client_cacert.get() << ": "
<< tlsconf.client_verify.cacert.get() << ": "
<< ERR_error_string(ERR_get_error(), nullptr);
DIE();
}
@ -591,11 +592,10 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file
// error even though it returns success. See
// http://forum.nginx.org/read.php?29,242540
ERR_clear_error();
auto list =
SSL_load_client_CA_file(get_config()->verify_client_cacert.get());
auto list = SSL_load_client_CA_file(tlsconf.client_verify.cacert.get());
if (!list) {
LOG(FATAL) << "Could not load ca certificates from "
<< get_config()->verify_client_cacert.get() << ": "
<< tlsconf.client_verify.cacert.get() << ": "
<< ERR_error_string(ERR_get_error(), nullptr);
DIE();
}
@ -656,11 +656,13 @@ SSL_CTX *create_ssl_client_context(
SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
SSL_CTX_set_options(ssl_ctx, ssl_opts | get_config()->tls_proto_mask);
auto &tlsconf = get_config()->tls;
SSL_CTX_set_options(ssl_ctx, ssl_opts | tlsconf.tls_proto_mask);
const char *ciphers;
if (get_config()->ciphers) {
ciphers = get_config()->ciphers.get();
if (tlsconf.ciphers) {
ciphers = tlsconf.ciphers.get();
} else {
ciphers = nghttp2::ssl::DEFAULT_CIPHER_LIST;
}
@ -678,44 +680,44 @@ SSL_CTX *create_ssl_client_context(
<< ERR_error_string(ERR_get_error(), nullptr);
}
if (get_config()->cacert) {
if (SSL_CTX_load_verify_locations(ssl_ctx, get_config()->cacert.get(),
nullptr) != 1) {
if (tlsconf.cacert) {
if (SSL_CTX_load_verify_locations(ssl_ctx, tlsconf.cacert.get(), nullptr) !=
1) {
LOG(FATAL) << "Could not load trusted ca certificates from "
<< get_config()->cacert.get() << ": "
<< tlsconf.cacert.get() << ": "
<< ERR_error_string(ERR_get_error(), nullptr);
DIE();
}
}
if (get_config()->client_private_key_file) {
if (tlsconf.client.private_key_file) {
#ifndef HAVE_NEVERBLEED
if (SSL_CTX_use_PrivateKey_file(ssl_ctx,
get_config()->client_private_key_file.get(),
tlsconf.client.private_key_file.get(),
SSL_FILETYPE_PEM) != 1) {
LOG(FATAL) << "Could not load client private key from "
<< get_config()->client_private_key_file.get() << ": "
<< tlsconf.client.private_key_file.get() << ": "
<< ERR_error_string(ERR_get_error(), nullptr);
DIE();
}
#else // HAVE_NEVERBLEED
std::array<char, NEVERBLEED_ERRBUF_SIZE> errbuf;
if (neverbleed_load_private_key_file(
nb, ssl_ctx, get_config()->client_private_key_file.get(),
errbuf.data()) != 1) {
if (neverbleed_load_private_key_file(nb, ssl_ctx,
tlsconf.client.private_key_file.get(),
errbuf.data()) != 1) {
LOG(FATAL) << "neverbleed_load_private_key_file failed: "
<< errbuf.data();
DIE();
}
#endif // HAVE_NEVERBLEED
}
if (get_config()->client_cert_file) {
if (tlsconf.client.cert_file) {
if (SSL_CTX_use_certificate_chain_file(
ssl_ctx, get_config()->client_cert_file.get()) != 1) {
ssl_ctx, tlsconf.client.cert_file.get()) != 1) {
LOG(FATAL) << "Could not load client certificate from "
<< get_config()->client_cert_file.get() << ": "
<< tlsconf.client.cert_file.get() << ": "
<< ERR_error_string(ERR_get_error(), nullptr);
DIE();
}
@ -971,9 +973,11 @@ int check_cert(SSL *ssl, const DownstreamAddr *addr) {
<< X509_verify_cert_error_string(verify_res);
return -1;
}
auto hostname = !get_config()->backend_tls_sni_name.empty()
? StringRef(get_config()->backend_tls_sni_name)
: StringRef(addr->host);
auto &backend_sni_name = get_config()->tls.backend_sni_name;
auto hostname = !backend_sni_name.empty() ? StringRef(backend_sni_name)
: StringRef(addr->host);
if (verify_hostname(cert, hostname.c_str(), hostname.size(), &addr->addr) !=
0) {
LOG(ERROR) << "Certificate verification failed: hostname does not match";
@ -1210,12 +1214,14 @@ 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;
}
auto ssl_ctx = ssl::create_ssl_context(get_config()->private_key_file.get(),
get_config()->cert_file.get()
auto &tlsconf = get_config()->tls;
auto ssl_ctx = ssl::create_ssl_context(tlsconf.private_key_file.get(),
tlsconf.cert_file.get()
#ifdef HAVE_NEVERBLEED
,
nb
@ -1224,7 +1230,7 @@ SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
all_ssl_ctx.push_back(ssl_ctx);
if (get_config()->subcerts.empty()) {
if (tlsconf.subcerts.empty()) {
return ssl_ctx;
}
@ -1234,7 +1240,7 @@ SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
return ssl_ctx;
}
for (auto &keycert : get_config()->subcerts) {
for (auto &keycert : tlsconf.subcerts) {
auto ssl_ctx =
ssl::create_ssl_context(keycert.first.c_str(), keycert.second.c_str()
#ifdef HAVE_NEVERBLEED
@ -1250,8 +1256,8 @@ SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
}
}
if (ssl::cert_lookup_tree_add_cert_from_file(
cert_tree, ssl_ctx, get_config()->cert_file.get()) == -1) {
if (ssl::cert_lookup_tree_add_cert_from_file(cert_tree, ssl_ctx,
tlsconf.cert_file.get()) == -1) {
LOG(FATAL) << "Failed to add default certificate.";
DIE();
}
@ -1260,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(
@ -1284,7 +1292,8 @@ SSL_CTX *setup_client_ssl_context(
}
CertLookupTree *create_cert_lookup_tree() {
if (get_config()->upstream_no_tls || get_config()->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_)),
@ -83,18 +84,22 @@ Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx,
ev_timer_init(&mcpool_clear_timer_, mcpool_clear_cb, 0., 0.);
mcpool_clear_timer_.data = this;
if (get_config()->session_cache_memcached_host) {
auto &session_cacheconf = get_config()->tls.session_cache;
if (session_cacheconf.memcached.host) {
session_cache_memcached_dispatcher_ = make_unique<MemcachedDispatcher>(
&get_config()->session_cache_memcached_addr, loop);
&session_cacheconf.memcached.addr, loop);
}
if (get_config()->downstream_proto == PROTO_HTTP2) {
auto n = get_config()->http2_downstream_connections_per_worker;
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>(
@ -149,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: {
@ -157,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

@ -170,7 +170,7 @@ void ipc_readcb(struct ev_loop *loop, ev_io *w, int revents) {
namespace {
int generate_ticket_key(TicketKey &ticket_key) {
ticket_key.cipher = get_config()->tls_ticket_key_cipher;
ticket_key.cipher = get_config()->tls.ticket.cipher;
ticket_key.hmac = EVP_sha256();
ticket_key.hmac_keylen = EVP_MD_size(ticket_key.hmac);
@ -217,7 +217,7 @@ void renew_ticket_key_cb(struct ev_loop *loop, ev_timer *w, int revents) {
auto max_tickets =
static_cast<size_t>(std::chrono::duration_cast<std::chrono::hours>(
get_config()->tls_session_timeout).count());
get_config()->tls.session_timeout).count());
new_keys.resize(std::min(max_tickets, old_keys.size() + 1));
std::copy_n(std::begin(old_keys), new_keys.size() - 1,
@ -297,14 +297,16 @@ void memcached_get_ticket_key_cb(struct ev_loop *loop, ev_timer *w,
auto end = p + value.size();
p += 4;
auto &ticketconf = get_config()->tls.ticket;
size_t expectedlen;
size_t enc_keylen;
size_t hmac_keylen;
if (get_config()->tls_ticket_key_cipher == EVP_aes_128_cbc()) {
if (ticketconf.cipher == EVP_aes_128_cbc()) {
expectedlen = 48;
enc_keylen = 16;
hmac_keylen = 16;
} else if (get_config()->tls_ticket_key_cipher == EVP_aes_256_cbc()) {
} else if (ticketconf.cipher == EVP_aes_256_cbc()) {
expectedlen = 80;
enc_keylen = 32;
hmac_keylen = 32;
@ -335,7 +337,7 @@ void memcached_get_ticket_key_cb(struct ev_loop *loop, ev_timer *w,
return;
}
auto key = TicketKey();
key.cipher = get_config()->tls_ticket_key_cipher;
key.cipher = ticketconf.cipher;
key.hmac = EVP_sha256();
key.hmac_keylen = hmac_keylen;
@ -421,12 +423,15 @@ 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 (get_config()->tls_ticket_key_memcached_host) {
if (!upstreamconf.no_tls) {
auto &ticketconf = get_config()->tls.ticket;
if (ticketconf.memcached.host) {
conn_handler.set_tls_ticket_key_memcached_dispatcher(
make_unique<MemcachedDispatcher>(
&get_config()->tls_ticket_key_memcached_addr, loop));
make_unique<MemcachedDispatcher>(&ticketconf.memcached.addr, loop));
ev_timer_init(&renew_ticket_key_timer, memcached_get_ticket_key_cb, 0.,
0.);
@ -435,8 +440,8 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
memcached_get_ticket_key_cb(loop, &renew_ticket_key_timer, 0);
} else {
bool auto_tls_ticket_key = true;
if (!get_config()->tls_ticket_key_files.empty()) {
if (!get_config()->tls_ticket_key_cipher_given) {
if (!ticketconf.files.empty()) {
if (!ticketconf.cipher_given) {
LOG(WARN)
<< "It is strongly recommended to specify "
"--tls-ticket-key-cipher=aes-128-cbc (or "
@ -446,8 +451,7 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
"becomes aes-256-cbc";
}
auto ticket_keys = read_tls_ticket_key_file(
get_config()->tls_ticket_key_files,
get_config()->tls_ticket_key_cipher, EVP_sha256());
ticketconf.files, ticketconf.cipher, EVP_sha256());
if (!ticket_keys) {
LOG(WARN) << "Use internal session ticket key generator";
} else {
@ -512,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()->no_ocsp) {
if (!upstreamconf.no_tls && !get_config()->tls.ocsp.disabled) {
conn_handler.proceed_next_cert_ocsp();
}

View File

@ -171,10 +171,18 @@ constexpr unsigned long long operator"" _g(unsigned long long g) {
// User-defined literals for time, converted into double in seconds
// hours
constexpr double operator"" _h(unsigned long long h) { return h * 60 * 60; }
// minutes
constexpr double operator"" _min(unsigned long long min) { return min * 60; }
// seconds
constexpr double operator"" _s(unsigned long long s) { return s; }
// milliseconds
constexpr double operator"" _ms(unsigned long long ms) { return ms / 1000.; }
// Returns a copy of NULL-terminated string [first, last).
template <typename InputIt>
std::unique_ptr<char[]> strcopy(InputIt first, InputIt last) {