12c593315Sopenharmony_ci/*
22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library
32c593315Sopenharmony_ci *
42c593315Sopenharmony_ci * Copyright (c) 2012 Tatsuhiro Tsujikawa
52c593315Sopenharmony_ci *
62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining
72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the
82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to
112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
122c593315Sopenharmony_ci * the following conditions:
132c593315Sopenharmony_ci *
142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be
152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software.
162c593315Sopenharmony_ci *
172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
242c593315Sopenharmony_ci */
252c593315Sopenharmony_ci#include "shrpx_config.h"
262c593315Sopenharmony_ci
272c593315Sopenharmony_ci#ifdef HAVE_PWD_H
282c593315Sopenharmony_ci#  include <pwd.h>
292c593315Sopenharmony_ci#endif // HAVE_PWD_H
302c593315Sopenharmony_ci#ifdef HAVE_NETDB_H
312c593315Sopenharmony_ci#  include <netdb.h>
322c593315Sopenharmony_ci#endif // HAVE_NETDB_H
332c593315Sopenharmony_ci#ifdef HAVE_SYSLOG_H
342c593315Sopenharmony_ci#  include <syslog.h>
352c593315Sopenharmony_ci#endif // HAVE_SYSLOG_H
362c593315Sopenharmony_ci#include <sys/types.h>
372c593315Sopenharmony_ci#include <sys/stat.h>
382c593315Sopenharmony_ci#ifdef HAVE_FCNTL_H
392c593315Sopenharmony_ci#  include <fcntl.h>
402c593315Sopenharmony_ci#endif // HAVE_FCNTL_H
412c593315Sopenharmony_ci#ifdef HAVE_UNISTD_H
422c593315Sopenharmony_ci#  include <unistd.h>
432c593315Sopenharmony_ci#endif // HAVE_UNISTD_H
442c593315Sopenharmony_ci#include <dirent.h>
452c593315Sopenharmony_ci
462c593315Sopenharmony_ci#include <cstring>
472c593315Sopenharmony_ci#include <cerrno>
482c593315Sopenharmony_ci#include <limits>
492c593315Sopenharmony_ci#include <fstream>
502c593315Sopenharmony_ci#include <unordered_map>
512c593315Sopenharmony_ci
522c593315Sopenharmony_ci#include <nghttp2/nghttp2.h>
532c593315Sopenharmony_ci
542c593315Sopenharmony_ci#include "url-parser/url_parser.h"
552c593315Sopenharmony_ci
562c593315Sopenharmony_ci#include "shrpx_log.h"
572c593315Sopenharmony_ci#include "shrpx_tls.h"
582c593315Sopenharmony_ci#include "shrpx_http.h"
592c593315Sopenharmony_ci#ifdef HAVE_MRUBY
602c593315Sopenharmony_ci#  include "shrpx_mruby.h"
612c593315Sopenharmony_ci#endif // HAVE_MRUBY
622c593315Sopenharmony_ci#include "util.h"
632c593315Sopenharmony_ci#include "base64.h"
642c593315Sopenharmony_ci#include "ssl_compat.h"
652c593315Sopenharmony_ci#include "xsi_strerror.h"
662c593315Sopenharmony_ci
672c593315Sopenharmony_cinamespace shrpx {
682c593315Sopenharmony_ci
692c593315Sopenharmony_cinamespace {
702c593315Sopenharmony_ciConfig *config;
712c593315Sopenharmony_ci} // namespace
722c593315Sopenharmony_ci
732c593315Sopenharmony_ciconstexpr auto SHRPX_UNIX_PATH_PREFIX = StringRef::from_lit("unix:");
742c593315Sopenharmony_ci
752c593315Sopenharmony_ciconst Config *get_config() { return config; }
762c593315Sopenharmony_ci
772c593315Sopenharmony_ciConfig *mod_config() { return config; }
782c593315Sopenharmony_ci
792c593315Sopenharmony_cistd::unique_ptr<Config> replace_config(std::unique_ptr<Config> another) {
802c593315Sopenharmony_ci  auto p = config;
812c593315Sopenharmony_ci  config = another.release();
822c593315Sopenharmony_ci  return std::unique_ptr<Config>(p);
832c593315Sopenharmony_ci}
842c593315Sopenharmony_ci
852c593315Sopenharmony_civoid create_config() { config = new Config(); }
862c593315Sopenharmony_ci
872c593315Sopenharmony_ciConfig::~Config() {
882c593315Sopenharmony_ci  auto &upstreamconf = http2.upstream;
892c593315Sopenharmony_ci
902c593315Sopenharmony_ci  nghttp2_option_del(upstreamconf.option);
912c593315Sopenharmony_ci  nghttp2_option_del(upstreamconf.alt_mode_option);
922c593315Sopenharmony_ci  nghttp2_session_callbacks_del(upstreamconf.callbacks);
932c593315Sopenharmony_ci
942c593315Sopenharmony_ci  auto &downstreamconf = http2.downstream;
952c593315Sopenharmony_ci
962c593315Sopenharmony_ci  nghttp2_option_del(downstreamconf.option);
972c593315Sopenharmony_ci  nghttp2_session_callbacks_del(downstreamconf.callbacks);
982c593315Sopenharmony_ci
992c593315Sopenharmony_ci  auto &dumpconf = http2.upstream.debug.dump;
1002c593315Sopenharmony_ci
1012c593315Sopenharmony_ci  if (dumpconf.request_header) {
1022c593315Sopenharmony_ci    fclose(dumpconf.request_header);
1032c593315Sopenharmony_ci  }
1042c593315Sopenharmony_ci
1052c593315Sopenharmony_ci  if (dumpconf.response_header) {
1062c593315Sopenharmony_ci    fclose(dumpconf.response_header);
1072c593315Sopenharmony_ci  }
1082c593315Sopenharmony_ci}
1092c593315Sopenharmony_ci
1102c593315Sopenharmony_ciTicketKeys::~TicketKeys() {
1112c593315Sopenharmony_ci  /* Erase keys from memory */
1122c593315Sopenharmony_ci  for (auto &key : keys) {
1132c593315Sopenharmony_ci    memset(&key, 0, sizeof(key));
1142c593315Sopenharmony_ci  }
1152c593315Sopenharmony_ci}
1162c593315Sopenharmony_ci
1172c593315Sopenharmony_cinamespace {
1182c593315Sopenharmony_ciint split_host_port(char *host, size_t hostlen, uint16_t *port_ptr,
1192c593315Sopenharmony_ci                    const StringRef &hostport, const StringRef &opt) {
1202c593315Sopenharmony_ci  // host and port in |hostport| is separated by single ','.
1212c593315Sopenharmony_ci  auto sep = std::find(std::begin(hostport), std::end(hostport), ',');
1222c593315Sopenharmony_ci  if (sep == std::end(hostport)) {
1232c593315Sopenharmony_ci    LOG(ERROR) << opt << ": Invalid host, port: " << hostport;
1242c593315Sopenharmony_ci    return -1;
1252c593315Sopenharmony_ci  }
1262c593315Sopenharmony_ci  size_t len = sep - std::begin(hostport);
1272c593315Sopenharmony_ci  if (hostlen < len + 1) {
1282c593315Sopenharmony_ci    LOG(ERROR) << opt << ": Hostname too long: " << hostport;
1292c593315Sopenharmony_ci    return -1;
1302c593315Sopenharmony_ci  }
1312c593315Sopenharmony_ci  std::copy(std::begin(hostport), sep, host);
1322c593315Sopenharmony_ci  host[len] = '\0';
1332c593315Sopenharmony_ci
1342c593315Sopenharmony_ci  auto portstr = StringRef{sep + 1, std::end(hostport)};
1352c593315Sopenharmony_ci  auto d = util::parse_uint(portstr);
1362c593315Sopenharmony_ci  if (1 <= d && d <= std::numeric_limits<uint16_t>::max()) {
1372c593315Sopenharmony_ci    *port_ptr = d;
1382c593315Sopenharmony_ci    return 0;
1392c593315Sopenharmony_ci  }
1402c593315Sopenharmony_ci
1412c593315Sopenharmony_ci  LOG(ERROR) << opt << ": Port is invalid: " << portstr;
1422c593315Sopenharmony_ci  return -1;
1432c593315Sopenharmony_ci}
1442c593315Sopenharmony_ci} // namespace
1452c593315Sopenharmony_ci
1462c593315Sopenharmony_cinamespace {
1472c593315Sopenharmony_cibool is_secure(const StringRef &filename) {
1482c593315Sopenharmony_ci  struct stat buf;
1492c593315Sopenharmony_ci  int rv = stat(filename.c_str(), &buf);
1502c593315Sopenharmony_ci  if (rv == 0) {
1512c593315Sopenharmony_ci    if ((buf.st_mode & S_IRWXU) && !(buf.st_mode & S_IRWXG) &&
1522c593315Sopenharmony_ci        !(buf.st_mode & S_IRWXO)) {
1532c593315Sopenharmony_ci      return true;
1542c593315Sopenharmony_ci    }
1552c593315Sopenharmony_ci  }
1562c593315Sopenharmony_ci
1572c593315Sopenharmony_ci  return false;
1582c593315Sopenharmony_ci}
1592c593315Sopenharmony_ci} // namespace
1602c593315Sopenharmony_ci
1612c593315Sopenharmony_cistd::unique_ptr<TicketKeys>
1622c593315Sopenharmony_ciread_tls_ticket_key_file(const std::vector<StringRef> &files,
1632c593315Sopenharmony_ci                         const EVP_CIPHER *cipher, const EVP_MD *hmac) {
1642c593315Sopenharmony_ci  auto ticket_keys = std::make_unique<TicketKeys>();
1652c593315Sopenharmony_ci  auto &keys = ticket_keys->keys;
1662c593315Sopenharmony_ci  keys.resize(files.size());
1672c593315Sopenharmony_ci  auto enc_keylen = EVP_CIPHER_key_length(cipher);
1682c593315Sopenharmony_ci  auto hmac_keylen = EVP_MD_size(hmac);
1692c593315Sopenharmony_ci  if (cipher == EVP_aes_128_cbc()) {
1702c593315Sopenharmony_ci    // backward compatibility, as a legacy of using same file format
1712c593315Sopenharmony_ci    // with nginx and apache.
1722c593315Sopenharmony_ci    hmac_keylen = 16;
1732c593315Sopenharmony_ci  }
1742c593315Sopenharmony_ci  auto expectedlen = keys[0].data.name.size() + enc_keylen + hmac_keylen;
1752c593315Sopenharmony_ci  char buf[256];
1762c593315Sopenharmony_ci  assert(sizeof(buf) >= expectedlen);
1772c593315Sopenharmony_ci
1782c593315Sopenharmony_ci  size_t i = 0;
1792c593315Sopenharmony_ci  for (auto &file : files) {
1802c593315Sopenharmony_ci    struct stat fst {};
1812c593315Sopenharmony_ci
1822c593315Sopenharmony_ci    if (stat(file.c_str(), &fst) == -1) {
1832c593315Sopenharmony_ci      auto error = errno;
1842c593315Sopenharmony_ci      LOG(ERROR) << "tls-ticket-key-file: could not stat file " << file
1852c593315Sopenharmony_ci                 << ", errno=" << error;
1862c593315Sopenharmony_ci      return nullptr;
1872c593315Sopenharmony_ci    }
1882c593315Sopenharmony_ci
1892c593315Sopenharmony_ci    if (static_cast<size_t>(fst.st_size) != expectedlen) {
1902c593315Sopenharmony_ci      LOG(ERROR) << "tls-ticket-key-file: the expected file size is "
1912c593315Sopenharmony_ci                 << expectedlen << ", the actual file size is " << fst.st_size;
1922c593315Sopenharmony_ci      return nullptr;
1932c593315Sopenharmony_ci    }
1942c593315Sopenharmony_ci
1952c593315Sopenharmony_ci    std::ifstream f(file.c_str());
1962c593315Sopenharmony_ci    if (!f) {
1972c593315Sopenharmony_ci      LOG(ERROR) << "tls-ticket-key-file: could not open file " << file;
1982c593315Sopenharmony_ci      return nullptr;
1992c593315Sopenharmony_ci    }
2002c593315Sopenharmony_ci
2012c593315Sopenharmony_ci    f.read(buf, expectedlen);
2022c593315Sopenharmony_ci    if (static_cast<size_t>(f.gcount()) != expectedlen) {
2032c593315Sopenharmony_ci      LOG(ERROR) << "tls-ticket-key-file: want to read " << expectedlen
2042c593315Sopenharmony_ci                 << " bytes but only read " << f.gcount() << " bytes from "
2052c593315Sopenharmony_ci                 << file;
2062c593315Sopenharmony_ci      return nullptr;
2072c593315Sopenharmony_ci    }
2082c593315Sopenharmony_ci
2092c593315Sopenharmony_ci    auto &key = keys[i++];
2102c593315Sopenharmony_ci    key.cipher = cipher;
2112c593315Sopenharmony_ci    key.hmac = hmac;
2122c593315Sopenharmony_ci    key.hmac_keylen = hmac_keylen;
2132c593315Sopenharmony_ci
2142c593315Sopenharmony_ci    if (LOG_ENABLED(INFO)) {
2152c593315Sopenharmony_ci      LOG(INFO) << "enc_keylen=" << enc_keylen
2162c593315Sopenharmony_ci                << ", hmac_keylen=" << key.hmac_keylen;
2172c593315Sopenharmony_ci    }
2182c593315Sopenharmony_ci
2192c593315Sopenharmony_ci    auto p = buf;
2202c593315Sopenharmony_ci    std::copy_n(p, key.data.name.size(), std::begin(key.data.name));
2212c593315Sopenharmony_ci    p += key.data.name.size();
2222c593315Sopenharmony_ci    std::copy_n(p, enc_keylen, std::begin(key.data.enc_key));
2232c593315Sopenharmony_ci    p += enc_keylen;
2242c593315Sopenharmony_ci    std::copy_n(p, hmac_keylen, std::begin(key.data.hmac_key));
2252c593315Sopenharmony_ci
2262c593315Sopenharmony_ci    if (LOG_ENABLED(INFO)) {
2272c593315Sopenharmony_ci      LOG(INFO) << "session ticket key: " << util::format_hex(key.data.name);
2282c593315Sopenharmony_ci    }
2292c593315Sopenharmony_ci  }
2302c593315Sopenharmony_ci  return ticket_keys;
2312c593315Sopenharmony_ci}
2322c593315Sopenharmony_ci
2332c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
2342c593315Sopenharmony_cistd::shared_ptr<QUICKeyingMaterials>
2352c593315Sopenharmony_ciread_quic_secret_file(const StringRef &path) {
2362c593315Sopenharmony_ci  constexpr size_t expectedlen =
2372c593315Sopenharmony_ci      SHRPX_QUIC_SECRET_RESERVEDLEN + SHRPX_QUIC_SECRETLEN + SHRPX_QUIC_SALTLEN;
2382c593315Sopenharmony_ci
2392c593315Sopenharmony_ci  auto qkms = std::make_shared<QUICKeyingMaterials>();
2402c593315Sopenharmony_ci  auto &kms = qkms->keying_materials;
2412c593315Sopenharmony_ci
2422c593315Sopenharmony_ci  std::ifstream f(path.c_str());
2432c593315Sopenharmony_ci  if (!f) {
2442c593315Sopenharmony_ci    LOG(ERROR) << "frontend-quic-secret-file: could not open file " << path;
2452c593315Sopenharmony_ci    return nullptr;
2462c593315Sopenharmony_ci  }
2472c593315Sopenharmony_ci
2482c593315Sopenharmony_ci  std::array<char, 4096> buf;
2492c593315Sopenharmony_ci
2502c593315Sopenharmony_ci  while (f.getline(buf.data(), buf.size())) {
2512c593315Sopenharmony_ci    auto len = strlen(buf.data());
2522c593315Sopenharmony_ci    if (len == 0 || buf[0] == '#') {
2532c593315Sopenharmony_ci      continue;
2542c593315Sopenharmony_ci    }
2552c593315Sopenharmony_ci
2562c593315Sopenharmony_ci    auto s = StringRef{std::begin(buf), std::begin(buf) + len};
2572c593315Sopenharmony_ci    if (s.size() != expectedlen * 2 || !util::is_hex_string(s)) {
2582c593315Sopenharmony_ci      LOG(ERROR) << "frontend-quic-secret-file: each line must be a "
2592c593315Sopenharmony_ci                 << expectedlen * 2 << " bytes hex encoded string";
2602c593315Sopenharmony_ci      return nullptr;
2612c593315Sopenharmony_ci    }
2622c593315Sopenharmony_ci
2632c593315Sopenharmony_ci    kms.emplace_back();
2642c593315Sopenharmony_ci    auto &qkm = kms.back();
2652c593315Sopenharmony_ci
2662c593315Sopenharmony_ci    auto p = std::begin(s);
2672c593315Sopenharmony_ci
2682c593315Sopenharmony_ci    util::decode_hex(std::begin(qkm.reserved),
2692c593315Sopenharmony_ci                     StringRef{p, p + qkm.reserved.size()});
2702c593315Sopenharmony_ci    p += qkm.reserved.size() * 2;
2712c593315Sopenharmony_ci    util::decode_hex(std::begin(qkm.secret),
2722c593315Sopenharmony_ci                     StringRef{p, p + qkm.secret.size()});
2732c593315Sopenharmony_ci    p += qkm.secret.size() * 2;
2742c593315Sopenharmony_ci    util::decode_hex(std::begin(qkm.salt), StringRef{p, p + qkm.salt.size()});
2752c593315Sopenharmony_ci    p += qkm.salt.size() * 2;
2762c593315Sopenharmony_ci
2772c593315Sopenharmony_ci    assert(static_cast<size_t>(p - std::begin(s)) == expectedlen * 2);
2782c593315Sopenharmony_ci
2792c593315Sopenharmony_ci    qkm.id = qkm.reserved[0] & 0xc0;
2802c593315Sopenharmony_ci
2812c593315Sopenharmony_ci    if (kms.size() == 4) {
2822c593315Sopenharmony_ci      break;
2832c593315Sopenharmony_ci    }
2842c593315Sopenharmony_ci  }
2852c593315Sopenharmony_ci
2862c593315Sopenharmony_ci  if (f.bad() || (!f.eof() && f.fail())) {
2872c593315Sopenharmony_ci    LOG(ERROR)
2882c593315Sopenharmony_ci        << "frontend-quic-secret-file: error occurred while reading file "
2892c593315Sopenharmony_ci        << path;
2902c593315Sopenharmony_ci    return nullptr;
2912c593315Sopenharmony_ci  }
2922c593315Sopenharmony_ci
2932c593315Sopenharmony_ci  if (kms.empty()) {
2942c593315Sopenharmony_ci    LOG(WARN)
2952c593315Sopenharmony_ci        << "frontend-quic-secret-file: no keying materials are present in file "
2962c593315Sopenharmony_ci        << path;
2972c593315Sopenharmony_ci    return nullptr;
2982c593315Sopenharmony_ci  }
2992c593315Sopenharmony_ci
3002c593315Sopenharmony_ci  return qkms;
3012c593315Sopenharmony_ci}
3022c593315Sopenharmony_ci#endif // ENABLE_HTTP3
3032c593315Sopenharmony_ci
3042c593315Sopenharmony_ciFILE *open_file_for_write(const char *filename) {
3052c593315Sopenharmony_ci  std::array<char, STRERROR_BUFSIZE> errbuf;
3062c593315Sopenharmony_ci
3072c593315Sopenharmony_ci#ifdef O_CLOEXEC
3082c593315Sopenharmony_ci  auto fd = open(filename, O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC,
3092c593315Sopenharmony_ci                 S_IRUSR | S_IWUSR);
3102c593315Sopenharmony_ci#else
3112c593315Sopenharmony_ci  auto fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
3122c593315Sopenharmony_ci
3132c593315Sopenharmony_ci  // We get race condition if execve is called at the same time.
3142c593315Sopenharmony_ci  if (fd != -1) {
3152c593315Sopenharmony_ci    util::make_socket_closeonexec(fd);
3162c593315Sopenharmony_ci  }
3172c593315Sopenharmony_ci#endif
3182c593315Sopenharmony_ci  if (fd == -1) {
3192c593315Sopenharmony_ci    auto error = errno;
3202c593315Sopenharmony_ci    LOG(ERROR) << "Failed to open " << filename << " for writing. Cause: "
3212c593315Sopenharmony_ci               << xsi_strerror(error, errbuf.data(), errbuf.size());
3222c593315Sopenharmony_ci    return nullptr;
3232c593315Sopenharmony_ci  }
3242c593315Sopenharmony_ci  auto f = fdopen(fd, "wb");
3252c593315Sopenharmony_ci  if (f == nullptr) {
3262c593315Sopenharmony_ci    auto error = errno;
3272c593315Sopenharmony_ci    LOG(ERROR) << "Failed to open " << filename << " for writing. Cause: "
3282c593315Sopenharmony_ci               << xsi_strerror(error, errbuf.data(), errbuf.size());
3292c593315Sopenharmony_ci    return nullptr;
3302c593315Sopenharmony_ci  }
3312c593315Sopenharmony_ci
3322c593315Sopenharmony_ci  return f;
3332c593315Sopenharmony_ci}
3342c593315Sopenharmony_ci
3352c593315Sopenharmony_cinamespace {
3362c593315Sopenharmony_ci// Read passwd from |filename|
3372c593315Sopenharmony_cistd::string read_passwd_from_file(const StringRef &opt,
3382c593315Sopenharmony_ci                                  const StringRef &filename) {
3392c593315Sopenharmony_ci  std::string line;
3402c593315Sopenharmony_ci
3412c593315Sopenharmony_ci  if (!is_secure(filename)) {
3422c593315Sopenharmony_ci    LOG(ERROR) << opt << ": Private key passwd file " << filename
3432c593315Sopenharmony_ci               << " has insecure mode.";
3442c593315Sopenharmony_ci    return line;
3452c593315Sopenharmony_ci  }
3462c593315Sopenharmony_ci
3472c593315Sopenharmony_ci  std::ifstream in(filename.c_str(), std::ios::binary);
3482c593315Sopenharmony_ci  if (!in) {
3492c593315Sopenharmony_ci    LOG(ERROR) << opt << ": Could not open key passwd file " << filename;
3502c593315Sopenharmony_ci    return line;
3512c593315Sopenharmony_ci  }
3522c593315Sopenharmony_ci
3532c593315Sopenharmony_ci  std::getline(in, line);
3542c593315Sopenharmony_ci  return line;
3552c593315Sopenharmony_ci}
3562c593315Sopenharmony_ci} // namespace
3572c593315Sopenharmony_ci
3582c593315Sopenharmony_ciHeaderRefs::value_type parse_header(BlockAllocator &balloc,
3592c593315Sopenharmony_ci                                    const StringRef &optarg) {
3602c593315Sopenharmony_ci  auto colon = std::find(std::begin(optarg), std::end(optarg), ':');
3612c593315Sopenharmony_ci
3622c593315Sopenharmony_ci  if (colon == std::end(optarg) || colon == std::begin(optarg)) {
3632c593315Sopenharmony_ci    return {};
3642c593315Sopenharmony_ci  }
3652c593315Sopenharmony_ci
3662c593315Sopenharmony_ci  auto value = colon + 1;
3672c593315Sopenharmony_ci  for (; *value == '\t' || *value == ' '; ++value)
3682c593315Sopenharmony_ci    ;
3692c593315Sopenharmony_ci
3702c593315Sopenharmony_ci  auto name_iov =
3712c593315Sopenharmony_ci      make_byte_ref(balloc, std::distance(std::begin(optarg), colon) + 1);
3722c593315Sopenharmony_ci  auto p = name_iov.base;
3732c593315Sopenharmony_ci  p = std::copy(std::begin(optarg), colon, p);
3742c593315Sopenharmony_ci  util::inp_strlower(name_iov.base, p);
3752c593315Sopenharmony_ci  *p = '\0';
3762c593315Sopenharmony_ci
3772c593315Sopenharmony_ci  auto nv =
3782c593315Sopenharmony_ci      HeaderRef(StringRef{name_iov.base, p},
3792c593315Sopenharmony_ci                make_string_ref(balloc, StringRef{value, std::end(optarg)}));
3802c593315Sopenharmony_ci
3812c593315Sopenharmony_ci  if (!nghttp2_check_header_name(nv.name.byte(), nv.name.size()) ||
3822c593315Sopenharmony_ci      !nghttp2_check_header_value_rfc9113(nv.value.byte(), nv.value.size())) {
3832c593315Sopenharmony_ci    return {};
3842c593315Sopenharmony_ci  }
3852c593315Sopenharmony_ci
3862c593315Sopenharmony_ci  return nv;
3872c593315Sopenharmony_ci}
3882c593315Sopenharmony_ci
3892c593315Sopenharmony_citemplate <typename T>
3902c593315Sopenharmony_ciint parse_uint(T *dest, const StringRef &opt, const StringRef &optarg) {
3912c593315Sopenharmony_ci  auto val = util::parse_uint(optarg);
3922c593315Sopenharmony_ci  if (val == -1) {
3932c593315Sopenharmony_ci    LOG(ERROR) << opt << ": bad value.  Specify an integer >= 0.";
3942c593315Sopenharmony_ci    return -1;
3952c593315Sopenharmony_ci  }
3962c593315Sopenharmony_ci
3972c593315Sopenharmony_ci  *dest = val;
3982c593315Sopenharmony_ci
3992c593315Sopenharmony_ci  return 0;
4002c593315Sopenharmony_ci}
4012c593315Sopenharmony_ci
4022c593315Sopenharmony_cinamespace {
4032c593315Sopenharmony_citemplate <typename T>
4042c593315Sopenharmony_ciint parse_uint_with_unit(T *dest, const StringRef &opt,
4052c593315Sopenharmony_ci                         const StringRef &optarg) {
4062c593315Sopenharmony_ci  auto n = util::parse_uint_with_unit(optarg);
4072c593315Sopenharmony_ci  if (n == -1) {
4082c593315Sopenharmony_ci    LOG(ERROR) << opt << ": bad value: '" << optarg << "'";
4092c593315Sopenharmony_ci    return -1;
4102c593315Sopenharmony_ci  }
4112c593315Sopenharmony_ci
4122c593315Sopenharmony_ci  if (static_cast<uint64_t>(std::numeric_limits<T>::max()) <
4132c593315Sopenharmony_ci      static_cast<uint64_t>(n)) {
4142c593315Sopenharmony_ci    LOG(ERROR) << opt
4152c593315Sopenharmony_ci               << ": too large.  The value should be less than or equal to "
4162c593315Sopenharmony_ci               << std::numeric_limits<T>::max();
4172c593315Sopenharmony_ci    return -1;
4182c593315Sopenharmony_ci  }
4192c593315Sopenharmony_ci
4202c593315Sopenharmony_ci  *dest = n;
4212c593315Sopenharmony_ci
4222c593315Sopenharmony_ci  return 0;
4232c593315Sopenharmony_ci}
4242c593315Sopenharmony_ci} // namespace
4252c593315Sopenharmony_ci
4262c593315Sopenharmony_cinamespace {
4272c593315Sopenharmony_ciint parse_altsvc(AltSvc &altsvc, const StringRef &opt,
4282c593315Sopenharmony_ci                 const StringRef &optarg) {
4292c593315Sopenharmony_ci  // PROTOID, PORT, HOST, ORIGIN, PARAMS.
4302c593315Sopenharmony_ci  auto tokens = util::split_str(optarg, ',', 5);
4312c593315Sopenharmony_ci
4322c593315Sopenharmony_ci  if (tokens.size() < 2) {
4332c593315Sopenharmony_ci    // Requires at least protocol_id and port
4342c593315Sopenharmony_ci    LOG(ERROR) << opt << ": too few parameters: " << optarg;
4352c593315Sopenharmony_ci    return -1;
4362c593315Sopenharmony_ci  }
4372c593315Sopenharmony_ci
4382c593315Sopenharmony_ci  int port;
4392c593315Sopenharmony_ci
4402c593315Sopenharmony_ci  if (parse_uint(&port, opt, tokens[1]) != 0) {
4412c593315Sopenharmony_ci    return -1;
4422c593315Sopenharmony_ci  }
4432c593315Sopenharmony_ci
4442c593315Sopenharmony_ci  if (port < 1 ||
4452c593315Sopenharmony_ci      port > static_cast<int>(std::numeric_limits<uint16_t>::max())) {
4462c593315Sopenharmony_ci    LOG(ERROR) << opt << ": port is invalid: " << tokens[1];
4472c593315Sopenharmony_ci    return -1;
4482c593315Sopenharmony_ci  }
4492c593315Sopenharmony_ci
4502c593315Sopenharmony_ci  altsvc.protocol_id = make_string_ref(config->balloc, tokens[0]);
4512c593315Sopenharmony_ci
4522c593315Sopenharmony_ci  altsvc.port = port;
4532c593315Sopenharmony_ci  altsvc.service = make_string_ref(config->balloc, tokens[1]);
4542c593315Sopenharmony_ci
4552c593315Sopenharmony_ci  if (tokens.size() > 2) {
4562c593315Sopenharmony_ci    if (!tokens[2].empty()) {
4572c593315Sopenharmony_ci      altsvc.host = make_string_ref(config->balloc, tokens[2]);
4582c593315Sopenharmony_ci    }
4592c593315Sopenharmony_ci
4602c593315Sopenharmony_ci    if (tokens.size() > 3) {
4612c593315Sopenharmony_ci      if (!tokens[3].empty()) {
4622c593315Sopenharmony_ci        altsvc.origin = make_string_ref(config->balloc, tokens[3]);
4632c593315Sopenharmony_ci      }
4642c593315Sopenharmony_ci
4652c593315Sopenharmony_ci      if (tokens.size() > 4) {
4662c593315Sopenharmony_ci        if (!tokens[4].empty()) {
4672c593315Sopenharmony_ci          altsvc.params = make_string_ref(config->balloc, tokens[4]);
4682c593315Sopenharmony_ci        }
4692c593315Sopenharmony_ci      }
4702c593315Sopenharmony_ci    }
4712c593315Sopenharmony_ci  }
4722c593315Sopenharmony_ci
4732c593315Sopenharmony_ci  return 0;
4742c593315Sopenharmony_ci}
4752c593315Sopenharmony_ci} // namespace
4762c593315Sopenharmony_ci
4772c593315Sopenharmony_cinamespace {
4782c593315Sopenharmony_ci// generated by gennghttpxfun.py
4792c593315Sopenharmony_ciLogFragmentType log_var_lookup_token(const char *name, size_t namelen) {
4802c593315Sopenharmony_ci  switch (namelen) {
4812c593315Sopenharmony_ci  case 3:
4822c593315Sopenharmony_ci    switch (name[2]) {
4832c593315Sopenharmony_ci    case 'd':
4842c593315Sopenharmony_ci      if (util::strieq_l("pi", name, 2)) {
4852c593315Sopenharmony_ci        return LogFragmentType::PID;
4862c593315Sopenharmony_ci      }
4872c593315Sopenharmony_ci      break;
4882c593315Sopenharmony_ci    }
4892c593315Sopenharmony_ci    break;
4902c593315Sopenharmony_ci  case 4:
4912c593315Sopenharmony_ci    switch (name[3]) {
4922c593315Sopenharmony_ci    case 'h':
4932c593315Sopenharmony_ci      if (util::strieq_l("pat", name, 3)) {
4942c593315Sopenharmony_ci        return LogFragmentType::PATH;
4952c593315Sopenharmony_ci      }
4962c593315Sopenharmony_ci      break;
4972c593315Sopenharmony_ci    case 'n':
4982c593315Sopenharmony_ci      if (util::strieq_l("alp", name, 3)) {
4992c593315Sopenharmony_ci        return LogFragmentType::ALPN;
5002c593315Sopenharmony_ci      }
5012c593315Sopenharmony_ci      break;
5022c593315Sopenharmony_ci    }
5032c593315Sopenharmony_ci    break;
5042c593315Sopenharmony_ci  case 6:
5052c593315Sopenharmony_ci    switch (name[5]) {
5062c593315Sopenharmony_ci    case 'd':
5072c593315Sopenharmony_ci      if (util::strieq_l("metho", name, 5)) {
5082c593315Sopenharmony_ci        return LogFragmentType::METHOD;
5092c593315Sopenharmony_ci      }
5102c593315Sopenharmony_ci      break;
5112c593315Sopenharmony_ci    case 's':
5122c593315Sopenharmony_ci      if (util::strieq_l("statu", name, 5)) {
5132c593315Sopenharmony_ci        return LogFragmentType::STATUS;
5142c593315Sopenharmony_ci      }
5152c593315Sopenharmony_ci      break;
5162c593315Sopenharmony_ci    }
5172c593315Sopenharmony_ci    break;
5182c593315Sopenharmony_ci  case 7:
5192c593315Sopenharmony_ci    switch (name[6]) {
5202c593315Sopenharmony_ci    case 'i':
5212c593315Sopenharmony_ci      if (util::strieq_l("tls_sn", name, 6)) {
5222c593315Sopenharmony_ci        return LogFragmentType::TLS_SNI;
5232c593315Sopenharmony_ci      }
5242c593315Sopenharmony_ci      break;
5252c593315Sopenharmony_ci    case 't':
5262c593315Sopenharmony_ci      if (util::strieq_l("reques", name, 6)) {
5272c593315Sopenharmony_ci        return LogFragmentType::REQUEST;
5282c593315Sopenharmony_ci      }
5292c593315Sopenharmony_ci      break;
5302c593315Sopenharmony_ci    }
5312c593315Sopenharmony_ci    break;
5322c593315Sopenharmony_ci  case 10:
5332c593315Sopenharmony_ci    switch (name[9]) {
5342c593315Sopenharmony_ci    case 'l':
5352c593315Sopenharmony_ci      if (util::strieq_l("time_loca", name, 9)) {
5362c593315Sopenharmony_ci        return LogFragmentType::TIME_LOCAL;
5372c593315Sopenharmony_ci      }
5382c593315Sopenharmony_ci      break;
5392c593315Sopenharmony_ci    case 'r':
5402c593315Sopenharmony_ci      if (util::strieq_l("ssl_ciphe", name, 9)) {
5412c593315Sopenharmony_ci        return LogFragmentType::SSL_CIPHER;
5422c593315Sopenharmony_ci      }
5432c593315Sopenharmony_ci      if (util::strieq_l("tls_ciphe", name, 9)) {
5442c593315Sopenharmony_ci        return LogFragmentType::TLS_CIPHER;
5452c593315Sopenharmony_ci      }
5462c593315Sopenharmony_ci      break;
5472c593315Sopenharmony_ci    }
5482c593315Sopenharmony_ci    break;
5492c593315Sopenharmony_ci  case 11:
5502c593315Sopenharmony_ci    switch (name[10]) {
5512c593315Sopenharmony_ci    case 'r':
5522c593315Sopenharmony_ci      if (util::strieq_l("remote_add", name, 10)) {
5532c593315Sopenharmony_ci        return LogFragmentType::REMOTE_ADDR;
5542c593315Sopenharmony_ci      }
5552c593315Sopenharmony_ci      break;
5562c593315Sopenharmony_ci    case 't':
5572c593315Sopenharmony_ci      if (util::strieq_l("remote_por", name, 10)) {
5582c593315Sopenharmony_ci        return LogFragmentType::REMOTE_PORT;
5592c593315Sopenharmony_ci      }
5602c593315Sopenharmony_ci      if (util::strieq_l("server_por", name, 10)) {
5612c593315Sopenharmony_ci        return LogFragmentType::SERVER_PORT;
5622c593315Sopenharmony_ci      }
5632c593315Sopenharmony_ci      break;
5642c593315Sopenharmony_ci    }
5652c593315Sopenharmony_ci    break;
5662c593315Sopenharmony_ci  case 12:
5672c593315Sopenharmony_ci    switch (name[11]) {
5682c593315Sopenharmony_ci    case '1':
5692c593315Sopenharmony_ci      if (util::strieq_l("time_iso860", name, 11)) {
5702c593315Sopenharmony_ci        return LogFragmentType::TIME_ISO8601;
5712c593315Sopenharmony_ci      }
5722c593315Sopenharmony_ci      break;
5732c593315Sopenharmony_ci    case 'e':
5742c593315Sopenharmony_ci      if (util::strieq_l("request_tim", name, 11)) {
5752c593315Sopenharmony_ci        return LogFragmentType::REQUEST_TIME;
5762c593315Sopenharmony_ci      }
5772c593315Sopenharmony_ci      break;
5782c593315Sopenharmony_ci    case 'l':
5792c593315Sopenharmony_ci      if (util::strieq_l("ssl_protoco", name, 11)) {
5802c593315Sopenharmony_ci        return LogFragmentType::SSL_PROTOCOL;
5812c593315Sopenharmony_ci      }
5822c593315Sopenharmony_ci      if (util::strieq_l("tls_protoco", name, 11)) {
5832c593315Sopenharmony_ci        return LogFragmentType::TLS_PROTOCOL;
5842c593315Sopenharmony_ci      }
5852c593315Sopenharmony_ci      break;
5862c593315Sopenharmony_ci    case 't':
5872c593315Sopenharmony_ci      if (util::strieq_l("backend_hos", name, 11)) {
5882c593315Sopenharmony_ci        return LogFragmentType::BACKEND_HOST;
5892c593315Sopenharmony_ci      }
5902c593315Sopenharmony_ci      if (util::strieq_l("backend_por", name, 11)) {
5912c593315Sopenharmony_ci        return LogFragmentType::BACKEND_PORT;
5922c593315Sopenharmony_ci      }
5932c593315Sopenharmony_ci      break;
5942c593315Sopenharmony_ci    }
5952c593315Sopenharmony_ci    break;
5962c593315Sopenharmony_ci  case 14:
5972c593315Sopenharmony_ci    switch (name[13]) {
5982c593315Sopenharmony_ci    case 'd':
5992c593315Sopenharmony_ci      if (util::strieq_l("ssl_session_i", name, 13)) {
6002c593315Sopenharmony_ci        return LogFragmentType::SSL_SESSION_ID;
6012c593315Sopenharmony_ci      }
6022c593315Sopenharmony_ci      if (util::strieq_l("tls_session_i", name, 13)) {
6032c593315Sopenharmony_ci        return LogFragmentType::TLS_SESSION_ID;
6042c593315Sopenharmony_ci      }
6052c593315Sopenharmony_ci      break;
6062c593315Sopenharmony_ci    }
6072c593315Sopenharmony_ci    break;
6082c593315Sopenharmony_ci  case 15:
6092c593315Sopenharmony_ci    switch (name[14]) {
6102c593315Sopenharmony_ci    case 't':
6112c593315Sopenharmony_ci      if (util::strieq_l("body_bytes_sen", name, 14)) {
6122c593315Sopenharmony_ci        return LogFragmentType::BODY_BYTES_SENT;
6132c593315Sopenharmony_ci      }
6142c593315Sopenharmony_ci      break;
6152c593315Sopenharmony_ci    }
6162c593315Sopenharmony_ci    break;
6172c593315Sopenharmony_ci  case 16:
6182c593315Sopenharmony_ci    switch (name[15]) {
6192c593315Sopenharmony_ci    case 'n':
6202c593315Sopenharmony_ci      if (util::strieq_l("protocol_versio", name, 15)) {
6212c593315Sopenharmony_ci        return LogFragmentType::PROTOCOL_VERSION;
6222c593315Sopenharmony_ci      }
6232c593315Sopenharmony_ci      break;
6242c593315Sopenharmony_ci    }
6252c593315Sopenharmony_ci    break;
6262c593315Sopenharmony_ci  case 17:
6272c593315Sopenharmony_ci    switch (name[16]) {
6282c593315Sopenharmony_ci    case 'l':
6292c593315Sopenharmony_ci      if (util::strieq_l("tls_client_seria", name, 16)) {
6302c593315Sopenharmony_ci        return LogFragmentType::TLS_CLIENT_SERIAL;
6312c593315Sopenharmony_ci      }
6322c593315Sopenharmony_ci      break;
6332c593315Sopenharmony_ci    }
6342c593315Sopenharmony_ci    break;
6352c593315Sopenharmony_ci  case 18:
6362c593315Sopenharmony_ci    switch (name[17]) {
6372c593315Sopenharmony_ci    case 'd':
6382c593315Sopenharmony_ci      if (util::strieq_l("ssl_session_reuse", name, 17)) {
6392c593315Sopenharmony_ci        return LogFragmentType::SSL_SESSION_REUSED;
6402c593315Sopenharmony_ci      }
6412c593315Sopenharmony_ci      if (util::strieq_l("tls_session_reuse", name, 17)) {
6422c593315Sopenharmony_ci        return LogFragmentType::TLS_SESSION_REUSED;
6432c593315Sopenharmony_ci      }
6442c593315Sopenharmony_ci      break;
6452c593315Sopenharmony_ci    case 'y':
6462c593315Sopenharmony_ci      if (util::strieq_l("path_without_quer", name, 17)) {
6472c593315Sopenharmony_ci        return LogFragmentType::PATH_WITHOUT_QUERY;
6482c593315Sopenharmony_ci      }
6492c593315Sopenharmony_ci      break;
6502c593315Sopenharmony_ci    }
6512c593315Sopenharmony_ci    break;
6522c593315Sopenharmony_ci  case 22:
6532c593315Sopenharmony_ci    switch (name[21]) {
6542c593315Sopenharmony_ci    case 'e':
6552c593315Sopenharmony_ci      if (util::strieq_l("tls_client_issuer_nam", name, 21)) {
6562c593315Sopenharmony_ci        return LogFragmentType::TLS_CLIENT_ISSUER_NAME;
6572c593315Sopenharmony_ci      }
6582c593315Sopenharmony_ci      break;
6592c593315Sopenharmony_ci    }
6602c593315Sopenharmony_ci    break;
6612c593315Sopenharmony_ci  case 23:
6622c593315Sopenharmony_ci    switch (name[22]) {
6632c593315Sopenharmony_ci    case 'e':
6642c593315Sopenharmony_ci      if (util::strieq_l("tls_client_subject_nam", name, 22)) {
6652c593315Sopenharmony_ci        return LogFragmentType::TLS_CLIENT_SUBJECT_NAME;
6662c593315Sopenharmony_ci      }
6672c593315Sopenharmony_ci      break;
6682c593315Sopenharmony_ci    }
6692c593315Sopenharmony_ci    break;
6702c593315Sopenharmony_ci  case 27:
6712c593315Sopenharmony_ci    switch (name[26]) {
6722c593315Sopenharmony_ci    case '1':
6732c593315Sopenharmony_ci      if (util::strieq_l("tls_client_fingerprint_sha", name, 26)) {
6742c593315Sopenharmony_ci        return LogFragmentType::TLS_CLIENT_FINGERPRINT_SHA1;
6752c593315Sopenharmony_ci      }
6762c593315Sopenharmony_ci      break;
6772c593315Sopenharmony_ci    }
6782c593315Sopenharmony_ci    break;
6792c593315Sopenharmony_ci  case 29:
6802c593315Sopenharmony_ci    switch (name[28]) {
6812c593315Sopenharmony_ci    case '6':
6822c593315Sopenharmony_ci      if (util::strieq_l("tls_client_fingerprint_sha25", name, 28)) {
6832c593315Sopenharmony_ci        return LogFragmentType::TLS_CLIENT_FINGERPRINT_SHA256;
6842c593315Sopenharmony_ci      }
6852c593315Sopenharmony_ci      break;
6862c593315Sopenharmony_ci    }
6872c593315Sopenharmony_ci    break;
6882c593315Sopenharmony_ci  }
6892c593315Sopenharmony_ci  return LogFragmentType::NONE;
6902c593315Sopenharmony_ci}
6912c593315Sopenharmony_ci} // namespace
6922c593315Sopenharmony_ci
6932c593315Sopenharmony_cinamespace {
6942c593315Sopenharmony_cibool var_token(char c) {
6952c593315Sopenharmony_ci  return util::is_alpha(c) || util::is_digit(c) || c == '_';
6962c593315Sopenharmony_ci}
6972c593315Sopenharmony_ci} // namespace
6982c593315Sopenharmony_ci
6992c593315Sopenharmony_cistd::vector<LogFragment> parse_log_format(BlockAllocator &balloc,
7002c593315Sopenharmony_ci                                          const StringRef &optarg) {
7012c593315Sopenharmony_ci  auto literal_start = std::begin(optarg);
7022c593315Sopenharmony_ci  auto p = literal_start;
7032c593315Sopenharmony_ci  auto eop = std::end(optarg);
7042c593315Sopenharmony_ci
7052c593315Sopenharmony_ci  auto res = std::vector<LogFragment>();
7062c593315Sopenharmony_ci
7072c593315Sopenharmony_ci  for (; p != eop;) {
7082c593315Sopenharmony_ci    if (*p != '$') {
7092c593315Sopenharmony_ci      ++p;
7102c593315Sopenharmony_ci      continue;
7112c593315Sopenharmony_ci    }
7122c593315Sopenharmony_ci
7132c593315Sopenharmony_ci    auto var_start = p;
7142c593315Sopenharmony_ci
7152c593315Sopenharmony_ci    ++p;
7162c593315Sopenharmony_ci
7172c593315Sopenharmony_ci    const char *var_name;
7182c593315Sopenharmony_ci    size_t var_namelen;
7192c593315Sopenharmony_ci    if (p != eop && *p == '{') {
7202c593315Sopenharmony_ci      var_name = ++p;
7212c593315Sopenharmony_ci      for (; p != eop && var_token(*p); ++p)
7222c593315Sopenharmony_ci        ;
7232c593315Sopenharmony_ci
7242c593315Sopenharmony_ci      if (p == eop || *p != '}') {
7252c593315Sopenharmony_ci        LOG(WARN) << "Missing '}' after " << StringRef{var_start, p};
7262c593315Sopenharmony_ci        continue;
7272c593315Sopenharmony_ci      }
7282c593315Sopenharmony_ci
7292c593315Sopenharmony_ci      var_namelen = p - var_name;
7302c593315Sopenharmony_ci      ++p;
7312c593315Sopenharmony_ci    } else {
7322c593315Sopenharmony_ci      var_name = p;
7332c593315Sopenharmony_ci      for (; p != eop && var_token(*p); ++p)
7342c593315Sopenharmony_ci        ;
7352c593315Sopenharmony_ci
7362c593315Sopenharmony_ci      var_namelen = p - var_name;
7372c593315Sopenharmony_ci    }
7382c593315Sopenharmony_ci
7392c593315Sopenharmony_ci    const char *value = nullptr;
7402c593315Sopenharmony_ci
7412c593315Sopenharmony_ci    auto type = log_var_lookup_token(var_name, var_namelen);
7422c593315Sopenharmony_ci
7432c593315Sopenharmony_ci    if (type == LogFragmentType::NONE) {
7442c593315Sopenharmony_ci      if (util::istarts_with_l(StringRef{var_name, var_namelen}, "http_")) {
7452c593315Sopenharmony_ci        if (util::streq_l("host", StringRef{var_name + str_size("http_"),
7462c593315Sopenharmony_ci                                            var_namelen - str_size("http_")})) {
7472c593315Sopenharmony_ci          // Special handling of host header field.  We will use
7482c593315Sopenharmony_ci          // :authority header field if host header is missing.  This
7492c593315Sopenharmony_ci          // is a typical case in HTTP/2.
7502c593315Sopenharmony_ci          type = LogFragmentType::AUTHORITY;
7512c593315Sopenharmony_ci        } else {
7522c593315Sopenharmony_ci          type = LogFragmentType::HTTP;
7532c593315Sopenharmony_ci          value = var_name + str_size("http_");
7542c593315Sopenharmony_ci        }
7552c593315Sopenharmony_ci      } else {
7562c593315Sopenharmony_ci        LOG(WARN) << "Unrecognized log format variable: "
7572c593315Sopenharmony_ci                  << StringRef{var_name, var_namelen};
7582c593315Sopenharmony_ci        continue;
7592c593315Sopenharmony_ci      }
7602c593315Sopenharmony_ci    }
7612c593315Sopenharmony_ci
7622c593315Sopenharmony_ci    if (literal_start < var_start) {
7632c593315Sopenharmony_ci      res.emplace_back(
7642c593315Sopenharmony_ci          LogFragmentType::LITERAL,
7652c593315Sopenharmony_ci          make_string_ref(balloc, StringRef{literal_start, var_start}));
7662c593315Sopenharmony_ci    }
7672c593315Sopenharmony_ci
7682c593315Sopenharmony_ci    literal_start = p;
7692c593315Sopenharmony_ci
7702c593315Sopenharmony_ci    if (value == nullptr) {
7712c593315Sopenharmony_ci      res.emplace_back(type);
7722c593315Sopenharmony_ci      continue;
7732c593315Sopenharmony_ci    }
7742c593315Sopenharmony_ci
7752c593315Sopenharmony_ci    {
7762c593315Sopenharmony_ci      auto iov = make_byte_ref(
7772c593315Sopenharmony_ci          balloc, std::distance(value, var_name + var_namelen) + 1);
7782c593315Sopenharmony_ci      auto p = iov.base;
7792c593315Sopenharmony_ci      p = std::copy(value, var_name + var_namelen, p);
7802c593315Sopenharmony_ci      for (auto cp = iov.base; cp != p; ++cp) {
7812c593315Sopenharmony_ci        if (*cp == '_') {
7822c593315Sopenharmony_ci          *cp = '-';
7832c593315Sopenharmony_ci        }
7842c593315Sopenharmony_ci      }
7852c593315Sopenharmony_ci      *p = '\0';
7862c593315Sopenharmony_ci      res.emplace_back(type, StringRef{iov.base, p});
7872c593315Sopenharmony_ci    }
7882c593315Sopenharmony_ci  }
7892c593315Sopenharmony_ci
7902c593315Sopenharmony_ci  if (literal_start != eop) {
7912c593315Sopenharmony_ci    res.emplace_back(LogFragmentType::LITERAL,
7922c593315Sopenharmony_ci                     make_string_ref(balloc, StringRef{literal_start, eop}));
7932c593315Sopenharmony_ci  }
7942c593315Sopenharmony_ci
7952c593315Sopenharmony_ci  return res;
7962c593315Sopenharmony_ci}
7972c593315Sopenharmony_ci
7982c593315Sopenharmony_cinamespace {
7992c593315Sopenharmony_ciint parse_address_family(int *dest, const StringRef &opt,
8002c593315Sopenharmony_ci                         const StringRef &optarg) {
8012c593315Sopenharmony_ci  if (util::strieq_l("auto", optarg)) {
8022c593315Sopenharmony_ci    *dest = AF_UNSPEC;
8032c593315Sopenharmony_ci    return 0;
8042c593315Sopenharmony_ci  }
8052c593315Sopenharmony_ci  if (util::strieq_l("IPv4", optarg)) {
8062c593315Sopenharmony_ci    *dest = AF_INET;
8072c593315Sopenharmony_ci    return 0;
8082c593315Sopenharmony_ci  }
8092c593315Sopenharmony_ci  if (util::strieq_l("IPv6", optarg)) {
8102c593315Sopenharmony_ci    *dest = AF_INET6;
8112c593315Sopenharmony_ci    return 0;
8122c593315Sopenharmony_ci  }
8132c593315Sopenharmony_ci
8142c593315Sopenharmony_ci  LOG(ERROR) << opt << ": bad value: '" << optarg << "'";
8152c593315Sopenharmony_ci  return -1;
8162c593315Sopenharmony_ci}
8172c593315Sopenharmony_ci} // namespace
8182c593315Sopenharmony_ci
8192c593315Sopenharmony_cinamespace {
8202c593315Sopenharmony_ciint parse_duration(ev_tstamp *dest, const StringRef &opt,
8212c593315Sopenharmony_ci                   const StringRef &optarg) {
8222c593315Sopenharmony_ci  auto t = util::parse_duration_with_unit(optarg);
8232c593315Sopenharmony_ci  if (t == std::numeric_limits<double>::infinity()) {
8242c593315Sopenharmony_ci    LOG(ERROR) << opt << ": bad value: '" << optarg << "'";
8252c593315Sopenharmony_ci    return -1;
8262c593315Sopenharmony_ci  }
8272c593315Sopenharmony_ci
8282c593315Sopenharmony_ci  *dest = t;
8292c593315Sopenharmony_ci
8302c593315Sopenharmony_ci  return 0;
8312c593315Sopenharmony_ci}
8322c593315Sopenharmony_ci} // namespace
8332c593315Sopenharmony_ci
8342c593315Sopenharmony_cinamespace {
8352c593315Sopenharmony_ciint parse_tls_proto_version(int &dest, const StringRef &opt,
8362c593315Sopenharmony_ci                            const StringRef &optarg) {
8372c593315Sopenharmony_ci  auto v = tls::proto_version_from_string(optarg);
8382c593315Sopenharmony_ci  if (v == -1) {
8392c593315Sopenharmony_ci    LOG(ERROR) << opt << ": invalid TLS protocol version: " << optarg;
8402c593315Sopenharmony_ci    return -1;
8412c593315Sopenharmony_ci  }
8422c593315Sopenharmony_ci
8432c593315Sopenharmony_ci  dest = v;
8442c593315Sopenharmony_ci
8452c593315Sopenharmony_ci  return 0;
8462c593315Sopenharmony_ci}
8472c593315Sopenharmony_ci} // namespace
8482c593315Sopenharmony_ci
8492c593315Sopenharmony_cistruct MemcachedConnectionParams {
8502c593315Sopenharmony_ci  bool tls;
8512c593315Sopenharmony_ci};
8522c593315Sopenharmony_ci
8532c593315Sopenharmony_cinamespace {
8542c593315Sopenharmony_ci// Parses memcached connection configuration parameter |src_params|,
8552c593315Sopenharmony_ci// and stores parsed results into |out|.  This function returns 0 if
8562c593315Sopenharmony_ci// it succeeds, or -1.
8572c593315Sopenharmony_ciint parse_memcached_connection_params(MemcachedConnectionParams &out,
8582c593315Sopenharmony_ci                                      const StringRef &src_params,
8592c593315Sopenharmony_ci                                      const StringRef &opt) {
8602c593315Sopenharmony_ci  auto last = std::end(src_params);
8612c593315Sopenharmony_ci  for (auto first = std::begin(src_params); first != last;) {
8622c593315Sopenharmony_ci    auto end = std::find(first, last, ';');
8632c593315Sopenharmony_ci    auto param = StringRef{first, end};
8642c593315Sopenharmony_ci
8652c593315Sopenharmony_ci    if (util::strieq_l("tls", param)) {
8662c593315Sopenharmony_ci      out.tls = true;
8672c593315Sopenharmony_ci    } else if (util::strieq_l("no-tls", param)) {
8682c593315Sopenharmony_ci      out.tls = false;
8692c593315Sopenharmony_ci    } else if (!param.empty()) {
8702c593315Sopenharmony_ci      LOG(ERROR) << opt << ": " << param << ": unknown keyword";
8712c593315Sopenharmony_ci      return -1;
8722c593315Sopenharmony_ci    }
8732c593315Sopenharmony_ci
8742c593315Sopenharmony_ci    if (end == last) {
8752c593315Sopenharmony_ci      break;
8762c593315Sopenharmony_ci    }
8772c593315Sopenharmony_ci
8782c593315Sopenharmony_ci    first = end + 1;
8792c593315Sopenharmony_ci  }
8802c593315Sopenharmony_ci
8812c593315Sopenharmony_ci  return 0;
8822c593315Sopenharmony_ci}
8832c593315Sopenharmony_ci} // namespace
8842c593315Sopenharmony_ci
8852c593315Sopenharmony_cistruct UpstreamParams {
8862c593315Sopenharmony_ci  UpstreamAltMode alt_mode;
8872c593315Sopenharmony_ci  bool tls;
8882c593315Sopenharmony_ci  bool sni_fwd;
8892c593315Sopenharmony_ci  bool proxyproto;
8902c593315Sopenharmony_ci  bool quic;
8912c593315Sopenharmony_ci};
8922c593315Sopenharmony_ci
8932c593315Sopenharmony_cinamespace {
8942c593315Sopenharmony_ci// Parses upstream configuration parameter |src_params|, and stores
8952c593315Sopenharmony_ci// parsed results into |out|.  This function returns 0 if it succeeds,
8962c593315Sopenharmony_ci// or -1.
8972c593315Sopenharmony_ciint parse_upstream_params(UpstreamParams &out, const StringRef &src_params) {
8982c593315Sopenharmony_ci  auto last = std::end(src_params);
8992c593315Sopenharmony_ci  for (auto first = std::begin(src_params); first != last;) {
9002c593315Sopenharmony_ci    auto end = std::find(first, last, ';');
9012c593315Sopenharmony_ci    auto param = StringRef{first, end};
9022c593315Sopenharmony_ci
9032c593315Sopenharmony_ci    if (util::strieq_l("tls", param)) {
9042c593315Sopenharmony_ci      out.tls = true;
9052c593315Sopenharmony_ci    } else if (util::strieq_l("sni-fwd", param)) {
9062c593315Sopenharmony_ci      out.sni_fwd = true;
9072c593315Sopenharmony_ci    } else if (util::strieq_l("no-tls", param)) {
9082c593315Sopenharmony_ci      out.tls = false;
9092c593315Sopenharmony_ci    } else if (util::strieq_l("api", param)) {
9102c593315Sopenharmony_ci      if (out.alt_mode != UpstreamAltMode::NONE &&
9112c593315Sopenharmony_ci          out.alt_mode != UpstreamAltMode::API) {
9122c593315Sopenharmony_ci        LOG(ERROR) << "frontend: api and healthmon are mutually exclusive";
9132c593315Sopenharmony_ci        return -1;
9142c593315Sopenharmony_ci      }
9152c593315Sopenharmony_ci      out.alt_mode = UpstreamAltMode::API;
9162c593315Sopenharmony_ci    } else if (util::strieq_l("healthmon", param)) {
9172c593315Sopenharmony_ci      if (out.alt_mode != UpstreamAltMode::NONE &&
9182c593315Sopenharmony_ci          out.alt_mode != UpstreamAltMode::HEALTHMON) {
9192c593315Sopenharmony_ci        LOG(ERROR) << "frontend: api and healthmon are mutually exclusive";
9202c593315Sopenharmony_ci        return -1;
9212c593315Sopenharmony_ci      }
9222c593315Sopenharmony_ci      out.alt_mode = UpstreamAltMode::HEALTHMON;
9232c593315Sopenharmony_ci    } else if (util::strieq_l("proxyproto", param)) {
9242c593315Sopenharmony_ci      out.proxyproto = true;
9252c593315Sopenharmony_ci    } else if (util::strieq_l("quic", param)) {
9262c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
9272c593315Sopenharmony_ci      out.quic = true;
9282c593315Sopenharmony_ci#else  // !ENABLE_HTTP3
9292c593315Sopenharmony_ci      LOG(ERROR) << "quic: QUIC is disabled at compile time";
9302c593315Sopenharmony_ci      return -1;
9312c593315Sopenharmony_ci#endif // !ENABLE_HTTP3
9322c593315Sopenharmony_ci    } else if (!param.empty()) {
9332c593315Sopenharmony_ci      LOG(ERROR) << "frontend: " << param << ": unknown keyword";
9342c593315Sopenharmony_ci      return -1;
9352c593315Sopenharmony_ci    }
9362c593315Sopenharmony_ci
9372c593315Sopenharmony_ci    if (end == last) {
9382c593315Sopenharmony_ci      break;
9392c593315Sopenharmony_ci    }
9402c593315Sopenharmony_ci
9412c593315Sopenharmony_ci    first = end + 1;
9422c593315Sopenharmony_ci  }
9432c593315Sopenharmony_ci
9442c593315Sopenharmony_ci  return 0;
9452c593315Sopenharmony_ci}
9462c593315Sopenharmony_ci} // namespace
9472c593315Sopenharmony_ci
9482c593315Sopenharmony_cistruct DownstreamParams {
9492c593315Sopenharmony_ci  StringRef sni;
9502c593315Sopenharmony_ci  StringRef mruby;
9512c593315Sopenharmony_ci  StringRef group;
9522c593315Sopenharmony_ci  AffinityConfig affinity;
9532c593315Sopenharmony_ci  ev_tstamp read_timeout;
9542c593315Sopenharmony_ci  ev_tstamp write_timeout;
9552c593315Sopenharmony_ci  size_t fall;
9562c593315Sopenharmony_ci  size_t rise;
9572c593315Sopenharmony_ci  uint32_t weight;
9582c593315Sopenharmony_ci  uint32_t group_weight;
9592c593315Sopenharmony_ci  Proto proto;
9602c593315Sopenharmony_ci  bool tls;
9612c593315Sopenharmony_ci  bool dns;
9622c593315Sopenharmony_ci  bool redirect_if_not_tls;
9632c593315Sopenharmony_ci  bool upgrade_scheme;
9642c593315Sopenharmony_ci  bool dnf;
9652c593315Sopenharmony_ci};
9662c593315Sopenharmony_ci
9672c593315Sopenharmony_cinamespace {
9682c593315Sopenharmony_ci// Parses |value| of parameter named |name| as duration.  This
9692c593315Sopenharmony_ci// function returns 0 if it succeeds and the parsed value is assigned
9702c593315Sopenharmony_ci// to |dest|, or -1.
9712c593315Sopenharmony_ciint parse_downstream_param_duration(ev_tstamp &dest, const StringRef &name,
9722c593315Sopenharmony_ci                                    const StringRef &value) {
9732c593315Sopenharmony_ci  auto t = util::parse_duration_with_unit(value);
9742c593315Sopenharmony_ci  if (t == std::numeric_limits<double>::infinity()) {
9752c593315Sopenharmony_ci    LOG(ERROR) << "backend: " << name << ": bad value: '" << value << "'";
9762c593315Sopenharmony_ci    return -1;
9772c593315Sopenharmony_ci  }
9782c593315Sopenharmony_ci  dest = t;
9792c593315Sopenharmony_ci  return 0;
9802c593315Sopenharmony_ci}
9812c593315Sopenharmony_ci} // namespace
9822c593315Sopenharmony_ci
9832c593315Sopenharmony_cinamespace {
9842c593315Sopenharmony_ci// Parses downstream configuration parameter |src_params|, and stores
9852c593315Sopenharmony_ci// parsed results into |out|.  This function returns 0 if it succeeds,
9862c593315Sopenharmony_ci// or -1.
9872c593315Sopenharmony_ciint parse_downstream_params(DownstreamParams &out,
9882c593315Sopenharmony_ci                            const StringRef &src_params) {
9892c593315Sopenharmony_ci  auto last = std::end(src_params);
9902c593315Sopenharmony_ci  for (auto first = std::begin(src_params); first != last;) {
9912c593315Sopenharmony_ci    auto end = std::find(first, last, ';');
9922c593315Sopenharmony_ci    auto param = StringRef{first, end};
9932c593315Sopenharmony_ci
9942c593315Sopenharmony_ci    if (util::istarts_with_l(param, "proto=")) {
9952c593315Sopenharmony_ci      auto protostr = StringRef{first + str_size("proto="), end};
9962c593315Sopenharmony_ci      if (protostr.empty()) {
9972c593315Sopenharmony_ci        LOG(ERROR) << "backend: proto: protocol is empty";
9982c593315Sopenharmony_ci        return -1;
9992c593315Sopenharmony_ci      }
10002c593315Sopenharmony_ci
10012c593315Sopenharmony_ci      if (util::streq_l("h2", std::begin(protostr), protostr.size())) {
10022c593315Sopenharmony_ci        out.proto = Proto::HTTP2;
10032c593315Sopenharmony_ci      } else if (util::streq_l("http/1.1", std::begin(protostr),
10042c593315Sopenharmony_ci                               protostr.size())) {
10052c593315Sopenharmony_ci        out.proto = Proto::HTTP1;
10062c593315Sopenharmony_ci      } else {
10072c593315Sopenharmony_ci        LOG(ERROR) << "backend: proto: unknown protocol " << protostr;
10082c593315Sopenharmony_ci        return -1;
10092c593315Sopenharmony_ci      }
10102c593315Sopenharmony_ci    } else if (util::istarts_with_l(param, "fall=")) {
10112c593315Sopenharmony_ci      auto valstr = StringRef{first + str_size("fall="), end};
10122c593315Sopenharmony_ci      if (valstr.empty()) {
10132c593315Sopenharmony_ci        LOG(ERROR) << "backend: fall: non-negative integer is expected";
10142c593315Sopenharmony_ci        return -1;
10152c593315Sopenharmony_ci      }
10162c593315Sopenharmony_ci
10172c593315Sopenharmony_ci      auto n = util::parse_uint(valstr);
10182c593315Sopenharmony_ci      if (n == -1) {
10192c593315Sopenharmony_ci        LOG(ERROR) << "backend: fall: non-negative integer is expected";
10202c593315Sopenharmony_ci        return -1;
10212c593315Sopenharmony_ci      }
10222c593315Sopenharmony_ci
10232c593315Sopenharmony_ci      out.fall = n;
10242c593315Sopenharmony_ci    } else if (util::istarts_with_l(param, "rise=")) {
10252c593315Sopenharmony_ci      auto valstr = StringRef{first + str_size("rise="), end};
10262c593315Sopenharmony_ci      if (valstr.empty()) {
10272c593315Sopenharmony_ci        LOG(ERROR) << "backend: rise: non-negative integer is expected";
10282c593315Sopenharmony_ci        return -1;
10292c593315Sopenharmony_ci      }
10302c593315Sopenharmony_ci
10312c593315Sopenharmony_ci      auto n = util::parse_uint(valstr);
10322c593315Sopenharmony_ci      if (n == -1) {
10332c593315Sopenharmony_ci        LOG(ERROR) << "backend: rise: non-negative integer is expected";
10342c593315Sopenharmony_ci        return -1;
10352c593315Sopenharmony_ci      }
10362c593315Sopenharmony_ci
10372c593315Sopenharmony_ci      out.rise = n;
10382c593315Sopenharmony_ci    } else if (util::strieq_l("tls", param)) {
10392c593315Sopenharmony_ci      out.tls = true;
10402c593315Sopenharmony_ci    } else if (util::strieq_l("no-tls", param)) {
10412c593315Sopenharmony_ci      out.tls = false;
10422c593315Sopenharmony_ci    } else if (util::istarts_with_l(param, "sni=")) {
10432c593315Sopenharmony_ci      out.sni = StringRef{first + str_size("sni="), end};
10442c593315Sopenharmony_ci    } else if (util::istarts_with_l(param, "affinity=")) {
10452c593315Sopenharmony_ci      auto valstr = StringRef{first + str_size("affinity="), end};
10462c593315Sopenharmony_ci      if (util::strieq_l("none", valstr)) {
10472c593315Sopenharmony_ci        out.affinity.type = SessionAffinity::NONE;
10482c593315Sopenharmony_ci      } else if (util::strieq_l("ip", valstr)) {
10492c593315Sopenharmony_ci        out.affinity.type = SessionAffinity::IP;
10502c593315Sopenharmony_ci      } else if (util::strieq_l("cookie", valstr)) {
10512c593315Sopenharmony_ci        out.affinity.type = SessionAffinity::COOKIE;
10522c593315Sopenharmony_ci      } else {
10532c593315Sopenharmony_ci        LOG(ERROR)
10542c593315Sopenharmony_ci            << "backend: affinity: value must be one of none, ip, and cookie";
10552c593315Sopenharmony_ci        return -1;
10562c593315Sopenharmony_ci      }
10572c593315Sopenharmony_ci    } else if (util::istarts_with_l(param, "affinity-cookie-name=")) {
10582c593315Sopenharmony_ci      auto val = StringRef{first + str_size("affinity-cookie-name="), end};
10592c593315Sopenharmony_ci      if (val.empty()) {
10602c593315Sopenharmony_ci        LOG(ERROR)
10612c593315Sopenharmony_ci            << "backend: affinity-cookie-name: non empty string is expected";
10622c593315Sopenharmony_ci        return -1;
10632c593315Sopenharmony_ci      }
10642c593315Sopenharmony_ci      out.affinity.cookie.name = val;
10652c593315Sopenharmony_ci    } else if (util::istarts_with_l(param, "affinity-cookie-path=")) {
10662c593315Sopenharmony_ci      out.affinity.cookie.path =
10672c593315Sopenharmony_ci          StringRef{first + str_size("affinity-cookie-path="), end};
10682c593315Sopenharmony_ci    } else if (util::istarts_with_l(param, "affinity-cookie-secure=")) {
10692c593315Sopenharmony_ci      auto valstr = StringRef{first + str_size("affinity-cookie-secure="), end};
10702c593315Sopenharmony_ci      if (util::strieq_l("auto", valstr)) {
10712c593315Sopenharmony_ci        out.affinity.cookie.secure = SessionAffinityCookieSecure::AUTO;
10722c593315Sopenharmony_ci      } else if (util::strieq_l("yes", valstr)) {
10732c593315Sopenharmony_ci        out.affinity.cookie.secure = SessionAffinityCookieSecure::YES;
10742c593315Sopenharmony_ci      } else if (util::strieq_l("no", valstr)) {
10752c593315Sopenharmony_ci        out.affinity.cookie.secure = SessionAffinityCookieSecure::NO;
10762c593315Sopenharmony_ci      } else {
10772c593315Sopenharmony_ci        LOG(ERROR) << "backend: affinity-cookie-secure: value must be one of "
10782c593315Sopenharmony_ci                      "auto, yes, and no";
10792c593315Sopenharmony_ci        return -1;
10802c593315Sopenharmony_ci      }
10812c593315Sopenharmony_ci    } else if (util::istarts_with_l(param, "affinity-cookie-stickiness=")) {
10822c593315Sopenharmony_ci      auto valstr =
10832c593315Sopenharmony_ci          StringRef{first + str_size("affinity-cookie-stickiness="), end};
10842c593315Sopenharmony_ci      if (util::strieq_l("loose", valstr)) {
10852c593315Sopenharmony_ci        out.affinity.cookie.stickiness = SessionAffinityCookieStickiness::LOOSE;
10862c593315Sopenharmony_ci      } else if (util::strieq_l("strict", valstr)) {
10872c593315Sopenharmony_ci        out.affinity.cookie.stickiness =
10882c593315Sopenharmony_ci            SessionAffinityCookieStickiness::STRICT;
10892c593315Sopenharmony_ci      } else {
10902c593315Sopenharmony_ci        LOG(ERROR) << "backend: affinity-cookie-stickiness: value must be "
10912c593315Sopenharmony_ci                      "either loose or strict";
10922c593315Sopenharmony_ci        return -1;
10932c593315Sopenharmony_ci      }
10942c593315Sopenharmony_ci    } else if (util::strieq_l("dns", param)) {
10952c593315Sopenharmony_ci      out.dns = true;
10962c593315Sopenharmony_ci    } else if (util::strieq_l("redirect-if-not-tls", param)) {
10972c593315Sopenharmony_ci      out.redirect_if_not_tls = true;
10982c593315Sopenharmony_ci    } else if (util::strieq_l("upgrade-scheme", param)) {
10992c593315Sopenharmony_ci      out.upgrade_scheme = true;
11002c593315Sopenharmony_ci    } else if (util::istarts_with_l(param, "mruby=")) {
11012c593315Sopenharmony_ci      auto valstr = StringRef{first + str_size("mruby="), end};
11022c593315Sopenharmony_ci      out.mruby = valstr;
11032c593315Sopenharmony_ci    } else if (util::istarts_with_l(param, "read-timeout=")) {
11042c593315Sopenharmony_ci      if (parse_downstream_param_duration(
11052c593315Sopenharmony_ci              out.read_timeout, StringRef::from_lit("read-timeout"),
11062c593315Sopenharmony_ci              StringRef{first + str_size("read-timeout="), end}) == -1) {
11072c593315Sopenharmony_ci        return -1;
11082c593315Sopenharmony_ci      }
11092c593315Sopenharmony_ci    } else if (util::istarts_with_l(param, "write-timeout=")) {
11102c593315Sopenharmony_ci      if (parse_downstream_param_duration(
11112c593315Sopenharmony_ci              out.write_timeout, StringRef::from_lit("write-timeout"),
11122c593315Sopenharmony_ci              StringRef{first + str_size("write-timeout="), end}) == -1) {
11132c593315Sopenharmony_ci        return -1;
11142c593315Sopenharmony_ci      }
11152c593315Sopenharmony_ci    } else if (util::istarts_with_l(param, "weight=")) {
11162c593315Sopenharmony_ci      auto valstr = StringRef{first + str_size("weight="), end};
11172c593315Sopenharmony_ci      if (valstr.empty()) {
11182c593315Sopenharmony_ci        LOG(ERROR)
11192c593315Sopenharmony_ci            << "backend: weight: non-negative integer [1, 256] is expected";
11202c593315Sopenharmony_ci        return -1;
11212c593315Sopenharmony_ci      }
11222c593315Sopenharmony_ci
11232c593315Sopenharmony_ci      auto n = util::parse_uint(valstr);
11242c593315Sopenharmony_ci      if (n < 1 || n > 256) {
11252c593315Sopenharmony_ci        LOG(ERROR)
11262c593315Sopenharmony_ci            << "backend: weight: non-negative integer [1, 256] is expected";
11272c593315Sopenharmony_ci        return -1;
11282c593315Sopenharmony_ci      }
11292c593315Sopenharmony_ci      out.weight = n;
11302c593315Sopenharmony_ci    } else if (util::istarts_with_l(param, "group=")) {
11312c593315Sopenharmony_ci      auto valstr = StringRef{first + str_size("group="), end};
11322c593315Sopenharmony_ci      if (valstr.empty()) {
11332c593315Sopenharmony_ci        LOG(ERROR) << "backend: group: empty string is not allowed";
11342c593315Sopenharmony_ci        return -1;
11352c593315Sopenharmony_ci      }
11362c593315Sopenharmony_ci      out.group = valstr;
11372c593315Sopenharmony_ci    } else if (util::istarts_with_l(param, "group-weight=")) {
11382c593315Sopenharmony_ci      auto valstr = StringRef{first + str_size("group-weight="), end};
11392c593315Sopenharmony_ci      if (valstr.empty()) {
11402c593315Sopenharmony_ci        LOG(ERROR) << "backend: group-weight: non-negative integer [1, 256] is "
11412c593315Sopenharmony_ci                      "expected";
11422c593315Sopenharmony_ci        return -1;
11432c593315Sopenharmony_ci      }
11442c593315Sopenharmony_ci
11452c593315Sopenharmony_ci      auto n = util::parse_uint(valstr);
11462c593315Sopenharmony_ci      if (n < 1 || n > 256) {
11472c593315Sopenharmony_ci        LOG(ERROR) << "backend: group-weight: non-negative integer [1, 256] is "
11482c593315Sopenharmony_ci                      "expected";
11492c593315Sopenharmony_ci        return -1;
11502c593315Sopenharmony_ci      }
11512c593315Sopenharmony_ci      out.group_weight = n;
11522c593315Sopenharmony_ci    } else if (util::strieq_l("dnf", param)) {
11532c593315Sopenharmony_ci      out.dnf = true;
11542c593315Sopenharmony_ci    } else if (!param.empty()) {
11552c593315Sopenharmony_ci      LOG(ERROR) << "backend: " << param << ": unknown keyword";
11562c593315Sopenharmony_ci      return -1;
11572c593315Sopenharmony_ci    }
11582c593315Sopenharmony_ci
11592c593315Sopenharmony_ci    if (end == last) {
11602c593315Sopenharmony_ci      break;
11612c593315Sopenharmony_ci    }
11622c593315Sopenharmony_ci
11632c593315Sopenharmony_ci    first = end + 1;
11642c593315Sopenharmony_ci  }
11652c593315Sopenharmony_ci
11662c593315Sopenharmony_ci  return 0;
11672c593315Sopenharmony_ci}
11682c593315Sopenharmony_ci} // namespace
11692c593315Sopenharmony_ci
11702c593315Sopenharmony_cinamespace {
11712c593315Sopenharmony_ci// Parses host-path mapping patterns in |src_pattern|, and stores
11722c593315Sopenharmony_ci// mappings in config.  We will store each host-path pattern found in
11732c593315Sopenharmony_ci// |src| with |addr|.  |addr| will be copied accordingly.  Also we
11742c593315Sopenharmony_ci// make a group based on the pattern.  The "/" pattern is considered
11752c593315Sopenharmony_ci// as catch-all.  We also parse protocol specified in |src_proto|.
11762c593315Sopenharmony_ci//
11772c593315Sopenharmony_ci// This function returns 0 if it succeeds, or -1.
11782c593315Sopenharmony_ciint parse_mapping(Config *config, DownstreamAddrConfig &addr,
11792c593315Sopenharmony_ci                  std::map<StringRef, size_t> &pattern_addr_indexer,
11802c593315Sopenharmony_ci                  const StringRef &src_pattern, const StringRef &src_params) {
11812c593315Sopenharmony_ci  // This returns at least 1 element (it could be empty string).  We
11822c593315Sopenharmony_ci  // will append '/' to all patterns, so it becomes catch-all pattern.
11832c593315Sopenharmony_ci  auto mapping = util::split_str(src_pattern, ':');
11842c593315Sopenharmony_ci  assert(!mapping.empty());
11852c593315Sopenharmony_ci  auto &downstreamconf = *config->conn.downstream;
11862c593315Sopenharmony_ci  auto &addr_groups = downstreamconf.addr_groups;
11872c593315Sopenharmony_ci
11882c593315Sopenharmony_ci  DownstreamParams params{};
11892c593315Sopenharmony_ci  params.proto = Proto::HTTP1;
11902c593315Sopenharmony_ci  params.weight = 1;
11912c593315Sopenharmony_ci
11922c593315Sopenharmony_ci  if (parse_downstream_params(params, src_params) != 0) {
11932c593315Sopenharmony_ci    return -1;
11942c593315Sopenharmony_ci  }
11952c593315Sopenharmony_ci
11962c593315Sopenharmony_ci  if (addr.host_unix && params.dns) {
11972c593315Sopenharmony_ci    LOG(ERROR) << "backend: dns: cannot be used for UNIX domain socket";
11982c593315Sopenharmony_ci    return -1;
11992c593315Sopenharmony_ci  }
12002c593315Sopenharmony_ci
12012c593315Sopenharmony_ci  if (params.affinity.type == SessionAffinity::COOKIE &&
12022c593315Sopenharmony_ci      params.affinity.cookie.name.empty()) {
12032c593315Sopenharmony_ci    LOG(ERROR) << "backend: affinity-cookie-name is mandatory if "
12042c593315Sopenharmony_ci                  "affinity=cookie is specified";
12052c593315Sopenharmony_ci    return -1;
12062c593315Sopenharmony_ci  }
12072c593315Sopenharmony_ci
12082c593315Sopenharmony_ci  addr.fall = params.fall;
12092c593315Sopenharmony_ci  addr.rise = params.rise;
12102c593315Sopenharmony_ci  addr.weight = params.weight;
12112c593315Sopenharmony_ci  addr.group = make_string_ref(downstreamconf.balloc, params.group);
12122c593315Sopenharmony_ci  addr.group_weight = params.group_weight;
12132c593315Sopenharmony_ci  addr.proto = params.proto;
12142c593315Sopenharmony_ci  addr.tls = params.tls;
12152c593315Sopenharmony_ci  addr.sni = make_string_ref(downstreamconf.balloc, params.sni);
12162c593315Sopenharmony_ci  addr.dns = params.dns;
12172c593315Sopenharmony_ci  addr.upgrade_scheme = params.upgrade_scheme;
12182c593315Sopenharmony_ci  addr.dnf = params.dnf;
12192c593315Sopenharmony_ci
12202c593315Sopenharmony_ci  auto &routerconf = downstreamconf.router;
12212c593315Sopenharmony_ci  auto &router = routerconf.router;
12222c593315Sopenharmony_ci  auto &rw_router = routerconf.rev_wildcard_router;
12232c593315Sopenharmony_ci  auto &wildcard_patterns = routerconf.wildcard_patterns;
12242c593315Sopenharmony_ci
12252c593315Sopenharmony_ci  for (const auto &raw_pattern : mapping) {
12262c593315Sopenharmony_ci    StringRef pattern;
12272c593315Sopenharmony_ci    auto slash = std::find(std::begin(raw_pattern), std::end(raw_pattern), '/');
12282c593315Sopenharmony_ci    if (slash == std::end(raw_pattern)) {
12292c593315Sopenharmony_ci      // This effectively makes empty pattern to "/".  2 for '/' and
12302c593315Sopenharmony_ci      // terminal NULL character.
12312c593315Sopenharmony_ci      auto iov = make_byte_ref(downstreamconf.balloc, raw_pattern.size() + 2);
12322c593315Sopenharmony_ci      auto p = iov.base;
12332c593315Sopenharmony_ci      p = std::copy(std::begin(raw_pattern), std::end(raw_pattern), p);
12342c593315Sopenharmony_ci      util::inp_strlower(iov.base, p);
12352c593315Sopenharmony_ci      *p++ = '/';
12362c593315Sopenharmony_ci      *p = '\0';
12372c593315Sopenharmony_ci      pattern = StringRef{iov.base, p};
12382c593315Sopenharmony_ci    } else {
12392c593315Sopenharmony_ci      auto path = http2::normalize_path_colon(
12402c593315Sopenharmony_ci          downstreamconf.balloc, StringRef{slash, std::end(raw_pattern)},
12412c593315Sopenharmony_ci          StringRef{});
12422c593315Sopenharmony_ci      auto iov = make_byte_ref(downstreamconf.balloc,
12432c593315Sopenharmony_ci                               std::distance(std::begin(raw_pattern), slash) +
12442c593315Sopenharmony_ci                                   path.size() + 1);
12452c593315Sopenharmony_ci      auto p = iov.base;
12462c593315Sopenharmony_ci      p = std::copy(std::begin(raw_pattern), slash, p);
12472c593315Sopenharmony_ci      util::inp_strlower(iov.base, p);
12482c593315Sopenharmony_ci      p = std::copy(std::begin(path), std::end(path), p);
12492c593315Sopenharmony_ci      *p = '\0';
12502c593315Sopenharmony_ci      pattern = StringRef{iov.base, p};
12512c593315Sopenharmony_ci    }
12522c593315Sopenharmony_ci    auto it = pattern_addr_indexer.find(pattern);
12532c593315Sopenharmony_ci    if (it != std::end(pattern_addr_indexer)) {
12542c593315Sopenharmony_ci      auto &g = addr_groups[(*it).second];
12552c593315Sopenharmony_ci      // Last value wins if we have multiple different affinity
12562c593315Sopenharmony_ci      // value under one group.
12572c593315Sopenharmony_ci      if (params.affinity.type != SessionAffinity::NONE) {
12582c593315Sopenharmony_ci        if (g.affinity.type == SessionAffinity::NONE) {
12592c593315Sopenharmony_ci          g.affinity.type = params.affinity.type;
12602c593315Sopenharmony_ci          if (params.affinity.type == SessionAffinity::COOKIE) {
12612c593315Sopenharmony_ci            g.affinity.cookie.name = make_string_ref(
12622c593315Sopenharmony_ci                downstreamconf.balloc, params.affinity.cookie.name);
12632c593315Sopenharmony_ci            if (!params.affinity.cookie.path.empty()) {
12642c593315Sopenharmony_ci              g.affinity.cookie.path = make_string_ref(
12652c593315Sopenharmony_ci                  downstreamconf.balloc, params.affinity.cookie.path);
12662c593315Sopenharmony_ci            }
12672c593315Sopenharmony_ci            g.affinity.cookie.secure = params.affinity.cookie.secure;
12682c593315Sopenharmony_ci            g.affinity.cookie.stickiness = params.affinity.cookie.stickiness;
12692c593315Sopenharmony_ci          }
12702c593315Sopenharmony_ci        } else if (g.affinity.type != params.affinity.type ||
12712c593315Sopenharmony_ci                   g.affinity.cookie.name != params.affinity.cookie.name ||
12722c593315Sopenharmony_ci                   g.affinity.cookie.path != params.affinity.cookie.path ||
12732c593315Sopenharmony_ci                   g.affinity.cookie.secure != params.affinity.cookie.secure ||
12742c593315Sopenharmony_ci                   g.affinity.cookie.stickiness !=
12752c593315Sopenharmony_ci                       params.affinity.cookie.stickiness) {
12762c593315Sopenharmony_ci          LOG(ERROR) << "backend: affinity: multiple different affinity "
12772c593315Sopenharmony_ci                        "configurations found in a single group";
12782c593315Sopenharmony_ci          return -1;
12792c593315Sopenharmony_ci        }
12802c593315Sopenharmony_ci      }
12812c593315Sopenharmony_ci      // If at least one backend requires frontend TLS connection,
12822c593315Sopenharmony_ci      // enable it for all backends sharing the same pattern.
12832c593315Sopenharmony_ci      if (params.redirect_if_not_tls) {
12842c593315Sopenharmony_ci        g.redirect_if_not_tls = true;
12852c593315Sopenharmony_ci      }
12862c593315Sopenharmony_ci      // All backends in the same group must have the same mruby path.
12872c593315Sopenharmony_ci      // If some backends do not specify mruby file, and there is at
12882c593315Sopenharmony_ci      // least one backend with mruby file, it is used for all
12892c593315Sopenharmony_ci      // backends in the group.
12902c593315Sopenharmony_ci      if (!params.mruby.empty()) {
12912c593315Sopenharmony_ci        if (g.mruby_file.empty()) {
12922c593315Sopenharmony_ci          g.mruby_file = make_string_ref(downstreamconf.balloc, params.mruby);
12932c593315Sopenharmony_ci        } else if (g.mruby_file != params.mruby) {
12942c593315Sopenharmony_ci          LOG(ERROR) << "backend: mruby: multiple different mruby file found "
12952c593315Sopenharmony_ci                        "in a single group";
12962c593315Sopenharmony_ci          return -1;
12972c593315Sopenharmony_ci        }
12982c593315Sopenharmony_ci      }
12992c593315Sopenharmony_ci      // All backends in the same group must have the same read/write
13002c593315Sopenharmony_ci      // timeout.  If some backends do not specify read/write timeout,
13012c593315Sopenharmony_ci      // and there is at least one backend with read/write timeout, it
13022c593315Sopenharmony_ci      // is used for all backends in the group.
13032c593315Sopenharmony_ci      if (params.read_timeout > 1e-9) {
13042c593315Sopenharmony_ci        if (g.timeout.read < 1e-9) {
13052c593315Sopenharmony_ci          g.timeout.read = params.read_timeout;
13062c593315Sopenharmony_ci        } else if (fabs(g.timeout.read - params.read_timeout) > 1e-9) {
13072c593315Sopenharmony_ci          LOG(ERROR)
13082c593315Sopenharmony_ci              << "backend: read-timeout: multiple different read-timeout "
13092c593315Sopenharmony_ci                 "found in a single group";
13102c593315Sopenharmony_ci          return -1;
13112c593315Sopenharmony_ci        }
13122c593315Sopenharmony_ci      }
13132c593315Sopenharmony_ci      if (params.write_timeout > 1e-9) {
13142c593315Sopenharmony_ci        if (g.timeout.write < 1e-9) {
13152c593315Sopenharmony_ci          g.timeout.write = params.write_timeout;
13162c593315Sopenharmony_ci        } else if (fabs(g.timeout.write - params.write_timeout) > 1e-9) {
13172c593315Sopenharmony_ci          LOG(ERROR) << "backend: write-timeout: multiple different "
13182c593315Sopenharmony_ci                        "write-timeout found in a single group";
13192c593315Sopenharmony_ci          return -1;
13202c593315Sopenharmony_ci        }
13212c593315Sopenharmony_ci      }
13222c593315Sopenharmony_ci      // All backends in the same group must have the same dnf
13232c593315Sopenharmony_ci      // setting.  If some backends do not specify dnf, and there is
13242c593315Sopenharmony_ci      // at least one backend with dnf, it is used for all backends in
13252c593315Sopenharmony_ci      // the group.  In general, multiple backends are not necessary
13262c593315Sopenharmony_ci      // for dnf because there is no need for load balancing.
13272c593315Sopenharmony_ci      if (params.dnf) {
13282c593315Sopenharmony_ci        g.dnf = true;
13292c593315Sopenharmony_ci      }
13302c593315Sopenharmony_ci
13312c593315Sopenharmony_ci      g.addrs.push_back(addr);
13322c593315Sopenharmony_ci      continue;
13332c593315Sopenharmony_ci    }
13342c593315Sopenharmony_ci
13352c593315Sopenharmony_ci    auto idx = addr_groups.size();
13362c593315Sopenharmony_ci    pattern_addr_indexer.emplace(pattern, idx);
13372c593315Sopenharmony_ci    addr_groups.emplace_back(pattern);
13382c593315Sopenharmony_ci    auto &g = addr_groups.back();
13392c593315Sopenharmony_ci    g.addrs.push_back(addr);
13402c593315Sopenharmony_ci    g.affinity.type = params.affinity.type;
13412c593315Sopenharmony_ci    if (params.affinity.type == SessionAffinity::COOKIE) {
13422c593315Sopenharmony_ci      g.affinity.cookie.name =
13432c593315Sopenharmony_ci          make_string_ref(downstreamconf.balloc, params.affinity.cookie.name);
13442c593315Sopenharmony_ci      if (!params.affinity.cookie.path.empty()) {
13452c593315Sopenharmony_ci        g.affinity.cookie.path =
13462c593315Sopenharmony_ci            make_string_ref(downstreamconf.balloc, params.affinity.cookie.path);
13472c593315Sopenharmony_ci      }
13482c593315Sopenharmony_ci      g.affinity.cookie.secure = params.affinity.cookie.secure;
13492c593315Sopenharmony_ci      g.affinity.cookie.stickiness = params.affinity.cookie.stickiness;
13502c593315Sopenharmony_ci    }
13512c593315Sopenharmony_ci    g.redirect_if_not_tls = params.redirect_if_not_tls;
13522c593315Sopenharmony_ci    g.mruby_file = make_string_ref(downstreamconf.balloc, params.mruby);
13532c593315Sopenharmony_ci    g.timeout.read = params.read_timeout;
13542c593315Sopenharmony_ci    g.timeout.write = params.write_timeout;
13552c593315Sopenharmony_ci    g.dnf = params.dnf;
13562c593315Sopenharmony_ci
13572c593315Sopenharmony_ci    if (pattern[0] == '*') {
13582c593315Sopenharmony_ci      // wildcard pattern
13592c593315Sopenharmony_ci      auto path_first =
13602c593315Sopenharmony_ci          std::find(std::begin(g.pattern), std::end(g.pattern), '/');
13612c593315Sopenharmony_ci
13622c593315Sopenharmony_ci      auto host = StringRef{std::begin(g.pattern) + 1, path_first};
13632c593315Sopenharmony_ci      auto path = StringRef{path_first, std::end(g.pattern)};
13642c593315Sopenharmony_ci
13652c593315Sopenharmony_ci      auto path_is_wildcard = false;
13662c593315Sopenharmony_ci      if (path[path.size() - 1] == '*') {
13672c593315Sopenharmony_ci        path = StringRef{std::begin(path), std::begin(path) + path.size() - 1};
13682c593315Sopenharmony_ci        path_is_wildcard = true;
13692c593315Sopenharmony_ci      }
13702c593315Sopenharmony_ci
13712c593315Sopenharmony_ci      auto it = std::find_if(
13722c593315Sopenharmony_ci          std::begin(wildcard_patterns), std::end(wildcard_patterns),
13732c593315Sopenharmony_ci          [&host](const WildcardPattern &wp) { return wp.host == host; });
13742c593315Sopenharmony_ci
13752c593315Sopenharmony_ci      if (it == std::end(wildcard_patterns)) {
13762c593315Sopenharmony_ci        wildcard_patterns.emplace_back(host);
13772c593315Sopenharmony_ci
13782c593315Sopenharmony_ci        auto &router = wildcard_patterns.back().router;
13792c593315Sopenharmony_ci        router.add_route(path, idx, path_is_wildcard);
13802c593315Sopenharmony_ci
13812c593315Sopenharmony_ci        auto iov = make_byte_ref(downstreamconf.balloc, host.size() + 1);
13822c593315Sopenharmony_ci        auto p = iov.base;
13832c593315Sopenharmony_ci        p = std::reverse_copy(std::begin(host), std::end(host), p);
13842c593315Sopenharmony_ci        *p = '\0';
13852c593315Sopenharmony_ci        auto rev_host = StringRef{iov.base, p};
13862c593315Sopenharmony_ci
13872c593315Sopenharmony_ci        rw_router.add_route(rev_host, wildcard_patterns.size() - 1);
13882c593315Sopenharmony_ci      } else {
13892c593315Sopenharmony_ci        (*it).router.add_route(path, idx, path_is_wildcard);
13902c593315Sopenharmony_ci      }
13912c593315Sopenharmony_ci
13922c593315Sopenharmony_ci      continue;
13932c593315Sopenharmony_ci    }
13942c593315Sopenharmony_ci
13952c593315Sopenharmony_ci    auto path_is_wildcard = false;
13962c593315Sopenharmony_ci    if (pattern[pattern.size() - 1] == '*') {
13972c593315Sopenharmony_ci      pattern = StringRef{std::begin(pattern),
13982c593315Sopenharmony_ci                          std::begin(pattern) + pattern.size() - 1};
13992c593315Sopenharmony_ci      path_is_wildcard = true;
14002c593315Sopenharmony_ci    }
14012c593315Sopenharmony_ci
14022c593315Sopenharmony_ci    router.add_route(pattern, idx, path_is_wildcard);
14032c593315Sopenharmony_ci  }
14042c593315Sopenharmony_ci  return 0;
14052c593315Sopenharmony_ci}
14062c593315Sopenharmony_ci} // namespace
14072c593315Sopenharmony_ci
14082c593315Sopenharmony_cinamespace {
14092c593315Sopenharmony_ciForwardedNode parse_forwarded_node_type(const StringRef &optarg) {
14102c593315Sopenharmony_ci  if (util::strieq_l("obfuscated", optarg)) {
14112c593315Sopenharmony_ci    return ForwardedNode::OBFUSCATED;
14122c593315Sopenharmony_ci  }
14132c593315Sopenharmony_ci
14142c593315Sopenharmony_ci  if (util::strieq_l("ip", optarg)) {
14152c593315Sopenharmony_ci    return ForwardedNode::IP;
14162c593315Sopenharmony_ci  }
14172c593315Sopenharmony_ci
14182c593315Sopenharmony_ci  if (optarg.size() < 2 || optarg[0] != '_') {
14192c593315Sopenharmony_ci    return static_cast<ForwardedNode>(-1);
14202c593315Sopenharmony_ci  }
14212c593315Sopenharmony_ci
14222c593315Sopenharmony_ci  if (std::find_if_not(std::begin(optarg), std::end(optarg), [](char c) {
14232c593315Sopenharmony_ci        return util::is_alpha(c) || util::is_digit(c) || c == '.' || c == '_' ||
14242c593315Sopenharmony_ci               c == '-';
14252c593315Sopenharmony_ci      }) != std::end(optarg)) {
14262c593315Sopenharmony_ci    return static_cast<ForwardedNode>(-1);
14272c593315Sopenharmony_ci  }
14282c593315Sopenharmony_ci
14292c593315Sopenharmony_ci  return ForwardedNode::OBFUSCATED;
14302c593315Sopenharmony_ci}
14312c593315Sopenharmony_ci} // namespace
14322c593315Sopenharmony_ci
14332c593315Sopenharmony_cinamespace {
14342c593315Sopenharmony_ciint parse_error_page(std::vector<ErrorPage> &error_pages, const StringRef &opt,
14352c593315Sopenharmony_ci                     const StringRef &optarg) {
14362c593315Sopenharmony_ci  std::array<char, STRERROR_BUFSIZE> errbuf;
14372c593315Sopenharmony_ci
14382c593315Sopenharmony_ci  auto eq = std::find(std::begin(optarg), std::end(optarg), '=');
14392c593315Sopenharmony_ci  if (eq == std::end(optarg) || eq + 1 == std::end(optarg)) {
14402c593315Sopenharmony_ci    LOG(ERROR) << opt << ": bad value: '" << optarg << "'";
14412c593315Sopenharmony_ci    return -1;
14422c593315Sopenharmony_ci  }
14432c593315Sopenharmony_ci
14442c593315Sopenharmony_ci  auto codestr = StringRef{std::begin(optarg), eq};
14452c593315Sopenharmony_ci  unsigned int code;
14462c593315Sopenharmony_ci
14472c593315Sopenharmony_ci  if (codestr == StringRef::from_lit("*")) {
14482c593315Sopenharmony_ci    code = 0;
14492c593315Sopenharmony_ci  } else {
14502c593315Sopenharmony_ci    auto n = util::parse_uint(codestr);
14512c593315Sopenharmony_ci
14522c593315Sopenharmony_ci    if (n == -1 || n < 400 || n > 599) {
14532c593315Sopenharmony_ci      LOG(ERROR) << opt << ": bad code: '" << codestr << "'";
14542c593315Sopenharmony_ci      return -1;
14552c593315Sopenharmony_ci    }
14562c593315Sopenharmony_ci
14572c593315Sopenharmony_ci    code = static_cast<unsigned int>(n);
14582c593315Sopenharmony_ci  }
14592c593315Sopenharmony_ci
14602c593315Sopenharmony_ci  auto path = StringRef{eq + 1, std::end(optarg)};
14612c593315Sopenharmony_ci
14622c593315Sopenharmony_ci  std::vector<uint8_t> content;
14632c593315Sopenharmony_ci  auto fd = open(path.c_str(), O_RDONLY);
14642c593315Sopenharmony_ci  if (fd == -1) {
14652c593315Sopenharmony_ci    auto error = errno;
14662c593315Sopenharmony_ci    LOG(ERROR) << opt << ": " << optarg << ": "
14672c593315Sopenharmony_ci               << xsi_strerror(error, errbuf.data(), errbuf.size());
14682c593315Sopenharmony_ci    return -1;
14692c593315Sopenharmony_ci  }
14702c593315Sopenharmony_ci
14712c593315Sopenharmony_ci  auto fd_closer = defer(close, fd);
14722c593315Sopenharmony_ci
14732c593315Sopenharmony_ci  std::array<uint8_t, 4096> buf;
14742c593315Sopenharmony_ci  for (;;) {
14752c593315Sopenharmony_ci    auto n = read(fd, buf.data(), buf.size());
14762c593315Sopenharmony_ci    if (n == -1) {
14772c593315Sopenharmony_ci      auto error = errno;
14782c593315Sopenharmony_ci      LOG(ERROR) << opt << ": " << optarg << ": "
14792c593315Sopenharmony_ci                 << xsi_strerror(error, errbuf.data(), errbuf.size());
14802c593315Sopenharmony_ci      return -1;
14812c593315Sopenharmony_ci    }
14822c593315Sopenharmony_ci    if (n == 0) {
14832c593315Sopenharmony_ci      break;
14842c593315Sopenharmony_ci    }
14852c593315Sopenharmony_ci    content.insert(std::end(content), std::begin(buf), std::begin(buf) + n);
14862c593315Sopenharmony_ci  }
14872c593315Sopenharmony_ci
14882c593315Sopenharmony_ci  error_pages.push_back(ErrorPage{std::move(content), code});
14892c593315Sopenharmony_ci
14902c593315Sopenharmony_ci  return 0;
14912c593315Sopenharmony_ci}
14922c593315Sopenharmony_ci} // namespace
14932c593315Sopenharmony_ci
14942c593315Sopenharmony_cinamespace {
14952c593315Sopenharmony_ci// Maximum size of SCT extension payload length.
14962c593315Sopenharmony_ciconstexpr size_t MAX_SCT_EXT_LEN = 16_k;
14972c593315Sopenharmony_ci} // namespace
14982c593315Sopenharmony_ci
14992c593315Sopenharmony_cistruct SubcertParams {
15002c593315Sopenharmony_ci  StringRef sct_dir;
15012c593315Sopenharmony_ci};
15022c593315Sopenharmony_ci
15032c593315Sopenharmony_cinamespace {
15042c593315Sopenharmony_ci// Parses subcert parameter |src_params|, and stores parsed results
15052c593315Sopenharmony_ci// into |out|.  This function returns 0 if it succeeds, or -1.
15062c593315Sopenharmony_ciint parse_subcert_params(SubcertParams &out, const StringRef &src_params) {
15072c593315Sopenharmony_ci  auto last = std::end(src_params);
15082c593315Sopenharmony_ci  for (auto first = std::begin(src_params); first != last;) {
15092c593315Sopenharmony_ci    auto end = std::find(first, last, ';');
15102c593315Sopenharmony_ci    auto param = StringRef{first, end};
15112c593315Sopenharmony_ci
15122c593315Sopenharmony_ci    if (util::istarts_with_l(param, "sct-dir=")) {
15132c593315Sopenharmony_ci#if !LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L
15142c593315Sopenharmony_ci      auto sct_dir =
15152c593315Sopenharmony_ci          StringRef{std::begin(param) + str_size("sct-dir="), std::end(param)};
15162c593315Sopenharmony_ci      if (sct_dir.empty()) {
15172c593315Sopenharmony_ci        LOG(ERROR) << "subcert: " << param << ": empty sct-dir";
15182c593315Sopenharmony_ci        return -1;
15192c593315Sopenharmony_ci      }
15202c593315Sopenharmony_ci      out.sct_dir = sct_dir;
15212c593315Sopenharmony_ci#else  // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L)
15222c593315Sopenharmony_ci      LOG(WARN) << "subcert: sct-dir requires OpenSSL >= 1.0.2";
15232c593315Sopenharmony_ci#endif // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L)
15242c593315Sopenharmony_ci    } else if (!param.empty()) {
15252c593315Sopenharmony_ci      LOG(ERROR) << "subcert: " << param << ": unknown keyword";
15262c593315Sopenharmony_ci      return -1;
15272c593315Sopenharmony_ci    }
15282c593315Sopenharmony_ci
15292c593315Sopenharmony_ci    if (end == last) {
15302c593315Sopenharmony_ci      break;
15312c593315Sopenharmony_ci    }
15322c593315Sopenharmony_ci
15332c593315Sopenharmony_ci    first = end + 1;
15342c593315Sopenharmony_ci  }
15352c593315Sopenharmony_ci
15362c593315Sopenharmony_ci  return 0;
15372c593315Sopenharmony_ci}
15382c593315Sopenharmony_ci} // namespace
15392c593315Sopenharmony_ci
15402c593315Sopenharmony_cinamespace {
15412c593315Sopenharmony_ci// Reads *.sct files from directory denoted by |dir_path|.  |dir_path|
15422c593315Sopenharmony_ci// must be NULL-terminated string.
15432c593315Sopenharmony_ciint read_tls_sct_from_dir(std::vector<uint8_t> &dst, const StringRef &opt,
15442c593315Sopenharmony_ci                          const StringRef &dir_path) {
15452c593315Sopenharmony_ci  std::array<char, STRERROR_BUFSIZE> errbuf;
15462c593315Sopenharmony_ci
15472c593315Sopenharmony_ci  auto dir = opendir(dir_path.c_str());
15482c593315Sopenharmony_ci  if (dir == nullptr) {
15492c593315Sopenharmony_ci    auto error = errno;
15502c593315Sopenharmony_ci    LOG(ERROR) << opt << ": " << dir_path << ": "
15512c593315Sopenharmony_ci               << xsi_strerror(error, errbuf.data(), errbuf.size());
15522c593315Sopenharmony_ci    return -1;
15532c593315Sopenharmony_ci  }
15542c593315Sopenharmony_ci
15552c593315Sopenharmony_ci  auto closer = defer(closedir, dir);
15562c593315Sopenharmony_ci
15572c593315Sopenharmony_ci  // 2 bytes total length field
15582c593315Sopenharmony_ci  auto len_idx = std::distance(std::begin(dst), std::end(dst));
15592c593315Sopenharmony_ci  dst.insert(std::end(dst), 2, 0);
15602c593315Sopenharmony_ci
15612c593315Sopenharmony_ci  for (;;) {
15622c593315Sopenharmony_ci    errno = 0;
15632c593315Sopenharmony_ci    auto ent = readdir(dir);
15642c593315Sopenharmony_ci    if (ent == nullptr) {
15652c593315Sopenharmony_ci      if (errno != 0) {
15662c593315Sopenharmony_ci        auto error = errno;
15672c593315Sopenharmony_ci        LOG(ERROR) << opt << ": failed to read directory " << dir_path << ": "
15682c593315Sopenharmony_ci                   << xsi_strerror(error, errbuf.data(), errbuf.size());
15692c593315Sopenharmony_ci        return -1;
15702c593315Sopenharmony_ci      }
15712c593315Sopenharmony_ci      break;
15722c593315Sopenharmony_ci    }
15732c593315Sopenharmony_ci
15742c593315Sopenharmony_ci    auto name = StringRef{ent->d_name};
15752c593315Sopenharmony_ci
15762c593315Sopenharmony_ci    if (name[0] == '.' || !util::iends_with_l(name, ".sct")) {
15772c593315Sopenharmony_ci      continue;
15782c593315Sopenharmony_ci    }
15792c593315Sopenharmony_ci
15802c593315Sopenharmony_ci    std::string path;
15812c593315Sopenharmony_ci    path.resize(dir_path.size() + 1 + name.size());
15822c593315Sopenharmony_ci    {
15832c593315Sopenharmony_ci      auto p = std::begin(path);
15842c593315Sopenharmony_ci      p = std::copy(std::begin(dir_path), std::end(dir_path), p);
15852c593315Sopenharmony_ci      *p++ = '/';
15862c593315Sopenharmony_ci      std::copy(std::begin(name), std::end(name), p);
15872c593315Sopenharmony_ci    }
15882c593315Sopenharmony_ci
15892c593315Sopenharmony_ci    auto fd = open(path.c_str(), O_RDONLY);
15902c593315Sopenharmony_ci    if (fd == -1) {
15912c593315Sopenharmony_ci      auto error = errno;
15922c593315Sopenharmony_ci      LOG(ERROR) << opt << ": failed to read SCT from " << path << ": "
15932c593315Sopenharmony_ci                 << xsi_strerror(error, errbuf.data(), errbuf.size());
15942c593315Sopenharmony_ci      return -1;
15952c593315Sopenharmony_ci    }
15962c593315Sopenharmony_ci
15972c593315Sopenharmony_ci    auto closer = defer(close, fd);
15982c593315Sopenharmony_ci
15992c593315Sopenharmony_ci    // 2 bytes length field for this SCT.
16002c593315Sopenharmony_ci    auto len_idx = std::distance(std::begin(dst), std::end(dst));
16012c593315Sopenharmony_ci    dst.insert(std::end(dst), 2, 0);
16022c593315Sopenharmony_ci
16032c593315Sopenharmony_ci    // *.sct file tends to be small; around 110+ bytes.
16042c593315Sopenharmony_ci    std::array<char, 256> buf;
16052c593315Sopenharmony_ci    for (;;) {
16062c593315Sopenharmony_ci      ssize_t nread;
16072c593315Sopenharmony_ci      while ((nread = read(fd, buf.data(), buf.size())) == -1 && errno == EINTR)
16082c593315Sopenharmony_ci        ;
16092c593315Sopenharmony_ci
16102c593315Sopenharmony_ci      if (nread == -1) {
16112c593315Sopenharmony_ci        auto error = errno;
16122c593315Sopenharmony_ci        LOG(ERROR) << opt << ": failed to read SCT data from " << path << ": "
16132c593315Sopenharmony_ci                   << xsi_strerror(error, errbuf.data(), errbuf.size());
16142c593315Sopenharmony_ci        return -1;
16152c593315Sopenharmony_ci      }
16162c593315Sopenharmony_ci
16172c593315Sopenharmony_ci      if (nread == 0) {
16182c593315Sopenharmony_ci        break;
16192c593315Sopenharmony_ci      }
16202c593315Sopenharmony_ci
16212c593315Sopenharmony_ci      dst.insert(std::end(dst), std::begin(buf), std::begin(buf) + nread);
16222c593315Sopenharmony_ci
16232c593315Sopenharmony_ci      if (dst.size() > MAX_SCT_EXT_LEN) {
16242c593315Sopenharmony_ci        LOG(ERROR) << opt << ": the concatenated SCT data from " << dir_path
16252c593315Sopenharmony_ci                   << " is too large.  Max " << MAX_SCT_EXT_LEN;
16262c593315Sopenharmony_ci        return -1;
16272c593315Sopenharmony_ci      }
16282c593315Sopenharmony_ci    }
16292c593315Sopenharmony_ci
16302c593315Sopenharmony_ci    auto len = dst.size() - len_idx - 2;
16312c593315Sopenharmony_ci
16322c593315Sopenharmony_ci    if (len == 0) {
16332c593315Sopenharmony_ci      dst.resize(dst.size() - 2);
16342c593315Sopenharmony_ci      continue;
16352c593315Sopenharmony_ci    }
16362c593315Sopenharmony_ci
16372c593315Sopenharmony_ci    dst[len_idx] = len >> 8;
16382c593315Sopenharmony_ci    dst[len_idx + 1] = len;
16392c593315Sopenharmony_ci  }
16402c593315Sopenharmony_ci
16412c593315Sopenharmony_ci  auto len = dst.size() - len_idx - 2;
16422c593315Sopenharmony_ci
16432c593315Sopenharmony_ci  if (len == 0) {
16442c593315Sopenharmony_ci    dst.resize(dst.size() - 2);
16452c593315Sopenharmony_ci    return 0;
16462c593315Sopenharmony_ci  }
16472c593315Sopenharmony_ci
16482c593315Sopenharmony_ci  dst[len_idx] = len >> 8;
16492c593315Sopenharmony_ci  dst[len_idx + 1] = len;
16502c593315Sopenharmony_ci
16512c593315Sopenharmony_ci  return 0;
16522c593315Sopenharmony_ci}
16532c593315Sopenharmony_ci} // namespace
16542c593315Sopenharmony_ci
16552c593315Sopenharmony_ci#if !LIBRESSL_LEGACY_API
16562c593315Sopenharmony_cinamespace {
16572c593315Sopenharmony_ci// Reads PSK secrets from path, and parses each line.  The result is
16582c593315Sopenharmony_ci// directly stored into config->tls.psk_secrets.  This function
16592c593315Sopenharmony_ci// returns 0 if it succeeds, or -1.
16602c593315Sopenharmony_ciint parse_psk_secrets(Config *config, const StringRef &path) {
16612c593315Sopenharmony_ci  auto &tlsconf = config->tls;
16622c593315Sopenharmony_ci
16632c593315Sopenharmony_ci  std::ifstream f(path.c_str(), std::ios::binary);
16642c593315Sopenharmony_ci  if (!f) {
16652c593315Sopenharmony_ci    LOG(ERROR) << SHRPX_OPT_PSK_SECRETS << ": could not open file " << path;
16662c593315Sopenharmony_ci    return -1;
16672c593315Sopenharmony_ci  }
16682c593315Sopenharmony_ci
16692c593315Sopenharmony_ci  size_t lineno = 0;
16702c593315Sopenharmony_ci  std::string line;
16712c593315Sopenharmony_ci  while (std::getline(f, line)) {
16722c593315Sopenharmony_ci    ++lineno;
16732c593315Sopenharmony_ci    if (line.empty() || line[0] == '#') {
16742c593315Sopenharmony_ci      continue;
16752c593315Sopenharmony_ci    }
16762c593315Sopenharmony_ci
16772c593315Sopenharmony_ci    auto sep_it = std::find(std::begin(line), std::end(line), ':');
16782c593315Sopenharmony_ci    if (sep_it == std::end(line)) {
16792c593315Sopenharmony_ci      LOG(ERROR) << SHRPX_OPT_PSK_SECRETS
16802c593315Sopenharmony_ci                 << ": could not fine separator at line " << lineno;
16812c593315Sopenharmony_ci      return -1;
16822c593315Sopenharmony_ci    }
16832c593315Sopenharmony_ci
16842c593315Sopenharmony_ci    if (sep_it == std::begin(line)) {
16852c593315Sopenharmony_ci      LOG(ERROR) << SHRPX_OPT_PSK_SECRETS << ": empty identity at line "
16862c593315Sopenharmony_ci                 << lineno;
16872c593315Sopenharmony_ci      return -1;
16882c593315Sopenharmony_ci    }
16892c593315Sopenharmony_ci
16902c593315Sopenharmony_ci    if (sep_it + 1 == std::end(line)) {
16912c593315Sopenharmony_ci      LOG(ERROR) << SHRPX_OPT_PSK_SECRETS << ": empty secret at line "
16922c593315Sopenharmony_ci                 << lineno;
16932c593315Sopenharmony_ci      return -1;
16942c593315Sopenharmony_ci    }
16952c593315Sopenharmony_ci
16962c593315Sopenharmony_ci    if (!util::is_hex_string(StringRef{sep_it + 1, std::end(line)})) {
16972c593315Sopenharmony_ci      LOG(ERROR) << SHRPX_OPT_PSK_SECRETS
16982c593315Sopenharmony_ci                 << ": secret must be hex string at line " << lineno;
16992c593315Sopenharmony_ci      return -1;
17002c593315Sopenharmony_ci    }
17012c593315Sopenharmony_ci
17022c593315Sopenharmony_ci    auto identity =
17032c593315Sopenharmony_ci        make_string_ref(config->balloc, StringRef{std::begin(line), sep_it});
17042c593315Sopenharmony_ci
17052c593315Sopenharmony_ci    auto secret =
17062c593315Sopenharmony_ci        util::decode_hex(config->balloc, StringRef{sep_it + 1, std::end(line)});
17072c593315Sopenharmony_ci
17082c593315Sopenharmony_ci    auto rv = tlsconf.psk_secrets.emplace(identity, secret);
17092c593315Sopenharmony_ci    if (!rv.second) {
17102c593315Sopenharmony_ci      LOG(ERROR) << SHRPX_OPT_PSK_SECRETS
17112c593315Sopenharmony_ci                 << ": identity has already been registered at line " << lineno;
17122c593315Sopenharmony_ci      return -1;
17132c593315Sopenharmony_ci    }
17142c593315Sopenharmony_ci  }
17152c593315Sopenharmony_ci
17162c593315Sopenharmony_ci  return 0;
17172c593315Sopenharmony_ci}
17182c593315Sopenharmony_ci} // namespace
17192c593315Sopenharmony_ci#endif // !LIBRESSL_LEGACY_API
17202c593315Sopenharmony_ci
17212c593315Sopenharmony_ci#if !LIBRESSL_LEGACY_API
17222c593315Sopenharmony_cinamespace {
17232c593315Sopenharmony_ci// Reads PSK secrets from path, and parses each line.  The result is
17242c593315Sopenharmony_ci// directly stored into config->tls.client.psk.  This function returns
17252c593315Sopenharmony_ci// 0 if it succeeds, or -1.
17262c593315Sopenharmony_ciint parse_client_psk_secrets(Config *config, const StringRef &path) {
17272c593315Sopenharmony_ci  auto &tlsconf = config->tls;
17282c593315Sopenharmony_ci
17292c593315Sopenharmony_ci  std::ifstream f(path.c_str(), std::ios::binary);
17302c593315Sopenharmony_ci  if (!f) {
17312c593315Sopenharmony_ci    LOG(ERROR) << SHRPX_OPT_CLIENT_PSK_SECRETS << ": could not open file "
17322c593315Sopenharmony_ci               << path;
17332c593315Sopenharmony_ci    return -1;
17342c593315Sopenharmony_ci  }
17352c593315Sopenharmony_ci
17362c593315Sopenharmony_ci  size_t lineno = 0;
17372c593315Sopenharmony_ci  std::string line;
17382c593315Sopenharmony_ci  while (std::getline(f, line)) {
17392c593315Sopenharmony_ci    ++lineno;
17402c593315Sopenharmony_ci    if (line.empty() || line[0] == '#') {
17412c593315Sopenharmony_ci      continue;
17422c593315Sopenharmony_ci    }
17432c593315Sopenharmony_ci
17442c593315Sopenharmony_ci    auto sep_it = std::find(std::begin(line), std::end(line), ':');
17452c593315Sopenharmony_ci    if (sep_it == std::end(line)) {
17462c593315Sopenharmony_ci      LOG(ERROR) << SHRPX_OPT_CLIENT_PSK_SECRETS
17472c593315Sopenharmony_ci                 << ": could not find separator at line " << lineno;
17482c593315Sopenharmony_ci      return -1;
17492c593315Sopenharmony_ci    }
17502c593315Sopenharmony_ci
17512c593315Sopenharmony_ci    if (sep_it == std::begin(line)) {
17522c593315Sopenharmony_ci      LOG(ERROR) << SHRPX_OPT_CLIENT_PSK_SECRETS << ": empty identity at line "
17532c593315Sopenharmony_ci                 << lineno;
17542c593315Sopenharmony_ci      return -1;
17552c593315Sopenharmony_ci    }
17562c593315Sopenharmony_ci
17572c593315Sopenharmony_ci    if (sep_it + 1 == std::end(line)) {
17582c593315Sopenharmony_ci      LOG(ERROR) << SHRPX_OPT_CLIENT_PSK_SECRETS << ": empty secret at line "
17592c593315Sopenharmony_ci                 << lineno;
17602c593315Sopenharmony_ci      return -1;
17612c593315Sopenharmony_ci    }
17622c593315Sopenharmony_ci
17632c593315Sopenharmony_ci    if (!util::is_hex_string(StringRef{sep_it + 1, std::end(line)})) {
17642c593315Sopenharmony_ci      LOG(ERROR) << SHRPX_OPT_CLIENT_PSK_SECRETS
17652c593315Sopenharmony_ci                 << ": secret must be hex string at line " << lineno;
17662c593315Sopenharmony_ci      return -1;
17672c593315Sopenharmony_ci    }
17682c593315Sopenharmony_ci
17692c593315Sopenharmony_ci    tlsconf.client.psk.identity =
17702c593315Sopenharmony_ci        make_string_ref(config->balloc, StringRef{std::begin(line), sep_it});
17712c593315Sopenharmony_ci
17722c593315Sopenharmony_ci    tlsconf.client.psk.secret =
17732c593315Sopenharmony_ci        util::decode_hex(config->balloc, StringRef{sep_it + 1, std::end(line)});
17742c593315Sopenharmony_ci
17752c593315Sopenharmony_ci    return 0;
17762c593315Sopenharmony_ci  }
17772c593315Sopenharmony_ci
17782c593315Sopenharmony_ci  return 0;
17792c593315Sopenharmony_ci}
17802c593315Sopenharmony_ci} // namespace
17812c593315Sopenharmony_ci#endif // !LIBRESSL_LEGACY_API
17822c593315Sopenharmony_ci
17832c593315Sopenharmony_ci// generated by gennghttpxfun.py
17842c593315Sopenharmony_ciint option_lookup_token(const char *name, size_t namelen) {
17852c593315Sopenharmony_ci  switch (namelen) {
17862c593315Sopenharmony_ci  case 4:
17872c593315Sopenharmony_ci    switch (name[3]) {
17882c593315Sopenharmony_ci    case 'f':
17892c593315Sopenharmony_ci      if (util::strieq_l("con", name, 3)) {
17902c593315Sopenharmony_ci        return SHRPX_OPTID_CONF;
17912c593315Sopenharmony_ci      }
17922c593315Sopenharmony_ci      break;
17932c593315Sopenharmony_ci    case 'r':
17942c593315Sopenharmony_ci      if (util::strieq_l("use", name, 3)) {
17952c593315Sopenharmony_ci        return SHRPX_OPTID_USER;
17962c593315Sopenharmony_ci      }
17972c593315Sopenharmony_ci      break;
17982c593315Sopenharmony_ci    }
17992c593315Sopenharmony_ci    break;
18002c593315Sopenharmony_ci  case 6:
18012c593315Sopenharmony_ci    switch (name[5]) {
18022c593315Sopenharmony_ci    case 'a':
18032c593315Sopenharmony_ci      if (util::strieq_l("no-vi", name, 5)) {
18042c593315Sopenharmony_ci        return SHRPX_OPTID_NO_VIA;
18052c593315Sopenharmony_ci      }
18062c593315Sopenharmony_ci      break;
18072c593315Sopenharmony_ci    case 'c':
18082c593315Sopenharmony_ci      if (util::strieq_l("altsv", name, 5)) {
18092c593315Sopenharmony_ci        return SHRPX_OPTID_ALTSVC;
18102c593315Sopenharmony_ci      }
18112c593315Sopenharmony_ci      break;
18122c593315Sopenharmony_ci    case 'n':
18132c593315Sopenharmony_ci      if (util::strieq_l("daemo", name, 5)) {
18142c593315Sopenharmony_ci        return SHRPX_OPTID_DAEMON;
18152c593315Sopenharmony_ci      }
18162c593315Sopenharmony_ci      break;
18172c593315Sopenharmony_ci    case 't':
18182c593315Sopenharmony_ci      if (util::strieq_l("cacer", name, 5)) {
18192c593315Sopenharmony_ci        return SHRPX_OPTID_CACERT;
18202c593315Sopenharmony_ci      }
18212c593315Sopenharmony_ci      if (util::strieq_l("clien", name, 5)) {
18222c593315Sopenharmony_ci        return SHRPX_OPTID_CLIENT;
18232c593315Sopenharmony_ci      }
18242c593315Sopenharmony_ci      break;
18252c593315Sopenharmony_ci    }
18262c593315Sopenharmony_ci    break;
18272c593315Sopenharmony_ci  case 7:
18282c593315Sopenharmony_ci    switch (name[6]) {
18292c593315Sopenharmony_ci    case 'd':
18302c593315Sopenharmony_ci      if (util::strieq_l("backen", name, 6)) {
18312c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND;
18322c593315Sopenharmony_ci      }
18332c593315Sopenharmony_ci      break;
18342c593315Sopenharmony_ci    case 'e':
18352c593315Sopenharmony_ci      if (util::strieq_l("includ", name, 6)) {
18362c593315Sopenharmony_ci        return SHRPX_OPTID_INCLUDE;
18372c593315Sopenharmony_ci      }
18382c593315Sopenharmony_ci      break;
18392c593315Sopenharmony_ci    case 'g':
18402c593315Sopenharmony_ci      if (util::strieq_l("backlo", name, 6)) {
18412c593315Sopenharmony_ci        return SHRPX_OPTID_BACKLOG;
18422c593315Sopenharmony_ci      }
18432c593315Sopenharmony_ci      if (util::strieq_l("paddin", name, 6)) {
18442c593315Sopenharmony_ci        return SHRPX_OPTID_PADDING;
18452c593315Sopenharmony_ci      }
18462c593315Sopenharmony_ci      break;
18472c593315Sopenharmony_ci    case 'p':
18482c593315Sopenharmony_ci      if (util::strieq_l("no-ocs", name, 6)) {
18492c593315Sopenharmony_ci        return SHRPX_OPTID_NO_OCSP;
18502c593315Sopenharmony_ci      }
18512c593315Sopenharmony_ci      break;
18522c593315Sopenharmony_ci    case 's':
18532c593315Sopenharmony_ci      if (util::strieq_l("cipher", name, 6)) {
18542c593315Sopenharmony_ci        return SHRPX_OPTID_CIPHERS;
18552c593315Sopenharmony_ci      }
18562c593315Sopenharmony_ci      if (util::strieq_l("worker", name, 6)) {
18572c593315Sopenharmony_ci        return SHRPX_OPTID_WORKERS;
18582c593315Sopenharmony_ci      }
18592c593315Sopenharmony_ci      break;
18602c593315Sopenharmony_ci    case 't':
18612c593315Sopenharmony_ci      if (util::strieq_l("subcer", name, 6)) {
18622c593315Sopenharmony_ci        return SHRPX_OPTID_SUBCERT;
18632c593315Sopenharmony_ci      }
18642c593315Sopenharmony_ci      break;
18652c593315Sopenharmony_ci    }
18662c593315Sopenharmony_ci    break;
18672c593315Sopenharmony_ci  case 8:
18682c593315Sopenharmony_ci    switch (name[7]) {
18692c593315Sopenharmony_ci    case 'd':
18702c593315Sopenharmony_ci      if (util::strieq_l("fronten", name, 7)) {
18712c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND;
18722c593315Sopenharmony_ci      }
18732c593315Sopenharmony_ci      break;
18742c593315Sopenharmony_ci    case 'e':
18752c593315Sopenharmony_ci      if (util::strieq_l("insecur", name, 7)) {
18762c593315Sopenharmony_ci        return SHRPX_OPTID_INSECURE;
18772c593315Sopenharmony_ci      }
18782c593315Sopenharmony_ci      if (util::strieq_l("pid-fil", name, 7)) {
18792c593315Sopenharmony_ci        return SHRPX_OPTID_PID_FILE;
18802c593315Sopenharmony_ci      }
18812c593315Sopenharmony_ci      break;
18822c593315Sopenharmony_ci    case 'n':
18832c593315Sopenharmony_ci      if (util::strieq_l("fastope", name, 7)) {
18842c593315Sopenharmony_ci        return SHRPX_OPTID_FASTOPEN;
18852c593315Sopenharmony_ci      }
18862c593315Sopenharmony_ci      break;
18872c593315Sopenharmony_ci    case 's':
18882c593315Sopenharmony_ci      if (util::strieq_l("tls-ktl", name, 7)) {
18892c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_KTLS;
18902c593315Sopenharmony_ci      }
18912c593315Sopenharmony_ci      break;
18922c593315Sopenharmony_ci    case 't':
18932c593315Sopenharmony_ci      if (util::strieq_l("npn-lis", name, 7)) {
18942c593315Sopenharmony_ci        return SHRPX_OPTID_NPN_LIST;
18952c593315Sopenharmony_ci      }
18962c593315Sopenharmony_ci      break;
18972c593315Sopenharmony_ci    }
18982c593315Sopenharmony_ci    break;
18992c593315Sopenharmony_ci  case 9:
19002c593315Sopenharmony_ci    switch (name[8]) {
19012c593315Sopenharmony_ci    case 'e':
19022c593315Sopenharmony_ci      if (util::strieq_l("no-kqueu", name, 8)) {
19032c593315Sopenharmony_ci        return SHRPX_OPTID_NO_KQUEUE;
19042c593315Sopenharmony_ci      }
19052c593315Sopenharmony_ci      if (util::strieq_l("read-rat", name, 8)) {
19062c593315Sopenharmony_ci        return SHRPX_OPTID_READ_RATE;
19072c593315Sopenharmony_ci      }
19082c593315Sopenharmony_ci      break;
19092c593315Sopenharmony_ci    case 'l':
19102c593315Sopenharmony_ci      if (util::strieq_l("log-leve", name, 8)) {
19112c593315Sopenharmony_ci        return SHRPX_OPTID_LOG_LEVEL;
19122c593315Sopenharmony_ci      }
19132c593315Sopenharmony_ci      break;
19142c593315Sopenharmony_ci    }
19152c593315Sopenharmony_ci    break;
19162c593315Sopenharmony_ci  case 10:
19172c593315Sopenharmony_ci    switch (name[9]) {
19182c593315Sopenharmony_ci    case 'e':
19192c593315Sopenharmony_ci      if (util::strieq_l("error-pag", name, 9)) {
19202c593315Sopenharmony_ci        return SHRPX_OPTID_ERROR_PAGE;
19212c593315Sopenharmony_ci      }
19222c593315Sopenharmony_ci      if (util::strieq_l("mruby-fil", name, 9)) {
19232c593315Sopenharmony_ci        return SHRPX_OPTID_MRUBY_FILE;
19242c593315Sopenharmony_ci      }
19252c593315Sopenharmony_ci      if (util::strieq_l("write-rat", name, 9)) {
19262c593315Sopenharmony_ci        return SHRPX_OPTID_WRITE_RATE;
19272c593315Sopenharmony_ci      }
19282c593315Sopenharmony_ci      break;
19292c593315Sopenharmony_ci    case 't':
19302c593315Sopenharmony_ci      if (util::strieq_l("read-burs", name, 9)) {
19312c593315Sopenharmony_ci        return SHRPX_OPTID_READ_BURST;
19322c593315Sopenharmony_ci      }
19332c593315Sopenharmony_ci      break;
19342c593315Sopenharmony_ci    }
19352c593315Sopenharmony_ci    break;
19362c593315Sopenharmony_ci  case 11:
19372c593315Sopenharmony_ci    switch (name[10]) {
19382c593315Sopenharmony_ci    case 'e':
19392c593315Sopenharmony_ci      if (util::strieq_l("server-nam", name, 10)) {
19402c593315Sopenharmony_ci        return SHRPX_OPTID_SERVER_NAME;
19412c593315Sopenharmony_ci      }
19422c593315Sopenharmony_ci      break;
19432c593315Sopenharmony_ci    case 'f':
19442c593315Sopenharmony_ci      if (util::strieq_l("no-quic-bp", name, 10)) {
19452c593315Sopenharmony_ci        return SHRPX_OPTID_NO_QUIC_BPF;
19462c593315Sopenharmony_ci      }
19472c593315Sopenharmony_ci      break;
19482c593315Sopenharmony_ci    case 'r':
19492c593315Sopenharmony_ci      if (util::strieq_l("tls-sct-di", name, 10)) {
19502c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_SCT_DIR;
19512c593315Sopenharmony_ci      }
19522c593315Sopenharmony_ci      break;
19532c593315Sopenharmony_ci    case 's':
19542c593315Sopenharmony_ci      if (util::strieq_l("backend-tl", name, 10)) {
19552c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_TLS;
19562c593315Sopenharmony_ci      }
19572c593315Sopenharmony_ci      if (util::strieq_l("ecdh-curve", name, 10)) {
19582c593315Sopenharmony_ci        return SHRPX_OPTID_ECDH_CURVES;
19592c593315Sopenharmony_ci      }
19602c593315Sopenharmony_ci      if (util::strieq_l("psk-secret", name, 10)) {
19612c593315Sopenharmony_ci        return SHRPX_OPTID_PSK_SECRETS;
19622c593315Sopenharmony_ci      }
19632c593315Sopenharmony_ci      break;
19642c593315Sopenharmony_ci    case 't':
19652c593315Sopenharmony_ci      if (util::strieq_l("write-burs", name, 10)) {
19662c593315Sopenharmony_ci        return SHRPX_OPTID_WRITE_BURST;
19672c593315Sopenharmony_ci      }
19682c593315Sopenharmony_ci      break;
19692c593315Sopenharmony_ci    case 'y':
19702c593315Sopenharmony_ci      if (util::strieq_l("dns-max-tr", name, 10)) {
19712c593315Sopenharmony_ci        return SHRPX_OPTID_DNS_MAX_TRY;
19722c593315Sopenharmony_ci      }
19732c593315Sopenharmony_ci      if (util::strieq_l("http2-prox", name, 10)) {
19742c593315Sopenharmony_ci        return SHRPX_OPTID_HTTP2_PROXY;
19752c593315Sopenharmony_ci      }
19762c593315Sopenharmony_ci      break;
19772c593315Sopenharmony_ci    }
19782c593315Sopenharmony_ci    break;
19792c593315Sopenharmony_ci  case 12:
19802c593315Sopenharmony_ci    switch (name[11]) {
19812c593315Sopenharmony_ci    case '4':
19822c593315Sopenharmony_ci      if (util::strieq_l("backend-ipv", name, 11)) {
19832c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_IPV4;
19842c593315Sopenharmony_ci      }
19852c593315Sopenharmony_ci      break;
19862c593315Sopenharmony_ci    case '6':
19872c593315Sopenharmony_ci      if (util::strieq_l("backend-ipv", name, 11)) {
19882c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_IPV6;
19892c593315Sopenharmony_ci      }
19902c593315Sopenharmony_ci      break;
19912c593315Sopenharmony_ci    case 'c':
19922c593315Sopenharmony_ci      if (util::strieq_l("http2-altsv", name, 11)) {
19932c593315Sopenharmony_ci        return SHRPX_OPTID_HTTP2_ALTSVC;
19942c593315Sopenharmony_ci      }
19952c593315Sopenharmony_ci      break;
19962c593315Sopenharmony_ci    case 'e':
19972c593315Sopenharmony_ci      if (util::strieq_l("host-rewrit", name, 11)) {
19982c593315Sopenharmony_ci        return SHRPX_OPTID_HOST_REWRITE;
19992c593315Sopenharmony_ci      }
20002c593315Sopenharmony_ci      if (util::strieq_l("http2-bridg", name, 11)) {
20012c593315Sopenharmony_ci        return SHRPX_OPTID_HTTP2_BRIDGE;
20022c593315Sopenharmony_ci      }
20032c593315Sopenharmony_ci      break;
20042c593315Sopenharmony_ci    case 'p':
20052c593315Sopenharmony_ci      if (util::strieq_l("ocsp-startu", name, 11)) {
20062c593315Sopenharmony_ci        return SHRPX_OPTID_OCSP_STARTUP;
20072c593315Sopenharmony_ci      }
20082c593315Sopenharmony_ci      break;
20092c593315Sopenharmony_ci    case 'y':
20102c593315Sopenharmony_ci      if (util::strieq_l("client-prox", name, 11)) {
20112c593315Sopenharmony_ci        return SHRPX_OPTID_CLIENT_PROXY;
20122c593315Sopenharmony_ci      }
20132c593315Sopenharmony_ci      if (util::strieq_l("forwarded-b", name, 11)) {
20142c593315Sopenharmony_ci        return SHRPX_OPTID_FORWARDED_BY;
20152c593315Sopenharmony_ci      }
20162c593315Sopenharmony_ci      break;
20172c593315Sopenharmony_ci    }
20182c593315Sopenharmony_ci    break;
20192c593315Sopenharmony_ci  case 13:
20202c593315Sopenharmony_ci    switch (name[12]) {
20212c593315Sopenharmony_ci    case 'd':
20222c593315Sopenharmony_ci      if (util::strieq_l("add-forwarde", name, 12)) {
20232c593315Sopenharmony_ci        return SHRPX_OPTID_ADD_FORWARDED;
20242c593315Sopenharmony_ci      }
20252c593315Sopenharmony_ci      if (util::strieq_l("single-threa", name, 12)) {
20262c593315Sopenharmony_ci        return SHRPX_OPTID_SINGLE_THREAD;
20272c593315Sopenharmony_ci      }
20282c593315Sopenharmony_ci      break;
20292c593315Sopenharmony_ci    case 'e':
20302c593315Sopenharmony_ci      if (util::strieq_l("dh-param-fil", name, 12)) {
20312c593315Sopenharmony_ci        return SHRPX_OPTID_DH_PARAM_FILE;
20322c593315Sopenharmony_ci      }
20332c593315Sopenharmony_ci      if (util::strieq_l("errorlog-fil", name, 12)) {
20342c593315Sopenharmony_ci        return SHRPX_OPTID_ERRORLOG_FILE;
20352c593315Sopenharmony_ci      }
20362c593315Sopenharmony_ci      if (util::strieq_l("rlimit-nofil", name, 12)) {
20372c593315Sopenharmony_ci        return SHRPX_OPTID_RLIMIT_NOFILE;
20382c593315Sopenharmony_ci      }
20392c593315Sopenharmony_ci      break;
20402c593315Sopenharmony_ci    case 'r':
20412c593315Sopenharmony_ci      if (util::strieq_l("forwarded-fo", name, 12)) {
20422c593315Sopenharmony_ci        return SHRPX_OPTID_FORWARDED_FOR;
20432c593315Sopenharmony_ci      }
20442c593315Sopenharmony_ci      break;
20452c593315Sopenharmony_ci    case 's':
20462c593315Sopenharmony_ci      if (util::strieq_l("tls13-cipher", name, 12)) {
20472c593315Sopenharmony_ci        return SHRPX_OPTID_TLS13_CIPHERS;
20482c593315Sopenharmony_ci      }
20492c593315Sopenharmony_ci      break;
20502c593315Sopenharmony_ci    case 't':
20512c593315Sopenharmony_ci      if (util::strieq_l("verify-clien", name, 12)) {
20522c593315Sopenharmony_ci        return SHRPX_OPTID_VERIFY_CLIENT;
20532c593315Sopenharmony_ci      }
20542c593315Sopenharmony_ci      break;
20552c593315Sopenharmony_ci    }
20562c593315Sopenharmony_ci    break;
20572c593315Sopenharmony_ci  case 14:
20582c593315Sopenharmony_ci    switch (name[13]) {
20592c593315Sopenharmony_ci    case 'd':
20602c593315Sopenharmony_ci      if (util::strieq_l("quic-server-i", name, 13)) {
20612c593315Sopenharmony_ci        return SHRPX_OPTID_QUIC_SERVER_ID;
20622c593315Sopenharmony_ci      }
20632c593315Sopenharmony_ci      break;
20642c593315Sopenharmony_ci    case 'e':
20652c593315Sopenharmony_ci      if (util::strieq_l("accesslog-fil", name, 13)) {
20662c593315Sopenharmony_ci        return SHRPX_OPTID_ACCESSLOG_FILE;
20672c593315Sopenharmony_ci      }
20682c593315Sopenharmony_ci      break;
20692c593315Sopenharmony_ci    case 'h':
20702c593315Sopenharmony_ci      if (util::strieq_l("no-server-pus", name, 13)) {
20712c593315Sopenharmony_ci        return SHRPX_OPTID_NO_SERVER_PUSH;
20722c593315Sopenharmony_ci      }
20732c593315Sopenharmony_ci      break;
20742c593315Sopenharmony_ci    case 'k':
20752c593315Sopenharmony_ci      if (util::strieq_l("rlimit-memloc", name, 13)) {
20762c593315Sopenharmony_ci        return SHRPX_OPTID_RLIMIT_MEMLOCK;
20772c593315Sopenharmony_ci      }
20782c593315Sopenharmony_ci      break;
20792c593315Sopenharmony_ci    case 'p':
20802c593315Sopenharmony_ci      if (util::strieq_l("no-verify-ocs", name, 13)) {
20812c593315Sopenharmony_ci        return SHRPX_OPTID_NO_VERIFY_OCSP;
20822c593315Sopenharmony_ci      }
20832c593315Sopenharmony_ci      break;
20842c593315Sopenharmony_ci    case 's':
20852c593315Sopenharmony_ci      if (util::strieq_l("backend-no-tl", name, 13)) {
20862c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_NO_TLS;
20872c593315Sopenharmony_ci      }
20882c593315Sopenharmony_ci      if (util::strieq_l("client-cipher", name, 13)) {
20892c593315Sopenharmony_ci        return SHRPX_OPTID_CLIENT_CIPHERS;
20902c593315Sopenharmony_ci      }
20912c593315Sopenharmony_ci      if (util::strieq_l("single-proces", name, 13)) {
20922c593315Sopenharmony_ci        return SHRPX_OPTID_SINGLE_PROCESS;
20932c593315Sopenharmony_ci      }
20942c593315Sopenharmony_ci      break;
20952c593315Sopenharmony_ci    case 't':
20962c593315Sopenharmony_ci      if (util::strieq_l("tls-proto-lis", name, 13)) {
20972c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_PROTO_LIST;
20982c593315Sopenharmony_ci      }
20992c593315Sopenharmony_ci      break;
21002c593315Sopenharmony_ci    }
21012c593315Sopenharmony_ci    break;
21022c593315Sopenharmony_ci  case 15:
21032c593315Sopenharmony_ci    switch (name[14]) {
21042c593315Sopenharmony_ci    case 'e':
21052c593315Sopenharmony_ci      if (util::strieq_l("no-host-rewrit", name, 14)) {
21062c593315Sopenharmony_ci        return SHRPX_OPTID_NO_HOST_REWRITE;
21072c593315Sopenharmony_ci      }
21082c593315Sopenharmony_ci      break;
21092c593315Sopenharmony_ci    case 'g':
21102c593315Sopenharmony_ci      if (util::strieq_l("errorlog-syslo", name, 14)) {
21112c593315Sopenharmony_ci        return SHRPX_OPTID_ERRORLOG_SYSLOG;
21122c593315Sopenharmony_ci      }
21132c593315Sopenharmony_ci      break;
21142c593315Sopenharmony_ci    case 's':
21152c593315Sopenharmony_ci      if (util::strieq_l("frontend-no-tl", name, 14)) {
21162c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_NO_TLS;
21172c593315Sopenharmony_ci      }
21182c593315Sopenharmony_ci      break;
21192c593315Sopenharmony_ci    case 'y':
21202c593315Sopenharmony_ci      if (util::strieq_l("syslog-facilit", name, 14)) {
21212c593315Sopenharmony_ci        return SHRPX_OPTID_SYSLOG_FACILITY;
21222c593315Sopenharmony_ci      }
21232c593315Sopenharmony_ci      break;
21242c593315Sopenharmony_ci    }
21252c593315Sopenharmony_ci    break;
21262c593315Sopenharmony_ci  case 16:
21272c593315Sopenharmony_ci    switch (name[15]) {
21282c593315Sopenharmony_ci    case 'e':
21292c593315Sopenharmony_ci      if (util::strieq_l("certificate-fil", name, 15)) {
21302c593315Sopenharmony_ci        return SHRPX_OPTID_CERTIFICATE_FILE;
21312c593315Sopenharmony_ci      }
21322c593315Sopenharmony_ci      if (util::strieq_l("client-cert-fil", name, 15)) {
21332c593315Sopenharmony_ci        return SHRPX_OPTID_CLIENT_CERT_FILE;
21342c593315Sopenharmony_ci      }
21352c593315Sopenharmony_ci      if (util::strieq_l("private-key-fil", name, 15)) {
21362c593315Sopenharmony_ci        return SHRPX_OPTID_PRIVATE_KEY_FILE;
21372c593315Sopenharmony_ci      }
21382c593315Sopenharmony_ci      if (util::strieq_l("worker-read-rat", name, 15)) {
21392c593315Sopenharmony_ci        return SHRPX_OPTID_WORKER_READ_RATE;
21402c593315Sopenharmony_ci      }
21412c593315Sopenharmony_ci      break;
21422c593315Sopenharmony_ci    case 'g':
21432c593315Sopenharmony_ci      if (util::strieq_l("accesslog-syslo", name, 15)) {
21442c593315Sopenharmony_ci        return SHRPX_OPTID_ACCESSLOG_SYSLOG;
21452c593315Sopenharmony_ci      }
21462c593315Sopenharmony_ci      break;
21472c593315Sopenharmony_ci    case 't':
21482c593315Sopenharmony_ci      if (util::strieq_l("accesslog-forma", name, 15)) {
21492c593315Sopenharmony_ci        return SHRPX_OPTID_ACCESSLOG_FORMAT;
21502c593315Sopenharmony_ci      }
21512c593315Sopenharmony_ci      break;
21522c593315Sopenharmony_ci    }
21532c593315Sopenharmony_ci    break;
21542c593315Sopenharmony_ci  case 17:
21552c593315Sopenharmony_ci    switch (name[16]) {
21562c593315Sopenharmony_ci    case 'e':
21572c593315Sopenharmony_ci      if (util::strieq_l("no-server-rewrit", name, 16)) {
21582c593315Sopenharmony_ci        return SHRPX_OPTID_NO_SERVER_REWRITE;
21592c593315Sopenharmony_ci      }
21602c593315Sopenharmony_ci      if (util::strieq_l("worker-write-rat", name, 16)) {
21612c593315Sopenharmony_ci        return SHRPX_OPTID_WORKER_WRITE_RATE;
21622c593315Sopenharmony_ci      }
21632c593315Sopenharmony_ci      break;
21642c593315Sopenharmony_ci    case 's':
21652c593315Sopenharmony_ci      if (util::strieq_l("backend-http1-tl", name, 16)) {
21662c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_HTTP1_TLS;
21672c593315Sopenharmony_ci      }
21682c593315Sopenharmony_ci      if (util::strieq_l("max-header-field", name, 16)) {
21692c593315Sopenharmony_ci        return SHRPX_OPTID_MAX_HEADER_FIELDS;
21702c593315Sopenharmony_ci      }
21712c593315Sopenharmony_ci      break;
21722c593315Sopenharmony_ci    case 't':
21732c593315Sopenharmony_ci      if (util::strieq_l("dns-cache-timeou", name, 16)) {
21742c593315Sopenharmony_ci        return SHRPX_OPTID_DNS_CACHE_TIMEOUT;
21752c593315Sopenharmony_ci      }
21762c593315Sopenharmony_ci      if (util::strieq_l("worker-read-burs", name, 16)) {
21772c593315Sopenharmony_ci        return SHRPX_OPTID_WORKER_READ_BURST;
21782c593315Sopenharmony_ci      }
21792c593315Sopenharmony_ci      break;
21802c593315Sopenharmony_ci    }
21812c593315Sopenharmony_ci    break;
21822c593315Sopenharmony_ci  case 18:
21832c593315Sopenharmony_ci    switch (name[17]) {
21842c593315Sopenharmony_ci    case 'a':
21852c593315Sopenharmony_ci      if (util::strieq_l("tls-max-early-dat", name, 17)) {
21862c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_MAX_EARLY_DATA;
21872c593315Sopenharmony_ci      }
21882c593315Sopenharmony_ci      break;
21892c593315Sopenharmony_ci    case 'r':
21902c593315Sopenharmony_ci      if (util::strieq_l("add-request-heade", name, 17)) {
21912c593315Sopenharmony_ci        return SHRPX_OPTID_ADD_REQUEST_HEADER;
21922c593315Sopenharmony_ci      }
21932c593315Sopenharmony_ci      break;
21942c593315Sopenharmony_ci    case 's':
21952c593315Sopenharmony_ci      if (util::strieq_l("client-psk-secret", name, 17)) {
21962c593315Sopenharmony_ci        return SHRPX_OPTID_CLIENT_PSK_SECRETS;
21972c593315Sopenharmony_ci      }
21982c593315Sopenharmony_ci      break;
21992c593315Sopenharmony_ci    case 't':
22002c593315Sopenharmony_ci      if (util::strieq_l("dns-lookup-timeou", name, 17)) {
22012c593315Sopenharmony_ci        return SHRPX_OPTID_DNS_LOOKUP_TIMEOUT;
22022c593315Sopenharmony_ci      }
22032c593315Sopenharmony_ci      if (util::strieq_l("worker-write-burs", name, 17)) {
22042c593315Sopenharmony_ci        return SHRPX_OPTID_WORKER_WRITE_BURST;
22052c593315Sopenharmony_ci      }
22062c593315Sopenharmony_ci      break;
22072c593315Sopenharmony_ci    }
22082c593315Sopenharmony_ci    break;
22092c593315Sopenharmony_ci  case 19:
22102c593315Sopenharmony_ci    switch (name[18]) {
22112c593315Sopenharmony_ci    case 'e':
22122c593315Sopenharmony_ci      if (util::strieq_l("no-location-rewrit", name, 18)) {
22132c593315Sopenharmony_ci        return SHRPX_OPTID_NO_LOCATION_REWRITE;
22142c593315Sopenharmony_ci      }
22152c593315Sopenharmony_ci      if (util::strieq_l("require-http-schem", name, 18)) {
22162c593315Sopenharmony_ci        return SHRPX_OPTID_REQUIRE_HTTP_SCHEME;
22172c593315Sopenharmony_ci      }
22182c593315Sopenharmony_ci      if (util::strieq_l("tls-ticket-key-fil", name, 18)) {
22192c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_TICKET_KEY_FILE;
22202c593315Sopenharmony_ci      }
22212c593315Sopenharmony_ci      break;
22222c593315Sopenharmony_ci    case 'f':
22232c593315Sopenharmony_ci      if (util::strieq_l("backend-max-backof", name, 18)) {
22242c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_MAX_BACKOFF;
22252c593315Sopenharmony_ci      }
22262c593315Sopenharmony_ci      break;
22272c593315Sopenharmony_ci    case 'r':
22282c593315Sopenharmony_ci      if (util::strieq_l("add-response-heade", name, 18)) {
22292c593315Sopenharmony_ci        return SHRPX_OPTID_ADD_RESPONSE_HEADER;
22302c593315Sopenharmony_ci      }
22312c593315Sopenharmony_ci      if (util::strieq_l("add-x-forwarded-fo", name, 18)) {
22322c593315Sopenharmony_ci        return SHRPX_OPTID_ADD_X_FORWARDED_FOR;
22332c593315Sopenharmony_ci      }
22342c593315Sopenharmony_ci      if (util::strieq_l("header-field-buffe", name, 18)) {
22352c593315Sopenharmony_ci        return SHRPX_OPTID_HEADER_FIELD_BUFFER;
22362c593315Sopenharmony_ci      }
22372c593315Sopenharmony_ci      break;
22382c593315Sopenharmony_ci    case 't':
22392c593315Sopenharmony_ci      if (util::strieq_l("redirect-https-por", name, 18)) {
22402c593315Sopenharmony_ci        return SHRPX_OPTID_REDIRECT_HTTPS_PORT;
22412c593315Sopenharmony_ci      }
22422c593315Sopenharmony_ci      if (util::strieq_l("stream-read-timeou", name, 18)) {
22432c593315Sopenharmony_ci        return SHRPX_OPTID_STREAM_READ_TIMEOUT;
22442c593315Sopenharmony_ci      }
22452c593315Sopenharmony_ci      break;
22462c593315Sopenharmony_ci    }
22472c593315Sopenharmony_ci    break;
22482c593315Sopenharmony_ci  case 20:
22492c593315Sopenharmony_ci    switch (name[19]) {
22502c593315Sopenharmony_ci    case 'g':
22512c593315Sopenharmony_ci      if (util::strieq_l("frontend-frame-debu", name, 19)) {
22522c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_FRAME_DEBUG;
22532c593315Sopenharmony_ci      }
22542c593315Sopenharmony_ci      break;
22552c593315Sopenharmony_ci    case 'l':
22562c593315Sopenharmony_ci      if (util::strieq_l("ocsp-update-interva", name, 19)) {
22572c593315Sopenharmony_ci        return SHRPX_OPTID_OCSP_UPDATE_INTERVAL;
22582c593315Sopenharmony_ci      }
22592c593315Sopenharmony_ci      break;
22602c593315Sopenharmony_ci    case 's':
22612c593315Sopenharmony_ci      if (util::strieq_l("max-worker-processe", name, 19)) {
22622c593315Sopenharmony_ci        return SHRPX_OPTID_MAX_WORKER_PROCESSES;
22632c593315Sopenharmony_ci      }
22642c593315Sopenharmony_ci      if (util::strieq_l("tls13-client-cipher", name, 19)) {
22652c593315Sopenharmony_ci        return SHRPX_OPTID_TLS13_CLIENT_CIPHERS;
22662c593315Sopenharmony_ci      }
22672c593315Sopenharmony_ci      break;
22682c593315Sopenharmony_ci    case 't':
22692c593315Sopenharmony_ci      if (util::strieq_l("backend-read-timeou", name, 19)) {
22702c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_READ_TIMEOUT;
22712c593315Sopenharmony_ci      }
22722c593315Sopenharmony_ci      if (util::strieq_l("stream-write-timeou", name, 19)) {
22732c593315Sopenharmony_ci        return SHRPX_OPTID_STREAM_WRITE_TIMEOUT;
22742c593315Sopenharmony_ci      }
22752c593315Sopenharmony_ci      if (util::strieq_l("verify-client-cacer", name, 19)) {
22762c593315Sopenharmony_ci        return SHRPX_OPTID_VERIFY_CLIENT_CACERT;
22772c593315Sopenharmony_ci      }
22782c593315Sopenharmony_ci      break;
22792c593315Sopenharmony_ci    case 'y':
22802c593315Sopenharmony_ci      if (util::strieq_l("api-max-request-bod", name, 19)) {
22812c593315Sopenharmony_ci        return SHRPX_OPTID_API_MAX_REQUEST_BODY;
22822c593315Sopenharmony_ci      }
22832c593315Sopenharmony_ci      break;
22842c593315Sopenharmony_ci    }
22852c593315Sopenharmony_ci    break;
22862c593315Sopenharmony_ci  case 21:
22872c593315Sopenharmony_ci    switch (name[20]) {
22882c593315Sopenharmony_ci    case 'd':
22892c593315Sopenharmony_ci      if (util::strieq_l("backend-tls-sni-fiel", name, 20)) {
22902c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_TLS_SNI_FIELD;
22912c593315Sopenharmony_ci      }
22922c593315Sopenharmony_ci      break;
22932c593315Sopenharmony_ci    case 'e':
22942c593315Sopenharmony_ci      if (util::strieq_l("quic-bpf-program-fil", name, 20)) {
22952c593315Sopenharmony_ci        return SHRPX_OPTID_QUIC_BPF_PROGRAM_FILE;
22962c593315Sopenharmony_ci      }
22972c593315Sopenharmony_ci      break;
22982c593315Sopenharmony_ci    case 'l':
22992c593315Sopenharmony_ci      if (util::strieq_l("accept-proxy-protoco", name, 20)) {
23002c593315Sopenharmony_ci        return SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL;
23012c593315Sopenharmony_ci      }
23022c593315Sopenharmony_ci      break;
23032c593315Sopenharmony_ci    case 'n':
23042c593315Sopenharmony_ci      if (util::strieq_l("tls-max-proto-versio", name, 20)) {
23052c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_MAX_PROTO_VERSION;
23062c593315Sopenharmony_ci      }
23072c593315Sopenharmony_ci      if (util::strieq_l("tls-min-proto-versio", name, 20)) {
23082c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_MIN_PROTO_VERSION;
23092c593315Sopenharmony_ci      }
23102c593315Sopenharmony_ci      break;
23112c593315Sopenharmony_ci    case 'r':
23122c593315Sopenharmony_ci      if (util::strieq_l("tls-ticket-key-ciphe", name, 20)) {
23132c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_TICKET_KEY_CIPHER;
23142c593315Sopenharmony_ci      }
23152c593315Sopenharmony_ci      break;
23162c593315Sopenharmony_ci    case 's':
23172c593315Sopenharmony_ci      if (util::strieq_l("frontend-max-request", name, 20)) {
23182c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_MAX_REQUESTS;
23192c593315Sopenharmony_ci      }
23202c593315Sopenharmony_ci      break;
23212c593315Sopenharmony_ci    case 't':
23222c593315Sopenharmony_ci      if (util::strieq_l("backend-write-timeou", name, 20)) {
23232c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_WRITE_TIMEOUT;
23242c593315Sopenharmony_ci      }
23252c593315Sopenharmony_ci      if (util::strieq_l("frontend-read-timeou", name, 20)) {
23262c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_READ_TIMEOUT;
23272c593315Sopenharmony_ci      }
23282c593315Sopenharmony_ci      break;
23292c593315Sopenharmony_ci    case 'y':
23302c593315Sopenharmony_ci      if (util::strieq_l("accesslog-write-earl", name, 20)) {
23312c593315Sopenharmony_ci        return SHRPX_OPTID_ACCESSLOG_WRITE_EARLY;
23322c593315Sopenharmony_ci      }
23332c593315Sopenharmony_ci      break;
23342c593315Sopenharmony_ci    }
23352c593315Sopenharmony_ci    break;
23362c593315Sopenharmony_ci  case 22:
23372c593315Sopenharmony_ci    switch (name[21]) {
23382c593315Sopenharmony_ci    case 'i':
23392c593315Sopenharmony_ci      if (util::strieq_l("backend-http-proxy-ur", name, 21)) {
23402c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_HTTP_PROXY_URI;
23412c593315Sopenharmony_ci      }
23422c593315Sopenharmony_ci      break;
23432c593315Sopenharmony_ci    case 'r':
23442c593315Sopenharmony_ci      if (util::strieq_l("backend-request-buffe", name, 21)) {
23452c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_REQUEST_BUFFER;
23462c593315Sopenharmony_ci      }
23472c593315Sopenharmony_ci      if (util::strieq_l("frontend-quic-qlog-di", name, 21)) {
23482c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_QUIC_QLOG_DIR;
23492c593315Sopenharmony_ci      }
23502c593315Sopenharmony_ci      break;
23512c593315Sopenharmony_ci    case 't':
23522c593315Sopenharmony_ci      if (util::strieq_l("frontend-write-timeou", name, 21)) {
23532c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_WRITE_TIMEOUT;
23542c593315Sopenharmony_ci      }
23552c593315Sopenharmony_ci      break;
23562c593315Sopenharmony_ci    case 'y':
23572c593315Sopenharmony_ci      if (util::strieq_l("backend-address-famil", name, 21)) {
23582c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_ADDRESS_FAMILY;
23592c593315Sopenharmony_ci      }
23602c593315Sopenharmony_ci      break;
23612c593315Sopenharmony_ci    }
23622c593315Sopenharmony_ci    break;
23632c593315Sopenharmony_ci  case 23:
23642c593315Sopenharmony_ci    switch (name[22]) {
23652c593315Sopenharmony_ci    case 'e':
23662c593315Sopenharmony_ci      if (util::strieq_l("client-private-key-fil", name, 22)) {
23672c593315Sopenharmony_ci        return SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE;
23682c593315Sopenharmony_ci      }
23692c593315Sopenharmony_ci      if (util::strieq_l("private-key-passwd-fil", name, 22)) {
23702c593315Sopenharmony_ci        return SHRPX_OPTID_PRIVATE_KEY_PASSWD_FILE;
23712c593315Sopenharmony_ci      }
23722c593315Sopenharmony_ci      break;
23732c593315Sopenharmony_ci    case 'g':
23742c593315Sopenharmony_ci      if (util::strieq_l("frontend-quic-debug-lo", name, 22)) {
23752c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_QUIC_DEBUG_LOG;
23762c593315Sopenharmony_ci      }
23772c593315Sopenharmony_ci      break;
23782c593315Sopenharmony_ci    case 'r':
23792c593315Sopenharmony_ci      if (util::strieq_l("backend-response-buffe", name, 22)) {
23802c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_RESPONSE_BUFFER;
23812c593315Sopenharmony_ci      }
23822c593315Sopenharmony_ci      break;
23832c593315Sopenharmony_ci    case 't':
23842c593315Sopenharmony_ci      if (util::strieq_l("backend-connect-timeou", name, 22)) {
23852c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_CONNECT_TIMEOUT;
23862c593315Sopenharmony_ci      }
23872c593315Sopenharmony_ci      break;
23882c593315Sopenharmony_ci    }
23892c593315Sopenharmony_ci    break;
23902c593315Sopenharmony_ci  case 24:
23912c593315Sopenharmony_ci    switch (name[23]) {
23922c593315Sopenharmony_ci    case 'a':
23932c593315Sopenharmony_ci      if (util::strieq_l("frontend-quic-early-dat", name, 23)) {
23942c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_QUIC_EARLY_DATA;
23952c593315Sopenharmony_ci      }
23962c593315Sopenharmony_ci      break;
23972c593315Sopenharmony_ci    case 'd':
23982c593315Sopenharmony_ci      if (util::strieq_l("strip-incoming-forwarde", name, 23)) {
23992c593315Sopenharmony_ci        return SHRPX_OPTID_STRIP_INCOMING_FORWARDED;
24002c593315Sopenharmony_ci      }
24012c593315Sopenharmony_ci      if (util::strieq_l("tls-ticket-key-memcache", name, 23)) {
24022c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED;
24032c593315Sopenharmony_ci      }
24042c593315Sopenharmony_ci      break;
24052c593315Sopenharmony_ci    case 'e':
24062c593315Sopenharmony_ci      if (util::strieq_l("fetch-ocsp-response-fil", name, 23)) {
24072c593315Sopenharmony_ci        return SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE;
24082c593315Sopenharmony_ci      }
24092c593315Sopenharmony_ci      break;
24102c593315Sopenharmony_ci    case 'o':
24112c593315Sopenharmony_ci      if (util::strieq_l("no-add-x-forwarded-prot", name, 23)) {
24122c593315Sopenharmony_ci        return SHRPX_OPTID_NO_ADD_X_FORWARDED_PROTO;
24132c593315Sopenharmony_ci      }
24142c593315Sopenharmony_ci      break;
24152c593315Sopenharmony_ci    case 't':
24162c593315Sopenharmony_ci      if (util::strieq_l("listener-disable-timeou", name, 23)) {
24172c593315Sopenharmony_ci        return SHRPX_OPTID_LISTENER_DISABLE_TIMEOUT;
24182c593315Sopenharmony_ci      }
24192c593315Sopenharmony_ci      if (util::strieq_l("tls-dyn-rec-idle-timeou", name, 23)) {
24202c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_DYN_REC_IDLE_TIMEOUT;
24212c593315Sopenharmony_ci      }
24222c593315Sopenharmony_ci      break;
24232c593315Sopenharmony_ci    }
24242c593315Sopenharmony_ci    break;
24252c593315Sopenharmony_ci  case 25:
24262c593315Sopenharmony_ci    switch (name[24]) {
24272c593315Sopenharmony_ci    case 'e':
24282c593315Sopenharmony_ci      if (util::strieq_l("backend-http2-window-siz", name, 24)) {
24292c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_HTTP2_WINDOW_SIZE;
24302c593315Sopenharmony_ci      }
24312c593315Sopenharmony_ci      if (util::strieq_l("frontend-quic-secret-fil", name, 24)) {
24322c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_QUIC_SECRET_FILE;
24332c593315Sopenharmony_ci      }
24342c593315Sopenharmony_ci      break;
24352c593315Sopenharmony_ci    case 'g':
24362c593315Sopenharmony_ci      if (util::strieq_l("http2-no-cookie-crumblin", name, 24)) {
24372c593315Sopenharmony_ci        return SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING;
24382c593315Sopenharmony_ci      }
24392c593315Sopenharmony_ci      break;
24402c593315Sopenharmony_ci    case 's':
24412c593315Sopenharmony_ci      if (util::strieq_l("backend-http2-window-bit", name, 24)) {
24422c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_HTTP2_WINDOW_BITS;
24432c593315Sopenharmony_ci      }
24442c593315Sopenharmony_ci      if (util::strieq_l("max-request-header-field", name, 24)) {
24452c593315Sopenharmony_ci        return SHRPX_OPTID_MAX_REQUEST_HEADER_FIELDS;
24462c593315Sopenharmony_ci      }
24472c593315Sopenharmony_ci      break;
24482c593315Sopenharmony_ci    case 't':
24492c593315Sopenharmony_ci      if (util::strieq_l("frontend-quic-initial-rt", name, 24)) {
24502c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_QUIC_INITIAL_RTT;
24512c593315Sopenharmony_ci      }
24522c593315Sopenharmony_ci      break;
24532c593315Sopenharmony_ci    }
24542c593315Sopenharmony_ci    break;
24552c593315Sopenharmony_ci  case 26:
24562c593315Sopenharmony_ci    switch (name[25]) {
24572c593315Sopenharmony_ci    case 'a':
24582c593315Sopenharmony_ci      if (util::strieq_l("tls-no-postpone-early-dat", name, 25)) {
24592c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_NO_POSTPONE_EARLY_DATA;
24602c593315Sopenharmony_ci      }
24612c593315Sopenharmony_ci      break;
24622c593315Sopenharmony_ci    case 'e':
24632c593315Sopenharmony_ci      if (util::strieq_l("frontend-http2-window-siz", name, 25)) {
24642c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_SIZE;
24652c593315Sopenharmony_ci      }
24662c593315Sopenharmony_ci      if (util::strieq_l("frontend-http3-window-siz", name, 25)) {
24672c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP3_WINDOW_SIZE;
24682c593315Sopenharmony_ci      }
24692c593315Sopenharmony_ci      break;
24702c593315Sopenharmony_ci    case 's':
24712c593315Sopenharmony_ci      if (util::strieq_l("frontend-http2-window-bit", name, 25)) {
24722c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS;
24732c593315Sopenharmony_ci      }
24742c593315Sopenharmony_ci      if (util::strieq_l("max-response-header-field", name, 25)) {
24752c593315Sopenharmony_ci        return SHRPX_OPTID_MAX_RESPONSE_HEADER_FIELDS;
24762c593315Sopenharmony_ci      }
24772c593315Sopenharmony_ci      break;
24782c593315Sopenharmony_ci    case 't':
24792c593315Sopenharmony_ci      if (util::strieq_l("backend-keep-alive-timeou", name, 25)) {
24802c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_KEEP_ALIVE_TIMEOUT;
24812c593315Sopenharmony_ci      }
24822c593315Sopenharmony_ci      if (util::strieq_l("frontend-quic-idle-timeou", name, 25)) {
24832c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_QUIC_IDLE_TIMEOUT;
24842c593315Sopenharmony_ci      }
24852c593315Sopenharmony_ci      if (util::strieq_l("no-http2-cipher-black-lis", name, 25)) {
24862c593315Sopenharmony_ci        return SHRPX_OPTID_NO_HTTP2_CIPHER_BLACK_LIST;
24872c593315Sopenharmony_ci      }
24882c593315Sopenharmony_ci      if (util::strieq_l("no-http2-cipher-block-lis", name, 25)) {
24892c593315Sopenharmony_ci        return SHRPX_OPTID_NO_HTTP2_CIPHER_BLOCK_LIST;
24902c593315Sopenharmony_ci      }
24912c593315Sopenharmony_ci      break;
24922c593315Sopenharmony_ci    }
24932c593315Sopenharmony_ci    break;
24942c593315Sopenharmony_ci  case 27:
24952c593315Sopenharmony_ci    switch (name[26]) {
24962c593315Sopenharmony_ci    case 'd':
24972c593315Sopenharmony_ci      if (util::strieq_l("tls-session-cache-memcache", name, 26)) {
24982c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED;
24992c593315Sopenharmony_ci      }
25002c593315Sopenharmony_ci      break;
25012c593315Sopenharmony_ci    case 'n':
25022c593315Sopenharmony_ci      if (util::strieq_l("frontend-quic-require-toke", name, 26)) {
25032c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_QUIC_REQUIRE_TOKEN;
25042c593315Sopenharmony_ci      }
25052c593315Sopenharmony_ci      break;
25062c593315Sopenharmony_ci    case 'r':
25072c593315Sopenharmony_ci      if (util::strieq_l("request-header-field-buffe", name, 26)) {
25082c593315Sopenharmony_ci        return SHRPX_OPTID_REQUEST_HEADER_FIELD_BUFFER;
25092c593315Sopenharmony_ci      }
25102c593315Sopenharmony_ci      break;
25112c593315Sopenharmony_ci    case 's':
25122c593315Sopenharmony_ci      if (util::strieq_l("worker-frontend-connection", name, 26)) {
25132c593315Sopenharmony_ci        return SHRPX_OPTID_WORKER_FRONTEND_CONNECTIONS;
25142c593315Sopenharmony_ci      }
25152c593315Sopenharmony_ci      break;
25162c593315Sopenharmony_ci    case 't':
25172c593315Sopenharmony_ci      if (util::strieq_l("frontend-http2-read-timeou", name, 26)) {
25182c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT;
25192c593315Sopenharmony_ci      }
25202c593315Sopenharmony_ci      if (util::strieq_l("frontend-http3-read-timeou", name, 26)) {
25212c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP3_READ_TIMEOUT;
25222c593315Sopenharmony_ci      }
25232c593315Sopenharmony_ci      if (util::strieq_l("frontend-keep-alive-timeou", name, 26)) {
25242c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_KEEP_ALIVE_TIMEOUT;
25252c593315Sopenharmony_ci      }
25262c593315Sopenharmony_ci      break;
25272c593315Sopenharmony_ci    }
25282c593315Sopenharmony_ci    break;
25292c593315Sopenharmony_ci  case 28:
25302c593315Sopenharmony_ci    switch (name[27]) {
25312c593315Sopenharmony_ci    case 'a':
25322c593315Sopenharmony_ci      if (util::strieq_l("no-strip-incoming-early-dat", name, 27)) {
25332c593315Sopenharmony_ci        return SHRPX_OPTID_NO_STRIP_INCOMING_EARLY_DATA;
25342c593315Sopenharmony_ci      }
25352c593315Sopenharmony_ci      break;
25362c593315Sopenharmony_ci    case 'd':
25372c593315Sopenharmony_ci      if (util::strieq_l("tls-dyn-rec-warmup-threshol", name, 27)) {
25382c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD;
25392c593315Sopenharmony_ci      }
25402c593315Sopenharmony_ci      break;
25412c593315Sopenharmony_ci    case 'r':
25422c593315Sopenharmony_ci      if (util::strieq_l("response-header-field-buffe", name, 27)) {
25432c593315Sopenharmony_ci        return SHRPX_OPTID_RESPONSE_HEADER_FIELD_BUFFER;
25442c593315Sopenharmony_ci      }
25452c593315Sopenharmony_ci      break;
25462c593315Sopenharmony_ci    case 's':
25472c593315Sopenharmony_ci      if (util::strieq_l("http2-max-concurrent-stream", name, 27)) {
25482c593315Sopenharmony_ci        return SHRPX_OPTID_HTTP2_MAX_CONCURRENT_STREAMS;
25492c593315Sopenharmony_ci      }
25502c593315Sopenharmony_ci      if (util::strieq_l("tls-ticket-key-memcached-tl", name, 27)) {
25512c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_TLS;
25522c593315Sopenharmony_ci      }
25532c593315Sopenharmony_ci      break;
25542c593315Sopenharmony_ci    case 't':
25552c593315Sopenharmony_ci      if (util::strieq_l("backend-connections-per-hos", name, 27)) {
25562c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_CONNECTIONS_PER_HOST;
25572c593315Sopenharmony_ci      }
25582c593315Sopenharmony_ci      break;
25592c593315Sopenharmony_ci    }
25602c593315Sopenharmony_ci    break;
25612c593315Sopenharmony_ci  case 30:
25622c593315Sopenharmony_ci    switch (name[29]) {
25632c593315Sopenharmony_ci    case 'd':
25642c593315Sopenharmony_ci      if (util::strieq_l("verify-client-tolerate-expire", name, 29)) {
25652c593315Sopenharmony_ci        return SHRPX_OPTID_VERIFY_CLIENT_TOLERATE_EXPIRED;
25662c593315Sopenharmony_ci      }
25672c593315Sopenharmony_ci      break;
25682c593315Sopenharmony_ci    case 'e':
25692c593315Sopenharmony_ci      if (util::strieq_l("frontend-http3-max-window-siz", name, 29)) {
25702c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP3_MAX_WINDOW_SIZE;
25712c593315Sopenharmony_ci      }
25722c593315Sopenharmony_ci      break;
25732c593315Sopenharmony_ci    case 'r':
25742c593315Sopenharmony_ci      if (util::strieq_l("ignore-per-pattern-mruby-erro", name, 29)) {
25752c593315Sopenharmony_ci        return SHRPX_OPTID_IGNORE_PER_PATTERN_MRUBY_ERROR;
25762c593315Sopenharmony_ci      }
25772c593315Sopenharmony_ci      if (util::strieq_l("strip-incoming-x-forwarded-fo", name, 29)) {
25782c593315Sopenharmony_ci        return SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR;
25792c593315Sopenharmony_ci      }
25802c593315Sopenharmony_ci      break;
25812c593315Sopenharmony_ci    case 't':
25822c593315Sopenharmony_ci      if (util::strieq_l("backend-http2-settings-timeou", name, 29)) {
25832c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_HTTP2_SETTINGS_TIMEOUT;
25842c593315Sopenharmony_ci      }
25852c593315Sopenharmony_ci      break;
25862c593315Sopenharmony_ci    }
25872c593315Sopenharmony_ci    break;
25882c593315Sopenharmony_ci  case 31:
25892c593315Sopenharmony_ci    switch (name[30]) {
25902c593315Sopenharmony_ci    case 's':
25912c593315Sopenharmony_ci      if (util::strieq_l("tls-session-cache-memcached-tl", name, 30)) {
25922c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_TLS;
25932c593315Sopenharmony_ci      }
25942c593315Sopenharmony_ci      break;
25952c593315Sopenharmony_ci    case 't':
25962c593315Sopenharmony_ci      if (util::strieq_l("frontend-http2-settings-timeou", name, 30)) {
25972c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP2_SETTINGS_TIMEOUT;
25982c593315Sopenharmony_ci      }
25992c593315Sopenharmony_ci      break;
26002c593315Sopenharmony_ci    }
26012c593315Sopenharmony_ci    break;
26022c593315Sopenharmony_ci  case 32:
26032c593315Sopenharmony_ci    switch (name[31]) {
26042c593315Sopenharmony_ci    case 'd':
26052c593315Sopenharmony_ci      if (util::strieq_l("backend-connections-per-fronten", name, 31)) {
26062c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_CONNECTIONS_PER_FRONTEND;
26072c593315Sopenharmony_ci      }
26082c593315Sopenharmony_ci      break;
26092c593315Sopenharmony_ci    }
26102c593315Sopenharmony_ci    break;
26112c593315Sopenharmony_ci  case 33:
26122c593315Sopenharmony_ci    switch (name[32]) {
26132c593315Sopenharmony_ci    case 'l':
26142c593315Sopenharmony_ci      if (util::strieq_l("tls-ticket-key-memcached-interva", name, 32)) {
26152c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_INTERVAL;
26162c593315Sopenharmony_ci      }
26172c593315Sopenharmony_ci      if (util::strieq_l("tls-ticket-key-memcached-max-fai", name, 32)) {
26182c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL;
26192c593315Sopenharmony_ci      }
26202c593315Sopenharmony_ci      break;
26212c593315Sopenharmony_ci    case 't':
26222c593315Sopenharmony_ci      if (util::strieq_l("client-no-http2-cipher-black-lis", name, 32)) {
26232c593315Sopenharmony_ci        return SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST;
26242c593315Sopenharmony_ci      }
26252c593315Sopenharmony_ci      if (util::strieq_l("client-no-http2-cipher-block-lis", name, 32)) {
26262c593315Sopenharmony_ci        return SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLOCK_LIST;
26272c593315Sopenharmony_ci      }
26282c593315Sopenharmony_ci      break;
26292c593315Sopenharmony_ci    }
26302c593315Sopenharmony_ci    break;
26312c593315Sopenharmony_ci  case 34:
26322c593315Sopenharmony_ci    switch (name[33]) {
26332c593315Sopenharmony_ci    case 'e':
26342c593315Sopenharmony_ci      if (util::strieq_l("tls-ticket-key-memcached-cert-fil", name, 33)) {
26352c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_CERT_FILE;
26362c593315Sopenharmony_ci      }
26372c593315Sopenharmony_ci      break;
26382c593315Sopenharmony_ci    case 'r':
26392c593315Sopenharmony_ci      if (util::strieq_l("frontend-http2-dump-request-heade", name, 33)) {
26402c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER;
26412c593315Sopenharmony_ci      }
26422c593315Sopenharmony_ci      break;
26432c593315Sopenharmony_ci    case 't':
26442c593315Sopenharmony_ci      if (util::strieq_l("backend-http1-connections-per-hos", name, 33)) {
26452c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_HOST;
26462c593315Sopenharmony_ci      }
26472c593315Sopenharmony_ci      break;
26482c593315Sopenharmony_ci    case 'y':
26492c593315Sopenharmony_ci      if (util::strieq_l("tls-ticket-key-memcached-max-retr", name, 33)) {
26502c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY;
26512c593315Sopenharmony_ci      }
26522c593315Sopenharmony_ci      break;
26532c593315Sopenharmony_ci    }
26542c593315Sopenharmony_ci    break;
26552c593315Sopenharmony_ci  case 35:
26562c593315Sopenharmony_ci    switch (name[34]) {
26572c593315Sopenharmony_ci    case 'e':
26582c593315Sopenharmony_ci      if (util::strieq_l("frontend-http2-optimize-window-siz", name, 34)) {
26592c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE;
26602c593315Sopenharmony_ci      }
26612c593315Sopenharmony_ci      break;
26622c593315Sopenharmony_ci    case 'o':
26632c593315Sopenharmony_ci      if (util::strieq_l("no-strip-incoming-x-forwarded-prot", name, 34)) {
26642c593315Sopenharmony_ci        return SHRPX_OPTID_NO_STRIP_INCOMING_X_FORWARDED_PROTO;
26652c593315Sopenharmony_ci      }
26662c593315Sopenharmony_ci      break;
26672c593315Sopenharmony_ci    case 'r':
26682c593315Sopenharmony_ci      if (util::strieq_l("frontend-http2-dump-response-heade", name, 34)) {
26692c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER;
26702c593315Sopenharmony_ci      }
26712c593315Sopenharmony_ci      if (util::strieq_l("frontend-quic-congestion-controlle", name, 34)) {
26722c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_QUIC_CONGESTION_CONTROLLER;
26732c593315Sopenharmony_ci      }
26742c593315Sopenharmony_ci      break;
26752c593315Sopenharmony_ci    }
26762c593315Sopenharmony_ci    break;
26772c593315Sopenharmony_ci  case 36:
26782c593315Sopenharmony_ci    switch (name[35]) {
26792c593315Sopenharmony_ci    case 'd':
26802c593315Sopenharmony_ci      if (util::strieq_l("worker-process-grace-shutdown-perio", name, 35)) {
26812c593315Sopenharmony_ci        return SHRPX_OPTID_WORKER_PROCESS_GRACE_SHUTDOWN_PERIOD;
26822c593315Sopenharmony_ci      }
26832c593315Sopenharmony_ci      break;
26842c593315Sopenharmony_ci    case 'e':
26852c593315Sopenharmony_ci      if (util::strieq_l("backend-http2-connection-window-siz", name, 35)) {
26862c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE;
26872c593315Sopenharmony_ci      }
26882c593315Sopenharmony_ci      break;
26892c593315Sopenharmony_ci    case 'r':
26902c593315Sopenharmony_ci      if (util::strieq_l("backend-http2-connections-per-worke", name, 35)) {
26912c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER;
26922c593315Sopenharmony_ci      }
26932c593315Sopenharmony_ci      break;
26942c593315Sopenharmony_ci    case 's':
26952c593315Sopenharmony_ci      if (util::strieq_l("backend-http2-connection-window-bit", name, 35)) {
26962c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_BITS;
26972c593315Sopenharmony_ci      }
26982c593315Sopenharmony_ci      if (util::strieq_l("backend-http2-max-concurrent-stream", name, 35)) {
26992c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS;
27002c593315Sopenharmony_ci      }
27012c593315Sopenharmony_ci      break;
27022c593315Sopenharmony_ci    }
27032c593315Sopenharmony_ci    break;
27042c593315Sopenharmony_ci  case 37:
27052c593315Sopenharmony_ci    switch (name[36]) {
27062c593315Sopenharmony_ci    case 'e':
27072c593315Sopenharmony_ci      if (util::strieq_l("frontend-http2-connection-window-siz", name, 36)) {
27082c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE;
27092c593315Sopenharmony_ci      }
27102c593315Sopenharmony_ci      if (util::strieq_l("frontend-http3-connection-window-siz", name, 36)) {
27112c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP3_CONNECTION_WINDOW_SIZE;
27122c593315Sopenharmony_ci      }
27132c593315Sopenharmony_ci      if (util::strieq_l("tls-session-cache-memcached-cert-fil", name, 36)) {
27142c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE;
27152c593315Sopenharmony_ci      }
27162c593315Sopenharmony_ci      break;
27172c593315Sopenharmony_ci    case 's':
27182c593315Sopenharmony_ci      if (util::strieq_l("frontend-http2-connection-window-bit", name, 36)) {
27192c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS;
27202c593315Sopenharmony_ci      }
27212c593315Sopenharmony_ci      if (util::strieq_l("frontend-http2-max-concurrent-stream", name, 36)) {
27222c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS;
27232c593315Sopenharmony_ci      }
27242c593315Sopenharmony_ci      if (util::strieq_l("frontend-http3-max-concurrent-stream", name, 36)) {
27252c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP3_MAX_CONCURRENT_STREAMS;
27262c593315Sopenharmony_ci      }
27272c593315Sopenharmony_ci      break;
27282c593315Sopenharmony_ci    }
27292c593315Sopenharmony_ci    break;
27302c593315Sopenharmony_ci  case 38:
27312c593315Sopenharmony_ci    switch (name[37]) {
27322c593315Sopenharmony_ci    case 'd':
27332c593315Sopenharmony_ci      if (util::strieq_l("backend-http1-connections-per-fronten", name, 37)) {
27342c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND;
27352c593315Sopenharmony_ci      }
27362c593315Sopenharmony_ci      break;
27372c593315Sopenharmony_ci    }
27382c593315Sopenharmony_ci    break;
27392c593315Sopenharmony_ci  case 39:
27402c593315Sopenharmony_ci    switch (name[38]) {
27412c593315Sopenharmony_ci    case 'y':
27422c593315Sopenharmony_ci      if (util::strieq_l("tls-ticket-key-memcached-address-famil", name, 38)) {
27432c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY;
27442c593315Sopenharmony_ci      }
27452c593315Sopenharmony_ci      break;
27462c593315Sopenharmony_ci    }
27472c593315Sopenharmony_ci    break;
27482c593315Sopenharmony_ci  case 40:
27492c593315Sopenharmony_ci    switch (name[39]) {
27502c593315Sopenharmony_ci    case 'e':
27512c593315Sopenharmony_ci      if (util::strieq_l("backend-http2-decoder-dynamic-table-siz", name, 39)) {
27522c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE;
27532c593315Sopenharmony_ci      }
27542c593315Sopenharmony_ci      if (util::strieq_l("backend-http2-encoder-dynamic-table-siz", name, 39)) {
27552c593315Sopenharmony_ci        return SHRPX_OPTID_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE;
27562c593315Sopenharmony_ci      }
27572c593315Sopenharmony_ci      break;
27582c593315Sopenharmony_ci    }
27592c593315Sopenharmony_ci    break;
27602c593315Sopenharmony_ci  case 41:
27612c593315Sopenharmony_ci    switch (name[40]) {
27622c593315Sopenharmony_ci    case 'e':
27632c593315Sopenharmony_ci      if (util::strieq_l("frontend-http2-decoder-dynamic-table-siz", name,
27642c593315Sopenharmony_ci                         40)) {
27652c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE;
27662c593315Sopenharmony_ci      }
27672c593315Sopenharmony_ci      if (util::strieq_l("frontend-http2-encoder-dynamic-table-siz", name,
27682c593315Sopenharmony_ci                         40)) {
27692c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE;
27702c593315Sopenharmony_ci      }
27712c593315Sopenharmony_ci      if (util::strieq_l("frontend-http2-optimize-write-buffer-siz", name,
27722c593315Sopenharmony_ci                         40)) {
27732c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE;
27742c593315Sopenharmony_ci      }
27752c593315Sopenharmony_ci      if (util::strieq_l("frontend-http3-max-connection-window-siz", name,
27762c593315Sopenharmony_ci                         40)) {
27772c593315Sopenharmony_ci        return SHRPX_OPTID_FRONTEND_HTTP3_MAX_CONNECTION_WINDOW_SIZE;
27782c593315Sopenharmony_ci      }
27792c593315Sopenharmony_ci      if (util::strieq_l("tls-ticket-key-memcached-private-key-fil", name,
27802c593315Sopenharmony_ci                         40)) {
27812c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE;
27822c593315Sopenharmony_ci      }
27832c593315Sopenharmony_ci      break;
27842c593315Sopenharmony_ci    }
27852c593315Sopenharmony_ci    break;
27862c593315Sopenharmony_ci  case 42:
27872c593315Sopenharmony_ci    switch (name[41]) {
27882c593315Sopenharmony_ci    case 'y':
27892c593315Sopenharmony_ci      if (util::strieq_l("tls-session-cache-memcached-address-famil", name,
27902c593315Sopenharmony_ci                         41)) {
27912c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY;
27922c593315Sopenharmony_ci      }
27932c593315Sopenharmony_ci      break;
27942c593315Sopenharmony_ci    }
27952c593315Sopenharmony_ci    break;
27962c593315Sopenharmony_ci  case 44:
27972c593315Sopenharmony_ci    switch (name[43]) {
27982c593315Sopenharmony_ci    case 'e':
27992c593315Sopenharmony_ci      if (util::strieq_l("tls-session-cache-memcached-private-key-fil", name,
28002c593315Sopenharmony_ci                         43)) {
28012c593315Sopenharmony_ci        return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE;
28022c593315Sopenharmony_ci      }
28032c593315Sopenharmony_ci      break;
28042c593315Sopenharmony_ci    }
28052c593315Sopenharmony_ci    break;
28062c593315Sopenharmony_ci  }
28072c593315Sopenharmony_ci  return -1;
28082c593315Sopenharmony_ci}
28092c593315Sopenharmony_ci
28102c593315Sopenharmony_ciint parse_config(Config *config, const StringRef &opt, const StringRef &optarg,
28112c593315Sopenharmony_ci                 std::set<StringRef> &included_set,
28122c593315Sopenharmony_ci                 std::map<StringRef, size_t> &pattern_addr_indexer) {
28132c593315Sopenharmony_ci  auto optid = option_lookup_token(opt.c_str(), opt.size());
28142c593315Sopenharmony_ci  return parse_config(config, optid, opt, optarg, included_set,
28152c593315Sopenharmony_ci                      pattern_addr_indexer);
28162c593315Sopenharmony_ci}
28172c593315Sopenharmony_ci
28182c593315Sopenharmony_ciint parse_config(Config *config, int optid, const StringRef &opt,
28192c593315Sopenharmony_ci                 const StringRef &optarg, std::set<StringRef> &included_set,
28202c593315Sopenharmony_ci                 std::map<StringRef, size_t> &pattern_addr_indexer) {
28212c593315Sopenharmony_ci  std::array<char, STRERROR_BUFSIZE> errbuf;
28222c593315Sopenharmony_ci  char host[NI_MAXHOST];
28232c593315Sopenharmony_ci  uint16_t port;
28242c593315Sopenharmony_ci
28252c593315Sopenharmony_ci  switch (optid) {
28262c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND: {
28272c593315Sopenharmony_ci    auto &downstreamconf = *config->conn.downstream;
28282c593315Sopenharmony_ci    auto addr_end = std::find(std::begin(optarg), std::end(optarg), ';');
28292c593315Sopenharmony_ci
28302c593315Sopenharmony_ci    DownstreamAddrConfig addr{};
28312c593315Sopenharmony_ci    if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) {
28322c593315Sopenharmony_ci      auto path = std::begin(optarg) + SHRPX_UNIX_PATH_PREFIX.size();
28332c593315Sopenharmony_ci      addr.host =
28342c593315Sopenharmony_ci          make_string_ref(downstreamconf.balloc, StringRef{path, addr_end});
28352c593315Sopenharmony_ci      addr.host_unix = true;
28362c593315Sopenharmony_ci    } else {
28372c593315Sopenharmony_ci      if (split_host_port(host, sizeof(host), &port,
28382c593315Sopenharmony_ci                          StringRef{std::begin(optarg), addr_end}, opt) == -1) {
28392c593315Sopenharmony_ci        return -1;
28402c593315Sopenharmony_ci      }
28412c593315Sopenharmony_ci
28422c593315Sopenharmony_ci      addr.host = make_string_ref(downstreamconf.balloc, StringRef{host});
28432c593315Sopenharmony_ci      addr.port = port;
28442c593315Sopenharmony_ci    }
28452c593315Sopenharmony_ci
28462c593315Sopenharmony_ci    auto mapping = addr_end == std::end(optarg) ? addr_end : addr_end + 1;
28472c593315Sopenharmony_ci    auto mapping_end = std::find(mapping, std::end(optarg), ';');
28482c593315Sopenharmony_ci
28492c593315Sopenharmony_ci    auto params =
28502c593315Sopenharmony_ci        mapping_end == std::end(optarg) ? mapping_end : mapping_end + 1;
28512c593315Sopenharmony_ci
28522c593315Sopenharmony_ci    if (parse_mapping(config, addr, pattern_addr_indexer,
28532c593315Sopenharmony_ci                      StringRef{mapping, mapping_end},
28542c593315Sopenharmony_ci                      StringRef{params, std::end(optarg)}) != 0) {
28552c593315Sopenharmony_ci      return -1;
28562c593315Sopenharmony_ci    }
28572c593315Sopenharmony_ci
28582c593315Sopenharmony_ci    return 0;
28592c593315Sopenharmony_ci  }
28602c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND: {
28612c593315Sopenharmony_ci    auto &apiconf = config->api;
28622c593315Sopenharmony_ci
28632c593315Sopenharmony_ci    auto addr_end = std::find(std::begin(optarg), std::end(optarg), ';');
28642c593315Sopenharmony_ci    auto src_params = StringRef{addr_end, std::end(optarg)};
28652c593315Sopenharmony_ci
28662c593315Sopenharmony_ci    UpstreamParams params{};
28672c593315Sopenharmony_ci    params.tls = true;
28682c593315Sopenharmony_ci
28692c593315Sopenharmony_ci    if (parse_upstream_params(params, src_params) != 0) {
28702c593315Sopenharmony_ci      return -1;
28712c593315Sopenharmony_ci    }
28722c593315Sopenharmony_ci
28732c593315Sopenharmony_ci    if (params.sni_fwd && !params.tls) {
28742c593315Sopenharmony_ci      LOG(ERROR) << "frontend: sni_fwd requires tls";
28752c593315Sopenharmony_ci      return -1;
28762c593315Sopenharmony_ci    }
28772c593315Sopenharmony_ci
28782c593315Sopenharmony_ci    if (params.quic) {
28792c593315Sopenharmony_ci      if (params.alt_mode != UpstreamAltMode::NONE) {
28802c593315Sopenharmony_ci        LOG(ERROR) << "frontend: api or healthmon cannot be used with quic";
28812c593315Sopenharmony_ci        return -1;
28822c593315Sopenharmony_ci      }
28832c593315Sopenharmony_ci
28842c593315Sopenharmony_ci      if (!params.tls) {
28852c593315Sopenharmony_ci        LOG(ERROR) << "frontend: quic requires TLS";
28862c593315Sopenharmony_ci        return -1;
28872c593315Sopenharmony_ci      }
28882c593315Sopenharmony_ci    }
28892c593315Sopenharmony_ci
28902c593315Sopenharmony_ci    UpstreamAddr addr{};
28912c593315Sopenharmony_ci    addr.fd = -1;
28922c593315Sopenharmony_ci    addr.tls = params.tls;
28932c593315Sopenharmony_ci    addr.sni_fwd = params.sni_fwd;
28942c593315Sopenharmony_ci    addr.alt_mode = params.alt_mode;
28952c593315Sopenharmony_ci    addr.accept_proxy_protocol = params.proxyproto;
28962c593315Sopenharmony_ci    addr.quic = params.quic;
28972c593315Sopenharmony_ci
28982c593315Sopenharmony_ci    if (addr.alt_mode == UpstreamAltMode::API) {
28992c593315Sopenharmony_ci      apiconf.enabled = true;
29002c593315Sopenharmony_ci    }
29012c593315Sopenharmony_ci
29022c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
29032c593315Sopenharmony_ci    auto &addrs = params.quic ? config->conn.quic_listener.addrs
29042c593315Sopenharmony_ci                              : config->conn.listener.addrs;
29052c593315Sopenharmony_ci#else  // !ENABLE_HTTP3
29062c593315Sopenharmony_ci    auto &addrs = config->conn.listener.addrs;
29072c593315Sopenharmony_ci#endif // !ENABLE_HTTP3
29082c593315Sopenharmony_ci
29092c593315Sopenharmony_ci    if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) {
29102c593315Sopenharmony_ci      if (addr.quic) {
29112c593315Sopenharmony_ci        LOG(ERROR) << "frontend: quic cannot be used on UNIX domain socket";
29122c593315Sopenharmony_ci        return -1;
29132c593315Sopenharmony_ci      }
29142c593315Sopenharmony_ci
29152c593315Sopenharmony_ci      auto path = std::begin(optarg) + SHRPX_UNIX_PATH_PREFIX.size();
29162c593315Sopenharmony_ci      addr.host = make_string_ref(config->balloc, StringRef{path, addr_end});
29172c593315Sopenharmony_ci      addr.host_unix = true;
29182c593315Sopenharmony_ci      addr.index = addrs.size();
29192c593315Sopenharmony_ci
29202c593315Sopenharmony_ci      addrs.push_back(std::move(addr));
29212c593315Sopenharmony_ci
29222c593315Sopenharmony_ci      return 0;
29232c593315Sopenharmony_ci    }
29242c593315Sopenharmony_ci
29252c593315Sopenharmony_ci    if (split_host_port(host, sizeof(host), &port,
29262c593315Sopenharmony_ci                        StringRef{std::begin(optarg), addr_end}, opt) == -1) {
29272c593315Sopenharmony_ci      return -1;
29282c593315Sopenharmony_ci    }
29292c593315Sopenharmony_ci
29302c593315Sopenharmony_ci    addr.host = make_string_ref(config->balloc, StringRef{host});
29312c593315Sopenharmony_ci    addr.port = port;
29322c593315Sopenharmony_ci
29332c593315Sopenharmony_ci    if (util::numeric_host(host, AF_INET)) {
29342c593315Sopenharmony_ci      addr.family = AF_INET;
29352c593315Sopenharmony_ci      addr.index = addrs.size();
29362c593315Sopenharmony_ci      addrs.push_back(std::move(addr));
29372c593315Sopenharmony_ci      return 0;
29382c593315Sopenharmony_ci    }
29392c593315Sopenharmony_ci
29402c593315Sopenharmony_ci    if (util::numeric_host(host, AF_INET6)) {
29412c593315Sopenharmony_ci      addr.family = AF_INET6;
29422c593315Sopenharmony_ci      addr.index = addrs.size();
29432c593315Sopenharmony_ci      addrs.push_back(std::move(addr));
29442c593315Sopenharmony_ci      return 0;
29452c593315Sopenharmony_ci    }
29462c593315Sopenharmony_ci
29472c593315Sopenharmony_ci    addr.family = AF_INET;
29482c593315Sopenharmony_ci    addr.index = addrs.size();
29492c593315Sopenharmony_ci    addrs.push_back(addr);
29502c593315Sopenharmony_ci
29512c593315Sopenharmony_ci    addr.family = AF_INET6;
29522c593315Sopenharmony_ci    addr.index = addrs.size();
29532c593315Sopenharmony_ci    addrs.push_back(std::move(addr));
29542c593315Sopenharmony_ci
29552c593315Sopenharmony_ci    return 0;
29562c593315Sopenharmony_ci  }
29572c593315Sopenharmony_ci  case SHRPX_OPTID_WORKERS:
29582c593315Sopenharmony_ci#ifdef NOTHREADS
29592c593315Sopenharmony_ci    LOG(WARN) << "Threading disabled at build time, no threads created.";
29602c593315Sopenharmony_ci    return 0;
29612c593315Sopenharmony_ci#else  // !NOTHREADS
29622c593315Sopenharmony_ci    return parse_uint(&config->num_worker, opt, optarg);
29632c593315Sopenharmony_ci#endif // !NOTHREADS
29642c593315Sopenharmony_ci  case SHRPX_OPTID_HTTP2_MAX_CONCURRENT_STREAMS: {
29652c593315Sopenharmony_ci    LOG(WARN) << opt << ": deprecated. Use "
29662c593315Sopenharmony_ci              << SHRPX_OPT_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS << " and "
29672c593315Sopenharmony_ci              << SHRPX_OPT_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS << " instead.";
29682c593315Sopenharmony_ci    size_t n;
29692c593315Sopenharmony_ci    if (parse_uint(&n, opt, optarg) != 0) {
29702c593315Sopenharmony_ci      return -1;
29712c593315Sopenharmony_ci    }
29722c593315Sopenharmony_ci    auto &http2conf = config->http2;
29732c593315Sopenharmony_ci    http2conf.upstream.max_concurrent_streams = n;
29742c593315Sopenharmony_ci    http2conf.downstream.max_concurrent_streams = n;
29752c593315Sopenharmony_ci
29762c593315Sopenharmony_ci    return 0;
29772c593315Sopenharmony_ci  }
29782c593315Sopenharmony_ci  case SHRPX_OPTID_LOG_LEVEL: {
29792c593315Sopenharmony_ci    auto level = Log::get_severity_level_by_name(optarg);
29802c593315Sopenharmony_ci    if (level == -1) {
29812c593315Sopenharmony_ci      LOG(ERROR) << opt << ": Invalid severity level: " << optarg;
29822c593315Sopenharmony_ci      return -1;
29832c593315Sopenharmony_ci    }
29842c593315Sopenharmony_ci    config->logging.severity = level;
29852c593315Sopenharmony_ci
29862c593315Sopenharmony_ci    return 0;
29872c593315Sopenharmony_ci  }
29882c593315Sopenharmony_ci  case SHRPX_OPTID_DAEMON:
29892c593315Sopenharmony_ci    config->daemon = util::strieq_l("yes", optarg);
29902c593315Sopenharmony_ci
29912c593315Sopenharmony_ci    return 0;
29922c593315Sopenharmony_ci  case SHRPX_OPTID_HTTP2_PROXY:
29932c593315Sopenharmony_ci    config->http2_proxy = util::strieq_l("yes", optarg);
29942c593315Sopenharmony_ci
29952c593315Sopenharmony_ci    return 0;
29962c593315Sopenharmony_ci  case SHRPX_OPTID_HTTP2_BRIDGE:
29972c593315Sopenharmony_ci    LOG(ERROR) << opt
29982c593315Sopenharmony_ci               << ": deprecated.  Use backend=<addr>,<port>;;proto=h2;tls";
29992c593315Sopenharmony_ci    return -1;
30002c593315Sopenharmony_ci  case SHRPX_OPTID_CLIENT_PROXY:
30012c593315Sopenharmony_ci    LOG(ERROR)
30022c593315Sopenharmony_ci        << opt
30032c593315Sopenharmony_ci        << ": deprecated.  Use http2-proxy, frontend=<addr>,<port>;no-tls "
30042c593315Sopenharmony_ci           "and backend=<addr>,<port>;;proto=h2;tls";
30052c593315Sopenharmony_ci    return -1;
30062c593315Sopenharmony_ci  case SHRPX_OPTID_ADD_X_FORWARDED_FOR:
30072c593315Sopenharmony_ci    config->http.xff.add = util::strieq_l("yes", optarg);
30082c593315Sopenharmony_ci
30092c593315Sopenharmony_ci    return 0;
30102c593315Sopenharmony_ci  case SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR:
30112c593315Sopenharmony_ci    config->http.xff.strip_incoming = util::strieq_l("yes", optarg);
30122c593315Sopenharmony_ci
30132c593315Sopenharmony_ci    return 0;
30142c593315Sopenharmony_ci  case SHRPX_OPTID_NO_VIA:
30152c593315Sopenharmony_ci    config->http.no_via = util::strieq_l("yes", optarg);
30162c593315Sopenharmony_ci
30172c593315Sopenharmony_ci    return 0;
30182c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT:
30192c593315Sopenharmony_ci    return parse_duration(&config->conn.upstream.timeout.http2_read, opt,
30202c593315Sopenharmony_ci                          optarg);
30212c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_READ_TIMEOUT:
30222c593315Sopenharmony_ci    return parse_duration(&config->conn.upstream.timeout.read, opt, optarg);
30232c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_WRITE_TIMEOUT:
30242c593315Sopenharmony_ci    return parse_duration(&config->conn.upstream.timeout.write, opt, optarg);
30252c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_READ_TIMEOUT:
30262c593315Sopenharmony_ci    return parse_duration(&config->conn.downstream->timeout.read, opt, optarg);
30272c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_WRITE_TIMEOUT:
30282c593315Sopenharmony_ci    return parse_duration(&config->conn.downstream->timeout.write, opt, optarg);
30292c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_CONNECT_TIMEOUT:
30302c593315Sopenharmony_ci    return parse_duration(&config->conn.downstream->timeout.connect, opt,
30312c593315Sopenharmony_ci                          optarg);
30322c593315Sopenharmony_ci  case SHRPX_OPTID_STREAM_READ_TIMEOUT:
30332c593315Sopenharmony_ci    return parse_duration(&config->http2.timeout.stream_read, opt, optarg);
30342c593315Sopenharmony_ci  case SHRPX_OPTID_STREAM_WRITE_TIMEOUT:
30352c593315Sopenharmony_ci    return parse_duration(&config->http2.timeout.stream_write, opt, optarg);
30362c593315Sopenharmony_ci  case SHRPX_OPTID_ACCESSLOG_FILE:
30372c593315Sopenharmony_ci    config->logging.access.file = make_string_ref(config->balloc, optarg);
30382c593315Sopenharmony_ci
30392c593315Sopenharmony_ci    return 0;
30402c593315Sopenharmony_ci  case SHRPX_OPTID_ACCESSLOG_SYSLOG:
30412c593315Sopenharmony_ci    config->logging.access.syslog = util::strieq_l("yes", optarg);
30422c593315Sopenharmony_ci
30432c593315Sopenharmony_ci    return 0;
30442c593315Sopenharmony_ci  case SHRPX_OPTID_ACCESSLOG_FORMAT:
30452c593315Sopenharmony_ci    config->logging.access.format = parse_log_format(config->balloc, optarg);
30462c593315Sopenharmony_ci
30472c593315Sopenharmony_ci    return 0;
30482c593315Sopenharmony_ci  case SHRPX_OPTID_ERRORLOG_FILE:
30492c593315Sopenharmony_ci    config->logging.error.file = make_string_ref(config->balloc, optarg);
30502c593315Sopenharmony_ci
30512c593315Sopenharmony_ci    return 0;
30522c593315Sopenharmony_ci  case SHRPX_OPTID_ERRORLOG_SYSLOG:
30532c593315Sopenharmony_ci    config->logging.error.syslog = util::strieq_l("yes", optarg);
30542c593315Sopenharmony_ci
30552c593315Sopenharmony_ci    return 0;
30562c593315Sopenharmony_ci  case SHRPX_OPTID_FASTOPEN:
30572c593315Sopenharmony_ci    return parse_uint(&config->conn.listener.fastopen, opt, optarg);
30582c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_KEEP_ALIVE_TIMEOUT:
30592c593315Sopenharmony_ci    return parse_duration(&config->conn.downstream->timeout.idle_read, opt,
30602c593315Sopenharmony_ci                          optarg);
30612c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS:
30622c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_HTTP2_WINDOW_BITS: {
30632c593315Sopenharmony_ci    LOG(WARN) << opt << ": deprecated.  Use "
30642c593315Sopenharmony_ci              << (optid == SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS
30652c593315Sopenharmony_ci                      ? SHRPX_OPT_FRONTEND_HTTP2_WINDOW_SIZE
30662c593315Sopenharmony_ci                      : SHRPX_OPT_BACKEND_HTTP2_WINDOW_SIZE);
30672c593315Sopenharmony_ci    int32_t *resp;
30682c593315Sopenharmony_ci
30692c593315Sopenharmony_ci    if (optid == SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS) {
30702c593315Sopenharmony_ci      resp = &config->http2.upstream.window_size;
30712c593315Sopenharmony_ci    } else {
30722c593315Sopenharmony_ci      resp = &config->http2.downstream.window_size;
30732c593315Sopenharmony_ci    }
30742c593315Sopenharmony_ci
30752c593315Sopenharmony_ci    errno = 0;
30762c593315Sopenharmony_ci
30772c593315Sopenharmony_ci    int n;
30782c593315Sopenharmony_ci
30792c593315Sopenharmony_ci    if (parse_uint(&n, opt, optarg) != 0) {
30802c593315Sopenharmony_ci      return -1;
30812c593315Sopenharmony_ci    }
30822c593315Sopenharmony_ci
30832c593315Sopenharmony_ci    if (n >= 31) {
30842c593315Sopenharmony_ci      LOG(ERROR) << opt
30852c593315Sopenharmony_ci                 << ": specify the integer in the range [0, 30], inclusive";
30862c593315Sopenharmony_ci      return -1;
30872c593315Sopenharmony_ci    }
30882c593315Sopenharmony_ci
30892c593315Sopenharmony_ci    // Make 16 bits to the HTTP/2 default 64KiB - 1.  This is the same
30902c593315Sopenharmony_ci    // behaviour of previous code.
30912c593315Sopenharmony_ci    *resp = (1 << n) - 1;
30922c593315Sopenharmony_ci
30932c593315Sopenharmony_ci    return 0;
30942c593315Sopenharmony_ci  }
30952c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS:
30962c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_BITS: {
30972c593315Sopenharmony_ci    LOG(WARN) << opt << ": deprecated.  Use "
30982c593315Sopenharmony_ci              << (optid == SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS
30992c593315Sopenharmony_ci                      ? SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE
31002c593315Sopenharmony_ci                      : SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE);
31012c593315Sopenharmony_ci    int32_t *resp;
31022c593315Sopenharmony_ci
31032c593315Sopenharmony_ci    if (optid == SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS) {
31042c593315Sopenharmony_ci      resp = &config->http2.upstream.connection_window_size;
31052c593315Sopenharmony_ci    } else {
31062c593315Sopenharmony_ci      resp = &config->http2.downstream.connection_window_size;
31072c593315Sopenharmony_ci    }
31082c593315Sopenharmony_ci
31092c593315Sopenharmony_ci    errno = 0;
31102c593315Sopenharmony_ci
31112c593315Sopenharmony_ci    int n;
31122c593315Sopenharmony_ci
31132c593315Sopenharmony_ci    if (parse_uint(&n, opt, optarg) != 0) {
31142c593315Sopenharmony_ci      return -1;
31152c593315Sopenharmony_ci    }
31162c593315Sopenharmony_ci
31172c593315Sopenharmony_ci    if (n < 16 || n >= 31) {
31182c593315Sopenharmony_ci      LOG(ERROR) << opt
31192c593315Sopenharmony_ci                 << ": specify the integer in the range [16, 30], inclusive";
31202c593315Sopenharmony_ci      return -1;
31212c593315Sopenharmony_ci    }
31222c593315Sopenharmony_ci
31232c593315Sopenharmony_ci    *resp = (1 << n) - 1;
31242c593315Sopenharmony_ci
31252c593315Sopenharmony_ci    return 0;
31262c593315Sopenharmony_ci  }
31272c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_NO_TLS:
31282c593315Sopenharmony_ci    LOG(WARN) << opt << ": deprecated.  Use no-tls keyword in "
31292c593315Sopenharmony_ci              << SHRPX_OPT_FRONTEND;
31302c593315Sopenharmony_ci    return 0;
31312c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_NO_TLS:
31322c593315Sopenharmony_ci    LOG(WARN) << opt
31332c593315Sopenharmony_ci              << ": deprecated.  backend connection is not encrypted by "
31342c593315Sopenharmony_ci                 "default.  See also "
31352c593315Sopenharmony_ci              << SHRPX_OPT_BACKEND_TLS;
31362c593315Sopenharmony_ci    return 0;
31372c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_TLS_SNI_FIELD:
31382c593315Sopenharmony_ci    LOG(WARN) << opt
31392c593315Sopenharmony_ci              << ": deprecated.  Use sni keyword in --backend option.  "
31402c593315Sopenharmony_ci                 "For now, all sni values of all backends are "
31412c593315Sopenharmony_ci                 "overridden by the given value "
31422c593315Sopenharmony_ci              << optarg;
31432c593315Sopenharmony_ci    config->tls.backend_sni_name = make_string_ref(config->balloc, optarg);
31442c593315Sopenharmony_ci
31452c593315Sopenharmony_ci    return 0;
31462c593315Sopenharmony_ci  case SHRPX_OPTID_PID_FILE:
31472c593315Sopenharmony_ci    config->pid_file = make_string_ref(config->balloc, optarg);
31482c593315Sopenharmony_ci
31492c593315Sopenharmony_ci    return 0;
31502c593315Sopenharmony_ci  case SHRPX_OPTID_USER: {
31512c593315Sopenharmony_ci    auto pwd = getpwnam(optarg.c_str());
31522c593315Sopenharmony_ci    if (!pwd) {
31532c593315Sopenharmony_ci      LOG(ERROR) << opt << ": failed to get uid from " << optarg << ": "
31542c593315Sopenharmony_ci                 << xsi_strerror(errno, errbuf.data(), errbuf.size());
31552c593315Sopenharmony_ci      return -1;
31562c593315Sopenharmony_ci    }
31572c593315Sopenharmony_ci    config->user = make_string_ref(config->balloc, StringRef{pwd->pw_name});
31582c593315Sopenharmony_ci    config->uid = pwd->pw_uid;
31592c593315Sopenharmony_ci    config->gid = pwd->pw_gid;
31602c593315Sopenharmony_ci
31612c593315Sopenharmony_ci    return 0;
31622c593315Sopenharmony_ci  }
31632c593315Sopenharmony_ci  case SHRPX_OPTID_PRIVATE_KEY_FILE:
31642c593315Sopenharmony_ci    config->tls.private_key_file = make_string_ref(config->balloc, optarg);
31652c593315Sopenharmony_ci
31662c593315Sopenharmony_ci    return 0;
31672c593315Sopenharmony_ci  case SHRPX_OPTID_PRIVATE_KEY_PASSWD_FILE: {
31682c593315Sopenharmony_ci    auto passwd = read_passwd_from_file(opt, optarg);
31692c593315Sopenharmony_ci    if (passwd.empty()) {
31702c593315Sopenharmony_ci      LOG(ERROR) << opt << ": Couldn't read key file's passwd from " << optarg;
31712c593315Sopenharmony_ci      return -1;
31722c593315Sopenharmony_ci    }
31732c593315Sopenharmony_ci    config->tls.private_key_passwd =
31742c593315Sopenharmony_ci        make_string_ref(config->balloc, StringRef{passwd});
31752c593315Sopenharmony_ci
31762c593315Sopenharmony_ci    return 0;
31772c593315Sopenharmony_ci  }
31782c593315Sopenharmony_ci  case SHRPX_OPTID_CERTIFICATE_FILE:
31792c593315Sopenharmony_ci    config->tls.cert_file = make_string_ref(config->balloc, optarg);
31802c593315Sopenharmony_ci
31812c593315Sopenharmony_ci    return 0;
31822c593315Sopenharmony_ci  case SHRPX_OPTID_DH_PARAM_FILE:
31832c593315Sopenharmony_ci    config->tls.dh_param_file = make_string_ref(config->balloc, optarg);
31842c593315Sopenharmony_ci
31852c593315Sopenharmony_ci    return 0;
31862c593315Sopenharmony_ci  case SHRPX_OPTID_SUBCERT: {
31872c593315Sopenharmony_ci    auto end_keys = std::find(std::begin(optarg), std::end(optarg), ';');
31882c593315Sopenharmony_ci    auto src_params = StringRef{end_keys, std::end(optarg)};
31892c593315Sopenharmony_ci
31902c593315Sopenharmony_ci    SubcertParams params;
31912c593315Sopenharmony_ci    if (parse_subcert_params(params, src_params) != 0) {
31922c593315Sopenharmony_ci      return -1;
31932c593315Sopenharmony_ci    }
31942c593315Sopenharmony_ci
31952c593315Sopenharmony_ci    std::vector<uint8_t> sct_data;
31962c593315Sopenharmony_ci
31972c593315Sopenharmony_ci    if (!params.sct_dir.empty()) {
31982c593315Sopenharmony_ci      // Make sure that dir_path is NULL terminated string.
31992c593315Sopenharmony_ci      if (read_tls_sct_from_dir(sct_data, opt,
32002c593315Sopenharmony_ci                                StringRef{params.sct_dir.str()}) != 0) {
32012c593315Sopenharmony_ci        return -1;
32022c593315Sopenharmony_ci      }
32032c593315Sopenharmony_ci    }
32042c593315Sopenharmony_ci
32052c593315Sopenharmony_ci    // Private Key file and certificate file separated by ':'.
32062c593315Sopenharmony_ci    auto sp = std::find(std::begin(optarg), end_keys, ':');
32072c593315Sopenharmony_ci    if (sp == end_keys) {
32082c593315Sopenharmony_ci      LOG(ERROR) << opt << ": missing ':' in "
32092c593315Sopenharmony_ci                 << StringRef{std::begin(optarg), end_keys};
32102c593315Sopenharmony_ci      return -1;
32112c593315Sopenharmony_ci    }
32122c593315Sopenharmony_ci
32132c593315Sopenharmony_ci    auto private_key_file = StringRef{std::begin(optarg), sp};
32142c593315Sopenharmony_ci
32152c593315Sopenharmony_ci    if (private_key_file.empty()) {
32162c593315Sopenharmony_ci      LOG(ERROR) << opt << ": missing private key file: "
32172c593315Sopenharmony_ci                 << StringRef{std::begin(optarg), end_keys};
32182c593315Sopenharmony_ci      return -1;
32192c593315Sopenharmony_ci    }
32202c593315Sopenharmony_ci
32212c593315Sopenharmony_ci    auto cert_file = StringRef{sp + 1, end_keys};
32222c593315Sopenharmony_ci
32232c593315Sopenharmony_ci    if (cert_file.empty()) {
32242c593315Sopenharmony_ci      LOG(ERROR) << opt << ": missing certificate file: "
32252c593315Sopenharmony_ci                 << StringRef{std::begin(optarg), end_keys};
32262c593315Sopenharmony_ci      return -1;
32272c593315Sopenharmony_ci    }
32282c593315Sopenharmony_ci
32292c593315Sopenharmony_ci    config->tls.subcerts.emplace_back(
32302c593315Sopenharmony_ci        make_string_ref(config->balloc, private_key_file),
32312c593315Sopenharmony_ci        make_string_ref(config->balloc, cert_file), std::move(sct_data));
32322c593315Sopenharmony_ci
32332c593315Sopenharmony_ci    return 0;
32342c593315Sopenharmony_ci  }
32352c593315Sopenharmony_ci  case SHRPX_OPTID_SYSLOG_FACILITY: {
32362c593315Sopenharmony_ci    int facility = int_syslog_facility(optarg);
32372c593315Sopenharmony_ci    if (facility == -1) {
32382c593315Sopenharmony_ci      LOG(ERROR) << opt << ": Unknown syslog facility: " << optarg;
32392c593315Sopenharmony_ci      return -1;
32402c593315Sopenharmony_ci    }
32412c593315Sopenharmony_ci    config->logging.syslog_facility = facility;
32422c593315Sopenharmony_ci
32432c593315Sopenharmony_ci    return 0;
32442c593315Sopenharmony_ci  }
32452c593315Sopenharmony_ci  case SHRPX_OPTID_BACKLOG:
32462c593315Sopenharmony_ci    return parse_uint(&config->conn.listener.backlog, opt, optarg);
32472c593315Sopenharmony_ci  case SHRPX_OPTID_CIPHERS:
32482c593315Sopenharmony_ci    config->tls.ciphers = make_string_ref(config->balloc, optarg);
32492c593315Sopenharmony_ci
32502c593315Sopenharmony_ci    return 0;
32512c593315Sopenharmony_ci  case SHRPX_OPTID_TLS13_CIPHERS:
32522c593315Sopenharmony_ci    config->tls.tls13_ciphers = make_string_ref(config->balloc, optarg);
32532c593315Sopenharmony_ci
32542c593315Sopenharmony_ci    return 0;
32552c593315Sopenharmony_ci  case SHRPX_OPTID_CLIENT:
32562c593315Sopenharmony_ci    LOG(ERROR) << opt
32572c593315Sopenharmony_ci               << ": deprecated.  Use frontend=<addr>,<port>;no-tls, "
32582c593315Sopenharmony_ci                  "backend=<addr>,<port>;;proto=h2;tls";
32592c593315Sopenharmony_ci    return -1;
32602c593315Sopenharmony_ci  case SHRPX_OPTID_INSECURE:
32612c593315Sopenharmony_ci    config->tls.insecure = util::strieq_l("yes", optarg);
32622c593315Sopenharmony_ci
32632c593315Sopenharmony_ci    return 0;
32642c593315Sopenharmony_ci  case SHRPX_OPTID_CACERT:
32652c593315Sopenharmony_ci    config->tls.cacert = make_string_ref(config->balloc, optarg);
32662c593315Sopenharmony_ci
32672c593315Sopenharmony_ci    return 0;
32682c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_IPV4:
32692c593315Sopenharmony_ci    LOG(WARN) << opt
32702c593315Sopenharmony_ci              << ": deprecated.  Use backend-address-family=IPv4 instead.";
32712c593315Sopenharmony_ci
32722c593315Sopenharmony_ci    config->conn.downstream->family = AF_INET;
32732c593315Sopenharmony_ci
32742c593315Sopenharmony_ci    return 0;
32752c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_IPV6:
32762c593315Sopenharmony_ci    LOG(WARN) << opt
32772c593315Sopenharmony_ci              << ": deprecated.  Use backend-address-family=IPv6 instead.";
32782c593315Sopenharmony_ci
32792c593315Sopenharmony_ci    config->conn.downstream->family = AF_INET6;
32802c593315Sopenharmony_ci
32812c593315Sopenharmony_ci    return 0;
32822c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_HTTP_PROXY_URI: {
32832c593315Sopenharmony_ci    auto &proxy = config->downstream_http_proxy;
32842c593315Sopenharmony_ci    // Reset here so that multiple option occurrence does not merge
32852c593315Sopenharmony_ci    // the results.
32862c593315Sopenharmony_ci    proxy = {};
32872c593315Sopenharmony_ci    // parse URI and get hostname, port and optionally userinfo.
32882c593315Sopenharmony_ci    http_parser_url u{};
32892c593315Sopenharmony_ci    int rv = http_parser_parse_url(optarg.c_str(), optarg.size(), 0, &u);
32902c593315Sopenharmony_ci    if (rv == 0) {
32912c593315Sopenharmony_ci      if (u.field_set & UF_USERINFO) {
32922c593315Sopenharmony_ci        auto uf = util::get_uri_field(optarg.c_str(), u, UF_USERINFO);
32932c593315Sopenharmony_ci        // Surprisingly, u.field_set & UF_USERINFO is nonzero even if
32942c593315Sopenharmony_ci        // userinfo component is empty string.
32952c593315Sopenharmony_ci        if (!uf.empty()) {
32962c593315Sopenharmony_ci          proxy.userinfo = util::percent_decode(config->balloc, uf);
32972c593315Sopenharmony_ci        }
32982c593315Sopenharmony_ci      }
32992c593315Sopenharmony_ci      if (u.field_set & UF_HOST) {
33002c593315Sopenharmony_ci        proxy.host = make_string_ref(
33012c593315Sopenharmony_ci            config->balloc, util::get_uri_field(optarg.c_str(), u, UF_HOST));
33022c593315Sopenharmony_ci      } else {
33032c593315Sopenharmony_ci        LOG(ERROR) << opt << ": no hostname specified";
33042c593315Sopenharmony_ci        return -1;
33052c593315Sopenharmony_ci      }
33062c593315Sopenharmony_ci      if (u.field_set & UF_PORT) {
33072c593315Sopenharmony_ci        proxy.port = u.port;
33082c593315Sopenharmony_ci      } else {
33092c593315Sopenharmony_ci        LOG(ERROR) << opt << ": no port specified";
33102c593315Sopenharmony_ci        return -1;
33112c593315Sopenharmony_ci      }
33122c593315Sopenharmony_ci    } else {
33132c593315Sopenharmony_ci      LOG(ERROR) << opt << ": parse error";
33142c593315Sopenharmony_ci      return -1;
33152c593315Sopenharmony_ci    }
33162c593315Sopenharmony_ci
33172c593315Sopenharmony_ci    return 0;
33182c593315Sopenharmony_ci  }
33192c593315Sopenharmony_ci  case SHRPX_OPTID_READ_RATE:
33202c593315Sopenharmony_ci    return parse_uint_with_unit(&config->conn.upstream.ratelimit.read.rate, opt,
33212c593315Sopenharmony_ci                                optarg);
33222c593315Sopenharmony_ci  case SHRPX_OPTID_READ_BURST:
33232c593315Sopenharmony_ci    return parse_uint_with_unit(&config->conn.upstream.ratelimit.read.burst,
33242c593315Sopenharmony_ci                                opt, optarg);
33252c593315Sopenharmony_ci  case SHRPX_OPTID_WRITE_RATE:
33262c593315Sopenharmony_ci    return parse_uint_with_unit(&config->conn.upstream.ratelimit.write.rate,
33272c593315Sopenharmony_ci                                opt, optarg);
33282c593315Sopenharmony_ci  case SHRPX_OPTID_WRITE_BURST:
33292c593315Sopenharmony_ci    return parse_uint_with_unit(&config->conn.upstream.ratelimit.write.burst,
33302c593315Sopenharmony_ci                                opt, optarg);
33312c593315Sopenharmony_ci  case SHRPX_OPTID_WORKER_READ_RATE:
33322c593315Sopenharmony_ci    LOG(WARN) << opt << ": not implemented yet";
33332c593315Sopenharmony_ci    return 0;
33342c593315Sopenharmony_ci  case SHRPX_OPTID_WORKER_READ_BURST:
33352c593315Sopenharmony_ci    LOG(WARN) << opt << ": not implemented yet";
33362c593315Sopenharmony_ci    return 0;
33372c593315Sopenharmony_ci  case SHRPX_OPTID_WORKER_WRITE_RATE:
33382c593315Sopenharmony_ci    LOG(WARN) << opt << ": not implemented yet";
33392c593315Sopenharmony_ci    return 0;
33402c593315Sopenharmony_ci  case SHRPX_OPTID_WORKER_WRITE_BURST:
33412c593315Sopenharmony_ci    LOG(WARN) << opt << ": not implemented yet";
33422c593315Sopenharmony_ci    return 0;
33432c593315Sopenharmony_ci  case SHRPX_OPTID_NPN_LIST: {
33442c593315Sopenharmony_ci    auto list = util::split_str(optarg, ',');
33452c593315Sopenharmony_ci    config->tls.npn_list.resize(list.size());
33462c593315Sopenharmony_ci    for (size_t i = 0; i < list.size(); ++i) {
33472c593315Sopenharmony_ci      config->tls.npn_list[i] = make_string_ref(config->balloc, list[i]);
33482c593315Sopenharmony_ci    }
33492c593315Sopenharmony_ci
33502c593315Sopenharmony_ci    return 0;
33512c593315Sopenharmony_ci  }
33522c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_PROTO_LIST: {
33532c593315Sopenharmony_ci    LOG(WARN) << opt
33542c593315Sopenharmony_ci              << ": deprecated.  Use tls-min-proto-version and "
33552c593315Sopenharmony_ci                 "tls-max-proto-version instead.";
33562c593315Sopenharmony_ci    auto list = util::split_str(optarg, ',');
33572c593315Sopenharmony_ci    config->tls.tls_proto_list.resize(list.size());
33582c593315Sopenharmony_ci    for (size_t i = 0; i < list.size(); ++i) {
33592c593315Sopenharmony_ci      config->tls.tls_proto_list[i] = make_string_ref(config->balloc, list[i]);
33602c593315Sopenharmony_ci    }
33612c593315Sopenharmony_ci
33622c593315Sopenharmony_ci    return 0;
33632c593315Sopenharmony_ci  }
33642c593315Sopenharmony_ci  case SHRPX_OPTID_VERIFY_CLIENT:
33652c593315Sopenharmony_ci    config->tls.client_verify.enabled = util::strieq_l("yes", optarg);
33662c593315Sopenharmony_ci
33672c593315Sopenharmony_ci    return 0;
33682c593315Sopenharmony_ci  case SHRPX_OPTID_VERIFY_CLIENT_CACERT:
33692c593315Sopenharmony_ci    config->tls.client_verify.cacert = make_string_ref(config->balloc, optarg);
33702c593315Sopenharmony_ci
33712c593315Sopenharmony_ci    return 0;
33722c593315Sopenharmony_ci  case SHRPX_OPTID_CLIENT_PRIVATE_KEY_FILE:
33732c593315Sopenharmony_ci    config->tls.client.private_key_file =
33742c593315Sopenharmony_ci        make_string_ref(config->balloc, optarg);
33752c593315Sopenharmony_ci
33762c593315Sopenharmony_ci    return 0;
33772c593315Sopenharmony_ci  case SHRPX_OPTID_CLIENT_CERT_FILE:
33782c593315Sopenharmony_ci    config->tls.client.cert_file = make_string_ref(config->balloc, optarg);
33792c593315Sopenharmony_ci
33802c593315Sopenharmony_ci    return 0;
33812c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER:
33822c593315Sopenharmony_ci    config->http2.upstream.debug.dump.request_header_file =
33832c593315Sopenharmony_ci        make_string_ref(config->balloc, optarg);
33842c593315Sopenharmony_ci
33852c593315Sopenharmony_ci    return 0;
33862c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER:
33872c593315Sopenharmony_ci    config->http2.upstream.debug.dump.response_header_file =
33882c593315Sopenharmony_ci        make_string_ref(config->balloc, optarg);
33892c593315Sopenharmony_ci
33902c593315Sopenharmony_ci    return 0;
33912c593315Sopenharmony_ci  case SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING:
33922c593315Sopenharmony_ci    config->http2.no_cookie_crumbling = util::strieq_l("yes", optarg);
33932c593315Sopenharmony_ci
33942c593315Sopenharmony_ci    return 0;
33952c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_FRAME_DEBUG:
33962c593315Sopenharmony_ci    config->http2.upstream.debug.frame_debug = util::strieq_l("yes", optarg);
33972c593315Sopenharmony_ci
33982c593315Sopenharmony_ci    return 0;
33992c593315Sopenharmony_ci  case SHRPX_OPTID_PADDING:
34002c593315Sopenharmony_ci    return parse_uint(&config->padding, opt, optarg);
34012c593315Sopenharmony_ci  case SHRPX_OPTID_ALTSVC: {
34022c593315Sopenharmony_ci    AltSvc altsvc{};
34032c593315Sopenharmony_ci
34042c593315Sopenharmony_ci    if (parse_altsvc(altsvc, opt, optarg) != 0) {
34052c593315Sopenharmony_ci      return -1;
34062c593315Sopenharmony_ci    }
34072c593315Sopenharmony_ci
34082c593315Sopenharmony_ci    config->http.altsvcs.push_back(std::move(altsvc));
34092c593315Sopenharmony_ci
34102c593315Sopenharmony_ci    return 0;
34112c593315Sopenharmony_ci  }
34122c593315Sopenharmony_ci  case SHRPX_OPTID_ADD_REQUEST_HEADER:
34132c593315Sopenharmony_ci  case SHRPX_OPTID_ADD_RESPONSE_HEADER: {
34142c593315Sopenharmony_ci    auto p = parse_header(config->balloc, optarg);
34152c593315Sopenharmony_ci    if (p.name.empty()) {
34162c593315Sopenharmony_ci      LOG(ERROR) << opt << ": invalid header field: " << optarg;
34172c593315Sopenharmony_ci      return -1;
34182c593315Sopenharmony_ci    }
34192c593315Sopenharmony_ci    if (optid == SHRPX_OPTID_ADD_REQUEST_HEADER) {
34202c593315Sopenharmony_ci      config->http.add_request_headers.push_back(std::move(p));
34212c593315Sopenharmony_ci    } else {
34222c593315Sopenharmony_ci      config->http.add_response_headers.push_back(std::move(p));
34232c593315Sopenharmony_ci    }
34242c593315Sopenharmony_ci    return 0;
34252c593315Sopenharmony_ci  }
34262c593315Sopenharmony_ci  case SHRPX_OPTID_WORKER_FRONTEND_CONNECTIONS:
34272c593315Sopenharmony_ci    return parse_uint(&config->conn.upstream.worker_connections, opt, optarg);
34282c593315Sopenharmony_ci  case SHRPX_OPTID_NO_LOCATION_REWRITE:
34292c593315Sopenharmony_ci    config->http.no_location_rewrite = util::strieq_l("yes", optarg);
34302c593315Sopenharmony_ci
34312c593315Sopenharmony_ci    return 0;
34322c593315Sopenharmony_ci  case SHRPX_OPTID_NO_HOST_REWRITE:
34332c593315Sopenharmony_ci    LOG(WARN) << SHRPX_OPT_NO_HOST_REWRITE
34342c593315Sopenharmony_ci              << ": deprecated.  :authority and host header fields are NOT "
34352c593315Sopenharmony_ci                 "altered by default.  To rewrite these headers, use "
34362c593315Sopenharmony_ci                 "--host-rewrite option.";
34372c593315Sopenharmony_ci
34382c593315Sopenharmony_ci    return 0;
34392c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_HOST:
34402c593315Sopenharmony_ci    LOG(WARN) << opt
34412c593315Sopenharmony_ci              << ": deprecated.  Use backend-connections-per-host instead.";
34422c593315Sopenharmony_ci  // fall through
34432c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_CONNECTIONS_PER_HOST: {
34442c593315Sopenharmony_ci    int n;
34452c593315Sopenharmony_ci
34462c593315Sopenharmony_ci    if (parse_uint(&n, opt, optarg) != 0) {
34472c593315Sopenharmony_ci      return -1;
34482c593315Sopenharmony_ci    }
34492c593315Sopenharmony_ci
34502c593315Sopenharmony_ci    if (n == 0) {
34512c593315Sopenharmony_ci      LOG(ERROR) << opt << ": specify an integer strictly more than 0";
34522c593315Sopenharmony_ci
34532c593315Sopenharmony_ci      return -1;
34542c593315Sopenharmony_ci    }
34552c593315Sopenharmony_ci
34562c593315Sopenharmony_ci    config->conn.downstream->connections_per_host = n;
34572c593315Sopenharmony_ci
34582c593315Sopenharmony_ci    return 0;
34592c593315Sopenharmony_ci  }
34602c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND:
34612c593315Sopenharmony_ci    LOG(WARN) << opt << ": deprecated.  Use "
34622c593315Sopenharmony_ci              << SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND << " instead.";
34632c593315Sopenharmony_ci  // fall through
34642c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_CONNECTIONS_PER_FRONTEND:
34652c593315Sopenharmony_ci    return parse_uint(&config->conn.downstream->connections_per_frontend, opt,
34662c593315Sopenharmony_ci                      optarg);
34672c593315Sopenharmony_ci  case SHRPX_OPTID_LISTENER_DISABLE_TIMEOUT:
34682c593315Sopenharmony_ci    return parse_duration(&config->conn.listener.timeout.sleep, opt, optarg);
34692c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_TICKET_KEY_FILE:
34702c593315Sopenharmony_ci    config->tls.ticket.files.emplace_back(
34712c593315Sopenharmony_ci        make_string_ref(config->balloc, optarg));
34722c593315Sopenharmony_ci    return 0;
34732c593315Sopenharmony_ci  case SHRPX_OPTID_RLIMIT_NOFILE: {
34742c593315Sopenharmony_ci    int n;
34752c593315Sopenharmony_ci
34762c593315Sopenharmony_ci    if (parse_uint(&n, opt, optarg) != 0) {
34772c593315Sopenharmony_ci      return -1;
34782c593315Sopenharmony_ci    }
34792c593315Sopenharmony_ci
34802c593315Sopenharmony_ci    if (n < 0) {
34812c593315Sopenharmony_ci      LOG(ERROR) << opt << ": specify the integer more than or equal to 0";
34822c593315Sopenharmony_ci
34832c593315Sopenharmony_ci      return -1;
34842c593315Sopenharmony_ci    }
34852c593315Sopenharmony_ci
34862c593315Sopenharmony_ci    config->rlimit_nofile = n;
34872c593315Sopenharmony_ci
34882c593315Sopenharmony_ci    return 0;
34892c593315Sopenharmony_ci  }
34902c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_REQUEST_BUFFER:
34912c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_RESPONSE_BUFFER: {
34922c593315Sopenharmony_ci    size_t n;
34932c593315Sopenharmony_ci    if (parse_uint_with_unit(&n, opt, optarg) != 0) {
34942c593315Sopenharmony_ci      return -1;
34952c593315Sopenharmony_ci    }
34962c593315Sopenharmony_ci
34972c593315Sopenharmony_ci    if (n == 0) {
34982c593315Sopenharmony_ci      LOG(ERROR) << opt << ": specify an integer strictly more than 0";
34992c593315Sopenharmony_ci
35002c593315Sopenharmony_ci      return -1;
35012c593315Sopenharmony_ci    }
35022c593315Sopenharmony_ci
35032c593315Sopenharmony_ci    if (optid == SHRPX_OPTID_BACKEND_REQUEST_BUFFER) {
35042c593315Sopenharmony_ci      config->conn.downstream->request_buffer_size = n;
35052c593315Sopenharmony_ci    } else {
35062c593315Sopenharmony_ci      config->conn.downstream->response_buffer_size = n;
35072c593315Sopenharmony_ci    }
35082c593315Sopenharmony_ci
35092c593315Sopenharmony_ci    return 0;
35102c593315Sopenharmony_ci  }
35112c593315Sopenharmony_ci
35122c593315Sopenharmony_ci  case SHRPX_OPTID_NO_SERVER_PUSH:
35132c593315Sopenharmony_ci    config->http2.no_server_push = util::strieq_l("yes", optarg);
35142c593315Sopenharmony_ci
35152c593315Sopenharmony_ci    return 0;
35162c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER:
35172c593315Sopenharmony_ci    LOG(WARN) << opt << ": deprecated.";
35182c593315Sopenharmony_ci    return 0;
35192c593315Sopenharmony_ci  case SHRPX_OPTID_FETCH_OCSP_RESPONSE_FILE:
35202c593315Sopenharmony_ci    config->tls.ocsp.fetch_ocsp_response_file =
35212c593315Sopenharmony_ci        make_string_ref(config->balloc, optarg);
35222c593315Sopenharmony_ci
35232c593315Sopenharmony_ci    return 0;
35242c593315Sopenharmony_ci  case SHRPX_OPTID_OCSP_UPDATE_INTERVAL:
35252c593315Sopenharmony_ci    return parse_duration(&config->tls.ocsp.update_interval, opt, optarg);
35262c593315Sopenharmony_ci  case SHRPX_OPTID_NO_OCSP:
35272c593315Sopenharmony_ci    config->tls.ocsp.disabled = util::strieq_l("yes", optarg);
35282c593315Sopenharmony_ci
35292c593315Sopenharmony_ci    return 0;
35302c593315Sopenharmony_ci  case SHRPX_OPTID_HEADER_FIELD_BUFFER:
35312c593315Sopenharmony_ci    LOG(WARN) << opt
35322c593315Sopenharmony_ci              << ": deprecated.  Use request-header-field-buffer instead.";
35332c593315Sopenharmony_ci  // fall through
35342c593315Sopenharmony_ci  case SHRPX_OPTID_REQUEST_HEADER_FIELD_BUFFER:
35352c593315Sopenharmony_ci    return parse_uint_with_unit(&config->http.request_header_field_buffer, opt,
35362c593315Sopenharmony_ci                                optarg);
35372c593315Sopenharmony_ci  case SHRPX_OPTID_MAX_HEADER_FIELDS:
35382c593315Sopenharmony_ci    LOG(WARN) << opt << ": deprecated.  Use max-request-header-fields instead.";
35392c593315Sopenharmony_ci  // fall through
35402c593315Sopenharmony_ci  case SHRPX_OPTID_MAX_REQUEST_HEADER_FIELDS:
35412c593315Sopenharmony_ci    return parse_uint(&config->http.max_request_header_fields, opt, optarg);
35422c593315Sopenharmony_ci  case SHRPX_OPTID_RESPONSE_HEADER_FIELD_BUFFER:
35432c593315Sopenharmony_ci    return parse_uint_with_unit(&config->http.response_header_field_buffer, opt,
35442c593315Sopenharmony_ci                                optarg);
35452c593315Sopenharmony_ci  case SHRPX_OPTID_MAX_RESPONSE_HEADER_FIELDS:
35462c593315Sopenharmony_ci    return parse_uint(&config->http.max_response_header_fields, opt, optarg);
35472c593315Sopenharmony_ci  case SHRPX_OPTID_INCLUDE: {
35482c593315Sopenharmony_ci    if (included_set.count(optarg)) {
35492c593315Sopenharmony_ci      LOG(ERROR) << opt << ": " << optarg << " has already been included";
35502c593315Sopenharmony_ci      return -1;
35512c593315Sopenharmony_ci    }
35522c593315Sopenharmony_ci
35532c593315Sopenharmony_ci    included_set.insert(optarg);
35542c593315Sopenharmony_ci    auto rv =
35552c593315Sopenharmony_ci        load_config(config, optarg.c_str(), included_set, pattern_addr_indexer);
35562c593315Sopenharmony_ci    included_set.erase(optarg);
35572c593315Sopenharmony_ci
35582c593315Sopenharmony_ci    if (rv != 0) {
35592c593315Sopenharmony_ci      return -1;
35602c593315Sopenharmony_ci    }
35612c593315Sopenharmony_ci
35622c593315Sopenharmony_ci    return 0;
35632c593315Sopenharmony_ci  }
35642c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_TICKET_KEY_CIPHER:
35652c593315Sopenharmony_ci    if (util::strieq_l("aes-128-cbc", optarg)) {
35662c593315Sopenharmony_ci      config->tls.ticket.cipher = EVP_aes_128_cbc();
35672c593315Sopenharmony_ci    } else if (util::strieq_l("aes-256-cbc", optarg)) {
35682c593315Sopenharmony_ci      config->tls.ticket.cipher = EVP_aes_256_cbc();
35692c593315Sopenharmony_ci    } else {
35702c593315Sopenharmony_ci      LOG(ERROR) << opt
35712c593315Sopenharmony_ci                 << ": unsupported cipher for ticket encryption: " << optarg;
35722c593315Sopenharmony_ci      return -1;
35732c593315Sopenharmony_ci    }
35742c593315Sopenharmony_ci    config->tls.ticket.cipher_given = true;
35752c593315Sopenharmony_ci
35762c593315Sopenharmony_ci    return 0;
35772c593315Sopenharmony_ci  case SHRPX_OPTID_HOST_REWRITE:
35782c593315Sopenharmony_ci    config->http.no_host_rewrite = !util::strieq_l("yes", optarg);
35792c593315Sopenharmony_ci
35802c593315Sopenharmony_ci    return 0;
35812c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED:
35822c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED: {
35832c593315Sopenharmony_ci    auto addr_end = std::find(std::begin(optarg), std::end(optarg), ';');
35842c593315Sopenharmony_ci    auto src_params = StringRef{addr_end, std::end(optarg)};
35852c593315Sopenharmony_ci
35862c593315Sopenharmony_ci    MemcachedConnectionParams params{};
35872c593315Sopenharmony_ci    if (parse_memcached_connection_params(params, src_params, StringRef{opt}) !=
35882c593315Sopenharmony_ci        0) {
35892c593315Sopenharmony_ci      return -1;
35902c593315Sopenharmony_ci    }
35912c593315Sopenharmony_ci
35922c593315Sopenharmony_ci    if (split_host_port(host, sizeof(host), &port,
35932c593315Sopenharmony_ci                        StringRef{std::begin(optarg), addr_end}, opt) == -1) {
35942c593315Sopenharmony_ci      return -1;
35952c593315Sopenharmony_ci    }
35962c593315Sopenharmony_ci
35972c593315Sopenharmony_ci    switch (optid) {
35982c593315Sopenharmony_ci    case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED: {
35992c593315Sopenharmony_ci      auto &memcachedconf = config->tls.session_cache.memcached;
36002c593315Sopenharmony_ci      memcachedconf.host = make_string_ref(config->balloc, StringRef{host});
36012c593315Sopenharmony_ci      memcachedconf.port = port;
36022c593315Sopenharmony_ci      memcachedconf.tls = params.tls;
36032c593315Sopenharmony_ci      break;
36042c593315Sopenharmony_ci    }
36052c593315Sopenharmony_ci    case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED: {
36062c593315Sopenharmony_ci      auto &memcachedconf = config->tls.ticket.memcached;
36072c593315Sopenharmony_ci      memcachedconf.host = make_string_ref(config->balloc, StringRef{host});
36082c593315Sopenharmony_ci      memcachedconf.port = port;
36092c593315Sopenharmony_ci      memcachedconf.tls = params.tls;
36102c593315Sopenharmony_ci      break;
36112c593315Sopenharmony_ci    }
36122c593315Sopenharmony_ci    };
36132c593315Sopenharmony_ci
36142c593315Sopenharmony_ci    return 0;
36152c593315Sopenharmony_ci  }
36162c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_INTERVAL:
36172c593315Sopenharmony_ci    return parse_duration(&config->tls.ticket.memcached.interval, opt, optarg);
36182c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY: {
36192c593315Sopenharmony_ci    int n;
36202c593315Sopenharmony_ci    if (parse_uint(&n, opt, optarg) != 0) {
36212c593315Sopenharmony_ci      return -1;
36222c593315Sopenharmony_ci    }
36232c593315Sopenharmony_ci
36242c593315Sopenharmony_ci    if (n > 30) {
36252c593315Sopenharmony_ci      LOG(ERROR) << opt << ": must be smaller than or equal to 30";
36262c593315Sopenharmony_ci      return -1;
36272c593315Sopenharmony_ci    }
36282c593315Sopenharmony_ci
36292c593315Sopenharmony_ci    config->tls.ticket.memcached.max_retry = n;
36302c593315Sopenharmony_ci    return 0;
36312c593315Sopenharmony_ci  }
36322c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL:
36332c593315Sopenharmony_ci    return parse_uint(&config->tls.ticket.memcached.max_fail, opt, optarg);
36342c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_DYN_REC_WARMUP_THRESHOLD: {
36352c593315Sopenharmony_ci    size_t n;
36362c593315Sopenharmony_ci    if (parse_uint_with_unit(&n, opt, optarg) != 0) {
36372c593315Sopenharmony_ci      return -1;
36382c593315Sopenharmony_ci    }
36392c593315Sopenharmony_ci
36402c593315Sopenharmony_ci    config->tls.dyn_rec.warmup_threshold = n;
36412c593315Sopenharmony_ci
36422c593315Sopenharmony_ci    return 0;
36432c593315Sopenharmony_ci  }
36442c593315Sopenharmony_ci
36452c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_DYN_REC_IDLE_TIMEOUT:
36462c593315Sopenharmony_ci    return parse_duration(&config->tls.dyn_rec.idle_timeout, opt, optarg);
36472c593315Sopenharmony_ci
36482c593315Sopenharmony_ci  case SHRPX_OPTID_MRUBY_FILE:
36492c593315Sopenharmony_ci#ifdef HAVE_MRUBY
36502c593315Sopenharmony_ci    config->mruby_file = make_string_ref(config->balloc, optarg);
36512c593315Sopenharmony_ci#else  // !HAVE_MRUBY
36522c593315Sopenharmony_ci    LOG(WARN) << opt
36532c593315Sopenharmony_ci              << ": ignored because mruby support is disabled at build time.";
36542c593315Sopenharmony_ci#endif // !HAVE_MRUBY
36552c593315Sopenharmony_ci    return 0;
36562c593315Sopenharmony_ci  case SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL:
36572c593315Sopenharmony_ci    LOG(WARN) << opt << ": deprecated.  Use proxyproto keyword in "
36582c593315Sopenharmony_ci              << SHRPX_OPT_FRONTEND << " instead.";
36592c593315Sopenharmony_ci    config->conn.upstream.accept_proxy_protocol = util::strieq_l("yes", optarg);
36602c593315Sopenharmony_ci
36612c593315Sopenharmony_ci    return 0;
36622c593315Sopenharmony_ci  case SHRPX_OPTID_ADD_FORWARDED: {
36632c593315Sopenharmony_ci    auto &fwdconf = config->http.forwarded;
36642c593315Sopenharmony_ci    fwdconf.params = FORWARDED_NONE;
36652c593315Sopenharmony_ci    for (const auto &param : util::split_str(optarg, ',')) {
36662c593315Sopenharmony_ci      if (util::strieq_l("by", param)) {
36672c593315Sopenharmony_ci        fwdconf.params |= FORWARDED_BY;
36682c593315Sopenharmony_ci        continue;
36692c593315Sopenharmony_ci      }
36702c593315Sopenharmony_ci      if (util::strieq_l("for", param)) {
36712c593315Sopenharmony_ci        fwdconf.params |= FORWARDED_FOR;
36722c593315Sopenharmony_ci        continue;
36732c593315Sopenharmony_ci      }
36742c593315Sopenharmony_ci      if (util::strieq_l("host", param)) {
36752c593315Sopenharmony_ci        fwdconf.params |= FORWARDED_HOST;
36762c593315Sopenharmony_ci        continue;
36772c593315Sopenharmony_ci      }
36782c593315Sopenharmony_ci      if (util::strieq_l("proto", param)) {
36792c593315Sopenharmony_ci        fwdconf.params |= FORWARDED_PROTO;
36802c593315Sopenharmony_ci        continue;
36812c593315Sopenharmony_ci      }
36822c593315Sopenharmony_ci
36832c593315Sopenharmony_ci      LOG(ERROR) << opt << ": unknown parameter " << optarg;
36842c593315Sopenharmony_ci
36852c593315Sopenharmony_ci      return -1;
36862c593315Sopenharmony_ci    }
36872c593315Sopenharmony_ci
36882c593315Sopenharmony_ci    return 0;
36892c593315Sopenharmony_ci  }
36902c593315Sopenharmony_ci  case SHRPX_OPTID_STRIP_INCOMING_FORWARDED:
36912c593315Sopenharmony_ci    config->http.forwarded.strip_incoming = util::strieq_l("yes", optarg);
36922c593315Sopenharmony_ci
36932c593315Sopenharmony_ci    return 0;
36942c593315Sopenharmony_ci  case SHRPX_OPTID_FORWARDED_BY:
36952c593315Sopenharmony_ci  case SHRPX_OPTID_FORWARDED_FOR: {
36962c593315Sopenharmony_ci    auto type = parse_forwarded_node_type(optarg);
36972c593315Sopenharmony_ci
36982c593315Sopenharmony_ci    if (type == static_cast<ForwardedNode>(-1) ||
36992c593315Sopenharmony_ci        (optid == SHRPX_OPTID_FORWARDED_FOR && optarg[0] == '_')) {
37002c593315Sopenharmony_ci      LOG(ERROR) << opt << ": unknown node type or illegal obfuscated string "
37012c593315Sopenharmony_ci                 << optarg;
37022c593315Sopenharmony_ci      return -1;
37032c593315Sopenharmony_ci    }
37042c593315Sopenharmony_ci
37052c593315Sopenharmony_ci    auto &fwdconf = config->http.forwarded;
37062c593315Sopenharmony_ci
37072c593315Sopenharmony_ci    switch (optid) {
37082c593315Sopenharmony_ci    case SHRPX_OPTID_FORWARDED_BY:
37092c593315Sopenharmony_ci      fwdconf.by_node_type = type;
37102c593315Sopenharmony_ci      if (optarg[0] == '_') {
37112c593315Sopenharmony_ci        fwdconf.by_obfuscated = make_string_ref(config->balloc, optarg);
37122c593315Sopenharmony_ci      } else {
37132c593315Sopenharmony_ci        fwdconf.by_obfuscated = StringRef::from_lit("");
37142c593315Sopenharmony_ci      }
37152c593315Sopenharmony_ci      break;
37162c593315Sopenharmony_ci    case SHRPX_OPTID_FORWARDED_FOR:
37172c593315Sopenharmony_ci      fwdconf.for_node_type = type;
37182c593315Sopenharmony_ci      break;
37192c593315Sopenharmony_ci    }
37202c593315Sopenharmony_ci
37212c593315Sopenharmony_ci    return 0;
37222c593315Sopenharmony_ci  }
37232c593315Sopenharmony_ci  case SHRPX_OPTID_NO_HTTP2_CIPHER_BLACK_LIST:
37242c593315Sopenharmony_ci    LOG(WARN) << opt << ": deprecated.  Use "
37252c593315Sopenharmony_ci              << SHRPX_OPT_NO_HTTP2_CIPHER_BLOCK_LIST << " instead.";
37262c593315Sopenharmony_ci    // fall through
37272c593315Sopenharmony_ci  case SHRPX_OPTID_NO_HTTP2_CIPHER_BLOCK_LIST:
37282c593315Sopenharmony_ci    config->tls.no_http2_cipher_block_list = util::strieq_l("yes", optarg);
37292c593315Sopenharmony_ci    return 0;
37302c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_HTTP1_TLS:
37312c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_TLS:
37322c593315Sopenharmony_ci    LOG(WARN) << opt << ": deprecated.  Use tls keyword in "
37332c593315Sopenharmony_ci              << SHRPX_OPT_BACKEND << " instead.";
37342c593315Sopenharmony_ci    return 0;
37352c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_TLS:
37362c593315Sopenharmony_ci    LOG(WARN) << opt << ": deprecated.  Use tls keyword in "
37372c593315Sopenharmony_ci              << SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED;
37382c593315Sopenharmony_ci    return 0;
37392c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE:
37402c593315Sopenharmony_ci    config->tls.session_cache.memcached.cert_file =
37412c593315Sopenharmony_ci        make_string_ref(config->balloc, optarg);
37422c593315Sopenharmony_ci
37432c593315Sopenharmony_ci    return 0;
37442c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE:
37452c593315Sopenharmony_ci    config->tls.session_cache.memcached.private_key_file =
37462c593315Sopenharmony_ci        make_string_ref(config->balloc, optarg);
37472c593315Sopenharmony_ci
37482c593315Sopenharmony_ci    return 0;
37492c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_TLS:
37502c593315Sopenharmony_ci    LOG(WARN) << opt << ": deprecated.  Use tls keyword in "
37512c593315Sopenharmony_ci              << SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED;
37522c593315Sopenharmony_ci    return 0;
37532c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_CERT_FILE:
37542c593315Sopenharmony_ci    config->tls.ticket.memcached.cert_file =
37552c593315Sopenharmony_ci        make_string_ref(config->balloc, optarg);
37562c593315Sopenharmony_ci
37572c593315Sopenharmony_ci    return 0;
37582c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE:
37592c593315Sopenharmony_ci    config->tls.ticket.memcached.private_key_file =
37602c593315Sopenharmony_ci        make_string_ref(config->balloc, optarg);
37612c593315Sopenharmony_ci
37622c593315Sopenharmony_ci    return 0;
37632c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY:
37642c593315Sopenharmony_ci    return parse_address_family(&config->tls.ticket.memcached.family, opt,
37652c593315Sopenharmony_ci                                optarg);
37662c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY:
37672c593315Sopenharmony_ci    return parse_address_family(&config->tls.session_cache.memcached.family,
37682c593315Sopenharmony_ci                                opt, optarg);
37692c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_ADDRESS_FAMILY:
37702c593315Sopenharmony_ci    return parse_address_family(&config->conn.downstream->family, opt, optarg);
37712c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS:
37722c593315Sopenharmony_ci    return parse_uint(&config->http2.upstream.max_concurrent_streams, opt,
37732c593315Sopenharmony_ci                      optarg);
37742c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS:
37752c593315Sopenharmony_ci    return parse_uint(&config->http2.downstream.max_concurrent_streams, opt,
37762c593315Sopenharmony_ci                      optarg);
37772c593315Sopenharmony_ci  case SHRPX_OPTID_ERROR_PAGE:
37782c593315Sopenharmony_ci    return parse_error_page(config->http.error_pages, opt, optarg);
37792c593315Sopenharmony_ci  case SHRPX_OPTID_NO_KQUEUE:
37802c593315Sopenharmony_ci    if ((ev_supported_backends() & EVBACKEND_KQUEUE) == 0) {
37812c593315Sopenharmony_ci      LOG(WARN) << opt << ": kqueue is not supported on this platform";
37822c593315Sopenharmony_ci      return 0;
37832c593315Sopenharmony_ci    }
37842c593315Sopenharmony_ci
37852c593315Sopenharmony_ci    config->ev_loop_flags = ev_recommended_backends() & ~EVBACKEND_KQUEUE;
37862c593315Sopenharmony_ci
37872c593315Sopenharmony_ci    return 0;
37882c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP2_SETTINGS_TIMEOUT:
37892c593315Sopenharmony_ci    return parse_duration(&config->http2.upstream.timeout.settings, opt,
37902c593315Sopenharmony_ci                          optarg);
37912c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_HTTP2_SETTINGS_TIMEOUT:
37922c593315Sopenharmony_ci    return parse_duration(&config->http2.downstream.timeout.settings, opt,
37932c593315Sopenharmony_ci                          optarg);
37942c593315Sopenharmony_ci  case SHRPX_OPTID_API_MAX_REQUEST_BODY:
37952c593315Sopenharmony_ci    return parse_uint_with_unit(&config->api.max_request_body, opt, optarg);
37962c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_MAX_BACKOFF:
37972c593315Sopenharmony_ci    return parse_duration(&config->conn.downstream->timeout.max_backoff, opt,
37982c593315Sopenharmony_ci                          optarg);
37992c593315Sopenharmony_ci  case SHRPX_OPTID_SERVER_NAME:
38002c593315Sopenharmony_ci    config->http.server_name = make_string_ref(config->balloc, optarg);
38012c593315Sopenharmony_ci
38022c593315Sopenharmony_ci    return 0;
38032c593315Sopenharmony_ci  case SHRPX_OPTID_NO_SERVER_REWRITE:
38042c593315Sopenharmony_ci    config->http.no_server_rewrite = util::strieq_l("yes", optarg);
38052c593315Sopenharmony_ci
38062c593315Sopenharmony_ci    return 0;
38072c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE:
38082c593315Sopenharmony_ci    config->http2.upstream.optimize_write_buffer_size =
38092c593315Sopenharmony_ci        util::strieq_l("yes", optarg);
38102c593315Sopenharmony_ci
38112c593315Sopenharmony_ci    return 0;
38122c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE:
38132c593315Sopenharmony_ci    config->http2.upstream.optimize_window_size = util::strieq_l("yes", optarg);
38142c593315Sopenharmony_ci
38152c593315Sopenharmony_ci    return 0;
38162c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_SIZE:
38172c593315Sopenharmony_ci    if (parse_uint_with_unit(&config->http2.upstream.window_size, opt,
38182c593315Sopenharmony_ci                             optarg) != 0) {
38192c593315Sopenharmony_ci      return -1;
38202c593315Sopenharmony_ci    }
38212c593315Sopenharmony_ci
38222c593315Sopenharmony_ci    return 0;
38232c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE:
38242c593315Sopenharmony_ci    if (parse_uint_with_unit(&config->http2.upstream.connection_window_size,
38252c593315Sopenharmony_ci                             opt, optarg) != 0) {
38262c593315Sopenharmony_ci      return -1;
38272c593315Sopenharmony_ci    }
38282c593315Sopenharmony_ci
38292c593315Sopenharmony_ci    return 0;
38302c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_HTTP2_WINDOW_SIZE:
38312c593315Sopenharmony_ci    if (parse_uint_with_unit(&config->http2.downstream.window_size, opt,
38322c593315Sopenharmony_ci                             optarg) != 0) {
38332c593315Sopenharmony_ci      return -1;
38342c593315Sopenharmony_ci    }
38352c593315Sopenharmony_ci
38362c593315Sopenharmony_ci    return 0;
38372c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE:
38382c593315Sopenharmony_ci    if (parse_uint_with_unit(&config->http2.downstream.connection_window_size,
38392c593315Sopenharmony_ci                             opt, optarg) != 0) {
38402c593315Sopenharmony_ci      return -1;
38412c593315Sopenharmony_ci    }
38422c593315Sopenharmony_ci
38432c593315Sopenharmony_ci    return 0;
38442c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE:
38452c593315Sopenharmony_ci    if (parse_uint_with_unit(&config->http2.upstream.encoder_dynamic_table_size,
38462c593315Sopenharmony_ci                             opt, optarg) != 0) {
38472c593315Sopenharmony_ci      return -1;
38482c593315Sopenharmony_ci    }
38492c593315Sopenharmony_ci
38502c593315Sopenharmony_ci    nghttp2_option_set_max_deflate_dynamic_table_size(
38512c593315Sopenharmony_ci        config->http2.upstream.option,
38522c593315Sopenharmony_ci        config->http2.upstream.encoder_dynamic_table_size);
38532c593315Sopenharmony_ci    nghttp2_option_set_max_deflate_dynamic_table_size(
38542c593315Sopenharmony_ci        config->http2.upstream.alt_mode_option,
38552c593315Sopenharmony_ci        config->http2.upstream.encoder_dynamic_table_size);
38562c593315Sopenharmony_ci
38572c593315Sopenharmony_ci    return 0;
38582c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE:
38592c593315Sopenharmony_ci    return parse_uint_with_unit(
38602c593315Sopenharmony_ci        &config->http2.upstream.decoder_dynamic_table_size, opt, optarg);
38612c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE:
38622c593315Sopenharmony_ci    if (parse_uint_with_unit(
38632c593315Sopenharmony_ci            &config->http2.downstream.encoder_dynamic_table_size, opt,
38642c593315Sopenharmony_ci            optarg) != 0) {
38652c593315Sopenharmony_ci      return -1;
38662c593315Sopenharmony_ci    }
38672c593315Sopenharmony_ci
38682c593315Sopenharmony_ci    nghttp2_option_set_max_deflate_dynamic_table_size(
38692c593315Sopenharmony_ci        config->http2.downstream.option,
38702c593315Sopenharmony_ci        config->http2.downstream.encoder_dynamic_table_size);
38712c593315Sopenharmony_ci
38722c593315Sopenharmony_ci    return 0;
38732c593315Sopenharmony_ci  case SHRPX_OPTID_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE:
38742c593315Sopenharmony_ci    return parse_uint_with_unit(
38752c593315Sopenharmony_ci        &config->http2.downstream.decoder_dynamic_table_size, opt, optarg);
38762c593315Sopenharmony_ci  case SHRPX_OPTID_ECDH_CURVES:
38772c593315Sopenharmony_ci#if !LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L
38782c593315Sopenharmony_ci    config->tls.ecdh_curves = make_string_ref(config->balloc, optarg);
38792c593315Sopenharmony_ci#else  // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L)
38802c593315Sopenharmony_ci    LOG(WARN) << opt << ": This option requires OpenSSL >= 1.0.2";
38812c593315Sopenharmony_ci#endif // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L)
38822c593315Sopenharmony_ci    return 0;
38832c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_SCT_DIR:
38842c593315Sopenharmony_ci#if !LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L
38852c593315Sopenharmony_ci    return read_tls_sct_from_dir(config->tls.sct_data, opt, optarg);
38862c593315Sopenharmony_ci#else  // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L)
38872c593315Sopenharmony_ci    LOG(WARN) << opt << ": This option requires OpenSSL >= 1.0.2";
38882c593315Sopenharmony_ci    return 0;
38892c593315Sopenharmony_ci#endif // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L)
38902c593315Sopenharmony_ci  case SHRPX_OPTID_DNS_CACHE_TIMEOUT:
38912c593315Sopenharmony_ci    return parse_duration(&config->dns.timeout.cache, opt, optarg);
38922c593315Sopenharmony_ci  case SHRPX_OPTID_DNS_LOOKUP_TIMEOUT:
38932c593315Sopenharmony_ci    return parse_duration(&config->dns.timeout.lookup, opt, optarg);
38942c593315Sopenharmony_ci  case SHRPX_OPTID_DNS_MAX_TRY: {
38952c593315Sopenharmony_ci    int n;
38962c593315Sopenharmony_ci    if (parse_uint(&n, opt, optarg) != 0) {
38972c593315Sopenharmony_ci      return -1;
38982c593315Sopenharmony_ci    }
38992c593315Sopenharmony_ci
39002c593315Sopenharmony_ci    if (n > 5) {
39012c593315Sopenharmony_ci      LOG(ERROR) << opt << ": must be smaller than or equal to 5";
39022c593315Sopenharmony_ci      return -1;
39032c593315Sopenharmony_ci    }
39042c593315Sopenharmony_ci
39052c593315Sopenharmony_ci    config->dns.max_try = n;
39062c593315Sopenharmony_ci    return 0;
39072c593315Sopenharmony_ci  }
39082c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_KEEP_ALIVE_TIMEOUT:
39092c593315Sopenharmony_ci    return parse_duration(&config->conn.upstream.timeout.idle_read, opt,
39102c593315Sopenharmony_ci                          optarg);
39112c593315Sopenharmony_ci  case SHRPX_OPTID_PSK_SECRETS:
39122c593315Sopenharmony_ci#if !LIBRESSL_LEGACY_API
39132c593315Sopenharmony_ci    return parse_psk_secrets(config, optarg);
39142c593315Sopenharmony_ci#else  // LIBRESSL_LEGACY_API
39152c593315Sopenharmony_ci    LOG(WARN)
39162c593315Sopenharmony_ci        << opt
39172c593315Sopenharmony_ci        << ": ignored because underlying TLS library does not support PSK";
39182c593315Sopenharmony_ci    return 0;
39192c593315Sopenharmony_ci#endif // LIBRESSL_LEGACY_API
39202c593315Sopenharmony_ci  case SHRPX_OPTID_CLIENT_PSK_SECRETS:
39212c593315Sopenharmony_ci#if !LIBRESSL_LEGACY_API
39222c593315Sopenharmony_ci    return parse_client_psk_secrets(config, optarg);
39232c593315Sopenharmony_ci#else  // LIBRESSL_LEGACY_API
39242c593315Sopenharmony_ci    LOG(WARN)
39252c593315Sopenharmony_ci        << opt
39262c593315Sopenharmony_ci        << ": ignored because underlying TLS library does not support PSK";
39272c593315Sopenharmony_ci    return 0;
39282c593315Sopenharmony_ci#endif // LIBRESSL_LEGACY_API
39292c593315Sopenharmony_ci  case SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST:
39302c593315Sopenharmony_ci    LOG(WARN) << opt << ": deprecated.  Use "
39312c593315Sopenharmony_ci              << SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLOCK_LIST << " instead.";
39322c593315Sopenharmony_ci    // fall through
39332c593315Sopenharmony_ci  case SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLOCK_LIST:
39342c593315Sopenharmony_ci    config->tls.client.no_http2_cipher_block_list =
39352c593315Sopenharmony_ci        util::strieq_l("yes", optarg);
39362c593315Sopenharmony_ci
39372c593315Sopenharmony_ci    return 0;
39382c593315Sopenharmony_ci  case SHRPX_OPTID_CLIENT_CIPHERS:
39392c593315Sopenharmony_ci    config->tls.client.ciphers = make_string_ref(config->balloc, optarg);
39402c593315Sopenharmony_ci
39412c593315Sopenharmony_ci    return 0;
39422c593315Sopenharmony_ci  case SHRPX_OPTID_TLS13_CLIENT_CIPHERS:
39432c593315Sopenharmony_ci    config->tls.client.tls13_ciphers = make_string_ref(config->balloc, optarg);
39442c593315Sopenharmony_ci
39452c593315Sopenharmony_ci    return 0;
39462c593315Sopenharmony_ci  case SHRPX_OPTID_ACCESSLOG_WRITE_EARLY:
39472c593315Sopenharmony_ci    config->logging.access.write_early = util::strieq_l("yes", optarg);
39482c593315Sopenharmony_ci
39492c593315Sopenharmony_ci    return 0;
39502c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_MIN_PROTO_VERSION:
39512c593315Sopenharmony_ci    return parse_tls_proto_version(config->tls.min_proto_version, opt, optarg);
39522c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_MAX_PROTO_VERSION:
39532c593315Sopenharmony_ci    return parse_tls_proto_version(config->tls.max_proto_version, opt, optarg);
39542c593315Sopenharmony_ci  case SHRPX_OPTID_REDIRECT_HTTPS_PORT: {
39552c593315Sopenharmony_ci    auto n = util::parse_uint(optarg);
39562c593315Sopenharmony_ci    if (n == -1 || n < 0 || n > 65535) {
39572c593315Sopenharmony_ci      LOG(ERROR) << opt
39582c593315Sopenharmony_ci                 << ": bad value.  Specify an integer in the range [0, "
39592c593315Sopenharmony_ci                    "65535], inclusive";
39602c593315Sopenharmony_ci      return -1;
39612c593315Sopenharmony_ci    }
39622c593315Sopenharmony_ci    config->http.redirect_https_port = make_string_ref(config->balloc, optarg);
39632c593315Sopenharmony_ci    return 0;
39642c593315Sopenharmony_ci  }
39652c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_MAX_REQUESTS:
39662c593315Sopenharmony_ci    return parse_uint(&config->http.max_requests, opt, optarg);
39672c593315Sopenharmony_ci  case SHRPX_OPTID_SINGLE_THREAD:
39682c593315Sopenharmony_ci    config->single_thread = util::strieq_l("yes", optarg);
39692c593315Sopenharmony_ci
39702c593315Sopenharmony_ci    return 0;
39712c593315Sopenharmony_ci  case SHRPX_OPTID_SINGLE_PROCESS:
39722c593315Sopenharmony_ci    config->single_process = util::strieq_l("yes", optarg);
39732c593315Sopenharmony_ci
39742c593315Sopenharmony_ci    return 0;
39752c593315Sopenharmony_ci  case SHRPX_OPTID_NO_ADD_X_FORWARDED_PROTO:
39762c593315Sopenharmony_ci    config->http.xfp.add = !util::strieq_l("yes", optarg);
39772c593315Sopenharmony_ci
39782c593315Sopenharmony_ci    return 0;
39792c593315Sopenharmony_ci  case SHRPX_OPTID_NO_STRIP_INCOMING_X_FORWARDED_PROTO:
39802c593315Sopenharmony_ci    config->http.xfp.strip_incoming = !util::strieq_l("yes", optarg);
39812c593315Sopenharmony_ci
39822c593315Sopenharmony_ci    return 0;
39832c593315Sopenharmony_ci  case SHRPX_OPTID_OCSP_STARTUP:
39842c593315Sopenharmony_ci    config->tls.ocsp.startup = util::strieq_l("yes", optarg);
39852c593315Sopenharmony_ci
39862c593315Sopenharmony_ci    return 0;
39872c593315Sopenharmony_ci  case SHRPX_OPTID_NO_VERIFY_OCSP:
39882c593315Sopenharmony_ci    config->tls.ocsp.no_verify = util::strieq_l("yes", optarg);
39892c593315Sopenharmony_ci
39902c593315Sopenharmony_ci    return 0;
39912c593315Sopenharmony_ci  case SHRPX_OPTID_VERIFY_CLIENT_TOLERATE_EXPIRED:
39922c593315Sopenharmony_ci    config->tls.client_verify.tolerate_expired = util::strieq_l("yes", optarg);
39932c593315Sopenharmony_ci
39942c593315Sopenharmony_ci    return 0;
39952c593315Sopenharmony_ci  case SHRPX_OPTID_IGNORE_PER_PATTERN_MRUBY_ERROR:
39962c593315Sopenharmony_ci    config->ignore_per_pattern_mruby_error = util::strieq_l("yes", optarg);
39972c593315Sopenharmony_ci
39982c593315Sopenharmony_ci    return 0;
39992c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_NO_POSTPONE_EARLY_DATA:
40002c593315Sopenharmony_ci    config->tls.no_postpone_early_data = util::strieq_l("yes", optarg);
40012c593315Sopenharmony_ci
40022c593315Sopenharmony_ci    return 0;
40032c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_MAX_EARLY_DATA: {
40042c593315Sopenharmony_ci    return parse_uint_with_unit(&config->tls.max_early_data, opt, optarg);
40052c593315Sopenharmony_ci  }
40062c593315Sopenharmony_ci  case SHRPX_OPTID_NO_STRIP_INCOMING_EARLY_DATA:
40072c593315Sopenharmony_ci    config->http.early_data.strip_incoming = !util::strieq_l("yes", optarg);
40082c593315Sopenharmony_ci
40092c593315Sopenharmony_ci    return 0;
40102c593315Sopenharmony_ci  case SHRPX_OPTID_QUIC_BPF_PROGRAM_FILE:
40112c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
40122c593315Sopenharmony_ci    config->quic.bpf.prog_file = make_string_ref(config->balloc, optarg);
40132c593315Sopenharmony_ci#endif // ENABLE_HTTP3
40142c593315Sopenharmony_ci
40152c593315Sopenharmony_ci    return 0;
40162c593315Sopenharmony_ci  case SHRPX_OPTID_NO_QUIC_BPF:
40172c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
40182c593315Sopenharmony_ci    config->quic.bpf.disabled = util::strieq_l("yes", optarg);
40192c593315Sopenharmony_ci#endif // ENABLE_HTTP3
40202c593315Sopenharmony_ci
40212c593315Sopenharmony_ci    return 0;
40222c593315Sopenharmony_ci  case SHRPX_OPTID_HTTP2_ALTSVC: {
40232c593315Sopenharmony_ci    AltSvc altsvc{};
40242c593315Sopenharmony_ci
40252c593315Sopenharmony_ci    if (parse_altsvc(altsvc, opt, optarg) != 0) {
40262c593315Sopenharmony_ci      return -1;
40272c593315Sopenharmony_ci    }
40282c593315Sopenharmony_ci
40292c593315Sopenharmony_ci    config->http.http2_altsvcs.push_back(std::move(altsvc));
40302c593315Sopenharmony_ci
40312c593315Sopenharmony_ci    return 0;
40322c593315Sopenharmony_ci  }
40332c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP3_READ_TIMEOUT:
40342c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
40352c593315Sopenharmony_ci    return parse_duration(&config->conn.upstream.timeout.http3_read, opt,
40362c593315Sopenharmony_ci                          optarg);
40372c593315Sopenharmony_ci#else  // !ENABLE_HTTP3
40382c593315Sopenharmony_ci    return 0;
40392c593315Sopenharmony_ci#endif // !ENABLE_HTTP3
40402c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_QUIC_IDLE_TIMEOUT:
40412c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
40422c593315Sopenharmony_ci    return parse_duration(&config->quic.upstream.timeout.idle, opt, optarg);
40432c593315Sopenharmony_ci#else  // !ENABLE_HTTP3
40442c593315Sopenharmony_ci    return 0;
40452c593315Sopenharmony_ci#endif // !ENABLE_HTTP3
40462c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_QUIC_DEBUG_LOG:
40472c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
40482c593315Sopenharmony_ci    config->quic.upstream.debug.log = util::strieq_l("yes", optarg);
40492c593315Sopenharmony_ci#endif // ENABLE_HTTP3
40502c593315Sopenharmony_ci
40512c593315Sopenharmony_ci    return 0;
40522c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP3_WINDOW_SIZE:
40532c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
40542c593315Sopenharmony_ci    if (parse_uint_with_unit(&config->http3.upstream.window_size, opt,
40552c593315Sopenharmony_ci                             optarg) != 0) {
40562c593315Sopenharmony_ci      return -1;
40572c593315Sopenharmony_ci    }
40582c593315Sopenharmony_ci#endif // ENABLE_HTTP3
40592c593315Sopenharmony_ci
40602c593315Sopenharmony_ci    return 0;
40612c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP3_CONNECTION_WINDOW_SIZE:
40622c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
40632c593315Sopenharmony_ci    if (parse_uint_with_unit(&config->http3.upstream.connection_window_size,
40642c593315Sopenharmony_ci                             opt, optarg) != 0) {
40652c593315Sopenharmony_ci      return -1;
40662c593315Sopenharmony_ci    }
40672c593315Sopenharmony_ci#endif // ENABLE_HTTP3
40682c593315Sopenharmony_ci
40692c593315Sopenharmony_ci    return 0;
40702c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP3_MAX_WINDOW_SIZE:
40712c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
40722c593315Sopenharmony_ci    if (parse_uint_with_unit(&config->http3.upstream.max_window_size, opt,
40732c593315Sopenharmony_ci                             optarg) != 0) {
40742c593315Sopenharmony_ci      return -1;
40752c593315Sopenharmony_ci    }
40762c593315Sopenharmony_ci#endif // ENABLE_HTTP3
40772c593315Sopenharmony_ci
40782c593315Sopenharmony_ci    return 0;
40792c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP3_MAX_CONNECTION_WINDOW_SIZE:
40802c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
40812c593315Sopenharmony_ci    if (parse_uint_with_unit(&config->http3.upstream.max_connection_window_size,
40822c593315Sopenharmony_ci                             opt, optarg) != 0) {
40832c593315Sopenharmony_ci      return -1;
40842c593315Sopenharmony_ci    }
40852c593315Sopenharmony_ci#endif // ENABLE_HTTP3
40862c593315Sopenharmony_ci
40872c593315Sopenharmony_ci    return 0;
40882c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_HTTP3_MAX_CONCURRENT_STREAMS:
40892c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
40902c593315Sopenharmony_ci    return parse_uint(&config->http3.upstream.max_concurrent_streams, opt,
40912c593315Sopenharmony_ci                      optarg);
40922c593315Sopenharmony_ci#else  // !ENABLE_HTTP3
40932c593315Sopenharmony_ci    return 0;
40942c593315Sopenharmony_ci#endif // !ENABLE_HTTP3
40952c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_QUIC_EARLY_DATA:
40962c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
40972c593315Sopenharmony_ci    config->quic.upstream.early_data = util::strieq_l("yes", optarg);
40982c593315Sopenharmony_ci#endif // ENABLE_HTTP3
40992c593315Sopenharmony_ci
41002c593315Sopenharmony_ci    return 0;
41012c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_QUIC_QLOG_DIR:
41022c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
41032c593315Sopenharmony_ci    config->quic.upstream.qlog.dir = make_string_ref(config->balloc, optarg);
41042c593315Sopenharmony_ci#endif // ENABLE_HTTP3
41052c593315Sopenharmony_ci
41062c593315Sopenharmony_ci    return 0;
41072c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_QUIC_REQUIRE_TOKEN:
41082c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
41092c593315Sopenharmony_ci    config->quic.upstream.require_token = util::strieq_l("yes", optarg);
41102c593315Sopenharmony_ci#endif // ENABLE_HTTP3
41112c593315Sopenharmony_ci
41122c593315Sopenharmony_ci    return 0;
41132c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_QUIC_CONGESTION_CONTROLLER:
41142c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
41152c593315Sopenharmony_ci    if (util::strieq_l("cubic", optarg)) {
41162c593315Sopenharmony_ci      config->quic.upstream.congestion_controller = NGTCP2_CC_ALGO_CUBIC;
41172c593315Sopenharmony_ci    } else if (util::strieq_l("bbr", optarg)) {
41182c593315Sopenharmony_ci      config->quic.upstream.congestion_controller = NGTCP2_CC_ALGO_BBR;
41192c593315Sopenharmony_ci    } else {
41202c593315Sopenharmony_ci      LOG(ERROR) << opt << ": must be either cubic or bbr";
41212c593315Sopenharmony_ci      return -1;
41222c593315Sopenharmony_ci    }
41232c593315Sopenharmony_ci#endif // ENABLE_HTTP3
41242c593315Sopenharmony_ci
41252c593315Sopenharmony_ci    return 0;
41262c593315Sopenharmony_ci  case SHRPX_OPTID_QUIC_SERVER_ID:
41272c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
41282c593315Sopenharmony_ci    if (optarg.size() != config->quic.server_id.size() * 2 ||
41292c593315Sopenharmony_ci        !util::is_hex_string(optarg)) {
41302c593315Sopenharmony_ci      LOG(ERROR) << opt << ": must be a hex-string";
41312c593315Sopenharmony_ci      return -1;
41322c593315Sopenharmony_ci    }
41332c593315Sopenharmony_ci    util::decode_hex(std::begin(config->quic.server_id), optarg);
41342c593315Sopenharmony_ci#endif // ENABLE_HTTP3
41352c593315Sopenharmony_ci
41362c593315Sopenharmony_ci    return 0;
41372c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_QUIC_SECRET_FILE:
41382c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
41392c593315Sopenharmony_ci    config->quic.upstream.secret_file = make_string_ref(config->balloc, optarg);
41402c593315Sopenharmony_ci#endif // ENABLE_HTTP3
41412c593315Sopenharmony_ci
41422c593315Sopenharmony_ci    return 0;
41432c593315Sopenharmony_ci  case SHRPX_OPTID_RLIMIT_MEMLOCK: {
41442c593315Sopenharmony_ci    int n;
41452c593315Sopenharmony_ci
41462c593315Sopenharmony_ci    if (parse_uint(&n, opt, optarg) != 0) {
41472c593315Sopenharmony_ci      return -1;
41482c593315Sopenharmony_ci    }
41492c593315Sopenharmony_ci
41502c593315Sopenharmony_ci    if (n < 0) {
41512c593315Sopenharmony_ci      LOG(ERROR) << opt << ": specify the integer more than or equal to 0";
41522c593315Sopenharmony_ci
41532c593315Sopenharmony_ci      return -1;
41542c593315Sopenharmony_ci    }
41552c593315Sopenharmony_ci
41562c593315Sopenharmony_ci    config->rlimit_memlock = n;
41572c593315Sopenharmony_ci
41582c593315Sopenharmony_ci    return 0;
41592c593315Sopenharmony_ci  }
41602c593315Sopenharmony_ci  case SHRPX_OPTID_MAX_WORKER_PROCESSES:
41612c593315Sopenharmony_ci    return parse_uint(&config->max_worker_processes, opt, optarg);
41622c593315Sopenharmony_ci  case SHRPX_OPTID_WORKER_PROCESS_GRACE_SHUTDOWN_PERIOD:
41632c593315Sopenharmony_ci    return parse_duration(&config->worker_process_grace_shutdown_period, opt,
41642c593315Sopenharmony_ci                          optarg);
41652c593315Sopenharmony_ci  case SHRPX_OPTID_FRONTEND_QUIC_INITIAL_RTT: {
41662c593315Sopenharmony_ci#ifdef ENABLE_HTTP3
41672c593315Sopenharmony_ci    return parse_duration(&config->quic.upstream.initial_rtt, opt, optarg);
41682c593315Sopenharmony_ci#endif // ENABLE_HTTP3
41692c593315Sopenharmony_ci
41702c593315Sopenharmony_ci    return 0;
41712c593315Sopenharmony_ci  }
41722c593315Sopenharmony_ci  case SHRPX_OPTID_REQUIRE_HTTP_SCHEME:
41732c593315Sopenharmony_ci    config->http.require_http_scheme = util::strieq_l("yes", optarg);
41742c593315Sopenharmony_ci    return 0;
41752c593315Sopenharmony_ci  case SHRPX_OPTID_TLS_KTLS:
41762c593315Sopenharmony_ci    config->tls.ktls = util::strieq_l("yes", optarg);
41772c593315Sopenharmony_ci    return 0;
41782c593315Sopenharmony_ci  case SHRPX_OPTID_CONF:
41792c593315Sopenharmony_ci    LOG(WARN) << "conf: ignored";
41802c593315Sopenharmony_ci
41812c593315Sopenharmony_ci    return 0;
41822c593315Sopenharmony_ci  }
41832c593315Sopenharmony_ci
41842c593315Sopenharmony_ci  LOG(ERROR) << "Unknown option: " << opt;
41852c593315Sopenharmony_ci
41862c593315Sopenharmony_ci  return -1;
41872c593315Sopenharmony_ci}
41882c593315Sopenharmony_ci
41892c593315Sopenharmony_ciint load_config(Config *config, const char *filename,
41902c593315Sopenharmony_ci                std::set<StringRef> &include_set,
41912c593315Sopenharmony_ci                std::map<StringRef, size_t> &pattern_addr_indexer) {
41922c593315Sopenharmony_ci  std::ifstream in(filename, std::ios::binary);
41932c593315Sopenharmony_ci  if (!in) {
41942c593315Sopenharmony_ci    LOG(ERROR) << "Could not open config file " << filename;
41952c593315Sopenharmony_ci    return -1;
41962c593315Sopenharmony_ci  }
41972c593315Sopenharmony_ci  std::string line;
41982c593315Sopenharmony_ci  int linenum = 0;
41992c593315Sopenharmony_ci  while (std::getline(in, line)) {
42002c593315Sopenharmony_ci    ++linenum;
42012c593315Sopenharmony_ci    if (line.empty() || line[0] == '#') {
42022c593315Sopenharmony_ci      continue;
42032c593315Sopenharmony_ci    }
42042c593315Sopenharmony_ci    auto eq = std::find(std::begin(line), std::end(line), '=');
42052c593315Sopenharmony_ci    if (eq == std::end(line)) {
42062c593315Sopenharmony_ci      LOG(ERROR) << "Bad configuration format in " << filename << " at line "
42072c593315Sopenharmony_ci                 << linenum;
42082c593315Sopenharmony_ci      return -1;
42092c593315Sopenharmony_ci    }
42102c593315Sopenharmony_ci    *eq = '\0';
42112c593315Sopenharmony_ci
42122c593315Sopenharmony_ci    if (parse_config(config, StringRef{std::begin(line), eq},
42132c593315Sopenharmony_ci                     StringRef{eq + 1, std::end(line)}, include_set,
42142c593315Sopenharmony_ci                     pattern_addr_indexer) != 0) {
42152c593315Sopenharmony_ci      return -1;
42162c593315Sopenharmony_ci    }
42172c593315Sopenharmony_ci  }
42182c593315Sopenharmony_ci  return 0;
42192c593315Sopenharmony_ci}
42202c593315Sopenharmony_ci
42212c593315Sopenharmony_ciStringRef str_syslog_facility(int facility) {
42222c593315Sopenharmony_ci  switch (facility) {
42232c593315Sopenharmony_ci  case (LOG_AUTH):
42242c593315Sopenharmony_ci    return StringRef::from_lit("auth");
42252c593315Sopenharmony_ci#ifdef LOG_AUTHPRIV
42262c593315Sopenharmony_ci  case (LOG_AUTHPRIV):
42272c593315Sopenharmony_ci    return StringRef::from_lit("authpriv");
42282c593315Sopenharmony_ci#endif // LOG_AUTHPRIV
42292c593315Sopenharmony_ci  case (LOG_CRON):
42302c593315Sopenharmony_ci    return StringRef::from_lit("cron");
42312c593315Sopenharmony_ci  case (LOG_DAEMON):
42322c593315Sopenharmony_ci    return StringRef::from_lit("daemon");
42332c593315Sopenharmony_ci#ifdef LOG_FTP
42342c593315Sopenharmony_ci  case (LOG_FTP):
42352c593315Sopenharmony_ci    return StringRef::from_lit("ftp");
42362c593315Sopenharmony_ci#endif // LOG_FTP
42372c593315Sopenharmony_ci  case (LOG_KERN):
42382c593315Sopenharmony_ci    return StringRef::from_lit("kern");
42392c593315Sopenharmony_ci  case (LOG_LOCAL0):
42402c593315Sopenharmony_ci    return StringRef::from_lit("local0");
42412c593315Sopenharmony_ci  case (LOG_LOCAL1):
42422c593315Sopenharmony_ci    return StringRef::from_lit("local1");
42432c593315Sopenharmony_ci  case (LOG_LOCAL2):
42442c593315Sopenharmony_ci    return StringRef::from_lit("local2");
42452c593315Sopenharmony_ci  case (LOG_LOCAL3):
42462c593315Sopenharmony_ci    return StringRef::from_lit("local3");
42472c593315Sopenharmony_ci  case (LOG_LOCAL4):
42482c593315Sopenharmony_ci    return StringRef::from_lit("local4");
42492c593315Sopenharmony_ci  case (LOG_LOCAL5):
42502c593315Sopenharmony_ci    return StringRef::from_lit("local5");
42512c593315Sopenharmony_ci  case (LOG_LOCAL6):
42522c593315Sopenharmony_ci    return StringRef::from_lit("local6");
42532c593315Sopenharmony_ci  case (LOG_LOCAL7):
42542c593315Sopenharmony_ci    return StringRef::from_lit("local7");
42552c593315Sopenharmony_ci  case (LOG_LPR):
42562c593315Sopenharmony_ci    return StringRef::from_lit("lpr");
42572c593315Sopenharmony_ci  case (LOG_MAIL):
42582c593315Sopenharmony_ci    return StringRef::from_lit("mail");
42592c593315Sopenharmony_ci  case (LOG_SYSLOG):
42602c593315Sopenharmony_ci    return StringRef::from_lit("syslog");
42612c593315Sopenharmony_ci  case (LOG_USER):
42622c593315Sopenharmony_ci    return StringRef::from_lit("user");
42632c593315Sopenharmony_ci  case (LOG_UUCP):
42642c593315Sopenharmony_ci    return StringRef::from_lit("uucp");
42652c593315Sopenharmony_ci  default:
42662c593315Sopenharmony_ci    return StringRef::from_lit("(unknown)");
42672c593315Sopenharmony_ci  }
42682c593315Sopenharmony_ci}
42692c593315Sopenharmony_ci
42702c593315Sopenharmony_ciint int_syslog_facility(const StringRef &strfacility) {
42712c593315Sopenharmony_ci  if (util::strieq_l("auth", strfacility)) {
42722c593315Sopenharmony_ci    return LOG_AUTH;
42732c593315Sopenharmony_ci  }
42742c593315Sopenharmony_ci
42752c593315Sopenharmony_ci#ifdef LOG_AUTHPRIV
42762c593315Sopenharmony_ci  if (util::strieq_l("authpriv", strfacility)) {
42772c593315Sopenharmony_ci    return LOG_AUTHPRIV;
42782c593315Sopenharmony_ci  }
42792c593315Sopenharmony_ci#endif // LOG_AUTHPRIV
42802c593315Sopenharmony_ci
42812c593315Sopenharmony_ci  if (util::strieq_l("cron", strfacility)) {
42822c593315Sopenharmony_ci    return LOG_CRON;
42832c593315Sopenharmony_ci  }
42842c593315Sopenharmony_ci
42852c593315Sopenharmony_ci  if (util::strieq_l("daemon", strfacility)) {
42862c593315Sopenharmony_ci    return LOG_DAEMON;
42872c593315Sopenharmony_ci  }
42882c593315Sopenharmony_ci
42892c593315Sopenharmony_ci#ifdef LOG_FTP
42902c593315Sopenharmony_ci  if (util::strieq_l("ftp", strfacility)) {
42912c593315Sopenharmony_ci    return LOG_FTP;
42922c593315Sopenharmony_ci  }
42932c593315Sopenharmony_ci#endif // LOG_FTP
42942c593315Sopenharmony_ci
42952c593315Sopenharmony_ci  if (util::strieq_l("kern", strfacility)) {
42962c593315Sopenharmony_ci    return LOG_KERN;
42972c593315Sopenharmony_ci  }
42982c593315Sopenharmony_ci
42992c593315Sopenharmony_ci  if (util::strieq_l("local0", strfacility)) {
43002c593315Sopenharmony_ci    return LOG_LOCAL0;
43012c593315Sopenharmony_ci  }
43022c593315Sopenharmony_ci
43032c593315Sopenharmony_ci  if (util::strieq_l("local1", strfacility)) {
43042c593315Sopenharmony_ci    return LOG_LOCAL1;
43052c593315Sopenharmony_ci  }
43062c593315Sopenharmony_ci
43072c593315Sopenharmony_ci  if (util::strieq_l("local2", strfacility)) {
43082c593315Sopenharmony_ci    return LOG_LOCAL2;
43092c593315Sopenharmony_ci  }
43102c593315Sopenharmony_ci
43112c593315Sopenharmony_ci  if (util::strieq_l("local3", strfacility)) {
43122c593315Sopenharmony_ci    return LOG_LOCAL3;
43132c593315Sopenharmony_ci  }
43142c593315Sopenharmony_ci
43152c593315Sopenharmony_ci  if (util::strieq_l("local4", strfacility)) {
43162c593315Sopenharmony_ci    return LOG_LOCAL4;
43172c593315Sopenharmony_ci  }
43182c593315Sopenharmony_ci
43192c593315Sopenharmony_ci  if (util::strieq_l("local5", strfacility)) {
43202c593315Sopenharmony_ci    return LOG_LOCAL5;
43212c593315Sopenharmony_ci  }
43222c593315Sopenharmony_ci
43232c593315Sopenharmony_ci  if (util::strieq_l("local6", strfacility)) {
43242c593315Sopenharmony_ci    return LOG_LOCAL6;
43252c593315Sopenharmony_ci  }
43262c593315Sopenharmony_ci
43272c593315Sopenharmony_ci  if (util::strieq_l("local7", strfacility)) {
43282c593315Sopenharmony_ci    return LOG_LOCAL7;
43292c593315Sopenharmony_ci  }
43302c593315Sopenharmony_ci
43312c593315Sopenharmony_ci  if (util::strieq_l("lpr", strfacility)) {
43322c593315Sopenharmony_ci    return LOG_LPR;
43332c593315Sopenharmony_ci  }
43342c593315Sopenharmony_ci
43352c593315Sopenharmony_ci  if (util::strieq_l("mail", strfacility)) {
43362c593315Sopenharmony_ci    return LOG_MAIL;
43372c593315Sopenharmony_ci  }
43382c593315Sopenharmony_ci
43392c593315Sopenharmony_ci  if (util::strieq_l("news", strfacility)) {
43402c593315Sopenharmony_ci    return LOG_NEWS;
43412c593315Sopenharmony_ci  }
43422c593315Sopenharmony_ci
43432c593315Sopenharmony_ci  if (util::strieq_l("syslog", strfacility)) {
43442c593315Sopenharmony_ci    return LOG_SYSLOG;
43452c593315Sopenharmony_ci  }
43462c593315Sopenharmony_ci
43472c593315Sopenharmony_ci  if (util::strieq_l("user", strfacility)) {
43482c593315Sopenharmony_ci    return LOG_USER;
43492c593315Sopenharmony_ci  }
43502c593315Sopenharmony_ci
43512c593315Sopenharmony_ci  if (util::strieq_l("uucp", strfacility)) {
43522c593315Sopenharmony_ci    return LOG_UUCP;
43532c593315Sopenharmony_ci  }
43542c593315Sopenharmony_ci
43552c593315Sopenharmony_ci  return -1;
43562c593315Sopenharmony_ci}
43572c593315Sopenharmony_ci
43582c593315Sopenharmony_ciStringRef strproto(Proto proto) {
43592c593315Sopenharmony_ci  switch (proto) {
43602c593315Sopenharmony_ci  case Proto::NONE:
43612c593315Sopenharmony_ci    return StringRef::from_lit("none");
43622c593315Sopenharmony_ci  case Proto::HTTP1:
43632c593315Sopenharmony_ci    return StringRef::from_lit("http/1.1");
43642c593315Sopenharmony_ci  case Proto::HTTP2:
43652c593315Sopenharmony_ci    return StringRef::from_lit("h2");
43662c593315Sopenharmony_ci  case Proto::HTTP3:
43672c593315Sopenharmony_ci    return StringRef::from_lit("h3");
43682c593315Sopenharmony_ci  case Proto::MEMCACHED:
43692c593315Sopenharmony_ci    return StringRef::from_lit("memcached");
43702c593315Sopenharmony_ci  }
43712c593315Sopenharmony_ci
43722c593315Sopenharmony_ci  // gcc needs this.
43732c593315Sopenharmony_ci  assert(0);
43742c593315Sopenharmony_ci  abort();
43752c593315Sopenharmony_ci}
43762c593315Sopenharmony_ci
43772c593315Sopenharmony_cinamespace {
43782c593315Sopenharmony_ci// Consistent hashing method described in
43792c593315Sopenharmony_ci// https://github.com/RJ/ketama.  Generate 160 32-bit hashes per |s|,
43802c593315Sopenharmony_ci// which is usually backend address.  The each hash is associated to
43812c593315Sopenharmony_ci// index of backend address.  When all hashes for every backend
43822c593315Sopenharmony_ci// address are calculated, sort it in ascending order of hash.  To
43832c593315Sopenharmony_ci// choose the index, compute 32-bit hash based on client IP address,
43842c593315Sopenharmony_ci// and do lower bound search in the array. The returned index is the
43852c593315Sopenharmony_ci// backend to use.
43862c593315Sopenharmony_ciint compute_affinity_hash(std::vector<AffinityHash> &res, size_t idx,
43872c593315Sopenharmony_ci                          const StringRef &s) {
43882c593315Sopenharmony_ci  int rv;
43892c593315Sopenharmony_ci  std::array<uint8_t, 32> buf;
43902c593315Sopenharmony_ci
43912c593315Sopenharmony_ci  for (auto i = 0; i < 20; ++i) {
43922c593315Sopenharmony_ci    auto t = s.str();
43932c593315Sopenharmony_ci    t += i;
43942c593315Sopenharmony_ci
43952c593315Sopenharmony_ci    rv = util::sha256(buf.data(), StringRef{t});
43962c593315Sopenharmony_ci    if (rv != 0) {
43972c593315Sopenharmony_ci      return -1;
43982c593315Sopenharmony_ci    }
43992c593315Sopenharmony_ci
44002c593315Sopenharmony_ci    for (int i = 0; i < 8; ++i) {
44012c593315Sopenharmony_ci      auto h = (static_cast<uint32_t>(buf[4 * i]) << 24) |
44022c593315Sopenharmony_ci               (static_cast<uint32_t>(buf[4 * i + 1]) << 16) |
44032c593315Sopenharmony_ci               (static_cast<uint32_t>(buf[4 * i + 2]) << 8) |
44042c593315Sopenharmony_ci               static_cast<uint32_t>(buf[4 * i + 3]);
44052c593315Sopenharmony_ci
44062c593315Sopenharmony_ci      res.emplace_back(idx, h);
44072c593315Sopenharmony_ci    }
44082c593315Sopenharmony_ci  }
44092c593315Sopenharmony_ci
44102c593315Sopenharmony_ci  return 0;
44112c593315Sopenharmony_ci}
44122c593315Sopenharmony_ci} // namespace
44132c593315Sopenharmony_ci
44142c593315Sopenharmony_ci// Configures the following member in |config|:
44152c593315Sopenharmony_ci// conn.downstream_router, conn.downstream.addr_groups,
44162c593315Sopenharmony_ci// conn.downstream.addr_group_catch_all.
44172c593315Sopenharmony_ciint configure_downstream_group(Config *config, bool http2_proxy,
44182c593315Sopenharmony_ci                               bool numeric_addr_only,
44192c593315Sopenharmony_ci                               const TLSConfig &tlsconf) {
44202c593315Sopenharmony_ci  int rv;
44212c593315Sopenharmony_ci
44222c593315Sopenharmony_ci  auto &downstreamconf = *config->conn.downstream;
44232c593315Sopenharmony_ci  auto &addr_groups = downstreamconf.addr_groups;
44242c593315Sopenharmony_ci  auto &routerconf = downstreamconf.router;
44252c593315Sopenharmony_ci  auto &router = routerconf.router;
44262c593315Sopenharmony_ci
44272c593315Sopenharmony_ci  if (addr_groups.empty()) {
44282c593315Sopenharmony_ci    DownstreamAddrConfig addr{};
44292c593315Sopenharmony_ci    addr.host = StringRef::from_lit(DEFAULT_DOWNSTREAM_HOST);
44302c593315Sopenharmony_ci    addr.port = DEFAULT_DOWNSTREAM_PORT;
44312c593315Sopenharmony_ci    addr.proto = Proto::HTTP1;
44322c593315Sopenharmony_ci    addr.weight = 1;
44332c593315Sopenharmony_ci    addr.group_weight = 1;
44342c593315Sopenharmony_ci
44352c593315Sopenharmony_ci    DownstreamAddrGroupConfig g(StringRef::from_lit("/"));
44362c593315Sopenharmony_ci    g.addrs.push_back(std::move(addr));
44372c593315Sopenharmony_ci    router.add_route(g.pattern, addr_groups.size());
44382c593315Sopenharmony_ci    addr_groups.push_back(std::move(g));
44392c593315Sopenharmony_ci  }
44402c593315Sopenharmony_ci
44412c593315Sopenharmony_ci  // backward compatibility: override all SNI fields with the option
44422c593315Sopenharmony_ci  // value --backend-tls-sni-field
44432c593315Sopenharmony_ci  if (!tlsconf.backend_sni_name.empty()) {
44442c593315Sopenharmony_ci    auto &sni = tlsconf.backend_sni_name;
44452c593315Sopenharmony_ci    for (auto &addr_group : addr_groups) {
44462c593315Sopenharmony_ci      for (auto &addr : addr_group.addrs) {
44472c593315Sopenharmony_ci        addr.sni = sni;
44482c593315Sopenharmony_ci      }
44492c593315Sopenharmony_ci    }
44502c593315Sopenharmony_ci  }
44512c593315Sopenharmony_ci
44522c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
44532c593315Sopenharmony_ci    LOG(INFO) << "Resolving backend address";
44542c593315Sopenharmony_ci  }
44552c593315Sopenharmony_ci
44562c593315Sopenharmony_ci  ssize_t catch_all_group = -1;
44572c593315Sopenharmony_ci  for (size_t i = 0; i < addr_groups.size(); ++i) {
44582c593315Sopenharmony_ci    auto &g = addr_groups[i];
44592c593315Sopenharmony_ci    if (g.pattern == StringRef::from_lit("/")) {
44602c593315Sopenharmony_ci      catch_all_group = i;
44612c593315Sopenharmony_ci    }
44622c593315Sopenharmony_ci    if (LOG_ENABLED(INFO)) {
44632c593315Sopenharmony_ci      LOG(INFO) << "Host-path pattern: group " << i << ": '" << g.pattern
44642c593315Sopenharmony_ci                << "'";
44652c593315Sopenharmony_ci      for (auto &addr : g.addrs) {
44662c593315Sopenharmony_ci        LOG(INFO) << "group " << i << " -> " << addr.host.c_str()
44672c593315Sopenharmony_ci                  << (addr.host_unix ? "" : ":" + util::utos(addr.port))
44682c593315Sopenharmony_ci                  << ", proto=" << strproto(addr.proto)
44692c593315Sopenharmony_ci                  << (addr.tls ? ", tls" : "");
44702c593315Sopenharmony_ci      }
44712c593315Sopenharmony_ci    }
44722c593315Sopenharmony_ci#ifdef HAVE_MRUBY
44732c593315Sopenharmony_ci    // Try compile mruby script and catch compile error early.
44742c593315Sopenharmony_ci    if (!g.mruby_file.empty()) {
44752c593315Sopenharmony_ci      if (mruby::create_mruby_context(g.mruby_file) == nullptr) {
44762c593315Sopenharmony_ci        LOG(config->ignore_per_pattern_mruby_error ? ERROR : FATAL)
44772c593315Sopenharmony_ci            << "backend: Could not compile mruby file for pattern "
44782c593315Sopenharmony_ci            << g.pattern;
44792c593315Sopenharmony_ci        if (!config->ignore_per_pattern_mruby_error) {
44802c593315Sopenharmony_ci          return -1;
44812c593315Sopenharmony_ci        }
44822c593315Sopenharmony_ci        g.mruby_file = StringRef{};
44832c593315Sopenharmony_ci      }
44842c593315Sopenharmony_ci    }
44852c593315Sopenharmony_ci#endif // HAVE_MRUBY
44862c593315Sopenharmony_ci  }
44872c593315Sopenharmony_ci
44882c593315Sopenharmony_ci#ifdef HAVE_MRUBY
44892c593315Sopenharmony_ci  // Try compile mruby script (--mruby-file) here to catch compile
44902c593315Sopenharmony_ci  // error early.
44912c593315Sopenharmony_ci  if (!config->mruby_file.empty()) {
44922c593315Sopenharmony_ci    if (mruby::create_mruby_context(config->mruby_file) == nullptr) {
44932c593315Sopenharmony_ci      LOG(FATAL) << "mruby-file: Could not compile mruby file";
44942c593315Sopenharmony_ci      return -1;
44952c593315Sopenharmony_ci    }
44962c593315Sopenharmony_ci  }
44972c593315Sopenharmony_ci#endif // HAVE_MRUBY
44982c593315Sopenharmony_ci
44992c593315Sopenharmony_ci  if (catch_all_group == -1) {
45002c593315Sopenharmony_ci    LOG(FATAL) << "backend: No catch-all backend address is configured";
45012c593315Sopenharmony_ci    return -1;
45022c593315Sopenharmony_ci  }
45032c593315Sopenharmony_ci
45042c593315Sopenharmony_ci  downstreamconf.addr_group_catch_all = catch_all_group;
45052c593315Sopenharmony_ci
45062c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
45072c593315Sopenharmony_ci    LOG(INFO) << "Catch-all pattern is group " << catch_all_group;
45082c593315Sopenharmony_ci  }
45092c593315Sopenharmony_ci
45102c593315Sopenharmony_ci  auto resolve_flags = numeric_addr_only ? AI_NUMERICHOST | AI_NUMERICSERV : 0;
45112c593315Sopenharmony_ci
45122c593315Sopenharmony_ci  std::array<char, util::max_hostport> hostport_buf;
45132c593315Sopenharmony_ci
45142c593315Sopenharmony_ci  for (auto &g : addr_groups) {
45152c593315Sopenharmony_ci    std::unordered_map<StringRef, uint32_t> wgchk;
45162c593315Sopenharmony_ci    for (auto &addr : g.addrs) {
45172c593315Sopenharmony_ci      if (addr.group_weight) {
45182c593315Sopenharmony_ci        auto it = wgchk.find(addr.group);
45192c593315Sopenharmony_ci        if (it == std::end(wgchk)) {
45202c593315Sopenharmony_ci          wgchk.emplace(addr.group, addr.group_weight);
45212c593315Sopenharmony_ci        } else if ((*it).second != addr.group_weight) {
45222c593315Sopenharmony_ci          LOG(FATAL) << "backend: inconsistent group-weight for a single group";
45232c593315Sopenharmony_ci          return -1;
45242c593315Sopenharmony_ci        }
45252c593315Sopenharmony_ci      }
45262c593315Sopenharmony_ci
45272c593315Sopenharmony_ci      if (addr.host_unix) {
45282c593315Sopenharmony_ci        // for AF_UNIX socket, we use "localhost" as host for backend
45292c593315Sopenharmony_ci        // hostport.  This is used as Host header field to backend and
45302c593315Sopenharmony_ci        // not going to be passed to any syscalls.
45312c593315Sopenharmony_ci        addr.hostport = StringRef::from_lit("localhost");
45322c593315Sopenharmony_ci
45332c593315Sopenharmony_ci        auto path = addr.host.c_str();
45342c593315Sopenharmony_ci        auto pathlen = addr.host.size();
45352c593315Sopenharmony_ci
45362c593315Sopenharmony_ci        if (pathlen + 1 > sizeof(addr.addr.su.un.sun_path)) {
45372c593315Sopenharmony_ci          LOG(FATAL) << "UNIX domain socket path " << path << " is too long > "
45382c593315Sopenharmony_ci                     << sizeof(addr.addr.su.un.sun_path);
45392c593315Sopenharmony_ci          return -1;
45402c593315Sopenharmony_ci        }
45412c593315Sopenharmony_ci
45422c593315Sopenharmony_ci        if (LOG_ENABLED(INFO)) {
45432c593315Sopenharmony_ci          LOG(INFO) << "Use UNIX domain socket path " << path
45442c593315Sopenharmony_ci                    << " for backend connection";
45452c593315Sopenharmony_ci        }
45462c593315Sopenharmony_ci
45472c593315Sopenharmony_ci        addr.addr.su.un.sun_family = AF_UNIX;
45482c593315Sopenharmony_ci        // copy path including terminal NULL
45492c593315Sopenharmony_ci        std::copy_n(path, pathlen + 1, addr.addr.su.un.sun_path);
45502c593315Sopenharmony_ci        addr.addr.len = sizeof(addr.addr.su.un);
45512c593315Sopenharmony_ci
45522c593315Sopenharmony_ci        continue;
45532c593315Sopenharmony_ci      }
45542c593315Sopenharmony_ci
45552c593315Sopenharmony_ci      addr.hostport =
45562c593315Sopenharmony_ci          util::make_http_hostport(downstreamconf.balloc, addr.host, addr.port);
45572c593315Sopenharmony_ci
45582c593315Sopenharmony_ci      auto hostport =
45592c593315Sopenharmony_ci          util::make_hostport(std::begin(hostport_buf), addr.host, addr.port);
45602c593315Sopenharmony_ci
45612c593315Sopenharmony_ci      if (!addr.dns) {
45622c593315Sopenharmony_ci        if (resolve_hostname(&addr.addr, addr.host.c_str(), addr.port,
45632c593315Sopenharmony_ci                             downstreamconf.family, resolve_flags) == -1) {
45642c593315Sopenharmony_ci          LOG(FATAL) << "Resolving backend address failed: " << hostport;
45652c593315Sopenharmony_ci          return -1;
45662c593315Sopenharmony_ci        }
45672c593315Sopenharmony_ci
45682c593315Sopenharmony_ci        if (LOG_ENABLED(INFO)) {
45692c593315Sopenharmony_ci          LOG(INFO) << "Resolved backend address: " << hostport << " -> "
45702c593315Sopenharmony_ci                    << util::to_numeric_addr(&addr.addr);
45712c593315Sopenharmony_ci        }
45722c593315Sopenharmony_ci      } else {
45732c593315Sopenharmony_ci        LOG(INFO) << "Resolving backend address " << hostport
45742c593315Sopenharmony_ci                  << " takes place dynamically";
45752c593315Sopenharmony_ci      }
45762c593315Sopenharmony_ci    }
45772c593315Sopenharmony_ci
45782c593315Sopenharmony_ci    for (auto &addr : g.addrs) {
45792c593315Sopenharmony_ci      if (addr.group_weight == 0) {
45802c593315Sopenharmony_ci        auto it = wgchk.find(addr.group);
45812c593315Sopenharmony_ci        if (it == std::end(wgchk)) {
45822c593315Sopenharmony_ci          addr.group_weight = 1;
45832c593315Sopenharmony_ci        } else {
45842c593315Sopenharmony_ci          addr.group_weight = (*it).second;
45852c593315Sopenharmony_ci        }
45862c593315Sopenharmony_ci      }
45872c593315Sopenharmony_ci    }
45882c593315Sopenharmony_ci
45892c593315Sopenharmony_ci    if (g.affinity.type != SessionAffinity::NONE) {
45902c593315Sopenharmony_ci      size_t idx = 0;
45912c593315Sopenharmony_ci      for (auto &addr : g.addrs) {
45922c593315Sopenharmony_ci        StringRef key;
45932c593315Sopenharmony_ci        if (addr.dns) {
45942c593315Sopenharmony_ci          if (addr.host_unix) {
45952c593315Sopenharmony_ci            key = addr.host;
45962c593315Sopenharmony_ci          } else {
45972c593315Sopenharmony_ci            key = addr.hostport;
45982c593315Sopenharmony_ci          }
45992c593315Sopenharmony_ci        } else {
46002c593315Sopenharmony_ci          auto p = reinterpret_cast<uint8_t *>(&addr.addr.su);
46012c593315Sopenharmony_ci          key = StringRef{p, addr.addr.len};
46022c593315Sopenharmony_ci        }
46032c593315Sopenharmony_ci        rv = compute_affinity_hash(g.affinity_hash, idx, key);
46042c593315Sopenharmony_ci        if (rv != 0) {
46052c593315Sopenharmony_ci          return -1;
46062c593315Sopenharmony_ci        }
46072c593315Sopenharmony_ci
46082c593315Sopenharmony_ci        if (g.affinity.cookie.stickiness ==
46092c593315Sopenharmony_ci            SessionAffinityCookieStickiness::STRICT) {
46102c593315Sopenharmony_ci          addr.affinity_hash = util::hash32(key);
46112c593315Sopenharmony_ci          g.affinity_hash_map.emplace(addr.affinity_hash, idx);
46122c593315Sopenharmony_ci        }
46132c593315Sopenharmony_ci
46142c593315Sopenharmony_ci        ++idx;
46152c593315Sopenharmony_ci      }
46162c593315Sopenharmony_ci
46172c593315Sopenharmony_ci      std::sort(std::begin(g.affinity_hash), std::end(g.affinity_hash),
46182c593315Sopenharmony_ci                [](const AffinityHash &lhs, const AffinityHash &rhs) {
46192c593315Sopenharmony_ci                  return lhs.hash < rhs.hash;
46202c593315Sopenharmony_ci                });
46212c593315Sopenharmony_ci    }
46222c593315Sopenharmony_ci
46232c593315Sopenharmony_ci    auto &timeout = g.timeout;
46242c593315Sopenharmony_ci    if (timeout.read < 1e-9) {
46252c593315Sopenharmony_ci      timeout.read = downstreamconf.timeout.read;
46262c593315Sopenharmony_ci    }
46272c593315Sopenharmony_ci    if (timeout.write < 1e-9) {
46282c593315Sopenharmony_ci      timeout.write = downstreamconf.timeout.write;
46292c593315Sopenharmony_ci    }
46302c593315Sopenharmony_ci  }
46312c593315Sopenharmony_ci
46322c593315Sopenharmony_ci  return 0;
46332c593315Sopenharmony_ci}
46342c593315Sopenharmony_ci
46352c593315Sopenharmony_ciint resolve_hostname(Address *addr, const char *hostname, uint16_t port,
46362c593315Sopenharmony_ci                     int family, int additional_flags) {
46372c593315Sopenharmony_ci  int rv;
46382c593315Sopenharmony_ci
46392c593315Sopenharmony_ci  auto service = util::utos(port);
46402c593315Sopenharmony_ci
46412c593315Sopenharmony_ci  addrinfo hints{};
46422c593315Sopenharmony_ci  hints.ai_family = family;
46432c593315Sopenharmony_ci  hints.ai_socktype = SOCK_STREAM;
46442c593315Sopenharmony_ci  hints.ai_flags |= additional_flags;
46452c593315Sopenharmony_ci#ifdef AI_ADDRCONFIG
46462c593315Sopenharmony_ci  hints.ai_flags |= AI_ADDRCONFIG;
46472c593315Sopenharmony_ci#endif // AI_ADDRCONFIG
46482c593315Sopenharmony_ci  addrinfo *res;
46492c593315Sopenharmony_ci
46502c593315Sopenharmony_ci  rv = getaddrinfo(hostname, service.c_str(), &hints, &res);
46512c593315Sopenharmony_ci#ifdef AI_ADDRCONFIG
46522c593315Sopenharmony_ci  if (rv != 0) {
46532c593315Sopenharmony_ci    // Retry without AI_ADDRCONFIG
46542c593315Sopenharmony_ci    hints.ai_flags &= ~AI_ADDRCONFIG;
46552c593315Sopenharmony_ci    rv = getaddrinfo(hostname, service.c_str(), &hints, &res);
46562c593315Sopenharmony_ci  }
46572c593315Sopenharmony_ci#endif // AI_ADDRCONFIG
46582c593315Sopenharmony_ci  if (rv != 0) {
46592c593315Sopenharmony_ci    LOG(FATAL) << "Unable to resolve address for " << hostname << ": "
46602c593315Sopenharmony_ci               << gai_strerror(rv);
46612c593315Sopenharmony_ci    return -1;
46622c593315Sopenharmony_ci  }
46632c593315Sopenharmony_ci
46642c593315Sopenharmony_ci  auto res_d = defer(freeaddrinfo, res);
46652c593315Sopenharmony_ci
46662c593315Sopenharmony_ci  char host[NI_MAXHOST];
46672c593315Sopenharmony_ci  rv = getnameinfo(res->ai_addr, res->ai_addrlen, host, sizeof(host), nullptr,
46682c593315Sopenharmony_ci                   0, NI_NUMERICHOST);
46692c593315Sopenharmony_ci  if (rv != 0) {
46702c593315Sopenharmony_ci    LOG(FATAL) << "Address resolution for " << hostname
46712c593315Sopenharmony_ci               << " failed: " << gai_strerror(rv);
46722c593315Sopenharmony_ci
46732c593315Sopenharmony_ci    return -1;
46742c593315Sopenharmony_ci  }
46752c593315Sopenharmony_ci
46762c593315Sopenharmony_ci  if (LOG_ENABLED(INFO)) {
46772c593315Sopenharmony_ci    LOG(INFO) << "Address resolution for " << hostname
46782c593315Sopenharmony_ci              << " succeeded: " << host;
46792c593315Sopenharmony_ci  }
46802c593315Sopenharmony_ci
46812c593315Sopenharmony_ci  memcpy(&addr->su, res->ai_addr, res->ai_addrlen);
46822c593315Sopenharmony_ci  addr->len = res->ai_addrlen;
46832c593315Sopenharmony_ci
46842c593315Sopenharmony_ci  return 0;
46852c593315Sopenharmony_ci}
46862c593315Sopenharmony_ci
46872c593315Sopenharmony_ci} // namespace shrpx
4688