Merge branch 'nghttpx-reorganize-config'
This commit is contained in:
commit
dc0f0123e9
1065
src/shrpx.cc
1065
src/shrpx.cc
File diff suppressed because it is too large
Load Diff
|
@ -87,7 +87,7 @@ void AcceptHandler::accept_connection() {
|
||||||
case ENFILE:
|
case ENFILE:
|
||||||
LOG(WARN) << "acceptor: running out file descriptor; disable acceptor "
|
LOG(WARN) << "acceptor: running out file descriptor; disable acceptor "
|
||||||
"temporarily";
|
"temporarily";
|
||||||
conn_hnr_->disable_acceptor_temporary(30.);
|
conn_hnr_->sleep_acceptor(get_config()->conn.listener.timeout.sleep);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -371,16 +371,16 @@ int ClientHandler::upstream_http1_connhd_read() {
|
||||||
ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl,
|
ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl,
|
||||||
const char *ipaddr, const char *port)
|
const char *ipaddr, const char *port)
|
||||||
: conn_(worker->get_loop(), fd, ssl, worker->get_mcpool(),
|
: conn_(worker->get_loop(), fd, ssl, worker->get_mcpool(),
|
||||||
get_config()->upstream_write_timeout,
|
get_config()->conn.upstream.timeout.write,
|
||||||
get_config()->upstream_read_timeout, get_config()->write_rate,
|
get_config()->conn.upstream.timeout.read,
|
||||||
get_config()->write_burst, get_config()->read_rate,
|
get_config()->conn.upstream.ratelimit.write,
|
||||||
get_config()->read_burst, writecb, readcb, timeoutcb, this,
|
get_config()->conn.upstream.ratelimit.read, writecb, readcb,
|
||||||
get_config()->tls_dyn_rec_warmup_threshold,
|
timeoutcb, this, get_config()->tls.dyn_rec.warmup_threshold,
|
||||||
get_config()->tls_dyn_rec_idle_timeout),
|
get_config()->tls.dyn_rec.idle_timeout),
|
||||||
pinned_http2sessions_(
|
pinned_http2sessions_(
|
||||||
get_config()->downstream_proto == PROTO_HTTP2
|
get_config()->conn.downstream.proto == PROTO_HTTP2
|
||||||
? make_unique<std::vector<ssize_t>>(
|
? make_unique<std::vector<ssize_t>>(
|
||||||
get_config()->downstream_addr_groups.size(), -1)
|
get_config()->conn.downstream.addr_groups.size(), -1)
|
||||||
: nullptr),
|
: nullptr),
|
||||||
ipaddr_(ipaddr), port_(port), worker_(worker),
|
ipaddr_(ipaddr), port_(port), worker_(worker),
|
||||||
left_connhd_len_(NGHTTP2_CLIENT_MAGIC_LEN),
|
left_connhd_len_(NGHTTP2_CLIENT_MAGIC_LEN),
|
||||||
|
@ -395,7 +395,7 @@ ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl,
|
||||||
conn_.rlimit.startw();
|
conn_.rlimit.startw();
|
||||||
ev_timer_again(conn_.loop, &conn_.rt);
|
ev_timer_again(conn_.loop, &conn_.rt);
|
||||||
|
|
||||||
if (get_config()->accept_proxy_protocol) {
|
if (get_config()->conn.upstream.accept_proxy_protocol) {
|
||||||
read_ = &ClientHandler::read_clear;
|
read_ = &ClientHandler::read_clear;
|
||||||
write_ = &ClientHandler::noop;
|
write_ = &ClientHandler::noop;
|
||||||
on_read_ = &ClientHandler::proxy_protocol_read;
|
on_read_ = &ClientHandler::proxy_protocol_read;
|
||||||
|
@ -404,14 +404,16 @@ ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl,
|
||||||
setup_upstream_io_callback();
|
setup_upstream_io_callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((get_config()->forwarded_params & FORWARDED_FOR) &&
|
auto &fwdconf = get_config()->http.forwarded;
|
||||||
get_config()->forwarded_for_node_type == FORWARDED_NODE_OBFUSCATED) {
|
|
||||||
if (get_config()->forwarded_for_obfuscated.empty()) {
|
if ((fwdconf.params & FORWARDED_FOR) &&
|
||||||
|
fwdconf.for_node_type == FORWARDED_NODE_OBFUSCATED) {
|
||||||
|
if (fwdconf.for_obfuscated.empty()) {
|
||||||
forwarded_for_obfuscated_ = "_";
|
forwarded_for_obfuscated_ = "_";
|
||||||
forwarded_for_obfuscated_ += util::random_alpha_digit(
|
forwarded_for_obfuscated_ += util::random_alpha_digit(
|
||||||
worker_->get_randgen(), SHRPX_OBFUSCATED_NODE_LENGTH);
|
worker_->get_randgen(), SHRPX_OBFUSCATED_NODE_LENGTH);
|
||||||
} else {
|
} 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;
|
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)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
CLOG(INFO, this) << "The negotiated protocol is not supported";
|
CLOG(INFO, this) << "The negotiated protocol is not supported";
|
||||||
}
|
}
|
||||||
|
@ -644,8 +647,9 @@ void ClientHandler::remove_downstream_connection(DownstreamConnection *dconn) {
|
||||||
std::unique_ptr<DownstreamConnection>
|
std::unique_ptr<DownstreamConnection>
|
||||||
ClientHandler::get_downstream_connection(Downstream *downstream) {
|
ClientHandler::get_downstream_connection(Downstream *downstream) {
|
||||||
size_t group;
|
size_t group;
|
||||||
auto &groups = get_config()->downstream_addr_groups;
|
auto &downstreamconf = get_config()->conn.downstream;
|
||||||
auto catch_all = get_config()->downstream_addr_group_catch_all;
|
auto &groups = downstreamconf.addr_groups;
|
||||||
|
auto catch_all = downstreamconf.addr_group_catch_all;
|
||||||
|
|
||||||
const auto &req = downstream->request();
|
const auto &req = downstream->request();
|
||||||
|
|
||||||
|
@ -690,7 +694,7 @@ ClientHandler::get_downstream_connection(Downstream *downstream) {
|
||||||
|
|
||||||
auto dconn_pool = worker_->get_dconn_pool();
|
auto dconn_pool = worker_->get_dconn_pool();
|
||||||
|
|
||||||
if (get_config()->downstream_proto == PROTO_HTTP2) {
|
if (downstreamconf.proto == PROTO_HTTP2) {
|
||||||
Http2Session *http2session;
|
Http2Session *http2session;
|
||||||
auto &pinned = (*pinned_http2sessions_)[group];
|
auto &pinned = (*pinned_http2sessions_)[group];
|
||||||
if (pinned == -1) {
|
if (pinned == -1) {
|
||||||
|
@ -833,7 +837,7 @@ void ClientHandler::write_accesslog(Downstream *downstream) {
|
||||||
const auto &resp = downstream->response();
|
const auto &resp = downstream->response();
|
||||||
|
|
||||||
upstream_accesslog(
|
upstream_accesslog(
|
||||||
get_config()->accesslog_format,
|
get_config()->logging.access.format,
|
||||||
LogSpec{
|
LogSpec{
|
||||||
downstream, ipaddr_, http2::to_method_string(req.method),
|
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
|
std::chrono::high_resolution_clock::now(), // request_end_time
|
||||||
|
|
||||||
req.http_major, req.http_minor, resp.http_status,
|
req.http_major, req.http_minor, resp.http_status,
|
||||||
downstream->response_sent_body_length, port_, get_config()->port,
|
downstream->response_sent_body_length, port_,
|
||||||
get_config()->pid,
|
get_config()->conn.listener.port, get_config()->pid,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -866,7 +870,7 @@ void ClientHandler::write_accesslog(int major, int minor, unsigned int status,
|
||||||
nghttp2::ssl::TLSSessionInfo tls_info;
|
nghttp2::ssl::TLSSessionInfo tls_info;
|
||||||
|
|
||||||
upstream_accesslog(
|
upstream_accesslog(
|
||||||
get_config()->accesslog_format,
|
get_config()->logging.access.format,
|
||||||
LogSpec{
|
LogSpec{
|
||||||
nullptr, ipaddr_,
|
nullptr, ipaddr_,
|
||||||
StringRef::from_lit("-"), // method
|
StringRef::from_lit("-"), // method
|
||||||
|
@ -877,7 +881,8 @@ void ClientHandler::write_accesslog(int major, int minor, unsigned int status,
|
||||||
// there a better value?
|
// there a better value?
|
||||||
highres_now, // request_end_time
|
highres_now, // request_end_time
|
||||||
major, minor, // major, minor
|
major, minor, // major, minor
|
||||||
status, body_bytes_sent, port_, get_config()->port, get_config()->pid,
|
status, body_bytes_sent, port_, get_config()->conn.listener.port,
|
||||||
|
get_config()->pid,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1119,8 +1124,10 @@ int ClientHandler::proxy_protocol_read() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &ClientHandler::get_forwarded_by() {
|
const std::string &ClientHandler::get_forwarded_by() {
|
||||||
if (get_config()->forwarded_by_node_type == FORWARDED_NODE_OBFUSCATED) {
|
auto &fwdconf = get_config()->http.forwarded;
|
||||||
return get_config()->forwarded_by_obfuscated;
|
|
||||||
|
if (fwdconf.by_node_type == FORWARDED_NODE_OBFUSCATED) {
|
||||||
|
return fwdconf.by_obfuscated;
|
||||||
}
|
}
|
||||||
if (!local_hostport_.empty()) {
|
if (!local_hostport_.empty()) {
|
||||||
return local_hostport_;
|
return local_hostport_;
|
||||||
|
@ -1151,13 +1158,13 @@ const std::string &ClientHandler::get_forwarded_by() {
|
||||||
local_hostport_ += ':';
|
local_hostport_ += ':';
|
||||||
}
|
}
|
||||||
|
|
||||||
local_hostport_ += util::utos(get_config()->port);
|
local_hostport_ += util::utos(get_config()->conn.listener.port);
|
||||||
|
|
||||||
return local_hostport_;
|
return local_hostport_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &ClientHandler::get_forwarded_for() const {
|
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_;
|
return forwarded_for_obfuscated_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -594,6 +594,8 @@ void parse_mapping(const DownstreamAddr &addr, const char *src) {
|
||||||
// will append '/' to all patterns, so it becomes catch-all pattern.
|
// will append '/' to all patterns, so it becomes catch-all pattern.
|
||||||
auto mapping = util::split_config_str_list(src, ':');
|
auto mapping = util::split_config_str_list(src, ':');
|
||||||
assert(!mapping.empty());
|
assert(!mapping.empty());
|
||||||
|
auto &addr_groups = mod_config()->conn.downstream.addr_groups;
|
||||||
|
|
||||||
for (const auto &raw_pattern : mapping) {
|
for (const auto &raw_pattern : mapping) {
|
||||||
auto done = false;
|
auto done = false;
|
||||||
std::string pattern;
|
std::string pattern;
|
||||||
|
@ -608,7 +610,7 @@ void parse_mapping(const DownstreamAddr &addr, const char *src) {
|
||||||
util::inp_strlower(pattern);
|
util::inp_strlower(pattern);
|
||||||
pattern += http2::normalize_path(slash, raw_pattern.second);
|
pattern += http2::normalize_path(slash, raw_pattern.second);
|
||||||
}
|
}
|
||||||
for (auto &g : mod_config()->downstream_addr_groups) {
|
for (auto &g : addr_groups) {
|
||||||
if (g.pattern.get() == pattern) {
|
if (g.pattern.get() == pattern) {
|
||||||
g.addrs.push_back(addr);
|
g.addrs.push_back(addr);
|
||||||
done = true;
|
done = true;
|
||||||
|
@ -622,9 +624,9 @@ void parse_mapping(const DownstreamAddr &addr, const char *src) {
|
||||||
g.addrs.push_back(addr);
|
g.addrs.push_back(addr);
|
||||||
|
|
||||||
mod_config()->router.add_route(g.pattern.get(), strlen(g.pattern.get()),
|
mod_config()->router.add_route(g.pattern.get(), strlen(g.pattern.get()),
|
||||||
get_config()->downstream_addr_groups.size());
|
addr_groups.size());
|
||||||
|
|
||||||
mod_config()->downstream_addr_groups.push_back(std::move(g));
|
addr_groups.push_back(std::move(g));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -1419,11 +1421,13 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_FRONTEND: {
|
case SHRPX_OPTID_FRONTEND: {
|
||||||
|
auto &listenerconf = mod_config()->conn.listener;
|
||||||
|
|
||||||
if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) {
|
if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) {
|
||||||
auto path = optarg + str_size(SHRPX_UNIX_PATH_PREFIX);
|
auto path = optarg + str_size(SHRPX_UNIX_PATH_PREFIX);
|
||||||
mod_config()->host = strcopy(path);
|
listenerconf.host = strcopy(path);
|
||||||
mod_config()->port = 0;
|
listenerconf.port = 0;
|
||||||
mod_config()->host_unix = true;
|
listenerconf.host_unix = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1433,9 +1437,9 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_config()->host = strcopy(host);
|
listenerconf.host = strcopy(host);
|
||||||
mod_config()->port = port;
|
listenerconf.port = port;
|
||||||
mod_config()->host_unix = false;
|
listenerconf.host_unix = false;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1447,7 +1451,7 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return parse_uint(&mod_config()->num_worker, opt, optarg);
|
return parse_uint(&mod_config()->num_worker, opt, optarg);
|
||||||
#endif // !NOTHREADS
|
#endif // !NOTHREADS
|
||||||
case SHRPX_OPTID_HTTP2_MAX_CONCURRENT_STREAMS:
|
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:
|
case SHRPX_OPTID_LOG_LEVEL:
|
||||||
if (Log::set_severity_level_by_name(optarg) == -1) {
|
if (Log::set_severity_level_by_name(optarg) == -1) {
|
||||||
LOG(ERROR) << opt << ": Invalid severity level: " << optarg;
|
LOG(ERROR) << opt << ": Invalid severity level: " << optarg;
|
||||||
|
@ -1472,50 +1476,56 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_ADD_X_FORWARDED_FOR:
|
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;
|
return 0;
|
||||||
case SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR:
|
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;
|
return 0;
|
||||||
case SHRPX_OPTID_NO_VIA:
|
case SHRPX_OPTID_NO_VIA:
|
||||||
mod_config()->no_via = util::strieq(optarg, "yes");
|
mod_config()->http.no_via = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT:
|
case SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT:
|
||||||
return parse_duration(&mod_config()->http2_upstream_read_timeout, opt,
|
return parse_duration(&mod_config()->conn.upstream.timeout.http2_read, opt,
|
||||||
optarg);
|
optarg);
|
||||||
case SHRPX_OPTID_FRONTEND_READ_TIMEOUT:
|
case SHRPX_OPTID_FRONTEND_READ_TIMEOUT:
|
||||||
return parse_duration(&mod_config()->upstream_read_timeout, opt, optarg);
|
return parse_duration(&mod_config()->conn.upstream.timeout.read, opt,
|
||||||
|
optarg);
|
||||||
case SHRPX_OPTID_FRONTEND_WRITE_TIMEOUT:
|
case SHRPX_OPTID_FRONTEND_WRITE_TIMEOUT:
|
||||||
return parse_duration(&mod_config()->upstream_write_timeout, opt, optarg);
|
return parse_duration(&mod_config()->conn.upstream.timeout.write, opt,
|
||||||
|
optarg);
|
||||||
case SHRPX_OPTID_BACKEND_READ_TIMEOUT:
|
case SHRPX_OPTID_BACKEND_READ_TIMEOUT:
|
||||||
return parse_duration(&mod_config()->downstream_read_timeout, opt, optarg);
|
return parse_duration(&mod_config()->conn.downstream.timeout.read, opt,
|
||||||
|
optarg);
|
||||||
case SHRPX_OPTID_BACKEND_WRITE_TIMEOUT:
|
case SHRPX_OPTID_BACKEND_WRITE_TIMEOUT:
|
||||||
return parse_duration(&mod_config()->downstream_write_timeout, opt, optarg);
|
return parse_duration(&mod_config()->conn.downstream.timeout.write, opt,
|
||||||
|
optarg);
|
||||||
case SHRPX_OPTID_STREAM_READ_TIMEOUT:
|
case SHRPX_OPTID_STREAM_READ_TIMEOUT:
|
||||||
return parse_duration(&mod_config()->stream_read_timeout, opt, optarg);
|
return parse_duration(&mod_config()->http2.timeout.stream_read, opt,
|
||||||
|
optarg);
|
||||||
case SHRPX_OPTID_STREAM_WRITE_TIMEOUT:
|
case SHRPX_OPTID_STREAM_WRITE_TIMEOUT:
|
||||||
return parse_duration(&mod_config()->stream_write_timeout, opt, optarg);
|
return parse_duration(&mod_config()->http2.timeout.stream_write, opt,
|
||||||
|
optarg);
|
||||||
case SHRPX_OPTID_ACCESSLOG_FILE:
|
case SHRPX_OPTID_ACCESSLOG_FILE:
|
||||||
mod_config()->accesslog_file = strcopy(optarg);
|
mod_config()->logging.access.file = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_ACCESSLOG_SYSLOG:
|
case SHRPX_OPTID_ACCESSLOG_SYSLOG:
|
||||||
mod_config()->accesslog_syslog = util::strieq(optarg, "yes");
|
mod_config()->logging.access.syslog = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_ACCESSLOG_FORMAT:
|
case SHRPX_OPTID_ACCESSLOG_FORMAT:
|
||||||
mod_config()->accesslog_format = parse_log_format(optarg);
|
mod_config()->logging.access.format = parse_log_format(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_ERRORLOG_FILE:
|
case SHRPX_OPTID_ERRORLOG_FILE:
|
||||||
mod_config()->errorlog_file = strcopy(optarg);
|
mod_config()->logging.error.file = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_ERRORLOG_SYSLOG:
|
case SHRPX_OPTID_ERRORLOG_SYSLOG:
|
||||||
mod_config()->errorlog_syslog = util::strieq(optarg, "yes");
|
mod_config()->logging.error.syslog = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_FASTOPEN: {
|
case SHRPX_OPTID_FASTOPEN: {
|
||||||
|
@ -1529,21 +1539,21 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_config()->fastopen = n;
|
mod_config()->conn.listener.fastopen = n;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_BACKEND_KEEP_ALIVE_TIMEOUT:
|
case SHRPX_OPTID_BACKEND_KEEP_ALIVE_TIMEOUT:
|
||||||
return parse_duration(&mod_config()->downstream_idle_read_timeout, opt,
|
return parse_duration(&mod_config()->conn.downstream.timeout.idle_read, opt,
|
||||||
optarg);
|
optarg);
|
||||||
case SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS:
|
case SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS:
|
||||||
case SHRPX_OPTID_BACKEND_HTTP2_WINDOW_BITS: {
|
case SHRPX_OPTID_BACKEND_HTTP2_WINDOW_BITS: {
|
||||||
size_t *resp;
|
size_t *resp;
|
||||||
|
|
||||||
if (optid == SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS) {
|
if (optid == SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS) {
|
||||||
resp = &mod_config()->http2_upstream_window_bits;
|
resp = &mod_config()->http2.upstream.window_bits;
|
||||||
} else {
|
} else {
|
||||||
resp = &mod_config()->http2_downstream_window_bits;
|
resp = &mod_config()->http2.downstream.window_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
@ -1569,9 +1579,9 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
size_t *resp;
|
size_t *resp;
|
||||||
|
|
||||||
if (optid == SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS) {
|
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 {
|
} else {
|
||||||
resp = &mod_config()->http2_downstream_connection_window_bits;
|
resp = &mod_config()->http2.downstream.connection_window_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
@ -1593,15 +1603,15 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_FRONTEND_NO_TLS:
|
case SHRPX_OPTID_FRONTEND_NO_TLS:
|
||||||
mod_config()->upstream_no_tls = util::strieq(optarg, "yes");
|
mod_config()->conn.upstream.no_tls = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_BACKEND_NO_TLS:
|
case SHRPX_OPTID_BACKEND_NO_TLS:
|
||||||
mod_config()->downstream_no_tls = util::strieq(optarg, "yes");
|
mod_config()->conn.downstream.no_tls = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_BACKEND_TLS_SNI_FIELD:
|
case SHRPX_OPTID_BACKEND_TLS_SNI_FIELD:
|
||||||
mod_config()->backend_tls_sni_name = optarg;
|
mod_config()->tls.backend_sni_name = optarg;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_PID_FILE:
|
case SHRPX_OPTID_PID_FILE:
|
||||||
|
@ -1622,7 +1632,7 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_PRIVATE_KEY_FILE:
|
case SHRPX_OPTID_PRIVATE_KEY_FILE:
|
||||||
mod_config()->private_key_file = strcopy(optarg);
|
mod_config()->tls.private_key_file = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_PRIVATE_KEY_PASSWD_FILE: {
|
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;
|
LOG(ERROR) << opt << ": Couldn't read key file's passwd from " << optarg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
mod_config()->private_key_passwd = strcopy(passwd);
|
mod_config()->tls.private_key_passwd = strcopy(passwd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_CERTIFICATE_FILE:
|
case SHRPX_OPTID_CERTIFICATE_FILE:
|
||||||
mod_config()->cert_file = strcopy(optarg);
|
mod_config()->tls.cert_file = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_DH_PARAM_FILE:
|
case SHRPX_OPTID_DH_PARAM_FILE:
|
||||||
mod_config()->dh_param_file = strcopy(optarg);
|
mod_config()->tls.dh_param_file = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_SUBCERT: {
|
case SHRPX_OPTID_SUBCERT: {
|
||||||
|
@ -1649,7 +1659,7 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
if (sp) {
|
if (sp) {
|
||||||
std::string keyfile(optarg, sp);
|
std::string keyfile(optarg, sp);
|
||||||
// TODO Do we need private key for subcert?
|
// 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;
|
return 0;
|
||||||
|
@ -1660,7 +1670,7 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
LOG(ERROR) << opt << ": Unknown syslog facility: " << optarg;
|
LOG(ERROR) << opt << ": Unknown syslog facility: " << optarg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
mod_config()->syslog_facility = facility;
|
mod_config()->logging.syslog_facility = facility;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1676,12 +1686,12 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_config()->backlog = n;
|
mod_config()->conn.listener.backlog = n;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_CIPHERS:
|
case SHRPX_OPTID_CIPHERS:
|
||||||
mod_config()->ciphers = strcopy(optarg);
|
mod_config()->tls.ciphers = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_CLIENT:
|
case SHRPX_OPTID_CLIENT:
|
||||||
|
@ -1689,19 +1699,19 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_INSECURE:
|
case SHRPX_OPTID_INSECURE:
|
||||||
mod_config()->insecure = util::strieq(optarg, "yes");
|
mod_config()->tls.insecure = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_CACERT:
|
case SHRPX_OPTID_CACERT:
|
||||||
mod_config()->cacert = strcopy(optarg);
|
mod_config()->tls.cacert = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_BACKEND_IPV4:
|
case SHRPX_OPTID_BACKEND_IPV4:
|
||||||
mod_config()->backend_ipv4 = util::strieq(optarg, "yes");
|
mod_config()->conn.downstream.ipv4 = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_BACKEND_IPV6:
|
case SHRPX_OPTID_BACKEND_IPV6:
|
||||||
mod_config()->backend_ipv6 = util::strieq(optarg, "yes");
|
mod_config()->conn.downstream.ipv6 = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_BACKEND_HTTP_PROXY_URI: {
|
case SHRPX_OPTID_BACKEND_HTTP_PROXY_URI: {
|
||||||
|
@ -1742,63 +1752,70 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_READ_RATE:
|
case SHRPX_OPTID_READ_RATE:
|
||||||
return parse_uint_with_unit(&mod_config()->read_rate, opt, optarg);
|
return parse_uint_with_unit(
|
||||||
|
&mod_config()->conn.upstream.ratelimit.read.rate, opt, optarg);
|
||||||
case SHRPX_OPTID_READ_BURST:
|
case SHRPX_OPTID_READ_BURST:
|
||||||
return parse_uint_with_unit(&mod_config()->read_burst, opt, optarg);
|
return parse_uint_with_unit(
|
||||||
|
&mod_config()->conn.upstream.ratelimit.read.burst, opt, optarg);
|
||||||
case SHRPX_OPTID_WRITE_RATE:
|
case SHRPX_OPTID_WRITE_RATE:
|
||||||
return parse_uint_with_unit(&mod_config()->write_rate, opt, optarg);
|
return parse_uint_with_unit(
|
||||||
|
&mod_config()->conn.upstream.ratelimit.write.rate, opt, optarg);
|
||||||
case SHRPX_OPTID_WRITE_BURST:
|
case SHRPX_OPTID_WRITE_BURST:
|
||||||
return parse_uint_with_unit(&mod_config()->write_burst, opt, optarg);
|
return parse_uint_with_unit(
|
||||||
|
&mod_config()->conn.upstream.ratelimit.write.burst, opt, optarg);
|
||||||
case SHRPX_OPTID_WORKER_READ_RATE:
|
case SHRPX_OPTID_WORKER_READ_RATE:
|
||||||
LOG(WARN) << opt << ": not implemented yet";
|
LOG(WARN) << opt << ": not implemented yet";
|
||||||
return parse_uint_with_unit(&mod_config()->worker_read_rate, opt, optarg);
|
return 0;
|
||||||
case SHRPX_OPTID_WORKER_READ_BURST:
|
case SHRPX_OPTID_WORKER_READ_BURST:
|
||||||
LOG(WARN) << opt << ": not implemented yet";
|
LOG(WARN) << opt << ": not implemented yet";
|
||||||
return parse_uint_with_unit(&mod_config()->worker_read_burst, opt, optarg);
|
return 0;
|
||||||
case SHRPX_OPTID_WORKER_WRITE_RATE:
|
case SHRPX_OPTID_WORKER_WRITE_RATE:
|
||||||
LOG(WARN) << opt << ": not implemented yet";
|
LOG(WARN) << opt << ": not implemented yet";
|
||||||
return parse_uint_with_unit(&mod_config()->worker_write_rate, opt, optarg);
|
return 0;
|
||||||
case SHRPX_OPTID_WORKER_WRITE_BURST:
|
case SHRPX_OPTID_WORKER_WRITE_BURST:
|
||||||
LOG(WARN) << opt << ": not implemented yet";
|
LOG(WARN) << opt << ": not implemented yet";
|
||||||
return parse_uint_with_unit(&mod_config()->worker_write_burst, opt, optarg);
|
return 0;
|
||||||
case SHRPX_OPTID_NPN_LIST:
|
case SHRPX_OPTID_NPN_LIST:
|
||||||
mod_config()->npn_list = util::parse_config_str_list(optarg);
|
mod_config()->tls.npn_list = util::parse_config_str_list(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_TLS_PROTO_LIST:
|
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;
|
return 0;
|
||||||
case SHRPX_OPTID_VERIFY_CLIENT:
|
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;
|
return 0;
|
||||||
case SHRPX_OPTID_VERIFY_CLIENT_CACERT:
|
case SHRPX_OPTID_VERIFY_CLIENT_CACERT:
|
||||||
mod_config()->verify_client_cacert = strcopy(optarg);
|
mod_config()->tls.client_verify.cacert = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE:
|
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;
|
return 0;
|
||||||
case SHRPX_OPTID_CLIENT_CERT_FILE:
|
case SHRPX_OPTID_CLIENT_CERT_FILE:
|
||||||
mod_config()->client_cert_file = strcopy(optarg);
|
mod_config()->tls.client.cert_file = strcopy(optarg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER:
|
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;
|
return 0;
|
||||||
case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER:
|
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;
|
return 0;
|
||||||
case SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING:
|
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;
|
return 0;
|
||||||
case SHRPX_OPTID_FRONTEND_FRAME_DEBUG:
|
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;
|
return 0;
|
||||||
case SHRPX_OPTID_PADDING:
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1857,16 +1874,17 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (optid == SHRPX_OPTID_ADD_REQUEST_HEADER) {
|
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 {
|
} else {
|
||||||
mod_config()->add_response_headers.push_back(std::move(p));
|
mod_config()->http.add_response_headers.push_back(std::move(p));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_WORKER_FRONTEND_CONNECTIONS:
|
case SHRPX_OPTID_WORKER_FRONTEND_CONNECTIONS:
|
||||||
return parse_uint(&mod_config()->worker_frontend_connections, opt, optarg);
|
return parse_uint(&mod_config()->conn.upstream.worker_connections, opt,
|
||||||
|
optarg);
|
||||||
case SHRPX_OPTID_NO_LOCATION_REWRITE:
|
case SHRPX_OPTID_NO_LOCATION_REWRITE:
|
||||||
mod_config()->no_location_rewrite = util::strieq(optarg, "yes");
|
mod_config()->http.no_location_rewrite = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_NO_HOST_REWRITE:
|
case SHRPX_OPTID_NO_HOST_REWRITE:
|
||||||
|
@ -1889,17 +1907,18 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_config()->downstream_connections_per_host = n;
|
mod_config()->conn.downstream.connections_per_host = n;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND:
|
case SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND:
|
||||||
return parse_uint(&mod_config()->downstream_connections_per_frontend, opt,
|
return parse_uint(&mod_config()->conn.downstream.connections_per_frontend,
|
||||||
optarg);
|
opt, optarg);
|
||||||
case SHRPX_OPTID_LISTENER_DISABLE_TIMEOUT:
|
case SHRPX_OPTID_LISTENER_DISABLE_TIMEOUT:
|
||||||
return parse_duration(&mod_config()->listener_disable_timeout, opt, optarg);
|
return parse_duration(&mod_config()->conn.listener.timeout.sleep, opt,
|
||||||
|
optarg);
|
||||||
case SHRPX_OPTID_TLS_TICKET_KEY_FILE:
|
case SHRPX_OPTID_TLS_TICKET_KEY_FILE:
|
||||||
mod_config()->tls_ticket_key_files.push_back(optarg);
|
mod_config()->tls.ticket.files.push_back(optarg);
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_RLIMIT_NOFILE: {
|
case SHRPX_OPTID_RLIMIT_NOFILE: {
|
||||||
int n;
|
int n;
|
||||||
|
@ -1932,36 +1951,36 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optid == SHRPX_OPTID_BACKEND_REQUEST_BUFFER) {
|
if (optid == SHRPX_OPTID_BACKEND_REQUEST_BUFFER) {
|
||||||
mod_config()->downstream_request_buffer_size = n;
|
mod_config()->conn.downstream.request_buffer_size = n;
|
||||||
} else {
|
} else {
|
||||||
mod_config()->downstream_response_buffer_size = n;
|
mod_config()->conn.downstream.response_buffer_size = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SHRPX_OPTID_NO_SERVER_PUSH:
|
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;
|
return 0;
|
||||||
case SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER:
|
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);
|
opt, optarg);
|
||||||
case SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE:
|
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;
|
return 0;
|
||||||
case SHRPX_OPTID_OCSP_UPDATE_INTERVAL:
|
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:
|
case SHRPX_OPTID_NO_OCSP:
|
||||||
mod_config()->no_ocsp = util::strieq(optarg, "yes");
|
mod_config()->tls.ocsp.disabled = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_HEADER_FIELD_BUFFER:
|
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);
|
optarg);
|
||||||
case SHRPX_OPTID_MAX_HEADER_FIELDS:
|
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: {
|
case SHRPX_OPTID_INCLUDE: {
|
||||||
if (included_set.count(optarg)) {
|
if (included_set.count(optarg)) {
|
||||||
LOG(ERROR) << opt << ": " << optarg << " has already been included";
|
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:
|
case SHRPX_OPTID_TLS_TICKET_KEY_CIPHER:
|
||||||
if (util::strieq(optarg, "aes-128-cbc")) {
|
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")) {
|
} 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 {
|
} else {
|
||||||
LOG(ERROR) << opt
|
LOG(ERROR) << opt
|
||||||
<< ": unsupported cipher for ticket encryption: " << optarg;
|
<< ": unsupported cipher for ticket encryption: " << optarg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
mod_config()->tls_ticket_key_cipher_given = true;
|
mod_config()->tls.ticket.cipher_given = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_HOST_REWRITE:
|
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;
|
return 0;
|
||||||
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED: {
|
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED: {
|
||||||
|
@ -2001,8 +2020,9 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_config()->session_cache_memcached_host = strcopy(host);
|
auto &memcachedconf = mod_config()->tls.session_cache.memcached;
|
||||||
mod_config()->session_cache_memcached_port = port;
|
memcachedconf.host = strcopy(host);
|
||||||
|
memcachedconf.port = port;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2012,13 +2032,14 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_config()->tls_ticket_key_memcached_host = strcopy(host);
|
auto &memcachedconf = mod_config()->tls.ticket.memcached;
|
||||||
mod_config()->tls_ticket_key_memcached_port = port;
|
memcachedconf.host = strcopy(host);
|
||||||
|
memcachedconf.port = port;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_INTERVAL:
|
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);
|
optarg);
|
||||||
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY: {
|
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY: {
|
||||||
int n;
|
int n;
|
||||||
|
@ -2031,11 +2052,11 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_config()->tls_ticket_key_memcached_max_retry = n;
|
mod_config()->tls.ticket.memcached.max_retry = n;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL:
|
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);
|
optarg);
|
||||||
case SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD: {
|
case SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD: {
|
||||||
size_t n;
|
size_t n;
|
||||||
|
@ -2043,13 +2064,13 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_config()->tls_dyn_rec_warmup_threshold = n;
|
mod_config()->tls.dyn_rec.warmup_threshold = n;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SHRPX_OPTID_TLS_DYN_REC_IDLE_TIMEOUT:
|
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:
|
case SHRPX_OPTID_MRUBY_FILE:
|
||||||
#ifdef HAVE_MRUBY
|
#ifdef HAVE_MRUBY
|
||||||
|
@ -2060,26 +2081,28 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
#endif // !HAVE_MRUBY
|
#endif // !HAVE_MRUBY
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL:
|
case SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL:
|
||||||
mod_config()->accept_proxy_protocol = util::strieq(optarg, "yes");
|
mod_config()->conn.upstream.accept_proxy_protocol =
|
||||||
|
util::strieq(optarg, "yes");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_ADD_FORWARDED:
|
case SHRPX_OPTID_ADD_FORWARDED: {
|
||||||
mod_config()->forwarded_params = FORWARDED_NONE;
|
auto &fwdconf = mod_config()->http.forwarded;
|
||||||
|
fwdconf.params = FORWARDED_NONE;
|
||||||
for (const auto ¶m : util::parse_config_str_list(optarg)) {
|
for (const auto ¶m : util::parse_config_str_list(optarg)) {
|
||||||
if (util::strieq(param, "by")) {
|
if (util::strieq(param, "by")) {
|
||||||
mod_config()->forwarded_params |= FORWARDED_BY;
|
fwdconf.params |= FORWARDED_BY;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (util::strieq(param, "for")) {
|
if (util::strieq(param, "for")) {
|
||||||
mod_config()->forwarded_params |= FORWARDED_FOR;
|
fwdconf.params |= FORWARDED_FOR;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (util::strieq(param, "host")) {
|
if (util::strieq(param, "host")) {
|
||||||
mod_config()->forwarded_params |= FORWARDED_HOST;
|
fwdconf.params |= FORWARDED_HOST;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (util::strieq(param, "proto")) {
|
if (util::strieq(param, "proto")) {
|
||||||
mod_config()->forwarded_params |= FORWARDED_PROTO;
|
fwdconf.params |= FORWARDED_PROTO;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2089,8 +2112,9 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
case SHRPX_OPTID_STRIP_INCOMING_FORWARDED:
|
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;
|
return 0;
|
||||||
case SHRPX_OPTID_FORWARDED_BY:
|
case SHRPX_OPTID_FORWARDED_BY:
|
||||||
|
@ -2103,23 +2127,23 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto &fwdconf = mod_config()->http.forwarded;
|
||||||
|
|
||||||
switch (optid) {
|
switch (optid) {
|
||||||
case SHRPX_OPTID_FORWARDED_BY:
|
case SHRPX_OPTID_FORWARDED_BY:
|
||||||
mod_config()->forwarded_by_node_type =
|
fwdconf.by_node_type = static_cast<shrpx_forwarded_node_type>(type);
|
||||||
static_cast<shrpx_forwarded_node_type>(type);
|
|
||||||
if (optarg[0] == '_') {
|
if (optarg[0] == '_') {
|
||||||
mod_config()->forwarded_by_obfuscated = optarg;
|
fwdconf.by_obfuscated = optarg;
|
||||||
} else {
|
} else {
|
||||||
mod_config()->forwarded_by_obfuscated = "";
|
fwdconf.by_obfuscated = "";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SHRPX_OPTID_FORWARDED_FOR:
|
case SHRPX_OPTID_FORWARDED_FOR:
|
||||||
mod_config()->forwarded_for_node_type =
|
fwdconf.for_node_type = static_cast<shrpx_forwarded_node_type>(type);
|
||||||
static_cast<shrpx_forwarded_node_type>(type);
|
|
||||||
if (optarg[0] == '_') {
|
if (optarg[0] == '_') {
|
||||||
mod_config()->forwarded_for_obfuscated = optarg;
|
fwdconf.for_obfuscated = optarg;
|
||||||
} else {
|
} else {
|
||||||
mod_config()->forwarded_for_obfuscated = "";
|
fwdconf.for_obfuscated = "";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -289,178 +289,263 @@ struct HttpProxy {
|
||||||
std::string host;
|
std::string host;
|
||||||
// userinfo in http proxy URI, not percent-encoded form
|
// userinfo in http proxy URI, not percent-encoded form
|
||||||
std::string userinfo;
|
std::string userinfo;
|
||||||
|
// port in http proxy URI
|
||||||
uint16_t port;
|
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
|
// The list of (private key file, certificate file) pair
|
||||||
std::vector<std::pair<std::string, std::string>> subcerts;
|
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<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
|
// list of supported NPN/ALPN protocol strings in the order of
|
||||||
// preference.
|
// preference.
|
||||||
std::vector<std::string> npn_list;
|
std::vector<std::string> npn_list;
|
||||||
// list of supported SSL/TLS protocol strings.
|
// list of supported SSL/TLS protocol strings.
|
||||||
std::vector<std::string> tls_proto_list;
|
std::vector<std::string> tls_proto_list;
|
||||||
Address session_cache_memcached_addr;
|
// Bit mask to disable SSL/TLS protocol versions. This will be
|
||||||
Address tls_ticket_key_memcached_addr;
|
// passed to SSL_CTX_set_options().
|
||||||
Router router;
|
long int tls_proto_mask;
|
||||||
HttpProxy downstream_http_proxy;
|
std::string backend_sni_name;
|
||||||
// obfuscated value used in "by" parameter of Forwarded header
|
std::chrono::seconds session_timeout;
|
||||||
// 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;
|
|
||||||
std::unique_ptr<char[]> private_key_file;
|
std::unique_ptr<char[]> private_key_file;
|
||||||
std::unique_ptr<char[]> private_key_passwd;
|
std::unique_ptr<char[]> private_key_passwd;
|
||||||
std::unique_ptr<char[]> cert_file;
|
std::unique_ptr<char[]> cert_file;
|
||||||
std::unique_ptr<char[]> dh_param_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[]> ciphers;
|
||||||
std::unique_ptr<char[]> cacert;
|
std::unique_ptr<char[]> cacert;
|
||||||
std::unique_ptr<char[]> http2_upstream_dump_request_header_file;
|
bool insecure;
|
||||||
std::unique_ptr<char[]> http2_upstream_dump_response_header_file;
|
};
|
||||||
// Path to file containing CA certificate solely used for client
|
|
||||||
// certificate validation
|
struct HttpConfig {
|
||||||
std::unique_ptr<char[]> verify_client_cacert;
|
struct {
|
||||||
std::unique_ptr<char[]> client_private_key_file;
|
// obfuscated value used in "by" parameter of Forwarded header
|
||||||
std::unique_ptr<char[]> client_cert_file;
|
// field.
|
||||||
std::unique_ptr<char[]> accesslog_file;
|
std::string by_obfuscated;
|
||||||
std::unique_ptr<char[]> errorlog_file;
|
// obfuscated value used in "for" parameter of Forwarded header
|
||||||
std::unique_ptr<char[]> fetch_ocsp_response_file;
|
// 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[]> user;
|
||||||
std::unique_ptr<char[]> session_cache_memcached_host;
|
|
||||||
std::unique_ptr<char[]> tls_ticket_key_memcached_host;
|
|
||||||
std::unique_ptr<char[]> mruby_file;
|
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 **original_argv;
|
||||||
char **argv;
|
char **argv;
|
||||||
char *cwd;
|
char *cwd;
|
||||||
size_t num_worker;
|
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 padding;
|
||||||
size_t worker_frontend_connections;
|
|
||||||
size_t rlimit_nofile;
|
size_t rlimit_nofile;
|
||||||
size_t downstream_request_buffer_size;
|
|
||||||
size_t downstream_response_buffer_size;
|
|
||||||
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 argc;
|
||||||
int fastopen;
|
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
// frontend listening port. 0 if frontend listens on UNIX domain
|
|
||||||
// socket, in this case |host_unix| must be true.
|
|
||||||
uint16_t port;
|
|
||||||
// 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 verbose;
|
||||||
bool daemon;
|
bool daemon;
|
||||||
bool verify_client;
|
|
||||||
bool http2_proxy;
|
bool http2_proxy;
|
||||||
bool http2_bridge;
|
bool http2_bridge;
|
||||||
bool client_proxy;
|
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;
|
bool client;
|
||||||
// true if --client or --client-proxy are enabled.
|
// true if --client or --client-proxy are enabled.
|
||||||
bool client_mode;
|
bool client_mode;
|
||||||
bool 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();
|
const Config *get_config();
|
||||||
|
|
|
@ -42,15 +42,17 @@ using namespace nghttp2;
|
||||||
namespace shrpx {
|
namespace shrpx {
|
||||||
Connection::Connection(struct ev_loop *loop, int fd, SSL *ssl,
|
Connection::Connection(struct ev_loop *loop, int fd, SSL *ssl,
|
||||||
MemchunkPool *mcpool, ev_tstamp write_timeout,
|
MemchunkPool *mcpool, ev_tstamp write_timeout,
|
||||||
ev_tstamp read_timeout, size_t write_rate,
|
ev_tstamp read_timeout,
|
||||||
size_t write_burst, size_t read_rate, size_t read_burst,
|
const RateLimitConfig &write_limit,
|
||||||
IOCb writecb, IOCb readcb, TimerCb timeoutcb, void *data,
|
const RateLimitConfig &read_limit, IOCb writecb,
|
||||||
|
IOCb readcb, TimerCb timeoutcb, void *data,
|
||||||
size_t tls_dyn_rec_warmup_threshold,
|
size_t tls_dyn_rec_warmup_threshold,
|
||||||
ev_tstamp tls_dyn_rec_idle_timeout)
|
ev_tstamp tls_dyn_rec_idle_timeout)
|
||||||
: tls{DefaultMemchunks(mcpool), DefaultPeekMemchunks(mcpool)},
|
: tls{DefaultMemchunks(mcpool), DefaultPeekMemchunks(mcpool)},
|
||||||
wlimit(loop, &wev, write_rate, write_burst),
|
wlimit(loop, &wev, write_limit.rate, write_limit.burst),
|
||||||
rlimit(loop, &rev, read_rate, read_burst, this), writecb(writecb),
|
rlimit(loop, &rev, read_limit.rate, read_limit.burst, this),
|
||||||
readcb(readcb), timeoutcb(timeoutcb), loop(loop), data(data), fd(fd),
|
writecb(writecb), readcb(readcb), timeoutcb(timeoutcb), loop(loop),
|
||||||
|
data(data), fd(fd),
|
||||||
tls_dyn_rec_warmup_threshold(tls_dyn_rec_warmup_threshold),
|
tls_dyn_rec_warmup_threshold(tls_dyn_rec_warmup_threshold),
|
||||||
tls_dyn_rec_idle_timeout(tls_dyn_rec_idle_timeout) {
|
tls_dyn_rec_idle_timeout(tls_dyn_rec_idle_timeout) {
|
||||||
|
|
||||||
|
|
|
@ -73,10 +73,10 @@ using TimerCb = EVCb<ev_timer>;
|
||||||
|
|
||||||
struct Connection {
|
struct Connection {
|
||||||
Connection(struct ev_loop *loop, int fd, SSL *ssl, MemchunkPool *mcpool,
|
Connection(struct ev_loop *loop, int fd, SSL *ssl, MemchunkPool *mcpool,
|
||||||
ev_tstamp write_timeout, ev_tstamp read_timeout, size_t write_rate,
|
ev_tstamp write_timeout, ev_tstamp read_timeout,
|
||||||
size_t write_burst, size_t read_rate, size_t read_burst,
|
const RateLimitConfig &write_limit,
|
||||||
IOCb writecb, IOCb readcb, TimerCb timeoutcb, void *data,
|
const RateLimitConfig &read_limit, IOCb writecb, IOCb readcb,
|
||||||
size_t tls_dyn_rec_warmup_threshold,
|
TimerCb timeoutcb, void *data, size_t tls_dyn_rec_warmup_threshold,
|
||||||
ev_tstamp tls_dyn_rec_idle_timeout);
|
ev_tstamp tls_dyn_rec_idle_timeout);
|
||||||
~Connection();
|
~Connection();
|
||||||
|
|
||||||
|
|
|
@ -300,13 +300,13 @@ int ConnectionHandler::handle_connection(int fd, sockaddr *addr, int addrlen) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_config()->num_worker == 1) {
|
if (get_config()->num_worker == 1) {
|
||||||
|
auto &upstreamconf = get_config()->conn.upstream;
|
||||||
if (single_worker_->get_worker_stat()->num_connections >=
|
if (single_worker_->get_worker_stat()->num_connections >=
|
||||||
get_config()->worker_frontend_connections) {
|
upstreamconf.worker_connections) {
|
||||||
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
LLOG(INFO, this) << "Too many connections >="
|
LLOG(INFO, this) << "Too many connections >="
|
||||||
<< get_config()->worker_frontend_connections;
|
<< upstreamconf.worker_connections;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -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_)) {
|
if (t == 0. || ev_is_active(&disable_acceptor_timer_)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -450,7 +450,7 @@ int ConnectionHandler::start_ocsp_update(const char *cert_file) {
|
||||||
assert(!ev_is_active(&ocsp_.chldev));
|
assert(!ev_is_active(&ocsp_.chldev));
|
||||||
|
|
||||||
char *const argv[] = {
|
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};
|
const_cast<char *>(cert_file), nullptr};
|
||||||
char *const envp[] = {nullptr};
|
char *const envp[] = {nullptr};
|
||||||
|
|
||||||
|
@ -634,7 +634,7 @@ void ConnectionHandler::proceed_next_cert_ocsp() {
|
||||||
if (ocsp_.next == all_ssl_ctx_.size()) {
|
if (ocsp_.next == all_ssl_ctx_.size()) {
|
||||||
ocsp_.next = 0;
|
ocsp_.next = 0;
|
||||||
// We have updated all ocsp response, and schedule next update.
|
// 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_);
|
ev_timer_start(loop_, &ocsp_timer_);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -673,7 +673,7 @@ ConnectionHandler::get_tls_ticket_key_memcached_dispatcher() const {
|
||||||
|
|
||||||
void ConnectionHandler::on_tls_ticket_key_network_error(ev_timer *w) {
|
void ConnectionHandler::on_tls_ticket_key_network_error(ev_timer *w) {
|
||||||
if (++tls_ticket_key_memcached_get_retry_count_ >=
|
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 "
|
LOG(WARN) << "Memcached: tls ticket get retry all failed "
|
||||||
<< tls_ticket_key_memcached_get_retry_count_ << " times.";
|
<< 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;
|
tls_ticket_key_memcached_get_retry_count_ = 0;
|
||||||
|
|
||||||
if (++tls_ticket_key_memcached_fail_count_ >=
|
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";
|
LOG(WARN) << "Memcached: could not get tls ticket; disable tls ticket";
|
||||||
|
|
||||||
tls_ticket_key_memcached_fail_count_ = 0;
|
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(
|
void ConnectionHandler::schedule_next_tls_ticket_key_memcached_get(
|
||||||
ev_timer *w) {
|
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);
|
ev_timer_start(loop_, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ public:
|
||||||
AcceptHandler *get_acceptor6() const;
|
AcceptHandler *get_acceptor6() const;
|
||||||
void enable_acceptor();
|
void enable_acceptor();
|
||||||
void disable_acceptor();
|
void disable_acceptor();
|
||||||
void disable_acceptor_temporary(ev_tstamp t);
|
void sleep_acceptor(ev_tstamp t);
|
||||||
void accept_pending_connection();
|
void accept_pending_connection();
|
||||||
void graceful_shutdown_worker();
|
void graceful_shutdown_worker();
|
||||||
void set_graceful_shutdown(bool f);
|
void set_graceful_shutdown(bool f);
|
||||||
|
|
|
@ -124,14 +124,16 @@ Downstream::Downstream(Upstream *upstream, MemchunkPool *mcpool,
|
||||||
chunked_response_(false), expect_final_response_(false),
|
chunked_response_(false), expect_final_response_(false),
|
||||||
request_pending_(false) {
|
request_pending_(false) {
|
||||||
|
|
||||||
|
auto &timeoutconf = get_config()->http2.timeout;
|
||||||
|
|
||||||
ev_timer_init(&upstream_rtimer_, &upstream_rtimeoutcb, 0.,
|
ev_timer_init(&upstream_rtimer_, &upstream_rtimeoutcb, 0.,
|
||||||
get_config()->stream_read_timeout);
|
timeoutconf.stream_read);
|
||||||
ev_timer_init(&upstream_wtimer_, &upstream_wtimeoutcb, 0.,
|
ev_timer_init(&upstream_wtimer_, &upstream_wtimeoutcb, 0.,
|
||||||
get_config()->stream_write_timeout);
|
timeoutconf.stream_write);
|
||||||
ev_timer_init(&downstream_rtimer_, &downstream_rtimeoutcb, 0.,
|
ev_timer_init(&downstream_rtimer_, &downstream_rtimeoutcb, 0.,
|
||||||
get_config()->stream_read_timeout);
|
timeoutconf.stream_read);
|
||||||
ev_timer_init(&downstream_wtimer_, &downstream_wtimeoutcb, 0.,
|
ev_timer_init(&downstream_wtimer_, &downstream_wtimeoutcb, 0.,
|
||||||
get_config()->stream_write_timeout);
|
timeoutconf.stream_write);
|
||||||
|
|
||||||
upstream_rtimer_.data = this;
|
upstream_rtimer_.data = this;
|
||||||
upstream_wtimer_.data = this;
|
upstream_wtimer_.data = this;
|
||||||
|
@ -491,7 +493,8 @@ void Downstream::set_chunked_request(bool f) { chunked_request_ = f; }
|
||||||
|
|
||||||
bool Downstream::request_buf_full() {
|
bool Downstream::request_buf_full() {
|
||||||
if (dconn_) {
|
if (dconn_) {
|
||||||
return request_buf_.rleft() >= get_config()->downstream_request_buffer_size;
|
return request_buf_.rleft() >=
|
||||||
|
get_config()->conn.downstream.request_buffer_size;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -582,7 +585,7 @@ DefaultMemchunks *Downstream::get_response_buf() { return &response_buf_; }
|
||||||
bool Downstream::response_buf_full() {
|
bool Downstream::response_buf_full() {
|
||||||
if (dconn_) {
|
if (dconn_) {
|
||||||
return response_buf_.rleft() >=
|
return response_buf_.rleft() >=
|
||||||
get_config()->downstream_response_buffer_size;
|
get_config()->conn.downstream.response_buffer_size;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -764,7 +767,7 @@ void disable_timer(struct ev_loop *loop, ev_timer *w) {
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void Downstream::reset_upstream_rtimer() {
|
void Downstream::reset_upstream_rtimer() {
|
||||||
if (get_config()->stream_read_timeout == 0.) {
|
if (get_config()->http2.timeout.stream_read == 0.) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto loop = upstream_->get_client_handler()->get_loop();
|
auto loop = upstream_->get_client_handler()->get_loop();
|
||||||
|
@ -773,16 +776,18 @@ void Downstream::reset_upstream_rtimer() {
|
||||||
|
|
||||||
void Downstream::reset_upstream_wtimer() {
|
void Downstream::reset_upstream_wtimer() {
|
||||||
auto loop = upstream_->get_client_handler()->get_loop();
|
auto loop = upstream_->get_client_handler()->get_loop();
|
||||||
if (get_config()->stream_write_timeout != 0.) {
|
auto &timeoutconf = get_config()->http2.timeout;
|
||||||
|
|
||||||
|
if (timeoutconf.stream_write != 0.) {
|
||||||
reset_timer(loop, &upstream_wtimer_);
|
reset_timer(loop, &upstream_wtimer_);
|
||||||
}
|
}
|
||||||
if (get_config()->stream_read_timeout != 0.) {
|
if (timeoutconf.stream_read != 0.) {
|
||||||
try_reset_timer(loop, &upstream_rtimer_);
|
try_reset_timer(loop, &upstream_rtimer_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Downstream::ensure_upstream_wtimer() {
|
void Downstream::ensure_upstream_wtimer() {
|
||||||
if (get_config()->stream_write_timeout == 0.) {
|
if (get_config()->http2.timeout.stream_write == 0.) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto loop = upstream_->get_client_handler()->get_loop();
|
auto loop = upstream_->get_client_handler()->get_loop();
|
||||||
|
@ -790,7 +795,7 @@ void Downstream::ensure_upstream_wtimer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Downstream::disable_upstream_rtimer() {
|
void Downstream::disable_upstream_rtimer() {
|
||||||
if (get_config()->stream_read_timeout == 0.) {
|
if (get_config()->http2.timeout.stream_read == 0.) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto loop = upstream_->get_client_handler()->get_loop();
|
auto loop = upstream_->get_client_handler()->get_loop();
|
||||||
|
@ -798,7 +803,7 @@ void Downstream::disable_upstream_rtimer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Downstream::disable_upstream_wtimer() {
|
void Downstream::disable_upstream_wtimer() {
|
||||||
if (get_config()->stream_write_timeout == 0.) {
|
if (get_config()->http2.timeout.stream_write == 0.) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto loop = upstream_->get_client_handler()->get_loop();
|
auto loop = upstream_->get_client_handler()->get_loop();
|
||||||
|
@ -806,7 +811,7 @@ void Downstream::disable_upstream_wtimer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Downstream::reset_downstream_rtimer() {
|
void Downstream::reset_downstream_rtimer() {
|
||||||
if (get_config()->stream_read_timeout == 0.) {
|
if (get_config()->http2.timeout.stream_read == 0.) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto loop = upstream_->get_client_handler()->get_loop();
|
auto loop = upstream_->get_client_handler()->get_loop();
|
||||||
|
@ -815,16 +820,18 @@ void Downstream::reset_downstream_rtimer() {
|
||||||
|
|
||||||
void Downstream::reset_downstream_wtimer() {
|
void Downstream::reset_downstream_wtimer() {
|
||||||
auto loop = upstream_->get_client_handler()->get_loop();
|
auto loop = upstream_->get_client_handler()->get_loop();
|
||||||
if (get_config()->stream_write_timeout != 0.) {
|
auto &timeoutconf = get_config()->http2.timeout;
|
||||||
|
|
||||||
|
if (timeoutconf.stream_write != 0.) {
|
||||||
reset_timer(loop, &downstream_wtimer_);
|
reset_timer(loop, &downstream_wtimer_);
|
||||||
}
|
}
|
||||||
if (get_config()->stream_read_timeout != 0.) {
|
if (timeoutconf.stream_read != 0.) {
|
||||||
try_reset_timer(loop, &downstream_rtimer_);
|
try_reset_timer(loop, &downstream_rtimer_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Downstream::ensure_downstream_wtimer() {
|
void Downstream::ensure_downstream_wtimer() {
|
||||||
if (get_config()->stream_write_timeout == 0.) {
|
if (get_config()->http2.timeout.stream_write == 0.) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto loop = upstream_->get_client_handler()->get_loop();
|
auto loop = upstream_->get_client_handler()->get_loop();
|
||||||
|
@ -832,7 +839,7 @@ void Downstream::ensure_downstream_wtimer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Downstream::disable_downstream_rtimer() {
|
void Downstream::disable_downstream_rtimer() {
|
||||||
if (get_config()->stream_read_timeout == 0.) {
|
if (get_config()->http2.timeout.stream_read == 0.) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto loop = upstream_->get_client_handler()->get_loop();
|
auto loop = upstream_->get_client_handler()->get_loop();
|
||||||
|
@ -840,7 +847,7 @@ void Downstream::disable_downstream_rtimer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Downstream::disable_downstream_wtimer() {
|
void Downstream::disable_downstream_wtimer() {
|
||||||
if (get_config()->stream_write_timeout == 0.) {
|
if (get_config()->http2.timeout.stream_write == 0.) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto loop = upstream_->get_client_handler()->get_loop();
|
auto loop = upstream_->get_client_handler()->get_loop();
|
||||||
|
|
|
@ -44,10 +44,10 @@ std::string create_error_html(unsigned int status_code) {
|
||||||
res += "</title><body><h1>";
|
res += "</title><body><h1>";
|
||||||
res += status;
|
res += status;
|
||||||
res += "</h1><footer>";
|
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.append(server_name.c_str(), server_name.size());
|
||||||
res += " at port ";
|
res += " at port ";
|
||||||
res += util::utos(get_config()->port);
|
res += util::utos(get_config()->conn.listener.port);
|
||||||
res += "</footer></body></html>";
|
res += "</footer></body></html>";
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,8 +256,11 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
|
|
||||||
const auto &req = downstream_->request();
|
const auto &req = downstream_->request();
|
||||||
|
|
||||||
|
auto &httpconf = get_config()->http;
|
||||||
|
auto &http2conf = get_config()->http2;
|
||||||
|
|
||||||
auto no_host_rewrite =
|
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;
|
get_config()->client_proxy || req.method == HTTP_CONNECT;
|
||||||
|
|
||||||
// http2session_ has already in CONNECTED state, so we can get
|
// 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 addr_idx = http2session_->get_addr_idx();
|
||||||
auto group = http2session_->get_group();
|
auto group = http2session_->get_group();
|
||||||
const auto &downstream_hostport =
|
const auto &downstream_hostport =
|
||||||
get_config()->downstream_addr_groups[group].addrs[addr_idx].hostport;
|
get_config()->conn.downstream.addr_groups[group].addrs[addr_idx].hostport;
|
||||||
|
|
||||||
// For HTTP/1.0 request, there is no authority in request. In that
|
// For HTTP/1.0 request, there is no authority in request. In that
|
||||||
// case, we use backend server's host nonetheless.
|
// case, we use backend server's host nonetheless.
|
||||||
|
@ -278,7 +281,7 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
downstream_->set_request_downstream_host(authority.str());
|
downstream_->set_request_downstream_host(authority.str());
|
||||||
|
|
||||||
size_t num_cookies = 0;
|
size_t num_cookies = 0;
|
||||||
if (!get_config()->http2_no_cookie_crumbling) {
|
if (!http2conf.no_cookie_crumbling) {
|
||||||
num_cookies = downstream_->count_crumble_request_cookie();
|
num_cookies = downstream_->count_crumble_request_cookie();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +297,7 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
// 9. forwarded (optional)
|
// 9. forwarded (optional)
|
||||||
auto nva = std::vector<nghttp2_nv>();
|
auto nva = std::vector<nghttp2_nv>();
|
||||||
nva.reserve(req.fs.headers().size() + 9 + num_cookies +
|
nva.reserve(req.fs.headers().size() + 9 + num_cookies +
|
||||||
get_config()->add_request_headers.size());
|
httpconf.add_request_headers.size());
|
||||||
|
|
||||||
nva.push_back(
|
nva.push_back(
|
||||||
http2::make_nv_lc_nocopy(":method", http2::to_method_string(req.method)));
|
http2::make_nv_lc_nocopy(":method", http2::to_method_string(req.method)));
|
||||||
|
@ -328,7 +331,7 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
chunked_encoding = true;
|
chunked_encoding = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!get_config()->http2_no_cookie_crumbling) {
|
if (!http2conf.no_cookie_crumbling) {
|
||||||
downstream_->crumble_request_cookie(nva);
|
downstream_->crumble_request_cookie(nva);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,12 +340,13 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
|
|
||||||
std::string forwarded_value;
|
std::string forwarded_value;
|
||||||
|
|
||||||
auto fwd = get_config()->strip_incoming_forwarded
|
auto &fwdconf = httpconf.forwarded;
|
||||||
? nullptr
|
|
||||||
: req.fs.header(http2::HD_FORWARDED);
|
|
||||||
|
|
||||||
if (get_config()->forwarded_params) {
|
auto fwd =
|
||||||
auto params = get_config()->forwarded_params;
|
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 ||
|
if (get_config()->http2_proxy || get_config()->client_proxy ||
|
||||||
req.method == HTTP_CONNECT) {
|
req.method == HTTP_CONNECT) {
|
||||||
|
@ -370,12 +374,14 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
forwarded_value = fwd->value;
|
forwarded_value = fwd->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string xff_value;
|
auto &xffconf = httpconf.xff;
|
||||||
auto xff = get_config()->strip_incoming_x_forwarded_for
|
|
||||||
? nullptr
|
|
||||||
: req.fs.header(http2::HD_X_FORWARDED_FOR);
|
|
||||||
|
|
||||||
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) {
|
if (xff) {
|
||||||
xff_value = (*xff).value;
|
xff_value = (*xff).value;
|
||||||
xff_value += ", ";
|
xff_value += ", ";
|
||||||
|
@ -394,7 +400,7 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||||
|
|
||||||
std::string via_value;
|
std::string via_value;
|
||||||
auto via = req.fs.header(http2::HD_VIA);
|
auto via = req.fs.header(http2::HD_VIA);
|
||||||
if (get_config()->no_via) {
|
if (httpconf.no_via) {
|
||||||
if (via) {
|
if (via) {
|
||||||
nva.push_back(http2::make_nv_ls_nocopy("via", (*via).value));
|
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"));
|
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));
|
nva.push_back(http2::make_nv_nocopy(p.first, p.second));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -146,10 +146,10 @@ Http2Session::Http2Session(struct ev_loop *loop, SSL_CTX *ssl_ctx,
|
||||||
ConnectBlocker *connect_blocker, Worker *worker,
|
ConnectBlocker *connect_blocker, Worker *worker,
|
||||||
size_t group, size_t idx)
|
size_t group, size_t idx)
|
||||||
: conn_(loop, -1, nullptr, worker->get_mcpool(),
|
: conn_(loop, -1, nullptr, worker->get_mcpool(),
|
||||||
get_config()->downstream_write_timeout,
|
get_config()->conn.downstream.timeout.write,
|
||||||
get_config()->downstream_read_timeout, 0, 0, 0, 0, writecb, readcb,
|
get_config()->conn.downstream.timeout.read, {}, {}, writecb, readcb,
|
||||||
timeoutcb, this, get_config()->tls_dyn_rec_warmup_threshold,
|
timeoutcb, this, get_config()->tls.dyn_rec.warmup_threshold,
|
||||||
get_config()->tls_dyn_rec_idle_timeout),
|
get_config()->tls.dyn_rec.idle_timeout),
|
||||||
worker_(worker), connect_blocker_(connect_blocker), ssl_ctx_(ssl_ctx),
|
worker_(worker), connect_blocker_(connect_blocker), ssl_ctx_(ssl_ctx),
|
||||||
session_(nullptr), data_pending_(nullptr), data_pendinglen_(0),
|
session_(nullptr), data_pending_(nullptr), data_pendinglen_(0),
|
||||||
addr_idx_(0), group_(group), index_(idx), state_(DISCONNECTED),
|
addr_idx_(0), group_(group), index_(idx), state_(DISCONNECTED),
|
||||||
|
@ -240,13 +240,13 @@ int Http2Session::disconnect(bool hard) {
|
||||||
int Http2Session::check_cert() {
|
int Http2Session::check_cert() {
|
||||||
return ssl::check_cert(
|
return ssl::check_cert(
|
||||||
conn_.tls.ssl,
|
conn_.tls.ssl,
|
||||||
&get_config()->downstream_addr_groups[group_].addrs[addr_idx_]);
|
&get_config()->conn.downstream.addr_groups[group_].addrs[addr_idx_]);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Http2Session::initiate_connection() {
|
int Http2Session::initiate_connection() {
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
|
||||||
auto &addrs = get_config()->downstream_addr_groups[group_].addrs;
|
auto &addrs = get_config()->conn.downstream.addr_groups[group_].addrs;
|
||||||
|
|
||||||
if (state_ == DISCONNECTED) {
|
if (state_ == DISCONNECTED) {
|
||||||
if (connect_blocker_->blocked()) {
|
if (connect_blocker_->blocked()) {
|
||||||
|
@ -331,8 +331,8 @@ int Http2Session::initiate_connection() {
|
||||||
conn_.set_ssl(ssl);
|
conn_.set_ssl(ssl);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef sni_name = !get_config()->backend_tls_sni_name.empty()
|
StringRef sni_name = !get_config()->tls.backend_sni_name.empty()
|
||||||
? get_config()->backend_tls_sni_name
|
? get_config()->tls.backend_sni_name
|
||||||
: downstream_addr.host;
|
: downstream_addr.host;
|
||||||
|
|
||||||
if (!util::numeric_host(sni_name.c_str())) {
|
if (!util::numeric_host(sni_name.c_str())) {
|
||||||
|
@ -509,7 +509,7 @@ int Http2Session::downstream_connect_proxy() {
|
||||||
SSLOG(INFO, this) << "Connected to the proxy";
|
SSLOG(INFO, this) << "Connected to the proxy";
|
||||||
}
|
}
|
||||||
auto &downstream_addr =
|
auto &downstream_addr =
|
||||||
get_config()->downstream_addr_groups[group_].addrs[addr_idx_];
|
get_config()->conn.downstream.addr_groups[group_].addrs[addr_idx_];
|
||||||
|
|
||||||
std::string req = "CONNECT ";
|
std::string req = "CONNECT ";
|
||||||
req.append(downstream_addr.hostport.c_str(), downstream_addr.hostport.size());
|
req.append(downstream_addr.hostport.c_str(), downstream_addr.hostport.size());
|
||||||
|
@ -1309,9 +1309,10 @@ int Http2Session::connection_made() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = nghttp2_session_client_new2(&session_,
|
auto &http2conf = get_config()->http2;
|
||||||
get_config()->http2_downstream_callbacks,
|
|
||||||
this, get_config()->http2_client_option);
|
rv = nghttp2_session_client_new2(&session_, http2conf.downstream.callbacks,
|
||||||
|
this, http2conf.downstream.option);
|
||||||
|
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1322,12 +1323,12 @@ int Http2Session::connection_made() {
|
||||||
std::array<nghttp2_settings_entry, 3> entry;
|
std::array<nghttp2_settings_entry, 3> entry;
|
||||||
size_t nentry = 2;
|
size_t nentry = 2;
|
||||||
entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
|
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].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) {
|
get_config()->client_proxy) {
|
||||||
entry[nentry].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
|
entry[nentry].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
|
||||||
entry[nentry].value = 0;
|
entry[nentry].value = 0;
|
||||||
|
@ -1340,17 +1341,17 @@ int Http2Session::connection_made() {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_config()->http2_downstream_connection_window_bits > 16) {
|
auto connection_window_bits = http2conf.downstream.connection_window_bits;
|
||||||
int32_t delta =
|
if (connection_window_bits > 16) {
|
||||||
(1 << get_config()->http2_downstream_connection_window_bits) - 1 -
|
int32_t delta = (1 << connection_window_bits) - 1 -
|
||||||
NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
|
NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
|
||||||
rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0, delta);
|
rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0, delta);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return -1;
|
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);
|
!nghttp2::ssl::check_http2_requirement(conn_.tls.ssl);
|
||||||
|
|
||||||
if (must_terminate) {
|
if (must_terminate) {
|
||||||
|
@ -1718,7 +1719,7 @@ int Http2Session::tls_handshake() {
|
||||||
SSLOG(INFO, this) << "SSL/TLS handshake completed";
|
SSLOG(INFO, this) << "SSL/TLS handshake completed";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!get_config()->downstream_no_tls && !get_config()->insecure &&
|
if (!get_config()->conn.downstream.no_tls && !get_config()->tls.insecure &&
|
||||||
check_cert() != 0) {
|
check_cert() != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 *name, size_t namelen,
|
||||||
const uint8_t *value, size_t valuelen, uint8_t flags,
|
const uint8_t *value, size_t valuelen, uint8_t flags,
|
||||||
void *user_data) {
|
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,
|
verbose_on_header_callback(session, frame, name, namelen, value, valuelen,
|
||||||
flags, user_data);
|
flags, user_data);
|
||||||
}
|
}
|
||||||
|
@ -170,9 +170,11 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
||||||
|
|
||||||
auto &req = downstream->request();
|
auto &req = downstream->request();
|
||||||
|
|
||||||
|
auto &httpconf = get_config()->http;
|
||||||
|
|
||||||
if (req.fs.buffer_size() + namelen + valuelen >
|
if (req.fs.buffer_size() + namelen + valuelen >
|
||||||
get_config()->header_field_buffer ||
|
httpconf.header_field_buffer ||
|
||||||
req.fs.num_fields() >= get_config()->max_header_fields) {
|
req.fs.num_fields() >= httpconf.max_header_fields) {
|
||||||
if (downstream->get_response_state() == Downstream::MSG_COMPLETE) {
|
if (downstream->get_response_state() == Downstream::MSG_COMPLETE) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -263,8 +265,10 @@ int Http2Upstream::on_request_headers(Downstream *downstream,
|
||||||
<< downstream->get_stream_id() << "\n" << ss.str();
|
<< downstream->get_stream_id() << "\n" << ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_config()->http2_upstream_dump_request_header) {
|
auto &dump = get_config()->http2.upstream.debug.dump;
|
||||||
http2::dump_nv(get_config()->http2_upstream_dump_request_header, nva);
|
|
||||||
|
if (dump.request_header) {
|
||||||
|
http2::dump_nv(dump.request_header, nva);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto content_length = req.fs.header(http2::HD_CONTENT_LENGTH);
|
auto content_length = req.fs.header(http2::HD_CONTENT_LENGTH);
|
||||||
|
@ -398,7 +402,7 @@ void Http2Upstream::initiate_downstream(Downstream *downstream) {
|
||||||
namespace {
|
namespace {
|
||||||
int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
||||||
void *user_data) {
|
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);
|
verbose_on_frame_recv_callback(session, frame, user_data);
|
||||||
}
|
}
|
||||||
auto upstream = static_cast<Http2Upstream *>(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 {
|
namespace {
|
||||||
int on_frame_send_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
int on_frame_send_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
||||||
void *user_data) {
|
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);
|
verbose_on_frame_send_callback(session, frame, user_data);
|
||||||
}
|
}
|
||||||
auto upstream = static_cast<Http2Upstream *>(user_data);
|
auto upstream = static_cast<Http2Upstream *>(user_data);
|
||||||
|
@ -848,9 +852,9 @@ nghttp2_session_callbacks *create_http2_upstream_callbacks() {
|
||||||
Http2Upstream::Http2Upstream(ClientHandler *handler)
|
Http2Upstream::Http2Upstream(ClientHandler *handler)
|
||||||
: downstream_queue_(
|
: downstream_queue_(
|
||||||
get_config()->http2_proxy
|
get_config()->http2_proxy
|
||||||
? get_config()->downstream_connections_per_host
|
? get_config()->conn.downstream.connections_per_host
|
||||||
: get_config()->downstream_proto == PROTO_HTTP
|
: get_config()->conn.downstream.proto == PROTO_HTTP
|
||||||
? get_config()->downstream_connections_per_frontend
|
? get_config()->conn.downstream.connections_per_frontend
|
||||||
: 0,
|
: 0,
|
||||||
!get_config()->http2_proxy),
|
!get_config()->http2_proxy),
|
||||||
pending_response_buf_(handler->get_worker()->get_mcpool()),
|
pending_response_buf_(handler->get_worker()->get_mcpool()),
|
||||||
|
@ -860,9 +864,10 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
|
||||||
|
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
rv = nghttp2_session_server_new2(&session_,
|
auto &http2conf = get_config()->http2;
|
||||||
get_config()->http2_upstream_callbacks, this,
|
|
||||||
get_config()->http2_option);
|
rv = nghttp2_session_server_new2(&session_, http2conf.upstream.callbacks,
|
||||||
|
this, http2conf.upstream.option);
|
||||||
|
|
||||||
assert(rv == 0);
|
assert(rv == 0);
|
||||||
|
|
||||||
|
@ -871,10 +876,10 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
|
||||||
// TODO Maybe call from outside?
|
// TODO Maybe call from outside?
|
||||||
std::array<nghttp2_settings_entry, 2> entry;
|
std::array<nghttp2_settings_entry, 2> entry;
|
||||||
entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
|
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].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(),
|
rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry.data(),
|
||||||
entry.size());
|
entry.size());
|
||||||
|
@ -883,9 +888,9 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
|
||||||
<< nghttp2_strerror(rv);
|
<< nghttp2_strerror(rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_config()->http2_upstream_connection_window_bits > 16) {
|
if (http2conf.upstream.connection_window_bits > 16) {
|
||||||
int32_t delta = (1 << get_config()->http2_upstream_connection_window_bits) -
|
int32_t delta = (1 << http2conf.upstream.connection_window_bits) - 1 -
|
||||||
1 - NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
|
NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
|
||||||
rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0, delta);
|
rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0, delta);
|
||||||
|
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
|
@ -909,7 +914,7 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
|
||||||
ev_prepare_start(handler_->get_loop(), &prep_);
|
ev_prepare_start(handler_->get_loop(), &prep_);
|
||||||
|
|
||||||
handler_->reset_upstream_read_timeout(
|
handler_->reset_upstream_read_timeout(
|
||||||
get_config()->http2_upstream_read_timeout);
|
get_config()->conn.upstream.timeout.http2_read);
|
||||||
|
|
||||||
handler_->signal_write();
|
handler_->signal_write();
|
||||||
}
|
}
|
||||||
|
@ -1337,7 +1342,7 @@ int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body,
|
||||||
|
|
||||||
if (!resp.fs.header(http2::HD_SERVER)) {
|
if (!resp.fs.header(http2::HD_SERVER)) {
|
||||||
nva.push_back(
|
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(),
|
rv = nghttp2_submit_response(session_, downstream->get_stream_id(),
|
||||||
|
@ -1386,7 +1391,7 @@ int Http2Upstream::error_reply(Downstream *downstream,
|
||||||
: http2::make_nv_ls(":status",
|
: http2::make_nv_ls(":status",
|
||||||
(status_code_str = util::utos(status_code))),
|
(status_code_str = util::utos(status_code))),
|
||||||
http2::make_nv_ll("content-type", "text/html; charset=UTF-8"),
|
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("content-length", content_length),
|
||||||
http2::make_nv_ls("date", lgconf->time_http_str));
|
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 &&
|
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);
|
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
|
// 4 means :status and possible server, via and x-http2-push header
|
||||||
// field.
|
// field.
|
||||||
nva.reserve(resp.fs.headers().size() + 4 +
|
nva.reserve(resp.fs.headers().size() + 4 +
|
||||||
get_config()->add_response_headers.size());
|
httpconf.add_response_headers.size());
|
||||||
std::string via_value;
|
std::string via_value;
|
||||||
std::string response_status;
|
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());
|
http2::copy_headers_to_nva_nocopy(nva, resp.fs.headers());
|
||||||
|
|
||||||
if (!get_config()->http2_proxy && !get_config()->client_proxy) {
|
if (!get_config()->http2_proxy && !get_config()->client_proxy) {
|
||||||
nva.push_back(
|
nva.push_back(http2::make_nv_ls_nocopy("server", httpconf.server_name));
|
||||||
http2::make_nv_ls_nocopy("server", get_config()->server_name));
|
|
||||||
} else {
|
} else {
|
||||||
auto server = resp.fs.header(http2::HD_SERVER);
|
auto server = resp.fs.header(http2::HD_SERVER);
|
||||||
if (server) {
|
if (server) {
|
||||||
|
@ -1516,7 +1522,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto via = resp.fs.header(http2::HD_VIA);
|
auto via = resp.fs.header(http2::HD_VIA);
|
||||||
if (get_config()->no_via) {
|
if (httpconf.no_via) {
|
||||||
if (via) {
|
if (via) {
|
||||||
nva.push_back(http2::make_nv_ls_nocopy("via", (*via).value));
|
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));
|
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));
|
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);
|
log_response_headers(downstream, nva);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_config()->http2_upstream_dump_response_header) {
|
auto &http2conf = get_config()->http2;
|
||||||
http2::dump_nv(get_config()->http2_upstream_dump_response_header,
|
|
||||||
nva.data(), nva.size());
|
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;
|
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
|
// * We requires GET or POST for associated resource. Probably we
|
||||||
// don't want to push for HEAD request. Not sure other methods
|
// don't want to push for HEAD request. Not sure other methods
|
||||||
// are also eligible for push.
|
// are also eligible for push.
|
||||||
if (!get_config()->no_server_push &&
|
if (!http2conf.no_server_push &&
|
||||||
nghttp2_session_get_remote_settings(session_,
|
nghttp2_session_get_remote_settings(session_,
|
||||||
NGHTTP2_SETTINGS_ENABLE_PUSH) == 1 &&
|
NGHTTP2_SETTINGS_ENABLE_PUSH) == 1 &&
|
||||||
!get_config()->http2_proxy && !get_config()->client_proxy &&
|
!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 {
|
bool Http2Upstream::push_enabled() const {
|
||||||
return !(get_config()->no_server_push ||
|
return !(get_config()->http2.no_server_push ||
|
||||||
nghttp2_session_get_remote_settings(
|
nghttp2_session_get_remote_settings(
|
||||||
session_, NGHTTP2_SETTINGS_ENABLE_PUSH) == 0 ||
|
session_, NGHTTP2_SETTINGS_ENABLE_PUSH) == 0 ||
|
||||||
get_config()->http2_proxy || get_config()->client_proxy);
|
get_config()->http2_proxy || get_config()->client_proxy);
|
||||||
|
|
|
@ -113,10 +113,11 @@ void connectcb(struct ev_loop *loop, ev_io *w, int revents) {
|
||||||
HttpDownstreamConnection::HttpDownstreamConnection(
|
HttpDownstreamConnection::HttpDownstreamConnection(
|
||||||
DownstreamConnectionPool *dconn_pool, size_t group, struct ev_loop *loop)
|
DownstreamConnectionPool *dconn_pool, size_t group, struct ev_loop *loop)
|
||||||
: DownstreamConnection(dconn_pool),
|
: DownstreamConnection(dconn_pool),
|
||||||
conn_(loop, -1, nullptr, nullptr, get_config()->downstream_write_timeout,
|
conn_(loop, -1, nullptr, nullptr,
|
||||||
get_config()->downstream_read_timeout, 0, 0, 0, 0, connectcb,
|
get_config()->conn.downstream.timeout.write,
|
||||||
readcb, timeoutcb, this, get_config()->tls_dyn_rec_warmup_threshold,
|
get_config()->conn.downstream.timeout.read, {}, {}, connectcb,
|
||||||
get_config()->tls_dyn_rec_idle_timeout),
|
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),
|
ioctrl_(&conn_.rlimit), response_htp_{0}, group_(group), addr_idx_(0),
|
||||||
connected_(false) {}
|
connected_(false) {}
|
||||||
|
|
||||||
|
@ -127,6 +128,8 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream) {
|
||||||
DCLOG(INFO, this) << "Attaching to DOWNSTREAM:" << downstream;
|
DCLOG(INFO, this) << "Attaching to DOWNSTREAM:" << downstream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto &downstreamconf = get_config()->conn.downstream;
|
||||||
|
|
||||||
if (conn_.fd == -1) {
|
if (conn_.fd == -1) {
|
||||||
auto connect_blocker = client_handler_->get_connect_blocker();
|
auto connect_blocker = client_handler_->get_connect_blocker();
|
||||||
|
|
||||||
|
@ -141,7 +144,7 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream) {
|
||||||
auto worker = client_handler_->get_worker();
|
auto worker = client_handler_->get_worker();
|
||||||
auto &next_downstream = worker->get_dgrp(group_)->next;
|
auto &next_downstream = worker->get_dgrp(group_)->next;
|
||||||
auto end = next_downstream;
|
auto end = next_downstream;
|
||||||
auto &addrs = get_config()->downstream_addr_groups[group_].addrs;
|
auto &addrs = downstreamconf.addr_groups[group_].addrs;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto &addr = addrs[next_downstream];
|
auto &addr = addrs[next_downstream];
|
||||||
auto i = next_downstream;
|
auto i = next_downstream;
|
||||||
|
@ -196,7 +199,7 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream) {
|
||||||
ev_timer_again(conn_.loop, &conn_.wt);
|
ev_timer_again(conn_.loop, &conn_.wt);
|
||||||
} else {
|
} else {
|
||||||
// we may set read timer cb to idle_timeoutcb. Reset again.
|
// we may set read timer cb to idle_timeoutcb. Reset again.
|
||||||
conn_.rt.repeat = get_config()->downstream_read_timeout;
|
conn_.rt.repeat = downstreamconf.timeout.read;
|
||||||
ev_set_cb(&conn_.rt, timeoutcb);
|
ev_set_cb(&conn_.rt, timeoutcb);
|
||||||
ev_timer_again(conn_.loop, &conn_.rt);
|
ev_timer_again(conn_.loop, &conn_.rt);
|
||||||
ev_set_cb(&conn_.rev, readcb);
|
ev_set_cb(&conn_.rev, readcb);
|
||||||
|
@ -211,16 +214,20 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int HttpDownstreamConnection::push_request_headers() {
|
int HttpDownstreamConnection::push_request_headers() {
|
||||||
const auto &downstream_hostport =
|
const auto &downstream_hostport = get_config()
|
||||||
get_config()->downstream_addr_groups[group_].addrs[addr_idx_].hostport;
|
->conn.downstream.addr_groups[group_]
|
||||||
|
.addrs[addr_idx_]
|
||||||
|
.hostport;
|
||||||
const auto &req = downstream_->request();
|
const auto &req = downstream_->request();
|
||||||
|
|
||||||
auto connect_method = req.method == HTTP_CONNECT;
|
auto connect_method = req.method == HTTP_CONNECT;
|
||||||
|
|
||||||
|
auto &httpconf = get_config()->http;
|
||||||
|
|
||||||
// For HTTP/1.0 request, there is no authority in request. In that
|
// For HTTP/1.0 request, there is no authority in request. In that
|
||||||
// case, we use backend server's host nonetheless.
|
// case, we use backend server's host nonetheless.
|
||||||
auto authority = StringRef(downstream_hostport);
|
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()->http2_proxy ||
|
||||||
get_config()->client_proxy || connect_method;
|
get_config()->client_proxy || connect_method;
|
||||||
|
|
||||||
|
@ -296,11 +303,13 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||||
auto upstream = downstream_->get_upstream();
|
auto upstream = downstream_->get_upstream();
|
||||||
auto handler = upstream->get_client_handler();
|
auto handler = upstream->get_client_handler();
|
||||||
|
|
||||||
auto fwd = get_config()->strip_incoming_forwarded
|
auto &fwdconf = httpconf.forwarded;
|
||||||
? nullptr
|
|
||||||
: req.fs.header(http2::HD_FORWARDED);
|
auto fwd =
|
||||||
if (get_config()->forwarded_params) {
|
fwdconf.strip_incoming ? nullptr : req.fs.header(http2::HD_FORWARDED);
|
||||||
auto params = get_config()->forwarded_params;
|
|
||||||
|
if (fwdconf.params) {
|
||||||
|
auto params = fwdconf.params;
|
||||||
|
|
||||||
if (get_config()->http2_proxy || get_config()->client_proxy ||
|
if (get_config()->http2_proxy || get_config()->client_proxy ||
|
||||||
connect_method) {
|
connect_method) {
|
||||||
|
@ -328,11 +337,12 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||||
buf->append("\r\n");
|
buf->append("\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto xff = get_config()->strip_incoming_x_forwarded_for
|
auto &xffconf = httpconf.xff;
|
||||||
? nullptr
|
|
||||||
: req.fs.header(http2::HD_X_FORWARDED_FOR);
|
|
||||||
|
|
||||||
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: ");
|
buf->append("X-Forwarded-For: ");
|
||||||
if (xff) {
|
if (xff) {
|
||||||
buf->append((*xff).value);
|
buf->append((*xff).value);
|
||||||
|
@ -353,7 +363,7 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||||
buf->append("\r\n");
|
buf->append("\r\n");
|
||||||
}
|
}
|
||||||
auto via = req.fs.header(http2::HD_VIA);
|
auto via = req.fs.header(http2::HD_VIA);
|
||||||
if (get_config()->no_via) {
|
if (httpconf.no_via) {
|
||||||
if (via) {
|
if (via) {
|
||||||
buf->append("Via: ");
|
buf->append("Via: ");
|
||||||
buf->append((*via).value);
|
buf->append((*via).value);
|
||||||
|
@ -369,7 +379,7 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||||
buf->append("\r\n");
|
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(p.first);
|
||||||
buf->append(": ");
|
buf->append(": ");
|
||||||
buf->append(p.second);
|
buf->append(p.second);
|
||||||
|
@ -474,7 +484,7 @@ void HttpDownstreamConnection::detach_downstream(Downstream *downstream) {
|
||||||
ev_set_cb(&conn_.rev, idle_readcb);
|
ev_set_cb(&conn_.rev, idle_readcb);
|
||||||
ioctrl_.force_resume_read();
|
ioctrl_.force_resume_read();
|
||||||
|
|
||||||
conn_.rt.repeat = get_config()->downstream_idle_read_timeout;
|
conn_.rt.repeat = get_config()->conn.downstream.timeout.idle_read;
|
||||||
ev_set_cb(&conn_.rt, idle_timeoutcb);
|
ev_set_cb(&conn_.rt, idle_timeoutcb);
|
||||||
ev_timer_again(conn_.loop, &conn_.rt);
|
ev_timer_again(conn_.loop, &conn_.rt);
|
||||||
|
|
||||||
|
@ -489,7 +499,7 @@ void HttpDownstreamConnection::pause_read(IOCtrlReason reason) {
|
||||||
int HttpDownstreamConnection::resume_read(IOCtrlReason reason,
|
int HttpDownstreamConnection::resume_read(IOCtrlReason reason,
|
||||||
size_t consumed) {
|
size_t consumed) {
|
||||||
if (downstream_->get_response_buf()->rleft() <=
|
if (downstream_->get_response_buf()->rleft() <=
|
||||||
get_config()->downstream_request_buffer_size / 2) {
|
get_config()->conn.downstream.request_buffer_size / 2) {
|
||||||
ioctrl_.resume_read(reason);
|
ioctrl_.resume_read(reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
// We happen to have the same value for method token.
|
||||||
req.method = htp->method;
|
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)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
ULOG(INFO, upstream) << "Too large URI size="
|
ULOG(INFO, upstream) << "Too large URI size="
|
||||||
<< req.fs.buffer_size() + len;
|
<< 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 upstream = static_cast<HttpsUpstream *>(htp->data);
|
||||||
auto downstream = upstream->get_downstream();
|
auto downstream = upstream->get_downstream();
|
||||||
auto &req = downstream->request();
|
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)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
ULOG(INFO, upstream) << "Too large header block size="
|
ULOG(INFO, upstream) << "Too large header block size="
|
||||||
<< req.fs.buffer_size() + len;
|
<< 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()) {
|
if (req.fs.header_key_prev()) {
|
||||||
req.fs.append_last_header_key(data, len);
|
req.fs.append_last_header_key(data, len);
|
||||||
} else {
|
} else {
|
||||||
if (req.fs.num_fields() >= get_config()->max_header_fields) {
|
if (req.fs.num_fields() >= httpconf.max_header_fields) {
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
ULOG(INFO, upstream)
|
ULOG(INFO, upstream)
|
||||||
<< "Too many header field num=" << req.fs.num_fields() + 1;
|
<< "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()) {
|
if (req.fs.trailer_key_prev()) {
|
||||||
req.fs.append_last_trailer_key(data, len);
|
req.fs.append_last_trailer_key(data, len);
|
||||||
} else {
|
} else {
|
||||||
if (req.fs.num_fields() >= get_config()->max_header_fields) {
|
if (req.fs.num_fields() >= httpconf.max_header_fields) {
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
ULOG(INFO, upstream)
|
ULOG(INFO, upstream)
|
||||||
<< "Too many header field num=" << req.fs.num_fields() + 1;
|
<< "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 downstream = upstream->get_downstream();
|
||||||
auto &req = downstream->request();
|
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)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
ULOG(INFO, upstream) << "Too large header block size="
|
ULOG(INFO, upstream) << "Too large header block size="
|
||||||
<< req.fs.buffer_size() + len;
|
<< 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)) {
|
if (!resp.fs.header(http2::HD_SERVER)) {
|
||||||
output->append("Server: ");
|
output->append("Server: ");
|
||||||
output->append(get_config()->server_name);
|
output->append(get_config()->http.server_name);
|
||||||
output->append("\r\n");
|
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);
|
auto status_str = http2::get_status_string(status_code);
|
||||||
output->append(status_str);
|
output->append(status_str);
|
||||||
output->append("\r\nServer: ");
|
output->append("\r\nServer: ");
|
||||||
const auto &server_name = get_config()->server_name;
|
output->append(get_config()->http.server_name);
|
||||||
output->append(server_name);
|
|
||||||
output->append("\r\nContent-Length: ");
|
output->append("\r\nContent-Length: ");
|
||||||
auto cl = util::utos(html.size());
|
auto cl = util::utos(html.size());
|
||||||
output->append(cl);
|
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(http2::get_status_string(resp.http_status));
|
||||||
buf->append("\r\n");
|
buf->append("\r\n");
|
||||||
|
|
||||||
|
auto &httpconf = get_config()->http;
|
||||||
|
|
||||||
if (!get_config()->http2_proxy && !get_config()->client_proxy &&
|
if (!get_config()->http2_proxy && !get_config()->client_proxy &&
|
||||||
!get_config()->no_location_rewrite) {
|
!httpconf.no_location_rewrite) {
|
||||||
downstream->rewrite_location_response_header(
|
downstream->rewrite_location_response_header(
|
||||||
get_client_handler()->get_upstream_scheme());
|
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)) {
|
if (!resp.fs.header(http2::HD_ALT_SVC)) {
|
||||||
// We won't change or alter alt-svc from backend for now
|
// 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: ");
|
buf->append("Alt-Svc: ");
|
||||||
|
|
||||||
auto &altsvcs = get_config()->altsvcs;
|
auto &altsvcs = httpconf.altsvcs;
|
||||||
write_altsvc(buf, altsvcs[0]);
|
write_altsvc(buf, altsvcs[0]);
|
||||||
for (size_t i = 1; i < altsvcs.size(); ++i) {
|
for (size_t i = 1; i < altsvcs.size(); ++i) {
|
||||||
buf->append(", ");
|
buf->append(", ");
|
||||||
|
@ -999,7 +1001,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
|
||||||
|
|
||||||
if (!get_config()->http2_proxy && !get_config()->client_proxy) {
|
if (!get_config()->http2_proxy && !get_config()->client_proxy) {
|
||||||
buf->append("Server: ");
|
buf->append("Server: ");
|
||||||
buf->append(get_config()->server_name);
|
buf->append(httpconf.server_name);
|
||||||
buf->append("\r\n");
|
buf->append("\r\n");
|
||||||
} else {
|
} else {
|
||||||
auto server = resp.fs.header(http2::HD_SERVER);
|
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);
|
auto via = resp.fs.header(http2::HD_VIA);
|
||||||
if (get_config()->no_via) {
|
if (httpconf.no_via) {
|
||||||
if (via) {
|
if (via) {
|
||||||
buf->append("Via: ");
|
buf->append("Via: ");
|
||||||
buf->append((*via).value);
|
buf->append((*via).value);
|
||||||
|
@ -1028,7 +1030,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
|
||||||
buf->append("\r\n");
|
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(p.first);
|
||||||
buf->append(": ");
|
buf->append(": ");
|
||||||
buf->append(p.second);
|
buf->append(p.second);
|
||||||
|
|
|
@ -109,12 +109,14 @@ Log::~Log() {
|
||||||
|
|
||||||
auto lgconf = log_config();
|
auto lgconf = log_config();
|
||||||
|
|
||||||
|
auto &errorconf = get_config()->logging.error;
|
||||||
|
|
||||||
if (!log_enabled(severity_) ||
|
if (!log_enabled(severity_) ||
|
||||||
(lgconf->errorlog_fd == -1 && !get_config()->errorlog_syslog)) {
|
(lgconf->errorlog_fd == -1 && !errorconf.syslog)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_config()->errorlog_syslog) {
|
if (errorconf.syslog) {
|
||||||
if (severity_ == NOTICE) {
|
if (severity_ == NOTICE) {
|
||||||
syslog(severity_to_syslog_level(severity_), "[%s] %s",
|
syslog(severity_to_syslog_level(severity_), "[%s] %s",
|
||||||
SEVERITY_STR[severity_], stream_.str().c_str());
|
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,
|
void upstream_accesslog(const std::vector<LogFragment> &lfv,
|
||||||
const LogSpec &lgsp) {
|
const LogSpec &lgsp) {
|
||||||
auto lgconf = log_config();
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,7 +363,7 @@ void upstream_accesslog(const std::vector<LogFragment> &lfv,
|
||||||
|
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
|
|
||||||
if (get_config()->accesslog_syslog) {
|
if (accessconf.syslog) {
|
||||||
syslog(LOG_INFO, "%s", buf);
|
syslog(LOG_INFO, "%s", buf);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -379,29 +382,27 @@ int reopen_log_files() {
|
||||||
int new_errorlog_fd = -1;
|
int new_errorlog_fd = -1;
|
||||||
|
|
||||||
auto lgconf = log_config();
|
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) {
|
if (!accessconf.syslog && accessconf.file) {
|
||||||
|
new_accesslog_fd = util::open_log_file(accessconf.file.get());
|
||||||
new_accesslog_fd = util::open_log_file(get_config()->accesslog_file.get());
|
|
||||||
|
|
||||||
if (new_accesslog_fd == -1) {
|
if (new_accesslog_fd == -1) {
|
||||||
LOG(ERROR) << "Failed to open accesslog file "
|
LOG(ERROR) << "Failed to open accesslog file " << accessconf.file.get();
|
||||||
<< get_config()->accesslog_file.get();
|
|
||||||
res = -1;
|
res = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!get_config()->errorlog_syslog && get_config()->errorlog_file) {
|
if (!errorconf.syslog && errorconf.file) {
|
||||||
|
new_errorlog_fd = util::open_log_file(errorconf.file.get());
|
||||||
new_errorlog_fd = util::open_log_file(get_config()->errorlog_file.get());
|
|
||||||
|
|
||||||
if (new_errorlog_fd == -1) {
|
if (new_errorlog_fd == -1) {
|
||||||
if (lgconf->errorlog_fd != -1) {
|
if (lgconf->errorlog_fd != -1) {
|
||||||
LOG(ERROR) << "Failed to open errorlog file "
|
LOG(ERROR) << "Failed to open errorlog file " << errorconf.file.get();
|
||||||
<< get_config()->errorlog_file.get();
|
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "Failed to open errorlog file "
|
std::cerr << "Failed to open errorlog file " << errorconf.file.get()
|
||||||
<< get_config()->errorlog_file.get() << std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = -1;
|
res = -1;
|
||||||
|
@ -444,8 +445,9 @@ void log_chld(pid_t pid, int rstatus, const char *msg) {
|
||||||
|
|
||||||
void redirect_stderr_to_errorlog() {
|
void redirect_stderr_to_errorlog() {
|
||||||
auto lgconf = log_config();
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ constexpr ev_tstamp read_timeout = 10.;
|
||||||
|
|
||||||
MemcachedConnection::MemcachedConnection(const Address *addr,
|
MemcachedConnection::MemcachedConnection(const Address *addr,
|
||||||
struct ev_loop *loop)
|
struct ev_loop *loop)
|
||||||
: conn_(loop, -1, nullptr, nullptr, write_timeout, read_timeout, 0, 0, 0, 0,
|
: conn_(loop, -1, nullptr, nullptr, write_timeout, read_timeout, {}, {},
|
||||||
connectcb, readcb, timeoutcb, this, 0, 0.),
|
connectcb, readcb, timeoutcb, this, 0, 0.),
|
||||||
parse_state_{}, addr_(addr), sendsum_(0), connected_(false) {}
|
parse_state_{}, addr_(addr), sendsum_(0), connected_(false) {}
|
||||||
|
|
||||||
|
|
|
@ -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]);
|
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
|
// spdy does not define usage of trailer fields, and we ignores
|
||||||
// them.
|
// them.
|
||||||
if (header_buffer > get_config()->header_field_buffer ||
|
if (header_buffer > httpconf.header_field_buffer ||
|
||||||
num_headers > get_config()->max_header_fields) {
|
num_headers > httpconf.max_header_fields) {
|
||||||
upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR);
|
upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -370,31 +372,33 @@ void on_data_chunk_recv_callback(spdylay_session *session, uint8_t flags,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto &http2conf = get_config()->http2;
|
||||||
|
|
||||||
// If connection-level window control is not enabled (e.g,
|
// If connection-level window control is not enabled (e.g,
|
||||||
// spdy/3), spdylay_session_get_recv_data_length() is always
|
// spdy/3), spdylay_session_get_recv_data_length() is always
|
||||||
// returns 0.
|
// returns 0.
|
||||||
if (spdylay_session_get_recv_data_length(session) >
|
if (spdylay_session_get_recv_data_length(session) >
|
||||||
std::max(SPDYLAY_INITIAL_WINDOW_SIZE,
|
std::max(SPDYLAY_INITIAL_WINDOW_SIZE,
|
||||||
1 << get_config()->http2_upstream_connection_window_bits)) {
|
1 << http2conf.upstream.connection_window_bits)) {
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
ULOG(INFO, upstream)
|
ULOG(INFO, upstream) << "Flow control error on connection: "
|
||||||
<< "Flow control error on connection: "
|
<< "recv_window_size="
|
||||||
<< "recv_window_size="
|
<< spdylay_session_get_recv_data_length(session)
|
||||||
<< spdylay_session_get_recv_data_length(session) << ", window_size="
|
<< ", window_size="
|
||||||
<< (1 << get_config()->http2_upstream_connection_window_bits);
|
<< (1 << http2conf.upstream.connection_window_bits);
|
||||||
}
|
}
|
||||||
spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
|
spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (spdylay_session_get_stream_recv_data_length(session, stream_id) >
|
if (spdylay_session_get_stream_recv_data_length(session, stream_id) >
|
||||||
std::max(SPDYLAY_INITIAL_WINDOW_SIZE,
|
std::max(SPDYLAY_INITIAL_WINDOW_SIZE,
|
||||||
1 << get_config()->http2_upstream_window_bits)) {
|
1 << http2conf.upstream.window_bits)) {
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
ULOG(INFO, upstream) << "Flow control error: recv_window_size="
|
ULOG(INFO, upstream) << "Flow control error: recv_window_size="
|
||||||
<< spdylay_session_get_stream_recv_data_length(
|
<< spdylay_session_get_stream_recv_data_length(
|
||||||
session, stream_id)
|
session, stream_id)
|
||||||
<< ", initial_window_size="
|
<< ", initial_window_size="
|
||||||
<< (1 << get_config()->http2_upstream_window_bits);
|
<< (1 << http2conf.upstream.window_bits);
|
||||||
}
|
}
|
||||||
upstream->rst_stream(downstream, SPDYLAY_FLOW_CONTROL_ERROR);
|
upstream->rst_stream(downstream, SPDYLAY_FLOW_CONTROL_ERROR);
|
||||||
return;
|
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)
|
SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
|
||||||
: downstream_queue_(
|
: downstream_queue_(
|
||||||
get_config()->http2_proxy
|
get_config()->http2_proxy
|
||||||
? get_config()->downstream_connections_per_host
|
? get_config()->conn.downstream.connections_per_host
|
||||||
: get_config()->downstream_proto == PROTO_HTTP
|
: get_config()->conn.downstream.proto == PROTO_HTTP
|
||||||
? get_config()->downstream_connections_per_frontend
|
? get_config()->conn.downstream.connections_per_frontend
|
||||||
: 0,
|
: 0,
|
||||||
!get_config()->http2_proxy),
|
!get_config()->http2_proxy),
|
||||||
handler_(handler), session_(nullptr) {
|
handler_(handler), session_(nullptr) {
|
||||||
|
@ -518,10 +522,12 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
|
||||||
&max_buffer, sizeof(max_buffer));
|
&max_buffer, sizeof(max_buffer));
|
||||||
assert(rv == 0);
|
assert(rv == 0);
|
||||||
|
|
||||||
|
auto &http2conf = get_config()->http2;
|
||||||
|
|
||||||
if (version >= SPDYLAY_PROTO_SPDY3) {
|
if (version >= SPDYLAY_PROTO_SPDY3) {
|
||||||
int val = 1;
|
int val = 1;
|
||||||
flow_control_ = true;
|
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(
|
rv = spdylay_session_set_option(
|
||||||
session_, SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE2, &val, sizeof(val));
|
session_, SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE2, &val, sizeof(val));
|
||||||
assert(rv == 0);
|
assert(rv == 0);
|
||||||
|
@ -532,7 +538,7 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
|
||||||
// TODO Maybe call from outside?
|
// TODO Maybe call from outside?
|
||||||
std::array<spdylay_settings_entry, 2> entry;
|
std::array<spdylay_settings_entry, 2> entry;
|
||||||
entry[0].settings_id = SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS;
|
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[0].flags = SPDYLAY_ID_FLAG_SETTINGS_NONE;
|
||||||
|
|
||||||
entry[1].settings_id = SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE;
|
entry[1].settings_id = SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE;
|
||||||
|
@ -544,15 +550,15 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
|
||||||
assert(rv == 0);
|
assert(rv == 0);
|
||||||
|
|
||||||
if (version >= SPDYLAY_PROTO_SPDY3_1 &&
|
if (version >= SPDYLAY_PROTO_SPDY3_1 &&
|
||||||
get_config()->http2_upstream_connection_window_bits > 16) {
|
http2conf.upstream.connection_window_bits > 16) {
|
||||||
int32_t delta = (1 << get_config()->http2_upstream_connection_window_bits) -
|
int32_t delta = (1 << http2conf.upstream.connection_window_bits) -
|
||||||
SPDYLAY_INITIAL_WINDOW_SIZE;
|
SPDYLAY_INITIAL_WINDOW_SIZE;
|
||||||
rv = spdylay_submit_window_update(session_, 0, delta);
|
rv = spdylay_submit_window_update(session_, 0, delta);
|
||||||
assert(rv == 0);
|
assert(rv == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
handler_->reset_upstream_read_timeout(
|
handler_->reset_upstream_read_timeout(
|
||||||
get_config()->http2_upstream_read_timeout);
|
get_config()->conn.upstream.timeout.http2_read);
|
||||||
|
|
||||||
handler_->signal_write();
|
handler_->signal_write();
|
||||||
}
|
}
|
||||||
|
@ -875,7 +881,7 @@ int SpdyUpstream::send_reply(Downstream *downstream, const uint8_t *body,
|
||||||
|
|
||||||
if (!resp.fs.header(http2::HD_SERVER)) {
|
if (!resp.fs.header(http2::HD_SERVER)) {
|
||||||
nva.push_back("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);
|
nva.push_back(nullptr);
|
||||||
|
@ -919,7 +925,7 @@ int SpdyUpstream::error_reply(Downstream *downstream,
|
||||||
std::string status_string = http2::get_status_string(status_code);
|
std::string status_string = http2::get_status_string(status_code);
|
||||||
const char *nv[] = {":status", status_string.c_str(), ":version", "http/1.1",
|
const char *nv[] = {":status", status_string.c_str(), ":version", "http/1.1",
|
||||||
"content-type", "text/html; charset=UTF-8", "server",
|
"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",
|
content_length.c_str(), "date",
|
||||||
lgconf->time_http_str.c_str(), nullptr};
|
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";
|
DLOG(INFO, downstream) << "HTTP response header completed";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto &httpconf = get_config()->http;
|
||||||
|
|
||||||
if (!get_config()->http2_proxy && !get_config()->client_proxy &&
|
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);
|
downstream->rewrite_location_response_header(req.scheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8 means server, :status, :version and possible via header field.
|
// 8 means server, :status, :version and possible via header field.
|
||||||
auto nv = make_unique<const char *[]>(
|
auto nv =
|
||||||
resp.fs.headers().size() * 2 + 8 +
|
make_unique<const char *[]>(resp.fs.headers().size() * 2 + 8 +
|
||||||
get_config()->add_response_headers.size() * 2 + 1);
|
httpconf.add_response_headers.size() * 2 + 1);
|
||||||
|
|
||||||
size_t hdidx = 0;
|
size_t hdidx = 0;
|
||||||
std::string via_value;
|
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) {
|
if (!get_config()->http2_proxy && !get_config()->client_proxy) {
|
||||||
nv[hdidx++] = "server";
|
nv[hdidx++] = "server";
|
||||||
nv[hdidx++] = get_config()->server_name.c_str();
|
nv[hdidx++] = httpconf.server_name.c_str();
|
||||||
} else {
|
} else {
|
||||||
auto server = resp.fs.header(http2::HD_SERVER);
|
auto server = resp.fs.header(http2::HD_SERVER);
|
||||||
if (server) {
|
if (server) {
|
||||||
|
@ -1044,7 +1052,7 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto via = resp.fs.header(http2::HD_VIA);
|
auto via = resp.fs.header(http2::HD_VIA);
|
||||||
if (get_config()->no_via) {
|
if (httpconf.no_via) {
|
||||||
if (via) {
|
if (via) {
|
||||||
nv[hdidx++] = "via";
|
nv[hdidx++] = "via";
|
||||||
nv[hdidx++] = via->value.c_str();
|
nv[hdidx++] = via->value.c_str();
|
||||||
|
@ -1060,7 +1068,7 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
|
||||||
nv[hdidx++] = via_value.c_str();
|
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.first.c_str();
|
||||||
nv[hdidx++] = p.second.c_str();
|
nv[hdidx++] = p.second.c_str();
|
||||||
}
|
}
|
||||||
|
|
109
src/shrpx_ssl.cc
109
src/shrpx_ssl.cc
|
@ -70,7 +70,7 @@ namespace ssl {
|
||||||
namespace {
|
namespace {
|
||||||
int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
|
int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
|
||||||
void *arg) {
|
void *arg) {
|
||||||
auto &prefs = get_config()->alpn_prefs;
|
auto &prefs = get_config()->tls.alpn_prefs;
|
||||||
*data = prefs.data();
|
*data = prefs.data();
|
||||||
*len = prefs.size();
|
*len = prefs.size();
|
||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
|
@ -124,13 +124,13 @@ set_alpn_prefs(const std::vector<std::string> &protos) {
|
||||||
namespace {
|
namespace {
|
||||||
int ssl_pem_passwd_cb(char *buf, int size, int rwflag, void *user_data) {
|
int ssl_pem_passwd_cb(char *buf, int size, int rwflag, void *user_data) {
|
||||||
auto config = static_cast<Config *>(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) {
|
if (size < len + 1) {
|
||||||
LOG(ERROR) << "ssl_pem_passwd_cb: buf is too small " << size;
|
LOG(ERROR) << "ssl_pem_passwd_cb: buf is too small " << size;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// Copy string including last '\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;
|
return len;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // 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);
|
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);
|
key.data.enc_key.data(), iv);
|
||||||
HMAC_Init_ex(hctx, key.data.hmac_key.data(), key.hmac_keylen, key.hmac,
|
HMAC_Init_ex(hctx, key.data.hmac_key.data(), key.hmac_keylen, key.hmac,
|
||||||
nullptr);
|
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
|
// We assume that get_config()->npn_list contains ALPN protocol
|
||||||
// identifier sorted by preference order. So we just break when we
|
// identifier sorted by preference order. So we just break when we
|
||||||
// found the first overlap.
|
// 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;) {
|
for (auto p = in, end = in + inlen; p < end;) {
|
||||||
auto proto_id = p + 1;
|
auto proto_id = p + 1;
|
||||||
auto proto_len = *p;
|
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_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_SINGLE_ECDH_USE |
|
||||||
SSL_OP_SINGLE_DH_USE | SSL_OP_CIPHER_SERVER_PREFERENCE;
|
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";
|
const unsigned char sid_ctx[] = "shrpx";
|
||||||
SSL_CTX_set_session_id_context(ssl_ctx, sid_ctx, sizeof(sid_ctx) - 1);
|
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);
|
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_new_cb(ssl_ctx, tls_session_new_cb);
|
||||||
SSL_CTX_sess_set_get_cb(ssl_ctx, tls_session_get_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;
|
const char *ciphers;
|
||||||
if (get_config()->ciphers) {
|
if (tlsconf.ciphers) {
|
||||||
ciphers = get_config()->ciphers.get();
|
ciphers = tlsconf.ciphers.get();
|
||||||
} else {
|
} else {
|
||||||
ciphers = nghttp2::ssl::DEFAULT_CIPHER_LIST;
|
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
|
#endif // OPENSSL_NO_EC
|
||||||
|
|
||||||
if (get_config()->dh_param_file) {
|
if (tlsconf.dh_param_file) {
|
||||||
// Read DH parameters from 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) {
|
if (bio == nullptr) {
|
||||||
LOG(FATAL) << "BIO_new_file() failed: "
|
LOG(FATAL) << "BIO_new_file() failed: "
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
<< 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_AUTO_RETRY);
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
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(ssl_ctx, ssl_pem_passwd_cb);
|
||||||
SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, (void *)get_config());
|
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);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
if (get_config()->verify_client) {
|
if (tlsconf.client_verify.enabled) {
|
||||||
if (get_config()->verify_client_cacert) {
|
if (tlsconf.client_verify.cacert) {
|
||||||
if (SSL_CTX_load_verify_locations(
|
if (SSL_CTX_load_verify_locations(
|
||||||
ssl_ctx, get_config()->verify_client_cacert.get(), nullptr) !=
|
ssl_ctx, tlsconf.client_verify.cacert.get(), nullptr) != 1) {
|
||||||
1) {
|
|
||||||
|
|
||||||
LOG(FATAL) << "Could not load trusted ca certificates from "
|
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);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
DIE();
|
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
|
// error even though it returns success. See
|
||||||
// http://forum.nginx.org/read.php?29,242540
|
// http://forum.nginx.org/read.php?29,242540
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
auto list =
|
auto list = SSL_load_client_CA_file(tlsconf.client_verify.cacert.get());
|
||||||
SSL_load_client_CA_file(get_config()->verify_client_cacert.get());
|
|
||||||
if (!list) {
|
if (!list) {
|
||||||
LOG(FATAL) << "Could not load ca certificates from "
|
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);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
|
@ -656,11 +656,13 @@ SSL_CTX *create_ssl_client_context(
|
||||||
SSL_OP_NO_COMPRESSION |
|
SSL_OP_NO_COMPRESSION |
|
||||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
|
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;
|
const char *ciphers;
|
||||||
if (get_config()->ciphers) {
|
if (tlsconf.ciphers) {
|
||||||
ciphers = get_config()->ciphers.get();
|
ciphers = tlsconf.ciphers.get();
|
||||||
} else {
|
} else {
|
||||||
ciphers = nghttp2::ssl::DEFAULT_CIPHER_LIST;
|
ciphers = nghttp2::ssl::DEFAULT_CIPHER_LIST;
|
||||||
}
|
}
|
||||||
|
@ -678,44 +680,44 @@ SSL_CTX *create_ssl_client_context(
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_config()->cacert) {
|
if (tlsconf.cacert) {
|
||||||
if (SSL_CTX_load_verify_locations(ssl_ctx, get_config()->cacert.get(),
|
if (SSL_CTX_load_verify_locations(ssl_ctx, tlsconf.cacert.get(), nullptr) !=
|
||||||
nullptr) != 1) {
|
1) {
|
||||||
|
|
||||||
LOG(FATAL) << "Could not load trusted ca certificates from "
|
LOG(FATAL) << "Could not load trusted ca certificates from "
|
||||||
<< get_config()->cacert.get() << ": "
|
<< tlsconf.cacert.get() << ": "
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_config()->client_private_key_file) {
|
if (tlsconf.client.private_key_file) {
|
||||||
#ifndef HAVE_NEVERBLEED
|
#ifndef HAVE_NEVERBLEED
|
||||||
if (SSL_CTX_use_PrivateKey_file(ssl_ctx,
|
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) {
|
SSL_FILETYPE_PEM) != 1) {
|
||||||
LOG(FATAL) << "Could not load client private key from "
|
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);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
#else // HAVE_NEVERBLEED
|
#else // HAVE_NEVERBLEED
|
||||||
std::array<char, NEVERBLEED_ERRBUF_SIZE> errbuf;
|
std::array<char, NEVERBLEED_ERRBUF_SIZE> errbuf;
|
||||||
if (neverbleed_load_private_key_file(
|
if (neverbleed_load_private_key_file(nb, ssl_ctx,
|
||||||
nb, ssl_ctx, get_config()->client_private_key_file.get(),
|
tlsconf.client.private_key_file.get(),
|
||||||
errbuf.data()) != 1) {
|
errbuf.data()) != 1) {
|
||||||
LOG(FATAL) << "neverbleed_load_private_key_file failed: "
|
LOG(FATAL) << "neverbleed_load_private_key_file failed: "
|
||||||
<< errbuf.data();
|
<< errbuf.data();
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
#endif // HAVE_NEVERBLEED
|
#endif // HAVE_NEVERBLEED
|
||||||
}
|
}
|
||||||
if (get_config()->client_cert_file) {
|
if (tlsconf.client.cert_file) {
|
||||||
if (SSL_CTX_use_certificate_chain_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 "
|
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);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
|
@ -971,9 +973,11 @@ int check_cert(SSL *ssl, const DownstreamAddr *addr) {
|
||||||
<< X509_verify_cert_error_string(verify_res);
|
<< X509_verify_cert_error_string(verify_res);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
auto hostname = !get_config()->backend_tls_sni_name.empty()
|
|
||||||
? StringRef(get_config()->backend_tls_sni_name)
|
auto &backend_sni_name = get_config()->tls.backend_sni_name;
|
||||||
: StringRef(addr->host);
|
|
||||||
|
auto hostname = !backend_sni_name.empty() ? StringRef(backend_sni_name)
|
||||||
|
: StringRef(addr->host);
|
||||||
if (verify_hostname(cert, hostname.c_str(), hostname.size(), &addr->addr) !=
|
if (verify_hostname(cert, hostname.c_str(), hostname.size(), &addr->addr) !=
|
||||||
0) {
|
0) {
|
||||||
LOG(ERROR) << "Certificate verification failed: hostname does not match";
|
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
|
neverbleed_t *nb
|
||||||
#endif // HAVE_NEVERBLEED
|
#endif // HAVE_NEVERBLEED
|
||||||
) {
|
) {
|
||||||
if (get_config()->upstream_no_tls) {
|
if (get_config()->conn.upstream.no_tls) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ssl_ctx = ssl::create_ssl_context(get_config()->private_key_file.get(),
|
auto &tlsconf = get_config()->tls;
|
||||||
get_config()->cert_file.get()
|
|
||||||
|
auto ssl_ctx = ssl::create_ssl_context(tlsconf.private_key_file.get(),
|
||||||
|
tlsconf.cert_file.get()
|
||||||
#ifdef HAVE_NEVERBLEED
|
#ifdef HAVE_NEVERBLEED
|
||||||
,
|
,
|
||||||
nb
|
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);
|
all_ssl_ctx.push_back(ssl_ctx);
|
||||||
|
|
||||||
if (get_config()->subcerts.empty()) {
|
if (tlsconf.subcerts.empty()) {
|
||||||
return ssl_ctx;
|
return ssl_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1234,7 +1240,7 @@ SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
|
||||||
return ssl_ctx;
|
return ssl_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &keycert : get_config()->subcerts) {
|
for (auto &keycert : tlsconf.subcerts) {
|
||||||
auto ssl_ctx =
|
auto ssl_ctx =
|
||||||
ssl::create_ssl_context(keycert.first.c_str(), keycert.second.c_str()
|
ssl::create_ssl_context(keycert.first.c_str(), keycert.second.c_str()
|
||||||
#ifdef HAVE_NEVERBLEED
|
#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(
|
if (ssl::cert_lookup_tree_add_cert_from_file(cert_tree, ssl_ctx,
|
||||||
cert_tree, ssl_ctx, get_config()->cert_file.get()) == -1) {
|
tlsconf.cert_file.get()) == -1) {
|
||||||
LOG(FATAL) << "Failed to add default certificate.";
|
LOG(FATAL) << "Failed to add default certificate.";
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
|
@ -1260,11 +1266,13 @@ SSL_CTX *setup_server_ssl_context(std::vector<SSL_CTX *> &all_ssl_ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool downstream_tls_enabled() {
|
bool downstream_tls_enabled() {
|
||||||
|
auto no_tls = get_config()->conn.downstream.no_tls;
|
||||||
|
|
||||||
if (get_config()->client_mode) {
|
if (get_config()->client_mode) {
|
||||||
return !get_config()->downstream_no_tls;
|
return !no_tls;
|
||||||
}
|
}
|
||||||
|
|
||||||
return get_config()->http2_bridge && !get_config()->downstream_no_tls;
|
return get_config()->http2_bridge && !no_tls;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_CTX *setup_client_ssl_context(
|
SSL_CTX *setup_client_ssl_context(
|
||||||
|
@ -1284,7 +1292,8 @@ SSL_CTX *setup_client_ssl_context(
|
||||||
}
|
}
|
||||||
|
|
||||||
CertLookupTree *create_cert_lookup_tree() {
|
CertLookupTree *create_cert_lookup_tree() {
|
||||||
if (get_config()->upstream_no_tls || get_config()->subcerts.empty()) {
|
if (get_config()->conn.upstream.no_tls ||
|
||||||
|
get_config()->tls.subcerts.empty()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return new ssl::CertLookupTree();
|
return new ssl::CertLookupTree();
|
||||||
|
|
|
@ -69,9 +69,10 @@ std::random_device rd;
|
||||||
Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx,
|
Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx,
|
||||||
ssl::CertLookupTree *cert_tree,
|
ssl::CertLookupTree *cert_tree,
|
||||||
const std::shared_ptr<TicketKeys> &ticket_keys)
|
const std::shared_ptr<TicketKeys> &ticket_keys)
|
||||||
: randgen_(rd()), dconn_pool_(get_config()->downstream_addr_groups.size()),
|
: randgen_(rd()),
|
||||||
worker_stat_(get_config()->downstream_addr_groups.size()),
|
dconn_pool_(get_config()->conn.downstream.addr_groups.size()),
|
||||||
dgrps_(get_config()->downstream_addr_groups.size()), loop_(loop),
|
worker_stat_(get_config()->conn.downstream.addr_groups.size()),
|
||||||
|
dgrps_(get_config()->conn.downstream.addr_groups.size()), loop_(loop),
|
||||||
sv_ssl_ctx_(sv_ssl_ctx), cl_ssl_ctx_(cl_ssl_ctx), cert_tree_(cert_tree),
|
sv_ssl_ctx_(sv_ssl_ctx), cl_ssl_ctx_(cl_ssl_ctx), cert_tree_(cert_tree),
|
||||||
ticket_keys_(ticket_keys),
|
ticket_keys_(ticket_keys),
|
||||||
connect_blocker_(make_unique<ConnectBlocker>(loop_)),
|
connect_blocker_(make_unique<ConnectBlocker>(loop_)),
|
||||||
|
@ -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.);
|
ev_timer_init(&mcpool_clear_timer_, mcpool_clear_cb, 0., 0.);
|
||||||
mcpool_clear_timer_.data = this;
|
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>(
|
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 &downstreamconf = get_config()->conn.downstream;
|
||||||
auto n = get_config()->http2_downstream_connections_per_worker;
|
|
||||||
|
if (downstreamconf.proto == PROTO_HTTP2) {
|
||||||
|
auto n = get_config()->http2.downstream.connections_per_worker;
|
||||||
size_t group = 0;
|
size_t group = 0;
|
||||||
for (auto &dgrp : dgrps_) {
|
for (auto &dgrp : dgrps_) {
|
||||||
auto m = n;
|
auto m = n;
|
||||||
if (m == 0) {
|
if (m == 0) {
|
||||||
m = get_config()->downstream_addr_groups[group].addrs.size();
|
m = downstreamconf.addr_groups[group].addrs.size();
|
||||||
}
|
}
|
||||||
for (size_t idx = 0; idx < m; ++idx) {
|
for (size_t idx = 0; idx < m; ++idx) {
|
||||||
dgrp.http2sessions.push_back(make_unique<Http2Session>(
|
dgrp.http2sessions.push_back(make_unique<Http2Session>(
|
||||||
|
@ -149,6 +154,9 @@ void Worker::process_events() {
|
||||||
std::lock_guard<std::mutex> g(m_);
|
std::lock_guard<std::mutex> g(m_);
|
||||||
q.swap(q_);
|
q.swap(q_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto worker_connections = get_config()->conn.upstream.worker_connections;
|
||||||
|
|
||||||
for (auto &wev : q) {
|
for (auto &wev : q) {
|
||||||
switch (wev.type) {
|
switch (wev.type) {
|
||||||
case NEW_CONNECTION: {
|
case NEW_CONNECTION: {
|
||||||
|
@ -157,12 +165,10 @@ void Worker::process_events() {
|
||||||
<< ", addrlen=" << wev.client_addrlen;
|
<< ", addrlen=" << wev.client_addrlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (worker_stat_.num_connections >=
|
if (worker_stat_.num_connections >= worker_connections) {
|
||||||
get_config()->worker_frontend_connections) {
|
|
||||||
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
WLOG(INFO, this) << "Too many connections >= "
|
WLOG(INFO, this) << "Too many connections >= " << worker_connections;
|
||||||
<< get_config()->worker_frontend_connections;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close(wev.client_fd);
|
close(wev.client_fd);
|
||||||
|
|
|
@ -170,7 +170,7 @@ void ipc_readcb(struct ev_loop *loop, ev_io *w, int revents) {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int generate_ticket_key(TicketKey &ticket_key) {
|
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 = EVP_sha256();
|
||||||
ticket_key.hmac_keylen = EVP_MD_size(ticket_key.hmac);
|
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 =
|
auto max_tickets =
|
||||||
static_cast<size_t>(std::chrono::duration_cast<std::chrono::hours>(
|
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));
|
new_keys.resize(std::min(max_tickets, old_keys.size() + 1));
|
||||||
std::copy_n(std::begin(old_keys), new_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();
|
auto end = p + value.size();
|
||||||
p += 4;
|
p += 4;
|
||||||
|
|
||||||
|
auto &ticketconf = get_config()->tls.ticket;
|
||||||
|
|
||||||
size_t expectedlen;
|
size_t expectedlen;
|
||||||
size_t enc_keylen;
|
size_t enc_keylen;
|
||||||
size_t hmac_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;
|
expectedlen = 48;
|
||||||
enc_keylen = 16;
|
enc_keylen = 16;
|
||||||
hmac_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;
|
expectedlen = 80;
|
||||||
enc_keylen = 32;
|
enc_keylen = 32;
|
||||||
hmac_keylen = 32;
|
hmac_keylen = 32;
|
||||||
|
@ -335,7 +337,7 @@ void memcached_get_ticket_key_cb(struct ev_loop *loop, ev_timer *w,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto key = TicketKey();
|
auto key = TicketKey();
|
||||||
key.cipher = get_config()->tls_ticket_key_cipher;
|
key.cipher = ticketconf.cipher;
|
||||||
key.hmac = EVP_sha256();
|
key.hmac = EVP_sha256();
|
||||||
key.hmac_keylen = hmac_keylen;
|
key.hmac_keylen = hmac_keylen;
|
||||||
|
|
||||||
|
@ -421,12 +423,15 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
|
||||||
|
|
||||||
#endif // HAVE_NEVERBLEED
|
#endif // HAVE_NEVERBLEED
|
||||||
|
|
||||||
|
auto &upstreamconf = get_config()->conn.upstream;
|
||||||
|
|
||||||
ev_timer renew_ticket_key_timer;
|
ev_timer renew_ticket_key_timer;
|
||||||
if (!get_config()->upstream_no_tls) {
|
if (!upstreamconf.no_tls) {
|
||||||
if (get_config()->tls_ticket_key_memcached_host) {
|
auto &ticketconf = get_config()->tls.ticket;
|
||||||
|
|
||||||
|
if (ticketconf.memcached.host) {
|
||||||
conn_handler.set_tls_ticket_key_memcached_dispatcher(
|
conn_handler.set_tls_ticket_key_memcached_dispatcher(
|
||||||
make_unique<MemcachedDispatcher>(
|
make_unique<MemcachedDispatcher>(&ticketconf.memcached.addr, loop));
|
||||||
&get_config()->tls_ticket_key_memcached_addr, loop));
|
|
||||||
|
|
||||||
ev_timer_init(&renew_ticket_key_timer, memcached_get_ticket_key_cb, 0.,
|
ev_timer_init(&renew_ticket_key_timer, memcached_get_ticket_key_cb, 0.,
|
||||||
0.);
|
0.);
|
||||||
|
@ -435,8 +440,8 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
|
||||||
memcached_get_ticket_key_cb(loop, &renew_ticket_key_timer, 0);
|
memcached_get_ticket_key_cb(loop, &renew_ticket_key_timer, 0);
|
||||||
} else {
|
} else {
|
||||||
bool auto_tls_ticket_key = true;
|
bool auto_tls_ticket_key = true;
|
||||||
if (!get_config()->tls_ticket_key_files.empty()) {
|
if (!ticketconf.files.empty()) {
|
||||||
if (!get_config()->tls_ticket_key_cipher_given) {
|
if (!ticketconf.cipher_given) {
|
||||||
LOG(WARN)
|
LOG(WARN)
|
||||||
<< "It is strongly recommended to specify "
|
<< "It is strongly recommended to specify "
|
||||||
"--tls-ticket-key-cipher=aes-128-cbc (or "
|
"--tls-ticket-key-cipher=aes-128-cbc (or "
|
||||||
|
@ -446,8 +451,7 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
|
||||||
"becomes aes-256-cbc";
|
"becomes aes-256-cbc";
|
||||||
}
|
}
|
||||||
auto ticket_keys = read_tls_ticket_key_file(
|
auto ticket_keys = read_tls_ticket_key_file(
|
||||||
get_config()->tls_ticket_key_files,
|
ticketconf.files, ticketconf.cipher, EVP_sha256());
|
||||||
get_config()->tls_ticket_key_cipher, EVP_sha256());
|
|
||||||
if (!ticket_keys) {
|
if (!ticket_keys) {
|
||||||
LOG(WARN) << "Use internal session ticket key generator";
|
LOG(WARN) << "Use internal session ticket key generator";
|
||||||
} else {
|
} else {
|
||||||
|
@ -512,7 +516,7 @@ int worker_process_event_loop(WorkerProcessConfig *wpconf) {
|
||||||
ipcev.data = &conn_handler;
|
ipcev.data = &conn_handler;
|
||||||
ev_io_start(loop, &ipcev);
|
ev_io_start(loop, &ipcev);
|
||||||
|
|
||||||
if (!get_config()->upstream_no_tls && !get_config()->no_ocsp) {
|
if (!upstreamconf.no_tls && !get_config()->tls.ocsp.disabled) {
|
||||||
conn_handler.proceed_next_cert_ocsp();
|
conn_handler.proceed_next_cert_ocsp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -171,10 +171,18 @@ constexpr unsigned long long operator"" _g(unsigned long long g) {
|
||||||
|
|
||||||
// User-defined literals for time, converted into double in seconds
|
// User-defined literals for time, converted into double in seconds
|
||||||
|
|
||||||
|
// hours
|
||||||
constexpr double operator"" _h(unsigned long long h) { return h * 60 * 60; }
|
constexpr double operator"" _h(unsigned long long h) { return h * 60 * 60; }
|
||||||
|
|
||||||
|
// minutes
|
||||||
constexpr double operator"" _min(unsigned long long min) { return min * 60; }
|
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).
|
// Returns a copy of NULL-terminated string [first, last).
|
||||||
template <typename InputIt>
|
template <typename InputIt>
|
||||||
std::unique_ptr<char[]> strcopy(InputIt first, InputIt last) {
|
std::unique_ptr<char[]> strcopy(InputIt first, InputIt last) {
|
||||||
|
|
Loading…
Reference in New Issue