nghttpx: Refactor option handling using StringRef

This commit is contained in:
Tatsuhiro Tsujikawa 2016-03-24 21:05:02 +09:00
parent daa1ae3a45
commit 13596bde90
8 changed files with 846 additions and 698 deletions

View File

@ -1956,7 +1956,7 @@ int main(int argc, char **argv) {
break; break;
case 4: case 4:
// npn-list option // npn-list option
config.npn_list = util::parse_config_str_list(optarg); config.npn_list = util::parse_config_str_list(StringRef{optarg});
break; break;
case 5: case 5:
// rate-period // rate-period
@ -1968,7 +1968,8 @@ int main(int argc, char **argv) {
break; break;
case 6: case 6:
// --h1 // --h1
config.npn_list = util::parse_config_str_list("http/1.1"); config.npn_list =
util::parse_config_str_list(StringRef::from_lit("http/1.1"));
config.no_tls_proto = Config::PROTO_HTTP1_1; config.no_tls_proto = Config::PROTO_HTTP1_1;
break; break;
} }
@ -1992,7 +1993,8 @@ int main(int argc, char **argv) {
} }
if (config.npn_list.empty()) { if (config.npn_list.empty()) {
config.npn_list = util::parse_config_str_list(DEFAULT_NPN_LIST); config.npn_list =
util::parse_config_str_list(StringRef::from_lit(DEFAULT_NPN_LIST));
} }
// serialize the APLN tokens // serialize the APLN tokens

File diff suppressed because it is too large Load Diff

View File

