nghttpx: Move option handling code to separate function
This commit is contained in:
parent
16549bb276
commit
a053d10839
672
src/shrpx.cc
672
src/shrpx.cc
|
@ -1723,6 +1723,345 @@ Misc:
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void process_options(
|
||||||
|
int argc, char **argv,
|
||||||
|
std::vector<std::pair<const char *, const char *>> &cmdcfgs) {
|
||||||
|
if (conf_exists(get_config()->conf_path.get())) {
|
||||||
|
std::set<std::string> include_set;
|
||||||
|
if (load_config(get_config()->conf_path.get(), include_set) == -1) {
|
||||||
|
LOG(FATAL) << "Failed to load configuration from "
|
||||||
|
<< get_config()->conf_path.get();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
assert(include_set.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc - optind >= 2) {
|
||||||
|
cmdcfgs.emplace_back(SHRPX_OPT_PRIVATE_KEY_FILE, argv[optind++]);
|
||||||
|
cmdcfgs.emplace_back(SHRPX_OPT_CERTIFICATE_FILE, argv[optind++]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reopen log files using configurations in file
|
||||||
|
reopen_log_files();
|
||||||
|
|
||||||
|
{
|
||||||
|
std::set<std::string> include_set;
|
||||||
|
|
||||||
|
for (size_t i = 0, len = cmdcfgs.size(); i < len; ++i) {
|
||||||
|
if (parse_config(cmdcfgs[i].first, cmdcfgs[i].second, include_set) ==
|
||||||
|
-1) {
|
||||||
|
LOG(FATAL) << "Failed to parse command-line argument.";
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(include_set.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_config()->accesslog_syslog || get_config()->errorlog_syslog) {
|
||||||
|
openlog("nghttpx", LOG_NDELAY | LOG_NOWAIT | LOG_PID,
|
||||||
|
get_config()->syslog_facility);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reopen_log_files() != 0) {
|
||||||
|
LOG(FATAL) << "Failed to open log file";
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
redirect_stderr_to_errorlog();
|
||||||
|
|
||||||
|
if (get_config()->uid != 0) {
|
||||||
|
if (log_config()->accesslog_fd != -1 &&
|
||||||
|
fchown(log_config()->accesslog_fd, get_config()->uid,
|
||||||
|
get_config()->gid) == -1) {
|
||||||
|
auto error = errno;
|
||||||
|
LOG(WARN) << "Changing owner of access log file failed: "
|
||||||
|
<< strerror(error);
|
||||||
|
}
|
||||||
|
if (log_config()->errorlog_fd != -1 &&
|
||||||
|
fchown(log_config()->errorlog_fd, get_config()->uid,
|
||||||
|
get_config()->gid) == -1) {
|
||||||
|
auto error = errno;
|
||||||
|
LOG(WARN) << "Changing owner of error log file failed: "
|
||||||
|
<< strerror(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &http2conf = mod_config()->http2;
|
||||||
|
{
|
||||||
|
auto &dumpconf = http2conf.upstream.debug.dump;
|
||||||
|
|
||||||
|
if (dumpconf.request_header_file) {
|
||||||
|
auto path = dumpconf.request_header_file.get();
|
||||||
|
auto f = open_file_for_write(path);
|
||||||
|
|
||||||
|
if (f == nullptr) {
|
||||||
|
LOG(FATAL) << "Failed to open http2 upstream request header file: "
|
||||||
|
<< path;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
dumpconf.request_header = f;
|
||||||
|
|
||||||
|
if (get_config()->uid != 0) {
|
||||||
|
if (chown_to_running_user(path) == -1) {
|
||||||
|
auto error = errno;
|
||||||
|
LOG(WARN) << "Changing owner of http2 upstream request header file "
|
||||||
|
<< path << " failed: " << strerror(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dumpconf.response_header_file) {
|
||||||
|
auto path = dumpconf.response_header_file.get();
|
||||||
|
auto f = open_file_for_write(path);
|
||||||
|
|
||||||
|
if (f == nullptr) {
|
||||||
|
LOG(FATAL) << "Failed to open http2 upstream response header file: "
|
||||||
|
<< path;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
dumpconf.response_header = f;
|
||||||
|
|
||||||
|
if (get_config()->uid != 0) {
|
||||||
|
if (chown_to_running_user(path) == -1) {
|
||||||
|
auto error = errno;
|
||||||
|
LOG(WARN) << "Changing owner of http2 upstream response header file"
|
||||||
|
<< " " << path << " failed: " << strerror(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &tlsconf = mod_config()->tls;
|
||||||
|
|
||||||
|
if (tlsconf.npn_list.empty()) {
|
||||||
|
tlsconf.npn_list = util::parse_config_str_list(DEFAULT_NPN_LIST);
|
||||||
|
}
|
||||||
|
if (tlsconf.tls_proto_list.empty()) {
|
||||||
|
tlsconf.tls_proto_list =
|
||||||
|
util::parse_config_str_list(DEFAULT_TLS_PROTO_LIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsconf.tls_proto_mask = ssl::create_tls_proto_mask(tlsconf.tls_proto_list);
|
||||||
|
|
||||||
|
tlsconf.alpn_prefs = ssl::set_alpn_prefs(tlsconf.npn_list);
|
||||||
|
|
||||||
|
if (get_config()->backend_ipv4 && get_config()->backend_ipv6) {
|
||||||
|
LOG(FATAL) << "--backend-ipv4 and --backend-ipv6 cannot be used at the "
|
||||||
|
<< "same time.";
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_config()->worker_frontend_connections == 0) {
|
||||||
|
mod_config()->worker_frontend_connections =
|
||||||
|
std::numeric_limits<size_t>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_config()->http2_proxy + get_config()->http2_bridge +
|
||||||
|
get_config()->client_proxy + get_config()->client >
|
||||||
|
1) {
|
||||||
|
LOG(FATAL) << "--http2-proxy, --http2-bridge, --client-proxy and --client "
|
||||||
|
<< "cannot be used at the same time.";
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_config()->client || get_config()->client_proxy) {
|
||||||
|
mod_config()->client_mode = true;
|
||||||
|
mod_config()->upstream_no_tls = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_config()->client_mode || get_config()->http2_bridge) {
|
||||||
|
mod_config()->downstream_proto = PROTO_HTTP2;
|
||||||
|
} else {
|
||||||
|
mod_config()->downstream_proto = PROTO_HTTP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!get_config()->upstream_no_tls &&
|
||||||
|
(!tlsconf.private_key_file || !tlsconf.cert_file)) {
|
||||||
|
print_usage(std::cerr);
|
||||||
|
LOG(FATAL) << "Too few arguments";
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!get_config()->upstream_no_tls && !tlsconf.ocsp.disabled) {
|
||||||
|
struct stat buf;
|
||||||
|
if (stat(tlsconf.ocsp.fetch_ocsp_response_file.get(), &buf) != 0) {
|
||||||
|
tlsconf.ocsp.disabled = true;
|
||||||
|
LOG(WARN) << "--fetch-ocsp-response-file: "
|
||||||
|
<< tlsconf.ocsp.fetch_ocsp_response_file.get()
|
||||||
|
<< " not found. OCSP stapling has been disabled.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_config()->downstream_addr_groups.empty()) {
|
||||||
|
DownstreamAddr addr;
|
||||||
|
addr.host = ImmutableString::from_lit(DEFAULT_DOWNSTREAM_HOST);
|
||||||
|
addr.port = DEFAULT_DOWNSTREAM_PORT;
|
||||||
|
|
||||||
|
DownstreamAddrGroup g("/");
|
||||||
|
g.addrs.push_back(std::move(addr));
|
||||||
|
mod_config()->router.add_route(g.pattern.get(), 1,
|
||||||
|
get_config()->downstream_addr_groups.size());
|
||||||
|
mod_config()->downstream_addr_groups.push_back(std::move(g));
|
||||||
|
} else if (get_config()->http2_proxy || get_config()->client_proxy) {
|
||||||
|
// We don't support host mapping in these cases. Move all
|
||||||
|
// non-catch-all patterns to catch-all pattern.
|
||||||
|
DownstreamAddrGroup catch_all("/");
|
||||||
|
for (auto &g : mod_config()->downstream_addr_groups) {
|
||||||
|
std::move(std::begin(g.addrs), std::end(g.addrs),
|
||||||
|
std::back_inserter(catch_all.addrs));
|
||||||
|
}
|
||||||
|
std::vector<DownstreamAddrGroup>().swap(
|
||||||
|
mod_config()->downstream_addr_groups);
|
||||||
|
// maybe not necessary?
|
||||||
|
mod_config()->router = Router();
|
||||||
|
mod_config()->router.add_route(catch_all.pattern.get(), 1,
|
||||||
|
get_config()->downstream_addr_groups.size());
|
||||||
|
mod_config()->downstream_addr_groups.push_back(std::move(catch_all));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LOG_ENABLED(INFO)) {
|
||||||
|
LOG(INFO) << "Resolving backend address";
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t catch_all_group = -1;
|
||||||
|
for (size_t i = 0; i < mod_config()->downstream_addr_groups.size(); ++i) {
|
||||||
|
auto &g = mod_config()->downstream_addr_groups[i];
|
||||||
|
if (util::streq(g.pattern.get(), "/")) {
|
||||||
|
catch_all_group = i;
|
||||||
|
}
|
||||||
|
if (LOG_ENABLED(INFO)) {
|
||||||
|
LOG(INFO) << "Host-path pattern: group " << i << ": '" << g.pattern.get()
|
||||||
|
<< "'";
|
||||||
|
for (auto &addr : g.addrs) {
|
||||||
|
LOG(INFO) << "group " << i << " -> " << addr.host.c_str()
|
||||||
|
<< (addr.host_unix ? "" : ":" + util::utos(addr.port));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (catch_all_group == -1) {
|
||||||
|
LOG(FATAL) << "-b: No catch-all backend address is configured";
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
mod_config()->downstream_addr_group_catch_all = catch_all_group;
|
||||||
|
|
||||||
|
if (LOG_ENABLED(INFO)) {
|
||||||
|
LOG(INFO) << "Catch-all pattern is group " << catch_all_group;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &g : mod_config()->downstream_addr_groups) {
|
||||||
|
for (auto &addr : g.addrs) {
|
||||||
|
|
||||||
|
if (addr.host_unix) {
|
||||||
|
// for AF_UNIX socket, we use "localhost" as host for backend
|
||||||
|
// hostport. This is used as Host header field to backend and
|
||||||
|
// not going to be passed to any syscalls.
|
||||||
|
addr.hostport = ImmutableString(
|
||||||
|
util::make_hostport("localhost", get_config()->port));
|
||||||
|
|
||||||
|
auto path = addr.host.c_str();
|
||||||
|
auto pathlen = addr.host.size();
|
||||||
|
|
||||||
|
if (pathlen + 1 > sizeof(addr.addr.su.un.sun_path)) {
|
||||||
|
LOG(FATAL) << "UNIX domain socket path " << path << " is too long > "
|
||||||
|
<< sizeof(addr.addr.su.un.sun_path);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(INFO) << "Use UNIX domain socket path " << path
|
||||||
|
<< " for backend connection";
|
||||||
|
|
||||||
|
addr.addr.su.un.sun_family = AF_UNIX;
|
||||||
|
// copy path including terminal NULL
|
||||||
|
std::copy_n(path, pathlen + 1, addr.addr.su.un.sun_path);
|
||||||
|
addr.addr.len = sizeof(addr.addr.su.un);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr.hostport =
|
||||||
|
ImmutableString(util::make_hostport(addr.host.c_str(), addr.port));
|
||||||
|
|
||||||
|
if (resolve_hostname(
|
||||||
|
&addr.addr, addr.host.c_str(), addr.port,
|
||||||
|
get_config()->backend_ipv4 ? AF_INET : (get_config()->backend_ipv6
|
||||||
|
? AF_INET6
|
||||||
|
: AF_UNSPEC)) == -1) {
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &proxy = mod_config()->downstream_http_proxy;
|
||||||
|
if (!proxy.host.empty()) {
|
||||||
|
if (LOG_ENABLED(INFO)) {
|
||||||
|
LOG(INFO) << "Resolving backend http proxy address";
|
||||||
|
}
|
||||||
|
if (resolve_hostname(&proxy.addr, proxy.host.c_str(), proxy.port,
|
||||||
|
AF_UNSPEC) == -1) {
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto &memcachedconf = tlsconf.session_cache.memcached;
|
||||||
|
if (memcachedconf.host) {
|
||||||
|
if (resolve_hostname(&memcachedconf.addr, memcachedconf.host.get(),
|
||||||
|
memcachedconf.port, AF_UNSPEC) == -1) {
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto &memcachedconf = tlsconf.ticket.memcached;
|
||||||
|
if (memcachedconf.host) {
|
||||||
|
if (resolve_hostname(&memcachedconf.addr, memcachedconf.host.get(),
|
||||||
|
memcachedconf.port, AF_UNSPEC) == -1) {
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_config()->rlimit_nofile) {
|
||||||
|
struct rlimit lim = {static_cast<rlim_t>(get_config()->rlimit_nofile),
|
||||||
|
static_cast<rlim_t>(get_config()->rlimit_nofile)};
|
||||||
|
if (setrlimit(RLIMIT_NOFILE, &lim) != 0) {
|
||||||
|
auto error = errno;
|
||||||
|
LOG(WARN) << "Setting rlimit-nofile failed: " << strerror(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &fwdconf = mod_config()->http.forwarded;
|
||||||
|
|
||||||
|
if (fwdconf.by_node_type == FORWARDED_NODE_OBFUSCATED &&
|
||||||
|
fwdconf.by_obfuscated.empty()) {
|
||||||
|
std::random_device rd;
|
||||||
|
std::mt19937 gen(rd());
|
||||||
|
auto &dst = fwdconf.by_obfuscated;
|
||||||
|
dst = "_";
|
||||||
|
dst += util::random_alpha_digit(gen, SHRPX_OBFUSCATED_NODE_LENGTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_config()->http2.upstream.debug.frame_debug) {
|
||||||
|
// To make it sync to logging
|
||||||
|
set_output(stderr);
|
||||||
|
if (isatty(fileno(stdout))) {
|
||||||
|
set_color_output(true);
|
||||||
|
}
|
||||||
|
reset_timer();
|
||||||
|
}
|
||||||
|
|
||||||
|
mod_config()->http2.upstream.callbacks = create_http2_upstream_callbacks();
|
||||||
|
mod_config()->http2.downstream.callbacks =
|
||||||
|
create_http2_downstream_callbacks();
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
nghttp2::ssl::libssl_init();
|
nghttp2::ssl::libssl_init();
|
||||||
|
|
||||||
|
@ -2321,338 +2660,7 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf_exists(get_config()->conf_path.get())) {
|
process_options(argc, argv, cmdcfgs);
|
||||||
std::set<std::string> include_set;
|
|
||||||
if (load_config(get_config()->conf_path.get(), include_set) == -1) {
|
|
||||||
LOG(FATAL) << "Failed to load configuration from "
|
|
||||||
<< get_config()->conf_path.get();
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
assert(include_set.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc - optind >= 2) {
|
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_PRIVATE_KEY_FILE, argv[optind++]);
|
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_CERTIFICATE_FILE, argv[optind++]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reopen log files using configurations in file
|
|
||||||
reopen_log_files();
|
|
||||||
|
|
||||||
{
|
|
||||||
std::set<std::string> include_set;
|
|
||||||
|
|
||||||
for (size_t i = 0, len = cmdcfgs.size(); i < len; ++i) {
|
|
||||||
if (parse_config(cmdcfgs[i].first, cmdcfgs[i].second, include_set) ==
|
|
||||||
-1) {
|
|
||||||
LOG(FATAL) << "Failed to parse command-line argument.";
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(include_set.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_config()->accesslog_syslog || get_config()->errorlog_syslog) {
|
|
||||||
openlog("nghttpx", LOG_NDELAY | LOG_NOWAIT | LOG_PID,
|
|
||||||
get_config()->syslog_facility);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reopen_log_files() != 0) {
|
|
||||||
LOG(FATAL) << "Failed to open log file";
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
redirect_stderr_to_errorlog();
|
|
||||||
|
|
||||||
if (get_config()->uid != 0) {
|
|
||||||
if (log_config()->accesslog_fd != -1 &&
|
|
||||||
fchown(log_config()->accesslog_fd, get_config()->uid,
|
|
||||||
get_config()->gid) == -1) {
|
|
||||||
auto error = errno;
|
|
||||||
LOG(WARN) << "Changing owner of access log file failed: "
|
|
||||||
<< strerror(error);
|
|
||||||
}
|
|
||||||
if (log_config()->errorlog_fd != -1 &&
|
|
||||||
fchown(log_config()->errorlog_fd, get_config()->uid,
|
|
||||||
get_config()->gid) == -1) {
|
|
||||||
auto error = errno;
|
|
||||||
LOG(WARN) << "Changing owner of error log file failed: "
|
|
||||||
<< strerror(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &http2conf = mod_config()->http2;
|
|
||||||
{
|
|
||||||
auto &dumpconf = http2conf.upstream.debug.dump;
|
|
||||||
|
|
||||||
if (dumpconf.request_header_file) {
|
|
||||||
auto path = dumpconf.request_header_file.get();
|
|
||||||
auto f = open_file_for_write(path);
|
|
||||||
|
|
||||||
if (f == nullptr) {
|
|
||||||
LOG(FATAL) << "Failed to open http2 upstream request header file: "
|
|
||||||
<< path;
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
dumpconf.request_header = f;
|
|
||||||
|
|
||||||
if (get_config()->uid != 0) {
|
|
||||||
if (chown_to_running_user(path) == -1) {
|
|
||||||
auto error = errno;
|
|
||||||
LOG(WARN) << "Changing owner of http2 upstream request header file "
|
|
||||||
<< path << " failed: " << strerror(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dumpconf.response_header_file) {
|
|
||||||
auto path = dumpconf.response_header_file.get();
|
|
||||||
auto f = open_file_for_write(path);
|
|
||||||
|
|
||||||
if (f == nullptr) {
|
|
||||||
LOG(FATAL) << "Failed to open http2 upstream response header file: "
|
|
||||||
<< path;
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
dumpconf.response_header = f;
|
|
||||||
|
|
||||||
if (get_config()->uid != 0) {
|
|
||||||
if (chown_to_running_user(path) == -1) {
|
|
||||||
auto error = errno;
|
|
||||||
LOG(WARN) << "Changing owner of http2 upstream response header file"
|
|
||||||
<< " " << path << " failed: " << strerror(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &tlsconf = mod_config()->tls;
|
|
||||||
|
|
||||||
if (tlsconf.npn_list.empty()) {
|
|
||||||
tlsconf.npn_list = util::parse_config_str_list(DEFAULT_NPN_LIST);
|
|
||||||
}
|
|
||||||
if (tlsconf.tls_proto_list.empty()) {
|
|
||||||
tlsconf.tls_proto_list =
|
|
||||||
util::parse_config_str_list(DEFAULT_TLS_PROTO_LIST);
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsconf.tls_proto_mask = ssl::create_tls_proto_mask(tlsconf.tls_proto_list);
|
|
||||||
|
|
||||||
tlsconf.alpn_prefs = ssl::set_alpn_prefs(tlsconf.npn_list);
|
|
||||||
|
|
||||||
if (get_config()->backend_ipv4 && get_config()->backend_ipv6) {
|
|
||||||
LOG(FATAL) << "--backend-ipv4 and --backend-ipv6 cannot be used at the "
|
|
||||||
<< "same time.";
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_config()->worker_frontend_connections == 0) {
|
|
||||||
mod_config()->worker_frontend_connections =
|
|
||||||
std::numeric_limits<size_t>::max();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_config()->http2_proxy + get_config()->http2_bridge +
|
|
||||||
get_config()->client_proxy + get_config()->client >
|
|
||||||
1) {
|
|
||||||
LOG(FATAL) << "--http2-proxy, --http2-bridge, --client-proxy and --client "
|
|
||||||
<< "cannot be used at the same time.";
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_config()->client || get_config()->client_proxy) {
|
|
||||||
mod_config()->client_mode = true;
|
|
||||||
mod_config()->upstream_no_tls = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_config()->client_mode || get_config()->http2_bridge) {
|
|
||||||
mod_config()->downstream_proto = PROTO_HTTP2;
|
|
||||||
} else {
|
|
||||||
mod_config()->downstream_proto = PROTO_HTTP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!get_config()->upstream_no_tls &&
|
|
||||||
(!tlsconf.private_key_file || !tlsconf.cert_file)) {
|
|
||||||
print_usage(std::cerr);
|
|
||||||
LOG(FATAL) << "Too few arguments";
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!get_config()->upstream_no_tls && !tlsconf.ocsp.disabled) {
|
|
||||||
struct stat buf;
|
|
||||||
if (stat(tlsconf.ocsp.fetch_ocsp_response_file.get(), &buf) != 0) {
|
|
||||||
tlsconf.ocsp.disabled = true;
|
|
||||||
LOG(WARN) << "--fetch-ocsp-response-file: "
|
|
||||||
<< tlsconf.ocsp.fetch_ocsp_response_file.get()
|
|
||||||
<< " not found. OCSP stapling has been disabled.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_config()->downstream_addr_groups.empty()) {
|
|
||||||
DownstreamAddr addr;
|
|
||||||
addr.host = ImmutableString::from_lit(DEFAULT_DOWNSTREAM_HOST);
|
|
||||||
addr.port = DEFAULT_DOWNSTREAM_PORT;
|
|
||||||
|
|
||||||
DownstreamAddrGroup g("/");
|
|
||||||
g.addrs.push_back(std::move(addr));
|
|
||||||
mod_config()->router.add_route(g.pattern.get(), 1,
|
|
||||||
get_config()->downstream_addr_groups.size());
|
|
||||||
mod_config()->downstream_addr_groups.push_back(std::move(g));
|
|
||||||
} else if (get_config()->http2_proxy || get_config()->client_proxy) {
|
|
||||||
// We don't support host mapping in these cases. Move all
|
|
||||||
// non-catch-all patterns to catch-all pattern.
|
|
||||||
DownstreamAddrGroup catch_all("/");
|
|
||||||
for (auto &g : mod_config()->downstream_addr_groups) {
|
|
||||||
std::move(std::begin(g.addrs), std::end(g.addrs),
|
|
||||||
std::back_inserter(catch_all.addrs));
|
|
||||||
}
|
|
||||||
std::vector<DownstreamAddrGroup>().swap(
|
|
||||||
mod_config()->downstream_addr_groups);
|
|
||||||
// maybe not necessary?
|
|
||||||
mod_config()->router = Router();
|
|
||||||
mod_config()->router.add_route(catch_all.pattern.get(), 1,
|
|
||||||
get_config()->downstream_addr_groups.size());
|
|
||||||
mod_config()->downstream_addr_groups.push_back(std::move(catch_all));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
|
||||||
LOG(INFO) << "Resolving backend address";
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t catch_all_group = -1;
|
|
||||||
for (size_t i = 0; i < mod_config()->downstream_addr_groups.size(); ++i) {
|
|
||||||
auto &g = mod_config()->downstream_addr_groups[i];
|
|
||||||
if (util::streq(g.pattern.get(), "/")) {
|
|
||||||
catch_all_group = i;
|
|
||||||
}
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
|
||||||
LOG(INFO) << "Host-path pattern: group " << i << ": '" << g.pattern.get()
|
|
||||||
<< "'";
|
|
||||||
for (auto &addr : g.addrs) {
|
|
||||||
LOG(INFO) << "group " << i << " -> " << addr.host.c_str()
|
|
||||||
<< (addr.host_unix ? "" : ":" + util::utos(addr.port));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (catch_all_group == -1) {
|
|
||||||
LOG(FATAL) << "-b: No catch-all backend address is configured";
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
mod_config()->downstream_addr_group_catch_all = catch_all_group;
|
|
||||||
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
|
||||||
LOG(INFO) << "Catch-all pattern is group " << catch_all_group;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &g : mod_config()->downstream_addr_groups) {
|
|
||||||
for (auto &addr : g.addrs) {
|
|
||||||
|
|
||||||
if (addr.host_unix) {
|
|
||||||
// for AF_UNIX socket, we use "localhost" as host for backend
|
|
||||||
// hostport. This is used as Host header field to backend and
|
|
||||||
// not going to be passed to any syscalls.
|
|
||||||
addr.hostport = ImmutableString(
|
|
||||||
util::make_hostport("localhost", get_config()->port));
|
|
||||||
|
|
||||||
auto path = addr.host.c_str();
|
|
||||||
auto pathlen = addr.host.size();
|
|
||||||
|
|
||||||
if (pathlen + 1 > sizeof(addr.addr.su.un.sun_path)) {
|
|
||||||
LOG(FATAL) << "UNIX domain socket path " << path << " is too long > "
|
|
||||||
<< sizeof(addr.addr.su.un.sun_path);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(INFO) << "Use UNIX domain socket path " << path
|
|
||||||
<< " for backend connection";
|
|
||||||
|
|
||||||
addr.addr.su.un.sun_family = AF_UNIX;
|
|
||||||
// copy path including terminal NULL
|
|
||||||
std::copy_n(path, pathlen + 1, addr.addr.su.un.sun_path);
|
|
||||||
addr.addr.len = sizeof(addr.addr.su.un);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr.hostport =
|
|
||||||
ImmutableString(util::make_hostport(addr.host.c_str(), addr.port));
|
|
||||||
|
|
||||||
if (resolve_hostname(
|
|
||||||
&addr.addr, addr.host.c_str(), addr.port,
|
|
||||||
get_config()->backend_ipv4 ? AF_INET : (get_config()->backend_ipv6
|
|
||||||
? AF_INET6
|
|
||||||
: AF_UNSPEC)) == -1) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &proxy = mod_config()->downstream_http_proxy;
|
|
||||||
if (!proxy.host.empty()) {
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
|
||||||
LOG(INFO) << "Resolving backend http proxy address";
|
|
||||||
}
|
|
||||||
if (resolve_hostname(&proxy.addr, proxy.host.c_str(), proxy.port,
|
|
||||||
AF_UNSPEC) == -1) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto &memcachedconf = tlsconf.session_cache.memcached;
|
|
||||||
if (memcachedconf.host) {
|
|
||||||
if (resolve_hostname(&memcachedconf.addr, memcachedconf.host.get(),
|
|
||||||
memcachedconf.port, AF_UNSPEC) == -1) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto &memcachedconf = tlsconf.ticket.memcached;
|
|
||||||
if (memcachedconf.host) {
|
|
||||||
if (resolve_hostname(&memcachedconf.addr, memcachedconf.host.get(),
|
|
||||||
memcachedconf.port, AF_UNSPEC) == -1) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_config()->rlimit_nofile) {
|
|
||||||
struct rlimit lim = {static_cast<rlim_t>(get_config()->rlimit_nofile),
|
|
||||||
static_cast<rlim_t>(get_config()->rlimit_nofile)};
|
|
||||||
if (setrlimit(RLIMIT_NOFILE, &lim) != 0) {
|
|
||||||
auto error = errno;
|
|
||||||
LOG(WARN) << "Setting rlimit-nofile failed: " << strerror(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &fwdconf = mod_config()->http.forwarded;
|
|
||||||
|
|
||||||
if (fwdconf.by_node_type == FORWARDED_NODE_OBFUSCATED &&
|
|
||||||
fwdconf.by_obfuscated.empty()) {
|
|
||||||
std::random_device rd;
|
|
||||||
std::mt19937 gen(rd());
|
|
||||||
auto &dst = fwdconf.by_obfuscated;
|
|
||||||
dst = "_";
|
|
||||||
dst += util::random_alpha_digit(gen, SHRPX_OBFUSCATED_NODE_LENGTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_config()->http2.upstream.debug.frame_debug) {
|
|
||||||
// To make it sync to logging
|
|
||||||
set_output(stderr);
|
|
||||||
if (isatty(fileno(stdout))) {
|
|
||||||
set_color_output(true);
|
|
||||||
}
|
|
||||||
reset_timer();
|
|
||||||
}
|
|
||||||
|
|
||||||
mod_config()->http2.upstream.callbacks = create_http2_upstream_callbacks();
|
|
||||||
mod_config()->http2.downstream.callbacks =
|
|
||||||
create_http2_downstream_callbacks();
|
|
||||||
|
|
||||||
if (event_loop() != 0) {
|
if (event_loop() != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Reference in New Issue