nghttpx: Add BlockAllocator to Config object

This commit is contained in:
Tatsuhiro Tsujikawa 2016-10-02 21:22:02 +09:00
parent 272cfa320e
commit 99a91e3172
11 changed files with 166 additions and 141 deletions

View File

@ -86,6 +86,7 @@
#include "app_helper.h" #include "app_helper.h"
#include "ssl.h" #include "ssl.h"
#include "template.h" #include "template.h"
#include "allocator.h"
extern char **environ; extern char **environ;
@ -151,7 +152,7 @@ StartupConfig suconfig;
struct InheritedAddr { struct InheritedAddr {
// IP address if TCP socket. Otherwise, UNIX domain socket path. // IP address if TCP socket. Otherwise, UNIX domain socket path.
ImmutableString host; StringRef host;
uint16_t port; uint16_t port;
// true if UNIX domain socket path // true if UNIX domain socket path
bool host_unix; bool host_unix;
@ -574,7 +575,7 @@ int create_unix_domain_server_socket(UpstreamAddr &faddr,
<< (faddr.tls ? ", tls" : ""); << (faddr.tls ? ", tls" : "");
(*found).used = true; (*found).used = true;
faddr.fd = (*found).fd; faddr.fd = (*found).fd;
faddr.hostport = ImmutableString::from_lit("localhost"); faddr.hostport = StringRef::from_lit("localhost");
return 0; return 0;
} }
@ -639,7 +640,7 @@ int create_unix_domain_server_socket(UpstreamAddr &faddr,
<< (faddr.tls ? ", tls" : ""); << (faddr.tls ? ", tls" : "");
faddr.fd = fd; faddr.fd = fd;
faddr.hostport = ImmutableString::from_lit("localhost"); faddr.hostport = StringRef::from_lit("localhost");
return 0; return 0;
} }
@ -791,8 +792,8 @@ int create_tcp_server_socket(UpstreamAddr &faddr,
} }
faddr.fd = fd; faddr.fd = fd;
faddr.hostport = ImmutableString{ faddr.hostport = util::make_http_hostport(mod_config()->balloc,
util::make_http_hostport(StringRef{host.data()}, faddr.port)}; StringRef{host.data()}, faddr.port);
LOG(NOTICE) << "Listening on " << faddr.hostport LOG(NOTICE) << "Listening on " << faddr.hostport
<< (faddr.tls ? ", tls" : ""); << (faddr.tls ? ", tls" : "");
@ -805,8 +806,7 @@ namespace {
// Returns array of InheritedAddr constructed from |config|. This // Returns array of InheritedAddr constructed from |config|. This
// function is intended to be used when reloading configuration, and // function is intended to be used when reloading configuration, and
// |config| is usually a current configuration. // |config| is usually a current configuration.
std::vector<InheritedAddr> std::vector<InheritedAddr> get_inherited_addr_from_config(Config *config) {
get_inherited_addr_from_config(const Config *config) {
int rv; int rv;
auto &listenerconf = config->conn.listener; auto &listenerconf = config->conn.listener;
@ -856,7 +856,7 @@ get_inherited_addr_from_config(const Config *config) {
continue; continue;
} }
iaddr.host = ImmutableString{host.data()}; iaddr.host = make_string_ref(config->balloc, StringRef{host.data()});
} }
return iaddrs; return iaddrs;
@ -867,7 +867,7 @@ namespace {
// Returns array of InheritedAddr constructed from environment // Returns array of InheritedAddr constructed from environment
// variables. This function handles the old environment variable // variables. This function handles the old environment variable
// names used in 1.7.0 or earlier. // names used in 1.7.0 or earlier.
std::vector<InheritedAddr> get_inherited_addr_from_env() { std::vector<InheritedAddr> get_inherited_addr_from_env(Config *config) {
int rv; int rv;
std::vector<InheritedAddr> iaddrs; std::vector<InheritedAddr> iaddrs;
@ -888,15 +888,13 @@ std::vector<InheritedAddr> get_inherited_addr_from_env() {
} }
} }
} else { } else {
auto pathenv = getenv(ENV_UNIX_PATH.c_str()); if (getenv(ENV_UNIX_PATH.c_str()) && getenv(ENV_UNIX_FD.c_str())) {
auto fdenv = getenv(ENV_UNIX_FD.c_str());
if (pathenv && fdenv) {
auto name = ENV_ACCEPT_PREFIX.str(); auto name = ENV_ACCEPT_PREFIX.str();
name += '1'; name += '1';
std::string value = "unix,"; std::string value = "unix,";
value += fdenv; value += getenv(ENV_UNIX_FD.c_str());
value += ','; value += ',';
value += pathenv; value += getenv(ENV_UNIX_PATH.c_str());
setenv(name.c_str(), value.c_str(), 0); setenv(name.c_str(), value.c_str(), 0);
} }
} }
@ -948,7 +946,7 @@ std::vector<InheritedAddr> get_inherited_addr_from_env() {
} }
InheritedAddr addr{}; InheritedAddr addr{};
addr.host = ImmutableString{path}; addr.host = make_string_ref(config->balloc, StringRef{path});
addr.host_unix = true; addr.host_unix = true;
addr.fd = static_cast<int>(fd); addr.fd = static_cast<int>(fd);
iaddrs.push_back(std::move(addr)); iaddrs.push_back(std::move(addr));
@ -1002,7 +1000,7 @@ std::vector<InheritedAddr> get_inherited_addr_from_env() {
} }
InheritedAddr addr{}; InheritedAddr addr{};
addr.host = ImmutableString{host.data()}; addr.host = make_string_ref(config->balloc, StringRef{host.data()});
addr.port = static_cast<uint16_t>(port); addr.port = static_cast<uint16_t>(port);
addr.fd = static_cast<int>(fd); addr.fd = static_cast<int>(fd);
iaddrs.push_back(std::move(addr)); iaddrs.push_back(std::move(addr));
@ -1209,7 +1207,7 @@ int event_loop() {
redirect_stderr_to_errorlog(); redirect_stderr_to_errorlog();
} }
auto iaddrs = get_inherited_addr_from_env(); auto iaddrs = get_inherited_addr_from_env(mod_config());
if (create_acceptor_socket(mod_config(), iaddrs) != 0) { if (create_acceptor_socket(mod_config(), iaddrs) != 0) {
return -1; return -1;
@ -1274,7 +1272,7 @@ constexpr auto DEFAULT_ACCESSLOG_FORMAT = StringRef::from_lit(
namespace { namespace {
void fill_default_config(Config *config) { void fill_default_config(Config *config) {
config->num_worker = 1; config->num_worker = 1;
config->conf_path = ImmutableString::from_lit("/etc/nghttpx/nghttpx.conf"); config->conf_path = StringRef::from_lit("/etc/nghttpx/nghttpx.conf");
config->pid = getpid(); config->pid = getpid();
if (ev_supported_backends() & ~ev_recommended_backends() & EVBACKEND_KQUEUE) { if (ev_supported_backends() & ~ev_recommended_backends() & EVBACKEND_KQUEUE) {
@ -1306,7 +1304,7 @@ void fill_default_config(Config *config) {
// ocsp update interval = 14400 secs = 4 hours, borrowed from h2o // ocsp update interval = 14400 secs = 4 hours, borrowed from h2o
ocspconf.update_interval = 4_h; ocspconf.update_interval = 4_h;
ocspconf.fetch_ocsp_response_file = ocspconf.fetch_ocsp_response_file =
ImmutableString::from_lit(PKGDATADIR "/fetch-ocsp-response"); StringRef::from_lit(PKGDATADIR "/fetch-ocsp-response");
} }
{ {
@ -1319,7 +1317,7 @@ void fill_default_config(Config *config) {
auto &httpconf = config->http; auto &httpconf = config->http;
httpconf.server_name = httpconf.server_name =
ImmutableString::from_lit("nghttpx nghttp2/" NGHTTP2_VERSION); StringRef::from_lit("nghttpx nghttp2/" NGHTTP2_VERSION);
httpconf.no_host_rewrite = true; httpconf.no_host_rewrite = true;
httpconf.request_header_field_buffer = 64_k; httpconf.request_header_field_buffer = 64_k;
httpconf.max_request_header_fields = 100; httpconf.max_request_header_fields = 100;
@ -1387,10 +1385,11 @@ void fill_default_config(Config *config) {
auto &loggingconf = config->logging; auto &loggingconf = config->logging;
{ {
auto &accessconf = loggingconf.access; auto &accessconf = loggingconf.access;
accessconf.format = parse_log_format(DEFAULT_ACCESSLOG_FORMAT); accessconf.format =
parse_log_format(config->balloc, DEFAULT_ACCESSLOG_FORMAT);
auto &errorconf = loggingconf.error; auto &errorconf = loggingconf.error;
errorconf.file = ImmutableString::from_lit("/dev/stderr"); errorconf.file = StringRef::from_lit("/dev/stderr");
} }
loggingconf.syslog_facility = LOG_DAEMON; loggingconf.syslog_facility = LOG_DAEMON;
@ -2466,7 +2465,7 @@ int process_options(Config *config,
if (listenerconf.addrs.empty()) { if (listenerconf.addrs.empty()) {
UpstreamAddr addr{}; UpstreamAddr addr{};
addr.host = ImmutableString::from_lit("*"); addr.host = StringRef::from_lit("*");
addr.port = 3000; addr.port = 3000;
addr.tls = true; addr.tls = true;
addr.family = AF_INET; addr.family = AF_INET;
@ -2567,12 +2566,14 @@ int process_options(Config *config,
if (fwdconf.by_node_type == FORWARDED_NODE_OBFUSCATED && if (fwdconf.by_node_type == FORWARDED_NODE_OBFUSCATED &&
fwdconf.by_obfuscated.empty()) { fwdconf.by_obfuscated.empty()) {
std::mt19937 gen(rd()); // 2 for '_' and terminal NULL
auto &dst = fwdconf.by_obfuscated; auto iov = make_byte_ref(config->balloc, SHRPX_OBFUSCATED_NODE_LENGTH + 2);
dst.resize(1 + SHRPX_OBFUSCATED_NODE_LENGTH); auto p = iov.base;
auto p = std::begin(dst);
*p++ = '_'; *p++ = '_';
util::random_alpha_digit(p, std::end(dst), gen); std::mt19937 gen(rd());
p = util::random_alpha_digit(p, p + SHRPX_OBFUSCATED_NODE_LENGTH, gen);
*p = '\0';
fwdconf.by_obfuscated = StringRef{iov.base, p};
} }
if (config->http2.upstream.debug.frame_debug) { if (config->http2.upstream.debug.frame_debug) {
@ -2618,12 +2619,13 @@ void reload_config(WorkerProcess *wp) {
LOG(NOTICE) << "Reloading configuration"; LOG(NOTICE) << "Reloading configuration";
auto cur_config = get_config(); auto cur_config = mod_config();
auto new_config = make_unique<Config>(); auto new_config = make_unique<Config>();
fill_default_config(new_config.get()); fill_default_config(new_config.get());
new_config->conf_path = cur_config->conf_path; new_config->conf_path =
make_string_ref(new_config->balloc, cur_config->conf_path);
// daemon option is ignored here. // daemon option is ignored here.
new_config->daemon = cur_config->daemon; new_config->daemon = cur_config->daemon;
// loop is reused, and ev_loop_flags gets ignored // loop is reused, and ev_loop_flags gets ignored
@ -3029,7 +3031,8 @@ int main(int argc, char **argv) {
break; break;
case 12: case 12:
// --conf // --conf
mod_config()->conf_path = ImmutableString{optarg}; mod_config()->conf_path =
make_string_ref(mod_config()->balloc, StringRef{optarg});
break; break;
case 14: case 14:
// --syslog-facility // --syslog-facility

View File

@ -1504,10 +1504,10 @@ StringRef ClientHandler::get_forwarded_by() const {
auto &fwdconf = get_config()->http.forwarded; auto &fwdconf = get_config()->http.forwarded;
if (fwdconf.by_node_type == FORWARDED_NODE_OBFUSCATED) { if (fwdconf.by_node_type == FORWARDED_NODE_OBFUSCATED) {
return StringRef(fwdconf.by_obfuscated); return fwdconf.by_obfuscated;
} }
return StringRef{faddr_->hostport}; return faddr_->hostport;
} }
StringRef ClientHandler::get_forwarded_for() const { return forwarded_for_; } StringRef ClientHandler::get_forwarded_for() const { return forwarded_for_; }

View File

@ -490,7 +490,8 @@ bool var_token(char c) {
} }
} // namespace } // namespace
std::vector<LogFragment> parse_log_format(const StringRef &optarg) { std::vector<LogFragment> parse_log_format(BlockAllocator &balloc,
const StringRef &optarg) {
auto literal_start = std::begin(optarg); auto literal_start = std::begin(optarg);
auto p = literal_start; auto p = literal_start;
auto eop = std::end(optarg); auto eop = std::end(optarg);
@ -553,8 +554,9 @@ std::vector<LogFragment> parse_log_format(const StringRef &optarg) {
} }
if (literal_start < var_start) { if (literal_start < var_start) {
res.emplace_back(SHRPX_LOGF_LITERAL, res.emplace_back(
ImmutableString(literal_start, var_start)); SHRPX_LOGF_LITERAL,
make_string_ref(balloc, StringRef{literal_start, var_start}));
} }
literal_start = p; literal_start = p;
@ -564,18 +566,24 @@ std::vector<LogFragment> parse_log_format(const StringRef &optarg) {
continue; continue;
} }
auto name = std::string(value, var_name + var_namelen); {
for (auto &c : name) { auto iov = make_byte_ref(
if (c == '_') { balloc, std::distance(value, var_name + var_namelen) + 1);
c = '-'; auto p = iov.base;
p = std::copy(value, var_name + var_namelen, p);
for (auto cp = iov.base; cp != p; ++cp) {
if (*cp == '_') {
*cp = '-';
}
} }
*p = '\0';
res.emplace_back(type, StringRef{iov.base, p});
} }
res.emplace_back(type, ImmutableString(name));
} }
if (literal_start != eop) { if (literal_start != eop) {
res.emplace_back(SHRPX_LOGF_LITERAL, ImmutableString(literal_start, eop)); res.emplace_back(SHRPX_LOGF_LITERAL,
make_string_ref(balloc, StringRef{literal_start, eop}));
} }
return res; return res;
@ -1877,7 +1885,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) { if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) {
auto path = std::begin(optarg) + SHRPX_UNIX_PATH_PREFIX.size(); auto path = std::begin(optarg) + SHRPX_UNIX_PATH_PREFIX.size();
addr.host = ImmutableString{path, addr_end}; addr.host = make_string_ref(config->balloc, StringRef{path, addr_end});
addr.host_unix = true; addr.host_unix = true;
listenerconf.addrs.push_back(std::move(addr)); listenerconf.addrs.push_back(std::move(addr));
@ -1890,7 +1898,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
return -1; return -1;
} }
addr.host = ImmutableString(host); addr.host = make_string_ref(config->balloc, StringRef{host});
addr.port = port; addr.port = port;
if (util::numeric_host(host, AF_INET)) { if (util::numeric_host(host, AF_INET)) {
@ -1987,8 +1995,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
case SHRPX_OPTID_STREAM_WRITE_TIMEOUT: case SHRPX_OPTID_STREAM_WRITE_TIMEOUT:
return parse_duration(&config->http2.timeout.stream_write, opt, optarg); return parse_duration(&config->http2.timeout.stream_write, opt, optarg);
case SHRPX_OPTID_ACCESSLOG_FILE: case SHRPX_OPTID_ACCESSLOG_FILE:
config->logging.access.file = config->logging.access.file = make_string_ref(config->balloc, optarg);
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_ACCESSLOG_SYSLOG: case SHRPX_OPTID_ACCESSLOG_SYSLOG:
@ -1996,12 +2003,11 @@ int parse_config(Config *config, int optid, const StringRef &opt,
return 0; return 0;
case SHRPX_OPTID_ACCESSLOG_FORMAT: case SHRPX_OPTID_ACCESSLOG_FORMAT:
config->logging.access.format = parse_log_format(optarg); config->logging.access.format = parse_log_format(config->balloc, optarg);
return 0; return 0;
case SHRPX_OPTID_ERRORLOG_FILE: case SHRPX_OPTID_ERRORLOG_FILE:
config->logging.error.file = config->logging.error.file = make_string_ref(config->balloc, optarg);
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_ERRORLOG_SYSLOG: case SHRPX_OPTID_ERRORLOG_SYSLOG:
@ -2105,11 +2111,11 @@ int parse_config(Config *config, int optid, const StringRef &opt,
LOG(WARN) << opt << ": deprecated. Use sni keyword in --backend option. " LOG(WARN) << opt << ": deprecated. Use sni keyword in --backend option. "
"For now, all sni values of all backends are " "For now, all sni values of all backends are "
"overridden by the given value " << optarg; "overridden by the given value " << optarg;
config->tls.backend_sni_name = optarg.str(); config->tls.backend_sni_name = make_string_ref(config->balloc, optarg);
return 0; return 0;
case SHRPX_OPTID_PID_FILE: case SHRPX_OPTID_PID_FILE:
config->pid_file = ImmutableString{std::begin(optarg), std::end(optarg)}; config->pid_file = make_string_ref(config->balloc, optarg);
return 0; return 0;
case SHRPX_OPTID_USER: { case SHRPX_OPTID_USER: {
@ -2119,15 +2125,14 @@ int parse_config(Config *config, int optid, const StringRef &opt,
<< strerror(errno); << strerror(errno);
return -1; return -1;
} }
config->user = ImmutableString{pwd->pw_name}; config->user = make_string_ref(config->balloc, StringRef{pwd->pw_name});
config->uid = pwd->pw_uid; config->uid = pwd->pw_uid;
config->gid = pwd->pw_gid; config->gid = pwd->pw_gid;
return 0; return 0;
} }
case SHRPX_OPTID_PRIVATE_KEY_FILE: case SHRPX_OPTID_PRIVATE_KEY_FILE:
config->tls.private_key_file = config->tls.private_key_file = make_string_ref(config->balloc, optarg);
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_PRIVATE_KEY_PASSWD_FILE: { case SHRPX_OPTID_PRIVATE_KEY_PASSWD_FILE: {
@ -2136,18 +2141,17 @@ int parse_config(Config *config, int optid, const StringRef &opt,
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;
} }
config->tls.private_key_passwd = ImmutableString{passwd}; config->tls.private_key_passwd =
make_string_ref(config->balloc, StringRef{passwd});
return 0; return 0;
} }
case SHRPX_OPTID_CERTIFICATE_FILE: case SHRPX_OPTID_CERTIFICATE_FILE:
config->tls.cert_file = config->tls.cert_file = make_string_ref(config->balloc, optarg);
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_DH_PARAM_FILE: case SHRPX_OPTID_DH_PARAM_FILE:
config->tls.dh_param_file = config->tls.dh_param_file = make_string_ref(config->balloc, optarg);
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_SUBCERT: { case SHRPX_OPTID_SUBCERT: {
@ -2203,7 +2207,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
return 0; return 0;
} }
case SHRPX_OPTID_CIPHERS: case SHRPX_OPTID_CIPHERS:
config->tls.ciphers = ImmutableString{std::begin(optarg), std::end(optarg)}; config->tls.ciphers = make_string_ref(config->balloc, optarg);
return 0; return 0;
case SHRPX_OPTID_CLIENT: case SHRPX_OPTID_CLIENT:
@ -2215,7 +2219,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
return 0; return 0;
case SHRPX_OPTID_CACERT: case SHRPX_OPTID_CACERT:
config->tls.cacert = ImmutableString{std::begin(optarg), std::end(optarg)}; config->tls.cacert = make_string_ref(config->balloc, optarg);
return 0; return 0;
case SHRPX_OPTID_BACKEND_IPV4: case SHRPX_OPTID_BACKEND_IPV4:
@ -2305,28 +2309,26 @@ int parse_config(Config *config, int optid, const StringRef &opt,
return 0; return 0;
case SHRPX_OPTID_VERIFY_CLIENT_CACERT: case SHRPX_OPTID_VERIFY_CLIENT_CACERT:
config->tls.client_verify.cacert = config->tls.client_verify.cacert = make_string_ref(config->balloc, optarg);
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE: case SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE:
config->tls.client.private_key_file = config->tls.client.private_key_file =
ImmutableString{std::begin(optarg), std::end(optarg)}; make_string_ref(config->balloc, optarg);
return 0; return 0;
case SHRPX_OPTID_CLIENT_CERT_FILE: case SHRPX_OPTID_CLIENT_CERT_FILE:
config->tls.client.cert_file = config->tls.client.cert_file = make_string_ref(config->balloc, optarg);
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER: case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER:
config->http2.upstream.debug.dump.request_header_file = config->http2.upstream.debug.dump.request_header_file =
ImmutableString{std::begin(optarg), std::end(optarg)}; make_string_ref(config->balloc, optarg);
return 0; return 0;
case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER: case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER:
config->http2.upstream.debug.dump.response_header_file = config->http2.upstream.debug.dump.response_header_file =
ImmutableString{std::begin(optarg), std::end(optarg)}; make_string_ref(config->balloc, optarg);
return 0; return 0;
case SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING: case SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING:
@ -2493,7 +2495,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
return 0; return 0;
case SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE: case SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE:
config->tls.ocsp.fetch_ocsp_response_file = config->tls.ocsp.fetch_ocsp_response_file =
ImmutableString{std::begin(optarg), std::end(optarg)}; make_string_ref(config->balloc, optarg);
return 0; return 0;
case SHRPX_OPTID_OCSP_UPDATE_INTERVAL: case SHRPX_OPTID_OCSP_UPDATE_INTERVAL:
@ -2571,14 +2573,14 @@ int parse_config(Config *config, int optid, const StringRef &opt,
switch (optid) { switch (optid) {
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED: { case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED: {
auto &memcachedconf = config->tls.session_cache.memcached; auto &memcachedconf = config->tls.session_cache.memcached;
memcachedconf.host = ImmutableString{host}; memcachedconf.host = make_string_ref(config->balloc, StringRef{host});
memcachedconf.port = port; memcachedconf.port = port;
memcachedconf.tls = params.tls; memcachedconf.tls = params.tls;
break; break;
} }
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED: { case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED: {
auto &memcachedconf = config->tls.ticket.memcached; auto &memcachedconf = config->tls.ticket.memcached;
memcachedconf.host = ImmutableString{host}; memcachedconf.host = make_string_ref(config->balloc, StringRef{host});
memcachedconf.port = port; memcachedconf.port = port;
memcachedconf.tls = params.tls; memcachedconf.tls = params.tls;
break; break;
@ -2621,7 +2623,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
case SHRPX_OPTID_MRUBY_FILE: case SHRPX_OPTID_MRUBY_FILE:
#ifdef HAVE_MRUBY #ifdef HAVE_MRUBY
config->mruby_file = ImmutableString{std::begin(optarg), std::end(optarg)}; config->mruby_file = make_string_ref(config->balloc, optarg);
#else // !HAVE_MRUBY #else // !HAVE_MRUBY
LOG(WARN) << opt LOG(WARN) << opt
<< ": ignored because mruby support is disabled at build time."; << ": ignored because mruby support is disabled at build time.";
@ -2680,9 +2682,9 @@ int parse_config(Config *config, int optid, const StringRef &opt,
case SHRPX_OPTID_FORWARDED_BY: case SHRPX_OPTID_FORWARDED_BY:
fwdconf.by_node_type = static_cast<shrpx_forwarded_node_type>(type); fwdconf.by_node_type = static_cast<shrpx_forwarded_node_type>(type);
if (optarg[0] == '_') { if (optarg[0] == '_') {
fwdconf.by_obfuscated = optarg.str(); fwdconf.by_obfuscated = make_string_ref(config->balloc, optarg);
} else { } else {
fwdconf.by_obfuscated = ""; fwdconf.by_obfuscated = StringRef::from_lit("");
} }
break; break;
case SHRPX_OPTID_FORWARDED_FOR: case SHRPX_OPTID_FORWARDED_FOR:
@ -2707,12 +2709,12 @@ int parse_config(Config *config, int optid, const StringRef &opt,
return 0; return 0;
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE: case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE:
config->tls.session_cache.memcached.cert_file = config->tls.session_cache.memcached.cert_file =
ImmutableString{std::begin(optarg), std::end(optarg)}; make_string_ref(config->balloc, optarg);
return 0; return 0;
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE: case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE:
config->tls.session_cache.memcached.private_key_file = config->tls.session_cache.memcached.private_key_file =
ImmutableString{std::begin(optarg), std::end(optarg)}; make_string_ref(config->balloc, optarg);
return 0; return 0;
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_TLS: case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_TLS:
@ -2721,12 +2723,12 @@ int parse_config(Config *config, int optid, const StringRef &opt,
return 0; return 0;
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_CERT_FILE: case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_CERT_FILE:
config->tls.ticket.memcached.cert_file = config->tls.ticket.memcached.cert_file =
ImmutableString{std::begin(optarg), std::end(optarg)}; make_string_ref(config->balloc, optarg);
return 0; return 0;
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE: case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE:
config->tls.ticket.memcached.private_key_file = config->tls.ticket.memcached.private_key_file =
ImmutableString{std::begin(optarg), std::end(optarg)}; make_string_ref(config->balloc, optarg);
return 0; return 0;
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY: case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY:
@ -2766,8 +2768,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
return parse_duration(&config->conn.downstream->timeout.max_backoff, opt, return parse_duration(&config->conn.downstream->timeout.max_backoff, opt,
optarg); optarg);
case SHRPX_OPTID_SERVER_NAME: case SHRPX_OPTID_SERVER_NAME:
config->http.server_name = config->http.server_name = make_string_ref(config->balloc, optarg);
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_NO_SERVER_REWRITE: case SHRPX_OPTID_NO_SERVER_REWRITE:

View File

@ -353,12 +353,13 @@ enum UpstreamAltMode {
struct UpstreamAddr { struct UpstreamAddr {
// The frontend address (e.g., FQDN, hostname, IP address). If // The frontend address (e.g., FQDN, hostname, IP address). If
// |host_unix| is true, this is UNIX domain socket path. // |host_unix| is true, this is UNIX domain socket path. This must
ImmutableString host; // be NULL terminated string.
StringRef host;
// For TCP socket, this is <IP address>:<PORT>. For IPv6 address, // For TCP socket, this is <IP address>:<PORT>. For IPv6 address,
// address is surrounded by square brackets. If socket is UNIX // address is surrounded by square brackets. If socket is UNIX
// domain socket, this is "localhost". // domain socket, this is "localhost".
ImmutableString hostport; StringRef hostport;
// frontend port. 0 if |host_unix| is true. // frontend port. 0 if |host_unix| is true.
uint16_t port; uint16_t port;
// For TCP socket, this is either AF_INET or AF_INET6. For UNIX // For TCP socket, this is either AF_INET or AF_INET6. For UNIX
@ -453,10 +454,10 @@ struct TLSConfig {
uint16_t port; uint16_t port;
// Hostname of memcached server. This is also used as SNI field // Hostname of memcached server. This is also used as SNI field
// if TLS is enabled. // if TLS is enabled.
ImmutableString host; StringRef host;
// Client private key and certificate for authentication // Client private key and certificate for authentication
ImmutableString private_key_file; StringRef private_key_file;
ImmutableString cert_file; StringRef cert_file;
ev_tstamp interval; ev_tstamp interval;
// Maximum number of retries when getting TLS ticket key from // Maximum number of retries when getting TLS ticket key from
// mamcached, due to network error. // mamcached, due to network error.
@ -482,10 +483,10 @@ struct TLSConfig {
uint16_t port; uint16_t port;
// Hostname of memcached server. This is also used as SNI field // Hostname of memcached server. This is also used as SNI field
// if TLS is enabled. // if TLS is enabled.
ImmutableString host; StringRef host;
// Client private key and certificate for authentication // Client private key and certificate for authentication
ImmutableString private_key_file; StringRef private_key_file;
ImmutableString cert_file; StringRef cert_file;
// Address family of memcached connection. One of either // Address family of memcached connection. One of either
// AF_INET, AF_INET6 or AF_UNSPEC. // AF_INET, AF_INET6 or AF_UNSPEC.
int family; int family;
@ -502,7 +503,7 @@ struct TLSConfig {
// OCSP realted configurations // OCSP realted configurations
struct { struct {
ev_tstamp update_interval; ev_tstamp update_interval;
ImmutableString fetch_ocsp_response_file; StringRef fetch_ocsp_response_file;
bool disabled; bool disabled;
} ocsp; } ocsp;
@ -510,14 +511,14 @@ struct TLSConfig {
struct { struct {
// Path to file containing CA certificate solely used for client // Path to file containing CA certificate solely used for client
// certificate validation // certificate validation
ImmutableString cacert; StringRef cacert;
bool enabled; bool enabled;
} client_verify; } client_verify;
// Client private key and certificate used in backend connections. // Client private key and certificate used in backend connections.
struct { struct {
ImmutableString private_key_file; StringRef private_key_file;
ImmutableString cert_file; StringRef cert_file;
} client; } client;
// The list of (private key file, certificate file) pair // The list of (private key file, certificate file) pair
@ -532,14 +533,14 @@ struct TLSConfig {
// Bit mask to disable SSL/TLS protocol versions. This will be // Bit mask to disable SSL/TLS protocol versions. This will be
// passed to SSL_CTX_set_options(). // passed to SSL_CTX_set_options().
long int tls_proto_mask; long int tls_proto_mask;
std::string backend_sni_name; StringRef backend_sni_name;
std::chrono::seconds session_timeout; std::chrono::seconds session_timeout;
ImmutableString private_key_file; StringRef private_key_file;
ImmutableString private_key_passwd; StringRef private_key_passwd;
ImmutableString cert_file; StringRef cert_file;
ImmutableString dh_param_file; StringRef dh_param_file;
ImmutableString ciphers; StringRef ciphers;
ImmutableString cacert; StringRef cacert;
bool insecure; bool insecure;
bool no_http2_cipher_black_list; bool no_http2_cipher_black_list;
}; };
@ -557,7 +558,7 @@ struct HttpConfig {
// obfuscated value used in "by" parameter of Forwarded header // obfuscated value used in "by" parameter of Forwarded header
// field. This is only used when user defined static obfuscated // field. This is only used when user defined static obfuscated
// string is provided. // string is provided.
std::string by_obfuscated; StringRef by_obfuscated;
// bitwise-OR of one or more of shrpx_forwarded_param values. // bitwise-OR of one or more of shrpx_forwarded_param values.
uint32_t params; uint32_t params;
// type of value recorded in "by" parameter of Forwarded header // type of value recorded in "by" parameter of Forwarded header
@ -576,7 +577,7 @@ struct HttpConfig {
std::vector<ErrorPage> error_pages; std::vector<ErrorPage> error_pages;
Headers add_request_headers; Headers add_request_headers;
Headers add_response_headers; Headers add_response_headers;
ImmutableString server_name; StringRef server_name;
size_t request_header_field_buffer; size_t request_header_field_buffer;
size_t max_request_header_fields; size_t max_request_header_fields;
size_t response_header_field_buffer; size_t response_header_field_buffer;
@ -591,8 +592,8 @@ struct Http2Config {
struct { struct {
struct { struct {
struct { struct {
ImmutableString request_header_file; StringRef request_header_file;
ImmutableString response_header_file; StringRef response_header_file;
FILE *request_header; FILE *request_header;
FILE *response_header; FILE *response_header;
} dump; } dump;
@ -635,12 +636,12 @@ struct Http2Config {
struct LoggingConfig { struct LoggingConfig {
struct { struct {
std::vector<LogFragment> format; std::vector<LogFragment> format;
ImmutableString file; StringRef file;
// Send accesslog to syslog, ignoring accesslog_file. // Send accesslog to syslog, ignoring accesslog_file.
bool syslog; bool syslog;
} access; } access;
struct { struct {
ImmutableString file; StringRef file;
// Send errorlog to syslog, ignoring errorlog_file. // Send errorlog to syslog, ignoring errorlog_file.
bool syslog; bool syslog;
} error; } error;
@ -754,7 +755,25 @@ struct APIConfig {
}; };
struct Config { struct Config {
Config() = default; Config()
: balloc(4096, 4096),
downstream_http_proxy{},
http{},
http2{},
tls{},
logging{},
conn{},
api{},
num_worker{0},
padding{0},
rlimit_nofile{0},
uid{0},
gid{0},
pid{0},
verbose{false},
daemon{false},
http2_proxy{false},
ev_loop_flags{0} {}
~Config(); ~Config();
Config(Config &&) = delete; Config(Config &&) = delete;
@ -762,6 +781,7 @@ struct Config {
Config &operator=(Config &&) = delete; Config &operator=(Config &&) = delete;
Config &operator=(const Config &&) = delete; Config &operator=(const Config &&) = delete;
BlockAllocator balloc;
HttpProxy downstream_http_proxy; HttpProxy downstream_http_proxy;
HttpConfig http; HttpConfig http;
Http2Config http2; Http2Config http2;
@ -769,10 +789,10 @@ struct Config {
LoggingConfig logging; LoggingConfig logging;
ConnectionConfig conn; ConnectionConfig conn;
APIConfig api; APIConfig api;
ImmutableString pid_file; StringRef pid_file;
ImmutableString conf_path; StringRef conf_path;
ImmutableString user; StringRef user;
ImmutableString mruby_file; StringRef mruby_file;
size_t num_worker; size_t num_worker;
size_t padding; size_t padding;
size_t rlimit_nofile; size_t rlimit_nofile;
@ -969,7 +989,8 @@ int load_config(Config *config, const char *filename,
// allowed. This function returns pair of NAME and VALUE. // allowed. This function returns pair of NAME and VALUE.
Headers::value_type parse_header(const StringRef &optarg); Headers::value_type parse_header(const StringRef &optarg);
std::vector<LogFragment> parse_log_format(const StringRef &optarg); std::vector<LogFragment> parse_log_format(BlockAllocator &balloc,
const StringRef &optarg);
// Returns string for syslog |facility|. // Returns string for syslog |facility|.
StringRef str_syslog_facility(int facility); StringRef str_syslog_facility(int facility);

View File

@ -67,10 +67,13 @@ void test_shrpx_config_parse_header(void) {
} }
void test_shrpx_config_parse_log_format(void) { void test_shrpx_config_parse_log_format(void) {
auto res = parse_log_format(StringRef::from_lit( BlockAllocator balloc(4096, 4096);
R"($remote_addr - $remote_user [$time_local] )"
R"("$request" $status $body_bytes_sent )" auto res = parse_log_format(
R"("${http_referer}" $http_host "$http_user_agent")")); balloc, StringRef::from_lit(
R"($remote_addr - $remote_user [$time_local] )"
R"("$request" $status $body_bytes_sent )"
R"("${http_referer}" $http_host "$http_user_agent")"));
CU_ASSERT(16 == res.size()); CU_ASSERT(16 == res.size());
CU_ASSERT(SHRPX_LOGF_REMOTE_ADDR == res[0].type); CU_ASSERT(SHRPX_LOGF_REMOTE_ADDR == res[0].type);
@ -115,35 +118,35 @@ void test_shrpx_config_parse_log_format(void) {
CU_ASSERT(SHRPX_LOGF_LITERAL == res[15].type); CU_ASSERT(SHRPX_LOGF_LITERAL == res[15].type);
CU_ASSERT("\"" == res[15].value); CU_ASSERT("\"" == res[15].value);
res = parse_log_format(StringRef::from_lit("$")); res = parse_log_format(balloc, StringRef::from_lit("$"));
CU_ASSERT(1 == res.size()); CU_ASSERT(1 == res.size());
CU_ASSERT(SHRPX_LOGF_LITERAL == res[0].type); CU_ASSERT(SHRPX_LOGF_LITERAL == res[0].type);
CU_ASSERT("$" == res[0].value); CU_ASSERT("$" == res[0].value);
res = parse_log_format(StringRef::from_lit("${")); res = parse_log_format(balloc, StringRef::from_lit("${"));
CU_ASSERT(1 == res.size()); CU_ASSERT(1 == res.size());
CU_ASSERT(SHRPX_LOGF_LITERAL == res[0].type); CU_ASSERT(SHRPX_LOGF_LITERAL == res[0].type);
CU_ASSERT("${" == res[0].value); CU_ASSERT("${" == res[0].value);
res = parse_log_format(StringRef::from_lit("${a")); res = parse_log_format(balloc, StringRef::from_lit("${a"));
CU_ASSERT(1 == res.size()); CU_ASSERT(1 == res.size());
CU_ASSERT(SHRPX_LOGF_LITERAL == res[0].type); CU_ASSERT(SHRPX_LOGF_LITERAL == res[0].type);
CU_ASSERT("${a" == res[0].value); CU_ASSERT("${a" == res[0].value);
res = parse_log_format(StringRef::from_lit("${a ")); res = parse_log_format(balloc, StringRef::from_lit("${a "));
CU_ASSERT(1 == res.size()); CU_ASSERT(1 == res.size());
CU_ASSERT(SHRPX_LOGF_LITERAL == res[0].type); CU_ASSERT(SHRPX_LOGF_LITERAL == res[0].type);
CU_ASSERT("${a " == res[0].value); CU_ASSERT("${a " == res[0].value);
res = parse_log_format(StringRef::from_lit("$$remote_addr")); res = parse_log_format(balloc, StringRef::from_lit("$$remote_addr"));
CU_ASSERT(2 == res.size()); CU_ASSERT(2 == res.size());

View File

@ -224,8 +224,8 @@ int ConnectionHandler::create_single_worker() {
#ifdef HAVE_NEVERBLEED #ifdef HAVE_NEVERBLEED
nb_.get(), nb_.get(),
#endif // HAVE_NEVERBLEED #endif // HAVE_NEVERBLEED
StringRef{tlsconf.cacert}, StringRef{memcachedconf.cert_file}, tlsconf.cacert, memcachedconf.cert_file, memcachedconf.private_key_file,
StringRef{memcachedconf.private_key_file}, nullptr); nullptr);
all_ssl_ctx_.push_back(session_cache_ssl_ctx); all_ssl_ctx_.push_back(session_cache_ssl_ctx);
} }
@ -280,8 +280,8 @@ int ConnectionHandler::create_worker_thread(size_t num) {
#ifdef HAVE_NEVERBLEED #ifdef HAVE_NEVERBLEED
nb_.get(), nb_.get(),
#endif // HAVE_NEVERBLEED #endif // HAVE_NEVERBLEED
StringRef{tlsconf.cacert}, StringRef{memcachedconf.cert_file}, tlsconf.cacert, memcachedconf.cert_file,
StringRef{memcachedconf.private_key_file}, nullptr); memcachedconf.private_key_file, nullptr);
all_ssl_ctx_.push_back(session_cache_ssl_ctx); all_ssl_ctx_.push_back(session_cache_ssl_ctx);
} }
auto worker = make_unique<Worker>( auto worker = make_unique<Worker>(
@ -835,8 +835,8 @@ SSL_CTX *ConnectionHandler::create_tls_ticket_key_memcached_ssl_ctx() {
#ifdef HAVE_NEVERBLEED #ifdef HAVE_NEVERBLEED
nb_.get(), nb_.get(),
#endif // HAVE_NEVERBLEED #endif // HAVE_NEVERBLEED
StringRef{tlsconf.cacert}, StringRef{memcachedconf.cert_file}, tlsconf.cacert, memcachedconf.cert_file, memcachedconf.private_key_file,
StringRef{memcachedconf.private_key_file}, nullptr); nullptr);
all_ssl_ctx_.push_back(ssl_ctx); all_ssl_ctx_.push_back(ssl_ctx);

View File

@ -46,12 +46,11 @@ StringRef create_error_html(BlockAllocator &balloc, unsigned int http_status) {
} }
auto status_string = http2::get_status_string(balloc, http_status); auto status_string = http2::get_status_string(balloc, http_status);
const auto &server_name = httpconf.server_name;
return concat_string_ref( return concat_string_ref(
balloc, StringRef::from_lit(R"(<!DOCTYPE html><html lang="en"><title>)"), balloc, StringRef::from_lit(R"(<!DOCTYPE html><html lang="en"><title>)"),
status_string, StringRef::from_lit("</title><body><h1>"), status_string, status_string, StringRef::from_lit("</title><body><h1>"), status_string,
StringRef::from_lit("</h1><footer>"), StringRef{server_name}, StringRef::from_lit("</h1><footer>"), httpconf.server_name,
StringRef::from_lit("</footer></body></html>")); StringRef::from_lit("</footer></body></html>"));
} }

View File

@ -1430,8 +1430,8 @@ 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(http2::make_nv_ls_nocopy( nva.push_back(
"server", StringRef{get_config()->http.server_name})); http2::make_nv_ls_nocopy("server", get_config()->http.server_name));
} }
for (auto &p : httpconf.add_response_headers) { for (auto &p : httpconf.add_response_headers) {
@ -1482,8 +1482,7 @@ int Http2Upstream::error_reply(Downstream *downstream,
auto nva = std::array<nghttp2_nv, 5>{ auto nva = std::array<nghttp2_nv, 5>{
{http2::make_nv_ls_nocopy(":status", response_status), {http2::make_nv_ls_nocopy(":status", response_status),
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", http2::make_nv_ls_nocopy("server", get_config()->http.server_name),
StringRef{get_config()->http.server_name}),
http2::make_nv_ls_nocopy("content-length", content_length), http2::make_nv_ls_nocopy("content-length", content_length),
http2::make_nv_ls_nocopy("date", date)}}; http2::make_nv_ls_nocopy("date", date)}};
@ -1630,8 +1629,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 && !httpconf.no_server_rewrite) { if (!get_config()->http2_proxy && !httpconf.no_server_rewrite) {
nva.push_back( nva.push_back(http2::make_nv_ls_nocopy("server", httpconf.server_name));
http2::make_nv_ls_nocopy("server", StringRef{httpconf.server_name}));
} else { } else {
auto server = resp.fs.header(http2::HD_SERVER); auto server = resp.fs.header(http2::HD_SERVER);
if (server) { if (server) {

View File

@ -290,7 +290,7 @@ void upstream_accesslog(const std::vector<LogFragment> &lfv,
break; break;
case SHRPX_LOGF_HTTP: case SHRPX_LOGF_HTTP:
if (req) { if (req) {
auto hd = req->fs.header(StringRef(lf.value)); auto hd = req->fs.header(lf.value);
if (hd) { if (hd) {
std::tie(p, avail) = copy((*hd).value, avail, p); std::tie(p, avail) = copy((*hd).value, avail, p);
break; break;

View File

@ -137,10 +137,10 @@ enum LogFragmentType {
}; };
struct LogFragment { struct LogFragment {
LogFragment(LogFragmentType type, ImmutableString value = ImmutableString()) LogFragment(LogFragmentType type, StringRef value = StringRef::from_lit(""))
: type(type), value(std::move(value)) {} : type(type), value(std::move(value)) {}
LogFragmentType type; LogFragmentType type;
ImmutableString value; StringRef value;
}; };
struct LogSpec { struct LogSpec {

View File

@ -1447,8 +1447,8 @@ SSL_CTX *setup_downstream_client_ssl_context(
#ifdef HAVE_NEVERBLEED #ifdef HAVE_NEVERBLEED
nb, nb,
#endif // HAVE_NEVERBLEED #endif // HAVE_NEVERBLEED
StringRef{tlsconf.cacert}, StringRef{tlsconf.client.cert_file}, tlsconf.cacert, tlsconf.client.cert_file, tlsconf.client.private_key_file,
StringRef{tlsconf.client.private_key_file}, select_next_proto_cb); select_next_proto_cb);
} }
void setup_downstream_http2_alpn(SSL *ssl) { void setup_downstream_http2_alpn(SSL *ssl) {