@ -78,7 +78,7 @@ TicketKeys::~TicketKeys() {
namespace { namespace {
int split_host_port(char *host, size_t hostlen, uint16_t *port_ptr, int split_host_port(char *host, size_t hostlen, uint16_t *port_ptr,
const StringRef &hostport, const char *opt) { const StringRef &hostport, const StringRef &opt) {
// host and port in |hostport| is separated by single ','. // host and port in |hostport| is separated by single ','.
auto sep = std::find(std::begin(hostport), std::end(hostport), ','); auto sep = std::find(std::begin(hostport), std::end(hostport), ',');
if (sep == std::end(hostport)) { if (sep == std::end(hostport)) {
@ -106,9 +106,9 @@ int split_host_port(char *host, size_t hostlen, uint16_t *port_ptr,
} // namespace } // namespace
namespace { namespace {
bool is_secure(const char *filename) { bool is_secure(const StringRef &filename) {
struct stat buf; struct stat buf;
int rv = stat(filename, &buf); int rv = stat(filename.c_str(), &buf);
if (rv == 0) { if (rv == 0) {
if ((buf.st_mode & S_IRWXU) && !(buf.st_mode & S_IRWXG) && if ((buf.st_mode & S_IRWXU) && !(buf.st_mode & S_IRWXG) &&
!(buf.st_mode & S_IRWXO)) { !(buf.st_mode & S_IRWXO)) {
@ -219,29 +219,33 @@ FILE *open_file_for_write(const char *filename) {
return f; return f;
} }
std::string read_passwd_from_file(const char *filename) { namespace {
// Read passwd from |filename|
std::string read_passwd_from_file(const StringRef &opt,
const StringRef &filename) {
std::string line; std::string line;
if (!is_secure(filename)) { if (!is_secure(filename)) {
LOG(ERROR) << "Private key passwd file " << filename LOG(ERROR) << opt << ": Private key passwd file " << filename
<< " has insecure mode."; << " has insecure mode.";
return line; return line;
} }
std::ifstream in(filename, std::ios::binary); std::ifstream in(filename.c_str(), std::ios::binary);
if (!in) { if (!in) {
LOG(ERROR) << "Could not open key passwd file " << filename; LOG(ERROR) << opt << ": Could not open key passwd file " << filename;
return line; return line;
} }
std::getline(in, line); std::getline(in, line);
return line; return line;
} }
} // namespace
Headers::value_type parse_header(const char *optarg) { Headers::value_type parse_header(const StringRef &optarg) {
const auto *colon = strchr(optarg, ':'); auto colon = std::find(std::begin(optarg), std::end(optarg), ':');
if (colon == nullptr || colon == optarg) { if (colon == std::end(optarg) || colon == std::begin(optarg)) {
return {"", ""}; return {"", ""};
} }
@ -249,29 +253,24 @@ Headers::value_type parse_header(const char *optarg) {
for (; *value == '\t' || *value == ' '; ++value) for (; *value == '\t' || *value == ' '; ++value)
; ;
auto p = auto p = Header(std::string{std::begin(optarg), colon},
Header(std::string(optarg, colon), std::string(value, strlen(value))); std::string{value, std::end(optarg)});
util::inp_strlower(p.name); util::inp_strlower(p.name);
if (!nghttp2_check_header_name( if (!nghttp2_check_header_name(
reinterpret_cast<const uint8_t *>(p.name.c_str()), p.name.size()) || reinterpret_cast<const uint8_t *>(p.name.c_str()), p.name.size()) ||
!nghttp2_check_header_value( !nghttp2_check_header_value(
reinterpret_cast<const uint8_t *>(p.value.c_str()), p.value.size())) { reinterpret_cast<const uint8_t *>(p.value.c_str()), p.value.size())) {
return Header(); return Header{};
} }
return p; return p;
} }
template <typename T> template <typename T>
int parse_uint(T *dest, const char *opt, const char *optarg) { int parse_uint(T *dest, const StringRef &opt, const StringRef &optarg) {
char *end = nullptr; auto val = util::parse_uint(optarg);
if (val == -1) {
errno = 0;
auto val = strtol(optarg, &end, 10);
if (!optarg[0] || errno != 0 || *end || val < 0) {
LOG(ERROR) << opt << ": bad value. Specify an integer >= 0."; LOG(ERROR) << opt << ": bad value. Specify an integer >= 0.";
return -1; return -1;
} }
@ -283,7 +282,8 @@ int parse_uint(T *dest, const char *opt, const char *optarg) {
namespace { namespace {
template <typename T> template <typename T>
int parse_uint_with_unit(T *dest, const char *opt, const char *optarg) { int parse_uint_with_unit(T *dest, const StringRef &opt,
const StringRef &optarg) {
auto n = util::parse_uint_with_unit(optarg); auto n = util::parse_uint_with_unit(optarg);
if (n == -1) { if (n == -1) {
LOG(ERROR) << opt << ": bad value: '" << optarg << "'"; LOG(ERROR) << opt << ": bad value: '" << optarg << "'";
@ -296,8 +296,10 @@ int parse_uint_with_unit(T *dest, const char *opt, const char *optarg) {
} }
} // namespace } // namespace
// Parses |optarg| as signed integer. This requires |optarg| to be
// NULL-terminated string.
template <typename T> template <typename T>
int parse_int(T *dest, const char *opt, const char *optarg) { int parse_int(T *dest, const StringRef &opt, const char *optarg) {
char *end = nullptr; char *end = nullptr;
errno = 0; errno = 0;
@ -442,10 +444,10 @@ bool var_token(char c) {
} }
} // namespace } // namespace
std::vector<LogFragment> parse_log_format(const char *optarg) { std::vector<LogFragment> parse_log_format(const StringRef &optarg) {
auto literal_start = optarg; auto literal_start = std::begin(optarg);
auto p = optarg; auto p = literal_start;
auto eop = p + strlen(optarg); auto eop = std::end(optarg);
auto res = std::vector<LogFragment>(); auto res = std::vector<LogFragment>();
@ -467,7 +469,7 @@ std::vector<LogFragment> parse_log_format(const char *optarg) {
; ;
if (p == eop || *p != '}') { if (p == eop || *p != '}') {
LOG(WARN) << "Missing '}' after " << std::string(var_start, p); LOG(WARN) << "Missing '}' after " << StringRef{var_start, p};
continue; continue;
} }
@ -499,7 +501,7 @@ std::vector<LogFragment> parse_log_format(const char *optarg) {
} }
} else { } else {
LOG(WARN) << "Unrecognized log format variable: " LOG(WARN) << "Unrecognized log format variable: "
<< std::string(var_name, var_namelen); << StringRef{var_name, var_namelen};
continue; continue;
} }
} }
@ -534,16 +536,17 @@ std::vector<LogFragment> parse_log_format(const char *optarg) {
} }
namespace { namespace {
int parse_address_family(int *dest, const char *opt, const char *optarg) { int parse_address_family(int *dest, const StringRef &opt,
if (util::strieq("auto", optarg)) { const StringRef &optarg) {
if (util::strieq_l("auto", optarg)) {
*dest = AF_UNSPEC; *dest = AF_UNSPEC;
return 0; return 0;
} }
if (util::strieq("IPv4", optarg)) { if (util::strieq_l("IPv4", optarg)) {
*dest = AF_INET; *dest = AF_INET;
return 0; return 0;
} }
if (util::strieq("IPv6", optarg)) { if (util::strieq_l("IPv6", optarg)) {
*dest = AF_INET6; *dest = AF_INET6;
return 0; return 0;
} }
@ -554,7 +557,8 @@ int parse_address_family(int *dest, const char *opt, const char *optarg) {
} // namespace } // namespace
namespace { namespace {
int parse_duration(ev_tstamp *dest, const char *opt, const char *optarg) { int parse_duration(ev_tstamp *dest, const StringRef &opt,
const StringRef &optarg) {
auto t = util::parse_duration_with_unit(optarg); auto t = util::parse_duration_with_unit(optarg);
if (t == std::numeric_limits<double>::infinity()) { if (t == std::numeric_limits<double>::infinity()) {
LOG(ERROR) << opt << ": bad value: '" << optarg << "'"; LOG(ERROR) << opt << ": bad value: '" << optarg << "'";
@ -791,12 +795,12 @@ int parse_mapping(const DownstreamAddrConfig &addr,
} // namespace } // namespace
namespace { namespace {
int parse_forwarded_node_type(const std::string &optarg) { int parse_forwarded_node_type(const StringRef &optarg) {
if (util::strieq(optarg, "obfuscated")) { if (util::strieq_l("obfuscated", optarg)) {
return FORWARDED_NODE_OBFUSCATED; return FORWARDED_NODE_OBFUSCATED;
} }
if (util::strieq(optarg, "ip")) { if (util::strieq_l("ip", optarg)) {
return FORWARDED_NODE_IP; return FORWARDED_NODE_IP;
} }
@ -816,16 +820,15 @@ int parse_forwarded_node_type(const std::string &optarg) {
} // namespace } // namespace
namespace { namespace {
int parse_error_page(std::vector<ErrorPage> &error_pages, const char *opt, int parse_error_page(std::vector<ErrorPage> &error_pages, const StringRef &opt,
const char *optarg) { const StringRef &optarg) {
auto arg = StringRef{optarg}; auto eq = std::find(std::begin(optarg), std::end(optarg), '=');
auto eq = std::find(std::begin(arg), std::end(arg), '='); if (eq == std::end(optarg) || eq + 1 == std::end(optarg)) {
if (eq == std::end(arg) || eq + 1 == std::end(arg)) { LOG(ERROR) << opt << ": bad value: '" << optarg << "'";
LOG(ERROR) << opt << ": bad value: '" << arg << "'";
return -1; return -1;
} }
auto codestr = StringRef{std::begin(arg), eq}; auto codestr = StringRef{std::begin(optarg), eq};
unsigned int code; unsigned int code;
if (codestr == "*") { if (codestr == "*") {
@ -841,7 +844,7 @@ int parse_error_page(std::vector<ErrorPage> &error_pages, const char *opt,
code = static_cast<unsigned int>(n); code = static_cast<unsigned int>(n);
} }
auto path = StringRef{eq + 1, std::end(arg)}; auto path = StringRef{eq + 1, std::end(optarg)};
std::vector<uint8_t> content; std::vector<uint8_t> content;
auto fd = open(path.c_str(), O_RDONLY); auto fd = open(path.c_str(), O_RDONLY);
@ -1734,26 +1737,25 @@ int option_lookup_token(const char *name, size_t namelen) {
} }
} // namespace } // namespace
int parse_config(const char *opt, const char *optarg, int parse_config(const StringRef &opt, const StringRef &optarg,
std::set<std::string> &included_set) { std::set<StringRef> &included_set) {
char host[NI_MAXHOST]; char host[NI_MAXHOST];
uint16_t port; uint16_t port;
auto optid = option_lookup_token(opt, strlen(opt)); auto optid = option_lookup_token(opt.c_str(), opt.size());
switch (optid) { switch (optid) {
case SHRPX_OPTID_BACKEND: { case SHRPX_OPTID_BACKEND: {
auto src = StringRef{optarg}; auto addr_end = std::find(std::begin(optarg), std::end(optarg), ';');
auto addr_end = std::find(std::begin(src), std::end(src), ';');
DownstreamAddrConfig addr{}; DownstreamAddrConfig addr{};
if (util::istarts_with_l(src, SHRPX_UNIX_PATH_PREFIX)) { if (util::istarts_with_l(optarg, SHRPX_UNIX_PATH_PREFIX)) {
auto path = std::begin(src) + str_size(SHRPX_UNIX_PATH_PREFIX); auto path = std::begin(optarg) + str_size(SHRPX_UNIX_PATH_PREFIX);
addr.host = ImmutableString(path, addr_end); addr.host = ImmutableString(path, addr_end);
addr.host_unix = true; addr.host_unix = true;
} else { } else {
if (split_host_port(host, sizeof(host), &port, if (split_host_port(host, sizeof(host), &port,
StringRef{std::begin(src), addr_end}, opt) == -1) { StringRef{std::begin(optarg), addr_end}, opt) == -1) {
return -1; return -1;
} }
@ -1761,13 +1763,14 @@ int parse_config(const char *opt, const char *optarg,
addr.port = port; addr.port = port;
} }
auto mapping = addr_end == std::end(src) ? addr_end : addr_end + 1; auto mapping = addr_end == std::end(optarg) ? addr_end : addr_end + 1;
auto mapping_end = std::find(mapping, std::end(src), ';'); auto mapping_end = std::find(mapping, std::end(optarg), ';');
auto params = mapping_end == std::end(src) ? mapping_end : mapping_end + 1; auto params =
mapping_end == std::end(optarg) ? mapping_end : mapping_end + 1;
if (parse_mapping(addr, StringRef{mapping, mapping_end}, if (parse_mapping(addr, StringRef{mapping, mapping_end},
StringRef{params, std::end(src)}) != 0) { StringRef{params, std::end(optarg)}) != 0) {
return -1; return -1;
} }
@ -1776,9 +1779,8 @@ int parse_config(const char *opt, const char *optarg,
case SHRPX_OPTID_FRONTEND: { case SHRPX_OPTID_FRONTEND: {
auto &listenerconf = mod_config()->conn.listener; auto &listenerconf = mod_config()->conn.listener;
auto src = StringRef{optarg}; auto addr_end = std::find(std::begin(optarg), std::end(optarg), ';');
auto addr_end = std::find(std::begin(src), std::end(src), ';'); auto src_params = StringRef{addr_end, std::end(optarg)};
auto src_params = StringRef{addr_end, std::end(src)};
UpstreamParams params{}; UpstreamParams params{};
params.tls = true; params.tls = true;
@ -1791,8 +1793,8 @@ int parse_config(const char *opt, const char *optarg,
addr.fd = -1; addr.fd = -1;
addr.tls = params.tls; addr.tls = params.tls;
if (util::istarts_with_l(src, SHRPX_UNIX_PATH_PREFIX)) { if (util::istarts_with_l(optarg, SHRPX_UNIX_PATH_PREFIX)) {
auto path = std::begin(src) + str_size(SHRPX_UNIX_PATH_PREFIX); auto path = std::begin(optarg) + str_size(SHRPX_UNIX_PATH_PREFIX);
addr.host = ImmutableString{path, addr_end}; addr.host = ImmutableString{path, addr_end};
addr.host_unix = true; addr.host_unix = true;
@ -1802,7 +1804,7 @@ int parse_config(const char *opt, const char *optarg,
} }
if (split_host_port(host, sizeof(host), &port, if (split_host_port(host, sizeof(host), &port,
StringRef{std::begin(src), addr_end}, opt) == -1) { StringRef{std::begin(optarg), addr_end}, opt) == -1) {
return -1; return -1;
} }
@ -1858,11 +1860,11 @@ int parse_config(const char *opt, const char *optarg,
return 0; return 0;
case SHRPX_OPTID_DAEMON: case SHRPX_OPTID_DAEMON:
mod_config()->daemon = util::strieq(optarg, "yes"); mod_config()->daemon = util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_HTTP2_PROXY: case SHRPX_OPTID_HTTP2_PROXY:
mod_config()->http2_proxy = util::strieq(optarg, "yes"); mod_config()->http2_proxy = util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_HTTP2_BRIDGE: case SHRPX_OPTID_HTTP2_BRIDGE:
@ -1874,15 +1876,15 @@ int parse_config(const char *opt, const char *optarg,
"backend=<addr>,<port>;;proto=h2 and backend-tls"; "backend=<addr>,<port>;;proto=h2 and backend-tls";
return -1; return -1;
case SHRPX_OPTID_ADD_X_FORWARDED_FOR: case SHRPX_OPTID_ADD_X_FORWARDED_FOR:
mod_config()->http.xff.add = util::strieq(optarg, "yes"); mod_config()->http.xff.add = util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR: case SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR:
mod_config()->http.xff.strip_incoming = util::strieq(optarg, "yes"); mod_config()->http.xff.strip_incoming = util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_NO_VIA: case SHRPX_OPTID_NO_VIA:
mod_config()->http.no_via = util::strieq(optarg, "yes"); mod_config()->http.no_via = util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT: case SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT:
@ -1907,11 +1909,12 @@ int parse_config(const char *opt, const char *optarg,
return parse_duration(&mod_config()->http2.timeout.stream_write, opt, return parse_duration(&mod_config()->http2.timeout.stream_write, opt,
optarg); optarg);
case SHRPX_OPTID_ACCESSLOG_FILE: case SHRPX_OPTID_ACCESSLOG_FILE:
mod_config()->logging.access.file = optarg; mod_config()->logging.access.file =
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_ACCESSLOG_SYSLOG: case SHRPX_OPTID_ACCESSLOG_SYSLOG:
mod_config()->logging.access.syslog = util::strieq(optarg, "yes"); mod_config()->logging.access.syslog = util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_ACCESSLOG_FORMAT: case SHRPX_OPTID_ACCESSLOG_FORMAT:
@ -1919,16 +1922,17 @@ int parse_config(const char *opt, const char *optarg,
return 0; return 0;
case SHRPX_OPTID_ERRORLOG_FILE: case SHRPX_OPTID_ERRORLOG_FILE:
mod_config()->logging.error.file = optarg; mod_config()->logging.error.file =
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_ERRORLOG_SYSLOG: case SHRPX_OPTID_ERRORLOG_SYSLOG:
mod_config()->logging.error.syslog = util::strieq(optarg, "yes"); mod_config()->logging.error.syslog = util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_FASTOPEN: { case SHRPX_OPTID_FASTOPEN: {
int n; int n;
if (parse_int(&n, opt, optarg) != 0) { if (parse_int(&n, opt, optarg.c_str()) != 0) {
return -1; return -1;
} }
@ -2009,15 +2013,16 @@ int parse_config(const char *opt, const char *optarg,
"default. See also " << SHRPX_OPT_BACKEND_TLS; "default. See also " << SHRPX_OPT_BACKEND_TLS;
return 0; return 0;
case SHRPX_OPTID_BACKEND_TLS_SNI_FIELD: case SHRPX_OPTID_BACKEND_TLS_SNI_FIELD:
mod_config()->tls.backend_sni_name = optarg; mod_config()->tls.backend_sni_name = optarg.str();
return 0; return 0;
case SHRPX_OPTID_PID_FILE: case SHRPX_OPTID_PID_FILE:
mod_config()->pid_file = optarg; mod_config()->pid_file =
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_USER: { case SHRPX_OPTID_USER: {
auto pwd = getpwnam(optarg); auto pwd = getpwnam(optarg.c_str());
if (!pwd) { if (!pwd) {
LOG(ERROR) << opt << ": failed to get uid from " << optarg << ": " LOG(ERROR) << opt << ": failed to get uid from " << optarg << ": "
<< strerror(errno); << strerror(errno);
@ -2030,11 +2035,12 @@ 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()->tls.private_key_file = optarg; mod_config()->tls.private_key_file =
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: {
auto passwd = read_passwd_from_file(optarg); auto passwd = read_passwd_from_file(opt, optarg);
if (passwd.empty()) { if (passwd.empty()) {
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;
@ -2044,22 +2050,40 @@ int parse_config(const char *opt, const char *optarg,
return 0; return 0;
} }
case SHRPX_OPTID_CERTIFICATE_FILE: case SHRPX_OPTID_CERTIFICATE_FILE:
mod_config()->tls.cert_file = optarg; mod_config()->tls.cert_file =
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_DH_PARAM_FILE: case SHRPX_OPTID_DH_PARAM_FILE:
mod_config()->tls.dh_param_file = optarg; mod_config()->tls.dh_param_file =
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_SUBCERT: { case SHRPX_OPTID_SUBCERT: {
// Private Key file and certificate file separated by ':'. // Private Key file and certificate file separated by ':'.
const char *sp = strchr(optarg, ':'); auto sp = std::find(std::begin(optarg), std::end(optarg), ':');
if (sp) { if (sp == std::end(optarg)) {
std::string keyfile(optarg, sp); LOG(ERROR) << opt << ": missing ':' in " << optarg;
// TODO Do we need private key for subcert? return -1;
mod_config()->tls.subcerts.emplace_back(keyfile, sp + 1);
} }
auto private_key_file = StringRef{std::begin(optarg), sp};
if (private_key_file.empty()) {
LOG(ERROR) << opt << ": missing private key file: " << optarg;
return -1;
}
auto cert_file = StringRef{sp + 1, std::end(optarg)};
if (cert_file.empty()) {
LOG(ERROR) << opt << ": missing certificate file: " << optarg;
return -1;
}
mod_config()->tls.subcerts.emplace_back(private_key_file.str(),
cert_file.str());
return 0; return 0;
} }
case SHRPX_OPTID_SYSLOG_FACILITY: { case SHRPX_OPTID_SYSLOG_FACILITY: {
@ -2074,7 +2098,7 @@ int parse_config(const char *opt, const char *optarg,
} }
case SHRPX_OPTID_BACKLOG: { case SHRPX_OPTID_BACKLOG: {
int n; int n;
if (parse_int(&n, opt, optarg) != 0) { if (parse_int(&n, opt, optarg.c_str()) != 0) {
return -1; return -1;
} }
@ -2089,7 +2113,8 @@ int parse_config(const char *opt, const char *optarg,
return 0; return 0;
} }
case SHRPX_OPTID_CIPHERS: case SHRPX_OPTID_CIPHERS:
mod_config()->tls.ciphers = optarg; mod_config()->tls.ciphers =
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_CLIENT: case SHRPX_OPTID_CLIENT:
@ -2097,11 +2122,12 @@ int parse_config(const char *opt, const char *optarg,
"backend=<addr>,<port>;;proto=h2 and backend-tls"; "backend=<addr>,<port>;;proto=h2 and backend-tls";
return -1; return -1;
case SHRPX_OPTID_INSECURE: case SHRPX_OPTID_INSECURE:
mod_config()->tls.insecure = util::strieq(optarg, "yes"); mod_config()->tls.insecure = util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_CACERT: case SHRPX_OPTID_CACERT:
mod_config()->tls.cacert = optarg; mod_config()->tls.cacert =
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_BACKEND_IPV4: case SHRPX_OPTID_BACKEND_IPV4:
@ -2125,19 +2151,18 @@ int parse_config(const char *opt, const char *optarg,
proxy = {}; proxy = {};
// parse URI and get hostname, port and optionally userinfo. // parse URI and get hostname, port and optionally userinfo.
http_parser_url u{}; http_parser_url u{};
int rv = http_parser_parse_url(optarg, strlen(optarg), 0, &u); int rv = http_parser_parse_url(optarg.c_str(), optarg.size(), 0, &u);
if (rv == 0) { if (rv == 0) {
std::string val;
if (u.field_set & UF_USERINFO) { if (u.field_set & UF_USERINFO) {
http2::copy_url_component(val, &u, UF_USERINFO, optarg); auto uf = util::get_uri_field(optarg.c_str(), u, UF_USERINFO);
// Surprisingly, u.field_set & UF_USERINFO is nonzero even if // Surprisingly, u.field_set & UF_USERINFO is nonzero even if
// userinfo component is empty string. // userinfo component is empty string.
if (!val.empty()) { if (!uf.empty()) {
proxy.userinfo = util::percent_decode(std::begin(val), std::end(val)); proxy.userinfo = util::percent_decode(std::begin(uf), std::end(uf));
} }
} }
if (u.field_set & UF_HOST) { if (u.field_set & UF_HOST) {
http2::copy_url_component(proxy.host, &u, UF_HOST, optarg); http2::copy_url_component(proxy.host, &u, UF_HOST, optarg.c_str());
} else { } else {
LOG(ERROR) << opt << ": no hostname specified"; LOG(ERROR) << opt << ": no hostname specified";
return -1; return -1;
@ -2188,42 +2213,47 @@ int parse_config(const char *opt, const char *optarg,
return 0; return 0;
case SHRPX_OPTID_VERIFY_CLIENT: case SHRPX_OPTID_VERIFY_CLIENT:
mod_config()->tls.client_verify.enabled = util::strieq(optarg, "yes"); mod_config()->tls.client_verify.enabled = util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_VERIFY_CLIENT_CACERT: case SHRPX_OPTID_VERIFY_CLIENT_CACERT:
mod_config()->tls.client_verify.cacert = optarg; mod_config()->tls.client_verify.cacert =
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:
mod_config()->tls.client.private_key_file = optarg; mod_config()->tls.client.private_key_file =
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_CLIENT_CERT_FILE: case SHRPX_OPTID_CLIENT_CERT_FILE:
mod_config()->tls.client.cert_file = optarg; mod_config()->tls.client.cert_file =
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:
mod_config()->http2.upstream.debug.dump.request_header_file = optarg; mod_config()->http2.upstream.debug.dump.request_header_file =
ImmutableString{std::begin(optarg), std::end(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.debug.dump.response_header_file = optarg; mod_config()->http2.upstream.debug.dump.response_header_file =
ImmutableString{std::begin(optarg), std::end(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_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_FRONTEND_FRAME_DEBUG: case SHRPX_OPTID_FRONTEND_FRAME_DEBUG:
mod_config()->http2.upstream.debug.frame_debug = mod_config()->http2.upstream.debug.frame_debug =
util::strieq(optarg, "yes"); util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_PADDING: case SHRPX_OPTID_PADDING:
return parse_uint(&mod_config()->padding, opt, optarg); return parse_uint(&mod_config()->padding, opt, optarg);
case SHRPX_OPTID_ALTSVC: { case SHRPX_OPTID_ALTSVC: {
auto tokens = util::parse_config_str_list(optarg); auto tokens = util::split_str(optarg, ',');
if (tokens.size() < 2) { if (tokens.size() < 2) {
// Requires at least protocol_id and port // Requires at least protocol_id and port
@ -2239,7 +2269,7 @@ int parse_config(const char *opt, const char *optarg,
int port; int port;
if (parse_uint(&port, opt, tokens[1].c_str()) != 0) { if (parse_uint(&port, opt, tokens[1]) != 0) {
return -1; return -1;
} }
@ -2251,16 +2281,16 @@ int parse_config(const char *opt, const char *optarg,
AltSvc altsvc{}; AltSvc altsvc{};
altsvc.protocol_id = std::move(tokens[0]); altsvc.protocol_id = tokens[0].str();
altsvc.port = port; altsvc.port = port;
altsvc.service = std::move(tokens[1]); altsvc.service = tokens[1].str();
if (tokens.size() > 2) { if (tokens.size() > 2) {
altsvc.host = std::move(tokens[2]); altsvc.host = tokens[2].str();
if (tokens.size() > 3) { if (tokens.size() > 3) {
altsvc.origin = std::move(tokens[3]); altsvc.origin = tokens[3].str();
} }
} }
@ -2286,7 +2316,7 @@ int parse_config(const char *opt, const char *optarg,
return parse_uint(&mod_config()->conn.upstream.worker_connections, opt, return parse_uint(&mod_config()->conn.upstream.worker_connections, opt,
optarg); optarg);
case SHRPX_OPTID_NO_LOCATION_REWRITE: case SHRPX_OPTID_NO_LOCATION_REWRITE:
mod_config()->http.no_location_rewrite = util::strieq(optarg, "yes"); mod_config()->http.no_location_rewrite = util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_NO_HOST_REWRITE: case SHRPX_OPTID_NO_HOST_REWRITE:
@ -2328,7 +2358,7 @@ int parse_config(const char *opt, const char *optarg,
return parse_duration(&mod_config()->conn.listener.timeout.sleep, opt, return parse_duration(&mod_config()->conn.listener.timeout.sleep, opt,
optarg); optarg);
case SHRPX_OPTID_TLS_TICKET_KEY_FILE: case SHRPX_OPTID_TLS_TICKET_KEY_FILE:
mod_config()->tls.ticket.files.push_back(optarg); mod_config()->tls.ticket.files.push_back(optarg.str());
return 0; return 0;
case SHRPX_OPTID_RLIMIT_NOFILE: { case SHRPX_OPTID_RLIMIT_NOFILE: {
int n; int n;
@ -2370,20 +2400,21 @@ int parse_config(const char *opt, const char *optarg,
} }
case SHRPX_OPTID_NO_SERVER_PUSH: case SHRPX_OPTID_NO_SERVER_PUSH:
mod_config()->http2.no_server_push = util::strieq(optarg, "yes"); mod_config()->http2.no_server_push = util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER: case SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER:
LOG(WARN) << opt << ": deprecated."; LOG(WARN) << opt << ": deprecated.";
return 0; return 0;
case SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE: case SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE:
mod_config()->tls.ocsp.fetch_ocsp_response_file = optarg; mod_config()->tls.ocsp.fetch_ocsp_response_file =
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_OCSP_UPDATE_INTERVAL: case SHRPX_OPTID_OCSP_UPDATE_INTERVAL:
return parse_duration(&mod_config()->tls.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()->tls.ocsp.disabled = util::strieq(optarg, "yes"); mod_config()->tls.ocsp.disabled = util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_HEADER_FIELD_BUFFER: case SHRPX_OPTID_HEADER_FIELD_BUFFER:
@ -2412,7 +2443,7 @@ int parse_config(const char *opt, const char *optarg,
} }
included_set.insert(optarg); included_set.insert(optarg);
auto rv = load_config(optarg, included_set); auto rv = load_config(optarg.c_str(), included_set);
included_set.erase(optarg); included_set.erase(optarg);
if (rv != 0) { if (rv != 0) {
@ -2422,9 +2453,9 @@ int parse_config(const char *opt, const char *optarg,
return 0; return 0;
} }
case SHRPX_OPTID_TLS_TICKET_KEY_CIPHER: case SHRPX_OPTID_TLS_TICKET_KEY_CIPHER:
if (util::strieq(optarg, "aes-128-cbc")) { if (util::strieq_l("aes-128-cbc", optarg)) {
mod_config()->tls.ticket.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_l("aes-256-cbc", optarg)) {
mod_config()->tls.ticket.cipher = EVP_aes_256_cbc(); mod_config()->tls.ticket.cipher = EVP_aes_256_cbc();
} else { } else {
LOG(ERROR) << opt LOG(ERROR) << opt
@ -2435,14 +2466,13 @@ int parse_config(const char *opt, const char *optarg,
return 0; return 0;
case SHRPX_OPTID_HOST_REWRITE: case SHRPX_OPTID_HOST_REWRITE:
mod_config()->http.no_host_rewrite = !util::strieq(optarg, "yes"); mod_config()->http.no_host_rewrite = !util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED: case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED:
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED: { case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED: {
auto src = StringRef{optarg}; auto addr_end = std::find(std::begin(optarg), std::end(optarg), ';');
auto addr_end = std::find(std::begin(src), std::end(src), ';'); auto src_params = StringRef{addr_end, std::end(optarg)};
auto src_params = StringRef{addr_end, std::end(src)};
MemcachedConnectionParams params{}; MemcachedConnectionParams params{};
if (parse_memcached_connection_params(params, src_params, StringRef{opt}) != if (parse_memcached_connection_params(params, src_params, StringRef{opt}) !=
@ -2451,7 +2481,7 @@ int parse_config(const char *opt, const char *optarg,
} }
if (split_host_port(host, sizeof(host), &port, if (split_host_port(host, sizeof(host), &port,
StringRef{std::begin(src), addr_end}, opt) == -1) { StringRef{std::begin(optarg), addr_end}, opt) == -1) {
return -1; return -1;
} }
@ -2510,7 +2540,8 @@ int parse_config(const char *opt, const char *optarg,
case SHRPX_OPTID_MRUBY_FILE: case SHRPX_OPTID_MRUBY_FILE:
#ifdef HAVE_MRUBY #ifdef HAVE_MRUBY
mod_config()->mruby_file = optarg; mod_config()->mruby_file =
ImmutableString{std::begin(optarg), std::end(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.";
@ -2518,26 +2549,26 @@ int parse_config(const char *opt, const char *optarg,
return 0; return 0;
case SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL: case SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL:
mod_config()->conn.upstream.accept_proxy_protocol = mod_config()->conn.upstream.accept_proxy_protocol =
util::strieq(optarg, "yes"); util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_ADD_FORWARDED: { case SHRPX_OPTID_ADD_FORWARDED: {
auto &fwdconf = mod_config()->http.forwarded; auto &fwdconf = mod_config()->http.forwarded;
fwdconf.params = FORWARDED_NONE; fwdconf.params = FORWARDED_NONE;
for (const auto &param : util::parse_config_str_list(optarg)) { for (const auto &param : util::split_str(optarg, ',')) {
if (util::strieq(param, "by")) { if (util::strieq_l("by", param)) {
fwdconf.params |= FORWARDED_BY; fwdconf.params |= FORWARDED_BY;
continue; continue;
} }
if (util::strieq(param, "for")) { if (util::strieq_l("for", param)) {
fwdconf.params |= FORWARDED_FOR; fwdconf.params |= FORWARDED_FOR;
continue; continue;
} }
if (util::strieq(param, "host")) { if (util::strieq_l("host", param)) {
fwdconf.params |= FORWARDED_HOST; fwdconf.params |= FORWARDED_HOST;
continue; continue;
} }
if (util::strieq(param, "proto")) { if (util::strieq_l("proto", param)) {
fwdconf.params |= FORWARDED_PROTO; fwdconf.params |= FORWARDED_PROTO;
continue; continue;
} }
@ -2550,7 +2581,7 @@ 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()->http.forwarded.strip_incoming = util::strieq(optarg, "yes"); mod_config()->http.forwarded.strip_incoming = util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_FORWARDED_BY: case SHRPX_OPTID_FORWARDED_BY:
@ -2570,7 +2601,7 @@ int parse_config(const char *opt, const char *optarg,
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; fwdconf.by_obfuscated = optarg.str();
} else { } else {
fwdconf.by_obfuscated = ""; fwdconf.by_obfuscated = "";
} }
@ -2583,7 +2614,8 @@ int parse_config(const char *opt, const char *optarg,
return 0; return 0;
} }
case SHRPX_OPTID_NO_HTTP2_CIPHER_BLACK_LIST: case SHRPX_OPTID_NO_HTTP2_CIPHER_BLACK_LIST:
mod_config()->tls.no_http2_cipher_black_list = util::strieq(optarg, "yes"); mod_config()->tls.no_http2_cipher_black_list =
util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_BACKEND_HTTP1_TLS: case SHRPX_OPTID_BACKEND_HTTP1_TLS:
@ -2596,11 +2628,13 @@ int parse_config(const char *opt, const char *optarg,
<< SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED; << SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED;
return 0; return 0;
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE: case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE:
mod_config()->tls.session_cache.memcached.cert_file = optarg; mod_config()->tls.session_cache.memcached.cert_file =
ImmutableString{std::begin(optarg), std::end(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:
mod_config()->tls.session_cache.memcached.private_key_file = optarg; mod_config()->tls.session_cache.memcached.private_key_file =
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_TLS: case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_TLS:
@ -2608,11 +2642,13 @@ int parse_config(const char *opt, const char *optarg,
<< SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED; << SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED;
return 0; return 0;
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_CERT_FILE: case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_CERT_FILE:
mod_config()->tls.ticket.memcached.cert_file = optarg; mod_config()->tls.ticket.memcached.cert_file =
ImmutableString{std::begin(optarg), std::end(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:
mod_config()->tls.ticket.memcached.private_key_file = optarg; mod_config()->tls.ticket.memcached.private_key_file =
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0; return 0;
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY: case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY:
@ -2643,7 +2679,7 @@ int parse_config(const char *opt, const char *optarg,
return -1; return -1;
} }
int load_config(const char *filename, std::set<std::string> &include_set) { int load_config(const char *filename, std::set<StringRef> &include_set) {
std::ifstream in(filename, std::ios::binary); std::ifstream in(filename, std::ios::binary);
if (!in) { if (!in) {
LOG(ERROR) << "Could not open config file " << filename; LOG(ERROR) << "Could not open config file " << filename;
@ -2656,155 +2692,153 @@ int load_config(const char *filename, std::set<std::string> &include_set) {
if (line.empty() || line[0] == '#') { if (line.empty() || line[0] == '#') {
continue; continue;
} }
size_t i; auto eq = std::find(std::begin(line), std::end(line), '=');
size_t size = line.size(); if (eq == std::end(line)) {
for (i = 0; i < size && line[i] != '='; ++i)
;
if (i == size) {
LOG(ERROR) << "Bad configuration format in " << filename << " at line " LOG(ERROR) << "Bad configuration format in " << filename << " at line "
<< linenum; << linenum;
return -1; return -1;
} }
line[i] = '\0'; *eq = '\0';
auto s = line.c_str();
if (parse_config(s, s + i + 1, include_set) == -1) { if (parse_config(StringRef{std::begin(line), eq},
StringRef{eq + 1, std::end(line)}, include_set) != 0) {
return -1; return -1;
} }
} }
return 0; return 0;
} }
const char *str_syslog_facility(int facility) { StringRef str_syslog_facility(int facility) {
switch (facility) { switch (facility) {
case (LOG_AUTH): case (LOG_AUTH):
return "auth"; return StringRef::from_lit("auth");
#ifdef LOG_AUTHPRIV #ifdef LOG_AUTHPRIV
case (LOG_AUTHPRIV): case (LOG_AUTHPRIV):
return "authpriv"; return StringRef::from_lit("authpriv");
#endif // LOG_AUTHPRIV #endif // LOG_AUTHPRIV
case (LOG_CRON): case (LOG_CRON):
return "cron"; return StringRef::from_lit("cron");
case (LOG_DAEMON): case (LOG_DAEMON):
return "daemon"; return StringRef::from_lit("daemon");
#ifdef LOG_FTP #ifdef LOG_FTP
case (LOG_FTP): case (LOG_FTP):
return "ftp"; return StringRef::from_lit("ftp");
#endif // LOG_FTP #endif // LOG_FTP
case (LOG_KERN): case (LOG_KERN):
return "kern"; return StringRef::from_lit("kern");
case (LOG_LOCAL0): case (LOG_LOCAL0):
return "local0"; return StringRef::from_lit("local0");
case (LOG_LOCAL1): case (LOG_LOCAL1):
return "local1"; return StringRef::from_lit("local1");
case (LOG_LOCAL2): case (LOG_LOCAL2):
return "local2"; return StringRef::from_lit("local2");
case (LOG_LOCAL3): case (LOG_LOCAL3):
return "local3"; return StringRef::from_lit("local3");
case (LOG_LOCAL4): case (LOG_LOCAL4):
return "local4"; return StringRef::from_lit("local4");
case (LOG_LOCAL5): case (LOG_LOCAL5):
return "local5"; return StringRef::from_lit("local5");
case (LOG_LOCAL6): case (LOG_LOCAL6):
return "local6"; return StringRef::from_lit("local6");
case (LOG_LOCAL7): case (LOG_LOCAL7):
return "local7"; return StringRef::from_lit("local7");
case (LOG_LPR): case (LOG_LPR):
return "lpr"; return StringRef::from_lit("lpr");
case (LOG_MAIL): case (LOG_MAIL):
return "mail"; return StringRef::from_lit("mail");
case (LOG_SYSLOG): case (LOG_SYSLOG):
return "syslog"; return StringRef::from_lit("syslog");
case (LOG_USER): case (LOG_USER):
return "user"; return StringRef::from_lit("user");
case (LOG_UUCP): case (LOG_UUCP):
return "uucp"; return StringRef::from_lit("uucp");
default: default:
return "(unknown)"; return StringRef::from_lit("(unknown)");
} }
} }
int int_syslog_facility(const char *strfacility) { int int_syslog_facility(const StringRef &strfacility) {
if (util::strieq(strfacility, "auth")) { if (util::strieq_l("auth", strfacility)) {
return LOG_AUTH; return LOG_AUTH;
} }
#ifdef LOG_AUTHPRIV #ifdef LOG_AUTHPRIV
if (util::strieq(strfacility, "authpriv")) { if (util::strieq_l("authpriv", strfacility)) {
return LOG_AUTHPRIV; return LOG_AUTHPRIV;
} }
#endif // LOG_AUTHPRIV #endif // LOG_AUTHPRIV
if (util::strieq(strfacility, "cron")) { if (util::strieq_l("cron", strfacility)) {
return LOG_CRON; return LOG_CRON;
} }
if (util::strieq(strfacility, "daemon")) { if (util::strieq_l("daemon", strfacility)) {
return LOG_DAEMON; return LOG_DAEMON;
} }
#ifdef LOG_FTP #ifdef LOG_FTP
if (util::strieq(strfacility, "ftp")) { if (util::strieq_l("ftp", strfacility)) {
return LOG_FTP; return LOG_FTP;
} }
#endif // LOG_FTP #endif // LOG_FTP
if (util::strieq(strfacility, "kern")) { if (util::strieq_l("kern", strfacility)) {
return LOG_KERN; return LOG_KERN;
} }
if (util::strieq(strfacility, "local0")) { if (util::strieq_l("local0", strfacility)) {
return LOG_LOCAL0; return LOG_LOCAL0;
} }
if (util::strieq(strfacility, "local1")) { if (util::strieq_l("local1", strfacility)) {
return LOG_LOCAL1; return LOG_LOCAL1;
} }
if (util::strieq(strfacility, "local2")) { if (util::strieq_l("local2", strfacility)) {
return LOG_LOCAL2; return LOG_LOCAL2;
} }
if (util::strieq(strfacility, "local3")) { if (util::strieq_l("local3", strfacility)) {
return LOG_LOCAL3; return LOG_LOCAL3;
} }
if (util::strieq(strfacility, "local4")) { if (util::strieq_l("local4", strfacility)) {
return LOG_LOCAL4; return LOG_LOCAL4;
} }
if (util::strieq(strfacility, "local5")) { if (util::strieq_l("local5", strfacility)) {
return LOG_LOCAL5; return LOG_LOCAL5;
} }
if (util::strieq(strfacility, "local6")) { if (util::strieq_l("local6", strfacility)) {
return LOG_LOCAL6; return LOG_LOCAL6;
} }
if (util::strieq(strfacility, "local7")) { if (util::strieq_l("local7", strfacility)) {
return LOG_LOCAL7; return LOG_LOCAL7;
} }
if (util::strieq(strfacility, "lpr")) { if (util::strieq_l("lpr", strfacility)) {
return LOG_LPR; return LOG_LPR;
} }
if (util::strieq(strfacility, "mail")) { if (util::strieq_l("mail", strfacility)) {
return LOG_MAIL; return LOG_MAIL;
} }
if (util::strieq(strfacility, "news")) { if (util::strieq_l("news", strfacility)) {
return LOG_NEWS; return LOG_NEWS;
} }
if (util::strieq(strfacility, "syslog")) { if (util::strieq_l("syslog", strfacility)) {
return LOG_SYSLOG; return LOG_SYSLOG;
} }
if (util::strieq(strfacility, "user")) { if (util::strieq_l("user", strfacility)) {
return LOG_USER; return LOG_USER;
} }
if (util::strieq(strfacility, "uucp")) { if (util::strieq_l("uucp", strfacility)) {
return LOG_UUCP; return LOG_UUCP;
} }

View File

@ -71,173 +71,212 @@ class CertLookupTree;
constexpr char SHRPX_UNIX_PATH_PREFIX[] = "unix:"; constexpr char SHRPX_UNIX_PATH_PREFIX[] = "unix:";
constexpr char SHRPX_OPT_PRIVATE_KEY_FILE[] = "private-key-file"; constexpr auto SHRPX_OPT_PRIVATE_KEY_FILE =
constexpr char SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE[] = "private-key-passwd-file"; StringRef::from_lit("private-key-file");
constexpr char SHRPX_OPT_CERTIFICATE_FILE[] = "certificate-file"; constexpr auto SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE =
constexpr char SHRPX_OPT_DH_PARAM_FILE[] = "dh-param-file"; StringRef::from_lit("private-key-passwd-file");
constexpr char SHRPX_OPT_SUBCERT[] = "subcert"; constexpr auto SHRPX_OPT_CERTIFICATE_FILE =
constexpr char SHRPX_OPT_BACKEND[] = "backend"; StringRef::from_lit("certificate-file");
constexpr char SHRPX_OPT_FRONTEND[] = "frontend"; constexpr auto SHRPX_OPT_DH_PARAM_FILE = StringRef::from_lit("dh-param-file");
constexpr char SHRPX_OPT_WORKERS[] = "workers"; constexpr auto SHRPX_OPT_SUBCERT = StringRef::from_lit("subcert");
constexpr char SHRPX_OPT_HTTP2_MAX_CONCURRENT_STREAMS[] = constexpr auto SHRPX_OPT_BACKEND = StringRef::from_lit("backend");
"http2-max-concurrent-streams"; constexpr auto SHRPX_OPT_FRONTEND = StringRef::from_lit("frontend");
constexpr char SHRPX_OPT_LOG_LEVEL[] = "log-level"; constexpr auto SHRPX_OPT_WORKERS = StringRef::from_lit("workers");
constexpr char SHRPX_OPT_DAEMON[] = "daemon"; constexpr auto SHRPX_OPT_HTTP2_MAX_CONCURRENT_STREAMS =
constexpr char SHRPX_OPT_HTTP2_PROXY[] = "http2-proxy"; StringRef::from_lit("http2-max-concurrent-streams");
constexpr char SHRPX_OPT_HTTP2_BRIDGE[] = "http2-bridge"; constexpr auto SHRPX_OPT_LOG_LEVEL = StringRef::from_lit("log-level");
constexpr char SHRPX_OPT_CLIENT_PROXY[] = "client-proxy"; constexpr auto SHRPX_OPT_DAEMON = StringRef::from_lit("daemon");
constexpr char SHRPX_OPT_ADD_X_FORWARDED_FOR[] = "add-x-forwarded-for"; constexpr auto SHRPX_OPT_HTTP2_PROXY = StringRef::from_lit("http2-proxy");
constexpr char SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR[] = constexpr auto SHRPX_OPT_HTTP2_BRIDGE = StringRef::from_lit("http2-bridge");
"strip-incoming-x-forwarded-for"; constexpr auto SHRPX_OPT_CLIENT_PROXY = StringRef::from_lit("client-proxy");
constexpr char SHRPX_OPT_NO_VIA[] = "no-via"; constexpr auto SHRPX_OPT_ADD_X_FORWARDED_FOR =
constexpr char SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT[] = StringRef::from_lit("add-x-forwarded-for");
"frontend-http2-read-timeout"; constexpr auto SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR =
constexpr char SHRPX_OPT_FRONTEND_READ_TIMEOUT[] = "frontend-read-timeout"; StringRef::from_lit("strip-incoming-x-forwarded-for");
constexpr char SHRPX_OPT_FRONTEND_WRITE_TIMEOUT[] = "frontend-write-timeout"; constexpr auto SHRPX_OPT_NO_VIA = StringRef::from_lit("no-via");
constexpr char SHRPX_OPT_BACKEND_READ_TIMEOUT[] = "backend-read-timeout"; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT =
constexpr char SHRPX_OPT_BACKEND_WRITE_TIMEOUT[] = "backend-write-timeout"; StringRef::from_lit("frontend-http2-read-timeout");
constexpr char SHRPX_OPT_STREAM_READ_TIMEOUT[] = "stream-read-timeout"; constexpr auto SHRPX_OPT_FRONTEND_READ_TIMEOUT =
constexpr char SHRPX_OPT_STREAM_WRITE_TIMEOUT[] = "stream-write-timeout"; StringRef::from_lit("frontend-read-timeout");
constexpr char SHRPX_OPT_ACCESSLOG_FILE[] = "accesslog-file"; constexpr auto SHRPX_OPT_FRONTEND_WRITE_TIMEOUT =
constexpr char SHRPX_OPT_ACCESSLOG_SYSLOG[] = "accesslog-syslog"; StringRef::from_lit("frontend-write-timeout");
constexpr char SHRPX_OPT_ACCESSLOG_FORMAT[] = "accesslog-format"; constexpr auto SHRPX_OPT_BACKEND_READ_TIMEOUT =
constexpr char SHRPX_OPT_ERRORLOG_FILE[] = "errorlog-file"; StringRef::from_lit("backend-read-timeout");
constexpr char SHRPX_OPT_ERRORLOG_SYSLOG[] = "errorlog-syslog"; constexpr auto SHRPX_OPT_BACKEND_WRITE_TIMEOUT =
constexpr char SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT[] = StringRef::from_lit("backend-write-timeout");
"backend-keep-alive-timeout"; constexpr auto SHRPX_OPT_STREAM_READ_TIMEOUT =
constexpr char SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS[] = StringRef::from_lit("stream-read-timeout");
"frontend-http2-window-bits"; constexpr auto SHRPX_OPT_STREAM_WRITE_TIMEOUT =
constexpr char SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS[] = StringRef::from_lit("stream-write-timeout");
"backend-http2-window-bits"; constexpr auto SHRPX_OPT_ACCESSLOG_FILE = StringRef::from_lit("accesslog-file");
constexpr char SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS[] = constexpr auto SHRPX_OPT_ACCESSLOG_SYSLOG =
"frontend-http2-connection-window-bits"; StringRef::from_lit("accesslog-syslog");
constexpr char SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_BITS[] = constexpr auto SHRPX_OPT_ACCESSLOG_FORMAT =
"backend-http2-connection-window-bits"; StringRef::from_lit("accesslog-format");
constexpr char SHRPX_OPT_FRONTEND_NO_TLS[] = "frontend-no-tls"; constexpr auto SHRPX_OPT_ERRORLOG_FILE = StringRef::from_lit("errorlog-file");
constexpr char SHRPX_OPT_BACKEND_NO_TLS[] = "backend-no-tls"; constexpr auto SHRPX_OPT_ERRORLOG_SYSLOG =
constexpr char SHRPX_OPT_BACKEND_TLS_SNI_FIELD[] = "backend-tls-sni-field"; StringRef::from_lit("errorlog-syslog");
constexpr char SHRPX_OPT_PID_FILE[] = "pid-file"; constexpr auto SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT =
constexpr char SHRPX_OPT_USER[] = "user"; StringRef::from_lit("backend-keep-alive-timeout");
constexpr char SHRPX_OPT_SYSLOG_FACILITY[] = "syslog-facility"; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS =
constexpr char SHRPX_OPT_BACKLOG[] = "backlog"; StringRef::from_lit("frontend-http2-window-bits");
constexpr char SHRPX_OPT_CIPHERS[] = "ciphers"; constexpr auto SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS =
constexpr char SHRPX_OPT_CLIENT[] = "client"; StringRef::from_lit("backend-http2-window-bits");
constexpr char SHRPX_OPT_INSECURE[] = "insecure"; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS =
constexpr char SHRPX_OPT_CACERT[] = "cacert"; StringRef::from_lit("frontend-http2-connection-window-bits");
constexpr char SHRPX_OPT_BACKEND_IPV4[] = "backend-ipv4"; constexpr auto SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_BITS =
constexpr char SHRPX_OPT_BACKEND_IPV6[] = "backend-ipv6"; StringRef::from_lit("backend-http2-connection-window-bits");
constexpr char SHRPX_OPT_BACKEND_HTTP_PROXY_URI[] = "backend-http-proxy-uri"; constexpr auto SHRPX_OPT_FRONTEND_NO_TLS =
constexpr char SHRPX_OPT_READ_RATE[] = "read-rate"; StringRef::from_lit("frontend-no-tls");
constexpr char SHRPX_OPT_READ_BURST[] = "read-burst"; constexpr auto SHRPX_OPT_BACKEND_NO_TLS = StringRef::from_lit("backend-no-tls");
constexpr char SHRPX_OPT_WRITE_RATE[] = "write-rate"; constexpr auto SHRPX_OPT_BACKEND_TLS_SNI_FIELD =
constexpr char SHRPX_OPT_WRITE_BURST[] = "write-burst"; StringRef::from_lit("backend-tls-sni-field");
constexpr char SHRPX_OPT_WORKER_READ_RATE[] = "worker-read-rate"; constexpr auto SHRPX_OPT_PID_FILE = StringRef::from_lit("pid-file");
constexpr char SHRPX_OPT_WORKER_READ_BURST[] = "worker-read-burst"; constexpr auto SHRPX_OPT_USER = StringRef::from_lit("user");
constexpr char SHRPX_OPT_WORKER_WRITE_RATE[] = "worker-write-rate"; constexpr auto SHRPX_OPT_SYSLOG_FACILITY =
constexpr char SHRPX_OPT_WORKER_WRITE_BURST[] = "worker-write-burst"; StringRef::from_lit("syslog-facility");
constexpr char SHRPX_OPT_NPN_LIST[] = "npn-list"; constexpr auto SHRPX_OPT_BACKLOG = StringRef::from_lit("backlog");
constexpr char SHRPX_OPT_TLS_PROTO_LIST[] = "tls-proto-list"; constexpr auto SHRPX_OPT_CIPHERS = StringRef::from_lit("ciphers");
constexpr char SHRPX_OPT_VERIFY_CLIENT[] = "verify-client"; constexpr auto SHRPX_OPT_CLIENT = StringRef::from_lit("client");
constexpr char SHRPX_OPT_VERIFY_CLIENT_CACERT[] = "verify-client-cacert"; constexpr auto SHRPX_OPT_INSECURE = StringRef::from_lit("insecure");
constexpr char SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE[] = "client-private-key-file"; constexpr auto SHRPX_OPT_CACERT = StringRef::from_lit("cacert");
constexpr char SHRPX_OPT_CLIENT_CERT_FILE[] = "client-cert-file"; constexpr auto SHRPX_OPT_BACKEND_IPV4 = StringRef::from_lit("backend-ipv4");
constexpr char SHRPX_OPT_FRONTEND_HTTP2_DUMP_REQUEST_HEADER[] = constexpr auto SHRPX_OPT_BACKEND_IPV6 = StringRef::from_lit("backend-ipv6");
"frontend-http2-dump-request-header"; constexpr auto SHRPX_OPT_BACKEND_HTTP_PROXY_URI =
constexpr char SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER[] = StringRef::from_lit("backend-http-proxy-uri");
"frontend-http2-dump-response-header"; constexpr auto SHRPX_OPT_READ_RATE = StringRef::from_lit("read-rate");
constexpr char SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING[] = constexpr auto SHRPX_OPT_READ_BURST = StringRef::from_lit("read-burst");
"http2-no-cookie-crumbling"; constexpr auto SHRPX_OPT_WRITE_RATE = StringRef::from_lit("write-rate");
constexpr char SHRPX_OPT_FRONTEND_FRAME_DEBUG[] = "frontend-frame-debug"; constexpr auto SHRPX_OPT_WRITE_BURST = StringRef::from_lit("write-burst");
constexpr char SHRPX_OPT_PADDING[] = "padding"; constexpr auto SHRPX_OPT_WORKER_READ_RATE =
constexpr char SHRPX_OPT_ALTSVC[] = "altsvc"; StringRef::from_lit("worker-read-rate");
constexpr char SHRPX_OPT_ADD_REQUEST_HEADER[] = "add-request-header"; constexpr auto SHRPX_OPT_WORKER_READ_BURST =
constexpr char SHRPX_OPT_ADD_RESPONSE_HEADER[] = "add-response-header"; StringRef::from_lit("worker-read-burst");
constexpr char SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS[] = constexpr auto SHRPX_OPT_WORKER_WRITE_RATE =
"worker-frontend-connections"; StringRef::from_lit("worker-write-rate");
constexpr char SHRPX_OPT_NO_LOCATION_REWRITE[] = "no-location-rewrite"; constexpr auto SHRPX_OPT_WORKER_WRITE_BURST =
constexpr char SHRPX_OPT_NO_HOST_REWRITE[] = "no-host-rewrite"; StringRef::from_lit("worker-write-burst");
constexpr char SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_HOST[] = constexpr auto SHRPX_OPT_NPN_LIST = StringRef::from_lit("npn-list");
"backend-http1-connections-per-host"; constexpr auto SHRPX_OPT_TLS_PROTO_LIST = StringRef::from_lit("tls-proto-list");
constexpr char SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND[] = constexpr auto SHRPX_OPT_VERIFY_CLIENT = StringRef::from_lit("verify-client");
"backend-http1-connections-per-frontend"; constexpr auto SHRPX_OPT_VERIFY_CLIENT_CACERT =
constexpr char SHRPX_OPT_LISTENER_DISABLE_TIMEOUT[] = StringRef::from_lit("verify-client-cacert");
"listener-disable-timeout"; constexpr auto SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE =
constexpr char SHRPX_OPT_TLS_TICKET_KEY_FILE[] = "tls-ticket-key-file"; StringRef::from_lit("client-private-key-file");
constexpr char SHRPX_OPT_RLIMIT_NOFILE[] = "rlimit-nofile"; constexpr auto SHRPX_OPT_CLIENT_CERT_FILE =
constexpr char SHRPX_OPT_BACKEND_REQUEST_BUFFER[] = "backend-request-buffer"; StringRef::from_lit("client-cert-file");
constexpr char SHRPX_OPT_BACKEND_RESPONSE_BUFFER[] = "backend-response-buffer"; constexpr auto SHRPX_OPT_FRONTEND_HTTP2_DUMP_REQUEST_HEADER =
constexpr char SHRPX_OPT_NO_SERVER_PUSH[] = "no-server-push"; StringRef::from_lit("frontend-http2-dump-request-header");
constexpr char SHRPX_OPT_BACKEND_HTTP2_CONNECTIONS_PER_WORKER[] = constexpr auto SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER =
"backend-http2-connections-per-worker"; StringRef::from_lit("frontend-http2-dump-response-header");
constexpr char SHRPX_OPT_FETCH_OCSP_RESPONSE_FILE[] = constexpr auto SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING =
"fetch-ocsp-response-file"; StringRef::from_lit("http2-no-cookie-crumbling");
constexpr char SHRPX_OPT_OCSP_UPDATE_INTERVAL[] = "ocsp-update-interval"; constexpr auto SHRPX_OPT_FRONTEND_FRAME_DEBUG =
constexpr char SHRPX_OPT_NO_OCSP[] = "no-ocsp"; StringRef::from_lit("frontend-frame-debug");
constexpr char SHRPX_OPT_HEADER_FIELD_BUFFER[] = "header-field-buffer"; constexpr auto SHRPX_OPT_PADDING = StringRef::from_lit("padding");
constexpr char SHRPX_OPT_MAX_HEADER_FIELDS[] = "max-header-fields"; constexpr auto SHRPX_OPT_ALTSVC = StringRef::from_lit("altsvc");
constexpr char SHRPX_OPT_INCLUDE[] = "include"; constexpr auto SHRPX_OPT_ADD_REQUEST_HEADER =
constexpr char SHRPX_OPT_TLS_TICKET_KEY_CIPHER[] = "tls-ticket-key-cipher"; StringRef::from_lit("add-request-header");
constexpr char SHRPX_OPT_HOST_REWRITE[] = "host-rewrite"; constexpr auto SHRPX_OPT_ADD_RESPONSE_HEADER =
constexpr char SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED[] = StringRef::from_lit("add-response-header");
"tls-session-cache-memcached"; constexpr auto SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS =
constexpr char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED[] = StringRef::from_lit("worker-frontend-connections");
"tls-ticket-key-memcached"; constexpr auto SHRPX_OPT_NO_LOCATION_REWRITE =
constexpr char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_INTERVAL[] = StringRef::from_lit("no-location-rewrite");
"tls-ticket-key-memcached-interval"; constexpr auto SHRPX_OPT_NO_HOST_REWRITE =
constexpr char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY[] = StringRef::from_lit("no-host-rewrite");
"tls-ticket-key-memcached-max-retry"; constexpr auto SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_HOST =
constexpr char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL[] = StringRef::from_lit("backend-http1-connections-per-host");
"tls-ticket-key-memcached-max-fail"; constexpr auto SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND =
constexpr char SHRPX_OPT_MRUBY_FILE[] = "mruby-file"; StringRef::from_lit("backend-http1-connections-per-frontend");
constexpr char SHRPX_OPT_ACCEPT_PROXY_PROTOCOL[] = "accept-proxy-protocol"; constexpr auto SHRPX_OPT_LISTENER_DISABLE_TIMEOUT =
constexpr char SHRPX_OPT_FASTOPEN[] = "fastopen"; StringRef::from_lit("listener-disable-timeout");
constexpr char SHRPX_OPT_TLS_DYN_REC_WARMUP_THRESHOLD[] = constexpr auto SHRPX_OPT_TLS_TICKET_KEY_FILE =
"tls-dyn-rec-warmup-threshold"; StringRef::from_lit("tls-ticket-key-file");
constexpr char SHRPX_OPT_TLS_DYN_REC_IDLE_TIMEOUT[] = constexpr auto SHRPX_OPT_RLIMIT_NOFILE = StringRef::from_lit("rlimit-nofile");
"tls-dyn-rec-idle-timeout"; constexpr auto SHRPX_OPT_BACKEND_REQUEST_BUFFER =
constexpr char SHRPX_OPT_ADD_FORWARDED[] = "add-forwarded"; StringRef::from_lit("backend-request-buffer");
constexpr char SHRPX_OPT_STRIP_INCOMING_FORWARDED[] = constexpr auto SHRPX_OPT_BACKEND_RESPONSE_BUFFER =
"strip-incoming-forwarded"; StringRef::from_lit("backend-response-buffer");
constexpr static char SHRPX_OPT_FORWARDED_BY[] = "forwarded-by"; constexpr auto SHRPX_OPT_NO_SERVER_PUSH = StringRef::from_lit("no-server-push");
constexpr char SHRPX_OPT_FORWARDED_FOR[] = "forwarded-for"; constexpr auto SHRPX_OPT_BACKEND_HTTP2_CONNECTIONS_PER_WORKER =
constexpr char SHRPX_OPT_REQUEST_HEADER_FIELD_BUFFER[] = StringRef::from_lit("backend-http2-connections-per-worker");
"request-header-field-buffer"; constexpr auto SHRPX_OPT_FETCH_OCSP_RESPONSE_FILE =
constexpr char SHRPX_OPT_MAX_REQUEST_HEADER_FIELDS[] = StringRef::from_lit("fetch-ocsp-response-file");
"max-request-header-fields"; constexpr auto SHRPX_OPT_OCSP_UPDATE_INTERVAL =
constexpr char SHRPX_OPT_RESPONSE_HEADER_FIELD_BUFFER[] = StringRef::from_lit("ocsp-update-interval");
"response-header-field-buffer"; constexpr auto SHRPX_OPT_NO_OCSP = StringRef::from_lit("no-ocsp");
constexpr char SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS[] = constexpr auto SHRPX_OPT_HEADER_FIELD_BUFFER =
"max-response-header-fields"; StringRef::from_lit("header-field-buffer");
constexpr char SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST[] = constexpr auto SHRPX_OPT_MAX_HEADER_FIELDS =
"no-http2-cipher-black-list"; StringRef::from_lit("max-header-fields");
constexpr char SHRPX_OPT_BACKEND_HTTP1_TLS[] = "backend-http1-tls"; constexpr auto SHRPX_OPT_INCLUDE = StringRef::from_lit("include");
constexpr char SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS[] = constexpr auto SHRPX_OPT_TLS_TICKET_KEY_CIPHER =
"tls-session-cache-memcached-tls"; StringRef::from_lit("tls-ticket-key-cipher");
constexpr char SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE[] = constexpr auto SHRPX_OPT_HOST_REWRITE = StringRef::from_lit("host-rewrite");
"tls-session-cache-memcached-cert-file"; constexpr auto SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED =
constexpr char SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE[] = StringRef::from_lit("tls-session-cache-memcached");
"tls-session-cache-memcached-private-key-file"; constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED =
constexpr char SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY[] = StringRef::from_lit("tls-ticket-key-memcached");
"tls-session-cache-memcached-address-family"; constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_INTERVAL =
constexpr char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_TLS[] = StringRef::from_lit("tls-ticket-key-memcached-interval");
"tls-ticket-key-memcached-tls"; constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY =
constexpr char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_CERT_FILE[] = StringRef::from_lit("tls-ticket-key-memcached-max-retry");
"tls-ticket-key-memcached-cert-file"; constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL =
constexpr char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE[] = StringRef::from_lit("tls-ticket-key-memcached-max-fail");
"tls-ticket-key-memcached-private-key-file"; constexpr auto SHRPX_OPT_MRUBY_FILE = StringRef::from_lit("mruby-file");
constexpr char SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY[] = constexpr auto SHRPX_OPT_ACCEPT_PROXY_PROTOCOL =
"tls-ticket-key-memcached-address-family"; StringRef::from_lit("accept-proxy-protocol");
constexpr char SHRPX_OPT_BACKEND_ADDRESS_FAMILY[] = "backend-address-family"; constexpr auto SHRPX_OPT_FASTOPEN = StringRef::from_lit("fastopen");
constexpr char SHRPX_OPT_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS[] = constexpr auto SHRPX_OPT_TLS_DYN_REC_WARMUP_THRESHOLD =
"frontend-http2-max-concurrent-streams"; StringRef::from_lit("tls-dyn-rec-warmup-threshold");
constexpr char SHRPX_OPT_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS[] = constexpr auto SHRPX_OPT_TLS_DYN_REC_IDLE_TIMEOUT =
"backend-http2-max-concurrent-streams"; StringRef::from_lit("tls-dyn-rec-idle-timeout");
constexpr char SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND[] = constexpr auto SHRPX_OPT_ADD_FORWARDED = StringRef::from_lit("add-forwarded");
"backend-connections-per-frontend"; constexpr auto SHRPX_OPT_STRIP_INCOMING_FORWARDED =
constexpr char SHRPX_OPT_BACKEND_TLS[] = "backend-tls"; StringRef::from_lit("strip-incoming-forwarded");
constexpr char SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST[] = constexpr auto SHRPX_OPT_FORWARDED_BY = StringRef::from_lit("forwarded-by");
"backend-connections-per-host"; constexpr auto SHRPX_OPT_FORWARDED_FOR = StringRef::from_lit("forwarded-for");
constexpr char SHRPX_OPT_ERROR_PAGE[] = "error-page"; constexpr auto SHRPX_OPT_REQUEST_HEADER_FIELD_BUFFER =
StringRef::from_lit("request-header-field-buffer");
constexpr auto SHRPX_OPT_MAX_REQUEST_HEADER_FIELDS =
StringRef::from_lit("max-request-header-fields");
constexpr auto SHRPX_OPT_RESPONSE_HEADER_FIELD_BUFFER =
StringRef::from_lit("response-header-field-buffer");
constexpr auto SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS =
StringRef::from_lit("max-response-header-fields");
constexpr auto SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST =
StringRef::from_lit("no-http2-cipher-black-list");
constexpr auto SHRPX_OPT_BACKEND_HTTP1_TLS =
StringRef::from_lit("backend-http1-tls");
constexpr auto SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS =
StringRef::from_lit("tls-session-cache-memcached-tls");
constexpr auto SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE =
StringRef::from_lit("tls-session-cache-memcached-cert-file");
constexpr auto SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE =
StringRef::from_lit("tls-session-cache-memcached-private-key-file");
constexpr auto SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY =
StringRef::from_lit("tls-session-cache-memcached-address-family");
constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_TLS =
StringRef::from_lit("tls-ticket-key-memcached-tls");
constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_CERT_FILE =
StringRef::from_lit("tls-ticket-key-memcached-cert-file");
constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE =
StringRef::from_lit("tls-ticket-key-memcached-private-key-file");
constexpr auto SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY =
StringRef::from_lit("tls-ticket-key-memcached-address-family");
constexpr auto SHRPX_OPT_BACKEND_ADDRESS_FAMILY =
StringRef::from_lit("backend-address-family");
constexpr auto SHRPX_OPT_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS =
StringRef::from_lit("frontend-http2-max-concurrent-streams");
constexpr auto SHRPX_OPT_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS =
StringRef::from_lit("backend-http2-max-concurrent-streams");
constexpr auto SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND =
StringRef::from_lit("backend-connections-per-frontend");
constexpr auto SHRPX_OPT_BACKEND_TLS = StringRef::from_lit("backend-tls");
constexpr auto SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST =
StringRef::from_lit("backend-connections-per-host");
constexpr auto SHRPX_OPT_ERROR_PAGE = StringRef::from_lit("error-page");
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
@ -628,30 +667,27 @@ void create_config();
// returns 0 if it succeeds, or -1. The |included_set| contains the // returns 0 if it succeeds, or -1. The |included_set| contains the
// all paths already included while processing this configuration, to // all paths already included while processing this configuration, to
// avoid loop in --include option. // avoid loop in --include option.
int parse_config(const char *opt, const char *optarg, int parse_config(const StringRef &opt, const StringRef &optarg,
std::set<std::string> &included_set); std::set<StringRef> &included_set);
// Loads configurations from |filename| and stores them in statically // Loads configurations from |filename| and stores them in statically
// allocated Config object. This function returns 0 if it succeeds, or // allocated Config object. This function returns 0 if it succeeds, or
// -1. See parse_config() for |include_set|. // -1. See parse_config() for |include_set|.
int load_config(const char *filename, std::set<std::string> &include_set); int load_config(const char *filename, std::set<StringRef> &include_set);
// Read passwd from |filename|
std::string read_passwd_from_file(const char *filename);
// Parses header field in |optarg|. We expect header field is formed // Parses header field in |optarg|. We expect header field is formed
// like "NAME: VALUE". We require that NAME is non empty string. ":" // like "NAME: VALUE". We require that NAME is non empty string. ":"
// is allowed at the start of the NAME, but NAME == ":" is not // is allowed at the start of the NAME, but NAME == ":" is not
// allowed. This function returns pair of NAME and VALUE. // allowed. This function returns pair of NAME and VALUE.
Headers::value_type parse_header(const char *optarg); Headers::value_type parse_header(const StringRef &optarg);
std::vector<LogFragment> parse_log_format(const char *optarg); std::vector<LogFragment> parse_log_format(const StringRef &optarg);
// Returns string for syslog |facility|. // Returns string for syslog |facility|.
const char *str_syslog_facility(int facility); StringRef str_syslog_facility(int facility);
// Returns integer value of syslog |facility| string. // Returns integer value of syslog |facility| string.
int int_syslog_facility(const char *strfacility); int int_syslog_facility(const StringRef &strfacility);
FILE *open_file_for_write(const char *filename); FILE *open_file_for_write(const char *filename);

View File

@ -53,7 +53,10 @@ using namespace nghttp2;
namespace shrpx { namespace shrpx {
namespace { namespace {
const char *SEVERITY_STR[] = {"INFO", "NOTICE", "WARN", "ERROR", "FATAL"}; const StringRef SEVERITY_STR[] = {
StringRef::from_lit("INFO"), StringRef::from_lit("NOTICE"),
StringRef::from_lit("WARN"), StringRef::from_lit("ERROR"),
StringRef::from_lit("FATAL")};
} // namespace } // namespace
namespace { namespace {
@ -70,9 +73,9 @@ int Log::severity_thres_ = NOTICE;
void Log::set_severity_level(int severity) { severity_thres_ = severity; } void Log::set_severity_level(int severity) { severity_thres_ = severity; }
int Log::set_severity_level_by_name(const char *name) { int Log::set_severity_level_by_name(const StringRef &name) {
for (size_t i = 0, max = array_size(SEVERITY_STR); i < max; ++i) { for (size_t i = 0, max = array_size(SEVERITY_STR); i < max; ++i) {
if (strcmp(SEVERITY_STR[i], name) == 0) { if (name == SEVERITY_STR[i]) {
severity_thres_ = i; severity_thres_ = i;
return 0; return 0;
} }
@ -119,10 +122,10 @@ Log::~Log() {
if (errorconf.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_].c_str(), stream_.str().c_str());
} else { } else {
syslog(severity_to_syslog_level(severity_), "[%s] %s (%s:%d)", syslog(severity_to_syslog_level(severity_), "[%s] %s (%s:%d)",
SEVERITY_STR[severity_], stream_.str().c_str(), filename_, SEVERITY_STR[severity_].c_str(), stream_.str().c_str(), filename_,
linenum_); linenum_);
} }
@ -136,16 +139,18 @@ Log::~Log() {
auto &time_local = lgconf->time_local_str; auto &time_local = lgconf->time_local_str;
if (severity_ == NOTICE) { if (severity_ == NOTICE) {
rv = snprintf(buf, sizeof(buf), "%s PID%d [%s%s%s] %s\n", rv =
time_local.c_str(), get_config()->pid, snprintf(buf, sizeof(buf), "%s PID%d [%s%s%s] %s\n", time_local.c_str(),
tty ? SEVERITY_COLOR[severity_] : "", SEVERITY_STR[severity_], get_config()->pid, tty ? SEVERITY_COLOR[severity_] : "",
tty ? "\033[0m" : "", stream_.str().c_str()); SEVERITY_STR[severity_].c_str(), tty ? "\033[0m" : "",
stream_.str().c_str());
} else { } else {
rv = snprintf(buf, sizeof(buf), "%s PID%d [%s%s%s] %s%s:%d%s %s\n", rv = snprintf(buf, sizeof(buf), "%s PID%d [%s%s%s] %s%s:%d%s %s\n",
time_local.c_str(), get_config()->pid, time_local.c_str(), get_config()->pid,
tty ? SEVERITY_COLOR[severity_] : "", SEVERITY_STR[severity_], tty ? SEVERITY_COLOR[severity_] : "",
tty ? "\033[0m" : "", tty ? "\033[1;30m" : "", filename_, SEVERITY_STR[severity_].c_str(), tty ? "\033[0m" : "",
linenum_, tty ? "\033[0m" : "", stream_.str().c_str()); tty ? "\033[1;30m" : "", filename_, linenum_,
tty ? "\033[0m" : "", stream_.str().c_str());
} }
if (rv < 0) { if (rv < 0) {

View File

@ -97,7 +97,7 @@ public:
return *this; return *this;
} }
static void set_severity_level(int severity); static void set_severity_level(int severity);
static int set_severity_level_by_name(const char *name); static int set_severity_level_by_name(const StringRef &name);
static bool log_enabled(int severity) { return severity >= severity_thres_; } static bool log_enabled(int severity) { return severity >= severity_thres_; }
private: private:

View File

@ -878,34 +878,12 @@ std::vector<StringRef> split_str(const StringRef &s, char delim) {
return list; return list;
} }
std::vector<Range<const char *>> split_config_str_list(const char *s, std::vector<std::string> parse_config_str_list(const StringRef &s, char delim) {
char delim) { auto sublist = split_str(s, delim);
size_t len = 1;
auto last = s + strlen(s);
for (const char *first = s, *d = nullptr;
(d = std::find(first, last, delim)) != last; ++len, first = d + 1)
;
auto list = std::vector<Range<const char *>>(len);
len = 0;
for (auto first = s;; ++len) {
auto stop = std::find(first, last, delim);
list[len] = {first, stop};
if (stop == last) {
break;
}
first = stop + 1;
}
return list;
}
std::vector<std::string> parse_config_str_list(const char *s, char delim) {
auto ranges = split_config_str_list(s, delim);
auto res = std::vector<std::string>(); auto res = std::vector<std::string>();
res.reserve(ranges.size()); res.reserve(sublist.size());
for (const auto &range : ranges) { for (const auto &s : sublist) {
res.emplace_back(range.first, range.second); res.emplace_back(std::begin(s), std::end(s));
} }
return res; return res;
} }
@ -1011,9 +989,16 @@ std::pair<int64_t, size_t> parse_uint_digits(const void *ss, size_t len) {
} // namespace } // namespace
int64_t parse_uint_with_unit(const char *s) { int64_t parse_uint_with_unit(const char *s) {
return parse_uint_with_unit(reinterpret_cast<const uint8_t *>(s), strlen(s));
}
int64_t parse_uint_with_unit(const StringRef &s) {
return parse_uint_with_unit(s.byte(), s.size());
}
int64_t parse_uint_with_unit(const uint8_t *s, size_t len) {
int64_t n; int64_t n;
size_t i; size_t i;
auto len = strlen(s);
std::tie(n, i) = parse_uint_digits(s, len); std::tie(n, i) = parse_uint_digits(s, len);
if (n == -1) { if (n == -1) {
return -1; return -1;
@ -1071,10 +1056,19 @@ int64_t parse_uint(const uint8_t *s, size_t len) {
} }
double parse_duration_with_unit(const char *s) { double parse_duration_with_unit(const char *s) {
return parse_duration_with_unit(reinterpret_cast<const uint8_t *>(s),
strlen(s));
}
double parse_duration_with_unit(const StringRef &s) {
return parse_duration_with_unit(s.byte(), s.size());
}
double parse_duration_with_unit(const uint8_t *s, size_t len) {
constexpr auto max = std::numeric_limits<int64_t>::max(); constexpr auto max = std::numeric_limits<int64_t>::max();
int64_t n; int64_t n;
size_t i; size_t i;
auto len = strlen(s);
std::tie(n, i) = parse_uint_digits(s, len); std::tie(n, i) = parse_uint_digits(s, len);
if (n == -1) { if (n == -1) {
goto fail; goto fail;

View File

@ -584,19 +584,11 @@ bool select_protocol(const unsigned char **out, unsigned char *outlen,
// HTTP/2 protocol identifier. // HTTP/2 protocol identifier.
std::vector<unsigned char> get_default_alpn(); std::vector<unsigned char> get_default_alpn();
template <typename T> using Range = std::pair<T, T>;
// Parses delimited strings in |s| and returns the array of substring, // Parses delimited strings in |s| and returns the array of substring,
// delimited by |delim|. The any white spaces around substring are // delimited by |delim|. The any white spaces around substring are
// treated as a part of substring. // treated as a part of substring.
std::vector<std::string> parse_config_str_list(const char *s, char delim = ','); std::vector<std::string> parse_config_str_list(const StringRef &s,
char delim = ',');
// Parses delimited strings in |s| and returns the array of pointers,
// each element points to the beginning and one beyond last of
// substring in |s|. The delimiter is given by |delim|. The any
// white spaces around substring are treated as a part of substring.
std::vector<Range<const char *>> split_config_str_list(const char *s,
char delim);
// Parses delimited strings in |s| and returns Substrings in |s| // Parses delimited strings in |s| and returns Substrings in |s|
// delimited by |delim|. The any white spaces around substring are // delimited by |delim|. The any white spaces around substring are
@ -653,10 +645,14 @@ bool ipv6_numeric_addr(const char *host);
// 1024 and 1024 * 1024 respectively. If there is an error, returns // 1024 and 1024 * 1024 respectively. If there is an error, returns
// -1. // -1.
int64_t parse_uint_with_unit(const char *s); int64_t parse_uint_with_unit(const char *s);
// The following overload does not require |s| is NULL terminated.
int64_t parse_uint_with_unit(const uint8_t *s, size_t len);
int64_t parse_uint_with_unit(const StringRef &s);
// Parses NULL terminated string |s| as unsigned integer and returns // Parses NULL terminated string |s| as unsigned integer and returns
// the parsed integer. If there is an error, returns -1. // the parsed integer. If there is an error, returns -1.
int64_t parse_uint(const char *s); int64_t parse_uint(const char *s);
// The following overload does not require |s| is NULL terminated.
int64_t parse_uint(const uint8_t *s, size_t len); int64_t parse_uint(const uint8_t *s, size_t len);
int64_t parse_uint(const std::string &s); int64_t parse_uint(const std::string &s);
int64_t parse_uint(const StringRef &s); int64_t parse_uint(const StringRef &s);
@ -669,6 +665,9 @@ int64_t parse_uint(const StringRef &s);
// unit is second. This function returns // unit is second. This function returns
// std::numeric_limits<double>::infinity() if error occurs. // std::numeric_limits<double>::infinity() if error occurs.
double parse_duration_with_unit(const char *s); double parse_duration_with_unit(const char *s);
// The following overload does not require |s| is NULL terminated.
double parse_duration_with_unit(const uint8_t *s, size_t len);
double parse_duration_with_unit(const StringRef &s);
// Returns string representation of time duration |t|. If t has // Returns string representation of time duration |t|. If t has
// fractional part (at least more than or equal to 1e-3), |t| is // fractional part (at least more than or equal to 1e-3), |t| is