Apply PIE to nghttpx
[platform/upstream/nghttp2.git] / src / shrpx.cc
1 /*
2  * nghttp2 - HTTP/2 C Library
3  *
4  * Copyright (c) 2012 Tatsuhiro Tsujikawa
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 #include "shrpx.h"
26
27 #include <sys/types.h>
28 #include <sys/wait.h>
29 #include <sys/stat.h>
30 #ifdef HAVE_SYS_SOCKET_H
31 #  include <sys/socket.h>
32 #endif // HAVE_SYS_SOCKET_H
33 #include <sys/un.h>
34 #ifdef HAVE_NETDB_H
35 #  include <netdb.h>
36 #endif // HAVE_NETDB_H
37 #include <signal.h>
38 #ifdef HAVE_NETINET_IN_H
39 #  include <netinet/in.h>
40 #endif // HAVE_NETINET_IN_H
41 #include <netinet/tcp.h>
42 #ifdef HAVE_ARPA_INET_H
43 #  include <arpa/inet.h>
44 #endif // HAVE_ARPA_INET_H
45 #ifdef HAVE_UNISTD_H
46 #  include <unistd.h>
47 #endif // HAVE_UNISTD_H
48 #include <getopt.h>
49 #ifdef HAVE_SYSLOG_H
50 #  include <syslog.h>
51 #endif // HAVE_SYSLOG_H
52 #ifdef HAVE_LIMITS_H
53 #  include <limits.h>
54 #endif // HAVE_LIMITS_H
55 #ifdef HAVE_SYS_TIME_H
56 #  include <sys/time.h>
57 #endif // HAVE_SYS_TIME_H
58 #include <sys/resource.h>
59 #ifdef HAVE_LIBSYSTEMD
60 #  include <systemd/sd-daemon.h>
61 #endif // HAVE_LIBSYSTEMD
62
63 #include <cinttypes>
64 #include <limits>
65 #include <cstdlib>
66 #include <iostream>
67 #include <fstream>
68 #include <vector>
69 #include <initializer_list>
70 #include <random>
71
72 #include <openssl/ssl.h>
73 #include <openssl/err.h>
74 #include <ev.h>
75
76 #include <nghttp2/nghttp2.h>
77
78 #include "shrpx_config.h"
79 #include "shrpx_tls.h"
80 #include "shrpx_log_config.h"
81 #include "shrpx_worker.h"
82 #include "shrpx_http2_upstream.h"
83 #include "shrpx_http2_session.h"
84 #include "shrpx_worker_process.h"
85 #include "shrpx_process.h"
86 #include "shrpx_signal.h"
87 #include "shrpx_connection.h"
88 #include "shrpx_log.h"
89 #include "util.h"
90 #include "app_helper.h"
91 #include "tls.h"
92 #include "template.h"
93 #include "allocator.h"
94 #include "ssl_compat.h"
95 #include "xsi_strerror.h"
96
97 extern char **environ;
98
99 using namespace nghttp2;
100
101 namespace shrpx {
102
103 // Deprecated: Environment variables to tell new binary the listening
104 // socket's file descriptors.  They are not close-on-exec.
105 constexpr auto ENV_LISTENER4_FD = StringRef::from_lit("NGHTTPX_LISTENER4_FD");
106 constexpr auto ENV_LISTENER6_FD = StringRef::from_lit("NGHTTPX_LISTENER6_FD");
107
108 // Deprecated: Environment variable to tell new binary the port number
109 // the current binary is listening to.
110 constexpr auto ENV_PORT = StringRef::from_lit("NGHTTPX_PORT");
111
112 // Deprecated: Environment variable to tell new binary the listening
113 // socket's file descriptor if frontend listens UNIX domain socket.
114 constexpr auto ENV_UNIX_FD = StringRef::from_lit("NGHTTP2_UNIX_FD");
115 // Deprecated: Environment variable to tell new binary the UNIX domain
116 // socket path.
117 constexpr auto ENV_UNIX_PATH = StringRef::from_lit("NGHTTP2_UNIX_PATH");
118
119 // Prefix of environment variables to tell new binary the listening
120 // socket's file descriptor.  They are not close-on-exec.  For TCP
121 // socket, the value must be comma separated 2 parameters: tcp,<FD>.
122 // <FD> is file descriptor.  For UNIX domain socket, the value must be
123 // comma separated 3 parameters: unix,<FD>,<PATH>.  <FD> is file
124 // descriptor.  <PATH> is a path to UNIX domain socket.
125 constexpr auto ENV_ACCEPT_PREFIX = StringRef::from_lit("NGHTTPX_ACCEPT_");
126
127 // This environment variable contains PID of the original master
128 // process, assuming that it created this master process as a result
129 // of SIGUSR2.  The new master process is expected to send QUIT signal
130 // to the original master process to shut it down gracefully.
131 constexpr auto ENV_ORIG_PID = StringRef::from_lit("NGHTTPX_ORIG_PID");
132
133 #ifndef _KERNEL_FASTOPEN
134 #  define _KERNEL_FASTOPEN
135 // conditional define for TCP_FASTOPEN mostly on ubuntu
136 #  ifndef TCP_FASTOPEN
137 #    define TCP_FASTOPEN 23
138 #  endif
139
140 // conditional define for SOL_TCP mostly on ubuntu
141 #  ifndef SOL_TCP
142 #    define SOL_TCP 6
143 #  endif
144 #endif
145
146 // This configuration is fixed at the first startup of the main
147 // process, and does not change after subsequent reloadings.
148 struct StartupConfig {
149   // This contains all options given in command-line.
150   std::vector<std::pair<StringRef, StringRef>> cmdcfgs;
151   // The current working directory where this process started.
152   char *cwd;
153   // The pointer to original argv (not sure why we have this?)
154   char **original_argv;
155   // The pointer to argv, this is a deep copy of original argv.
156   char **argv;
157   // The number of elements in argv.
158   int argc;
159 };
160
161 namespace {
162 StartupConfig suconfig;
163 } // namespace
164
165 struct InheritedAddr {
166   // IP address if TCP socket.  Otherwise, UNIX domain socket path.
167   StringRef host;
168   uint16_t port;
169   // true if UNIX domain socket path
170   bool host_unix;
171   int fd;
172   bool used;
173 };
174
175 namespace {
176 void signal_cb(struct ev_loop *loop, ev_signal *w, int revents);
177 } // namespace
178
179 namespace {
180 void worker_process_child_cb(struct ev_loop *loop, ev_child *w, int revents);
181 } // namespace
182
183 struct WorkerProcess {
184   WorkerProcess(struct ev_loop *loop, pid_t worker_pid, int ipc_fd)
185       : loop(loop), worker_pid(worker_pid), ipc_fd(ipc_fd) {
186     ev_signal_init(&reopen_log_signalev, signal_cb, REOPEN_LOG_SIGNAL);
187     reopen_log_signalev.data = this;
188     ev_signal_start(loop, &reopen_log_signalev);
189
190     ev_signal_init(&exec_binary_signalev, signal_cb, EXEC_BINARY_SIGNAL);
191     exec_binary_signalev.data = this;
192     ev_signal_start(loop, &exec_binary_signalev);
193
194     ev_signal_init(&graceful_shutdown_signalev, signal_cb,
195                    GRACEFUL_SHUTDOWN_SIGNAL);
196     graceful_shutdown_signalev.data = this;
197     ev_signal_start(loop, &graceful_shutdown_signalev);
198
199     ev_signal_init(&reload_signalev, signal_cb, RELOAD_SIGNAL);
200     reload_signalev.data = this;
201     ev_signal_start(loop, &reload_signalev);
202
203     ev_child_init(&worker_process_childev, worker_process_child_cb, worker_pid,
204                   0);
205     worker_process_childev.data = this;
206     ev_child_start(loop, &worker_process_childev);
207   }
208
209   ~WorkerProcess() {
210     shutdown_signal_watchers();
211
212     ev_child_stop(loop, &worker_process_childev);
213
214     if (ipc_fd != -1) {
215       shutdown(ipc_fd, SHUT_WR);
216       close(ipc_fd);
217     }
218   }
219
220   void shutdown_signal_watchers() {
221     ev_signal_stop(loop, &reopen_log_signalev);
222     ev_signal_stop(loop, &exec_binary_signalev);
223     ev_signal_stop(loop, &graceful_shutdown_signalev);
224     ev_signal_stop(loop, &reload_signalev);
225   }
226
227   ev_signal reopen_log_signalev;
228   ev_signal exec_binary_signalev;
229   ev_signal graceful_shutdown_signalev;
230   ev_signal reload_signalev;
231   ev_child worker_process_childev;
232   struct ev_loop *loop;
233   pid_t worker_pid;
234   int ipc_fd;
235 };
236
237 namespace {
238 void reload_config(WorkerProcess *wp);
239 } // namespace
240
241 namespace {
242 std::deque<std::unique_ptr<WorkerProcess>> worker_processes;
243 } // namespace
244
245 namespace {
246 void worker_process_add(std::unique_ptr<WorkerProcess> wp) {
247   worker_processes.push_back(std::move(wp));
248 }
249 } // namespace
250
251 namespace {
252 void worker_process_remove(const WorkerProcess *wp) {
253   for (auto it = std::begin(worker_processes); it != std::end(worker_processes);
254        ++it) {
255     auto &s = *it;
256
257     if (s.get() != wp) {
258       continue;
259     }
260
261     worker_processes.erase(it);
262     break;
263   }
264 }
265 } // namespace
266
267 namespace {
268 void worker_process_remove_all() {
269   std::deque<std::unique_ptr<WorkerProcess>>().swap(worker_processes);
270 }
271 } // namespace
272
273 namespace {
274 // Send signal |signum| to all worker processes, and clears
275 // worker_processes.
276 void worker_process_kill(int signum) {
277   for (auto &s : worker_processes) {
278     if (s->worker_pid == -1) {
279       continue;
280     }
281     kill(s->worker_pid, signum);
282   }
283   worker_process_remove_all();
284 }
285 } // namespace
286
287 namespace {
288 // Returns the last PID of worker process.  Returns -1 if there is no
289 // worker process at the moment.
290 int worker_process_last_pid() {
291   if (worker_processes.empty()) {
292     return -1;
293   }
294
295   return worker_processes.back()->worker_pid;
296 }
297 } // namespace
298
299 namespace {
300 int save_pid() {
301   std::array<char, STRERROR_BUFSIZE> errbuf;
302   auto config = get_config();
303
304   constexpr auto SUFFIX = StringRef::from_lit(".XXXXXX");
305   auto &pid_file = config->pid_file;
306
307   auto len = config->pid_file.size() + SUFFIX.size();
308   auto buf = std::make_unique<char[]>(len + 1);
309   auto p = buf.get();
310
311   p = std::copy(std::begin(pid_file), std::end(pid_file), p);
312   p = std::copy(std::begin(SUFFIX), std::end(SUFFIX), p);
313   *p = '\0';
314
315   auto temp_path = buf.get();
316
317   auto fd = mkstemp(temp_path);
318   if (fd == -1) {
319     auto error = errno;
320     LOG(ERROR) << "Could not save PID to file " << pid_file << ": "
321                << xsi_strerror(error, errbuf.data(), errbuf.size());
322     return -1;
323   }
324
325   auto content = util::utos(config->pid) + '\n';
326
327   if (write(fd, content.c_str(), content.size()) == -1) {
328     auto error = errno;
329     LOG(ERROR) << "Could not save PID to file " << pid_file << ": "
330                << xsi_strerror(error, errbuf.data(), errbuf.size());
331     return -1;
332   }
333
334   if (fsync(fd) == -1) {
335     auto error = errno;
336     LOG(ERROR) << "Could not save PID to file " << pid_file << ": "
337                << xsi_strerror(error, errbuf.data(), errbuf.size());
338     return -1;
339   }
340
341   close(fd);
342
343   if (rename(temp_path, pid_file.c_str()) == -1) {
344     auto error = errno;
345     LOG(ERROR) << "Could not save PID to file " << pid_file << ": "
346                << xsi_strerror(error, errbuf.data(), errbuf.size());
347
348     unlink(temp_path);
349
350     return -1;
351   }
352
353   if (config->uid != 0) {
354     if (chown(pid_file.c_str(), config->uid, config->gid) == -1) {
355       auto error = errno;
356       LOG(WARN) << "Changing owner of pid file " << pid_file << " failed: "
357                 << xsi_strerror(error, errbuf.data(), errbuf.size());
358     }
359   }
360
361   return 0;
362 }
363 } // namespace
364
365 namespace {
366 void shrpx_sd_notifyf(int unset_environment, const char *format, ...) {
367 #ifdef HAVE_LIBSYSTEMD
368   va_list args;
369
370   va_start(args, format);
371   sd_notifyf(unset_environment, format, va_arg(args, char *));
372   va_end(args);
373 #endif // HAVE_LIBSYSTEMD
374 }
375 } // namespace
376
377 namespace {
378 void exec_binary() {
379   int rv;
380   sigset_t oldset;
381   std::array<char, STRERROR_BUFSIZE> errbuf;
382
383   LOG(NOTICE) << "Executing new binary";
384
385   shrpx_sd_notifyf(0, "RELOADING=1");
386
387   rv = shrpx_signal_block_all(&oldset);
388   if (rv != 0) {
389     auto error = errno;
390     LOG(ERROR) << "Blocking all signals failed: "
391                << xsi_strerror(error, errbuf.data(), errbuf.size());
392
393     return;
394   }
395
396   auto pid = fork();
397
398   if (pid != 0) {
399     if (pid == -1) {
400       auto error = errno;
401       LOG(ERROR) << "fork() failed errno=" << error;
402     } else {
403       // update PID tracking information in systemd
404       shrpx_sd_notifyf(0, "MAINPID=%d\n", pid);
405     }
406
407     rv = shrpx_signal_set(&oldset);
408
409     if (rv != 0) {
410       auto error = errno;
411       LOG(FATAL) << "Restoring signal mask failed: "
412                  << xsi_strerror(error, errbuf.data(), errbuf.size());
413
414       exit(EXIT_FAILURE);
415     }
416
417     return;
418   }
419
420   // child process
421
422   shrpx_signal_unset_master_proc_ign_handler();
423
424   rv = shrpx_signal_unblock_all();
425   if (rv != 0) {
426     auto error = errno;
427     LOG(ERROR) << "Unblocking all signals failed: "
428                << xsi_strerror(error, errbuf.data(), errbuf.size());
429
430     nghttp2_Exit(EXIT_FAILURE);
431   }
432
433   auto exec_path =
434       util::get_exec_path(suconfig.argc, suconfig.argv, suconfig.cwd);
435
436   if (!exec_path) {
437     LOG(ERROR) << "Could not resolve the executable path";
438     nghttp2_Exit(EXIT_FAILURE);
439   }
440
441   auto argv = std::make_unique<char *[]>(suconfig.argc + 1);
442
443   argv[0] = exec_path;
444   for (int i = 1; i < suconfig.argc; ++i) {
445     argv[i] = suconfig.argv[i];
446   }
447   argv[suconfig.argc] = nullptr;
448
449   size_t envlen = 0;
450   for (char **p = environ; *p; ++p, ++envlen)
451     ;
452
453   auto config = get_config();
454   auto &listenerconf = config->conn.listener;
455
456   // 2 for ENV_ORIG_PID and terminal nullptr.
457   auto envp =
458       std::make_unique<char *[]>(envlen + listenerconf.addrs.size() + 2);
459   size_t envidx = 0;
460
461   std::vector<ImmutableString> fd_envs;
462   for (size_t i = 0; i < listenerconf.addrs.size(); ++i) {
463     auto &addr = listenerconf.addrs[i];
464     auto s = ENV_ACCEPT_PREFIX.str();
465     s += util::utos(i + 1);
466     s += '=';
467     if (addr.host_unix) {
468       s += "unix,";
469       s += util::utos(addr.fd);
470       s += ',';
471       s += addr.host;
472     } else {
473       s += "tcp,";
474       s += util::utos(addr.fd);
475     }
476
477     fd_envs.emplace_back(s);
478     envp[envidx++] = const_cast<char *>(fd_envs.back().c_str());
479   }
480
481   auto ipc_fd_str = ENV_ORIG_PID.str();
482   ipc_fd_str += '=';
483   ipc_fd_str += util::utos(config->pid);
484   envp[envidx++] = const_cast<char *>(ipc_fd_str.c_str());
485
486   for (size_t i = 0; i < envlen; ++i) {
487     auto env = StringRef{environ[i]};
488     if (util::starts_with(env, ENV_ACCEPT_PREFIX) ||
489         util::starts_with(env, ENV_LISTENER4_FD) ||
490         util::starts_with(env, ENV_LISTENER6_FD) ||
491         util::starts_with(env, ENV_PORT) ||
492         util::starts_with(env, ENV_UNIX_FD) ||
493         util::starts_with(env, ENV_UNIX_PATH) ||
494         util::starts_with(env, ENV_ORIG_PID)) {
495       continue;
496     }
497
498     envp[envidx++] = environ[i];
499   }
500
501   envp[envidx++] = nullptr;
502
503   if (LOG_ENABLED(INFO)) {
504     LOG(INFO) << "cmdline";
505     for (int i = 0; argv[i]; ++i) {
506       LOG(INFO) << i << ": " << argv[i];
507     }
508     LOG(INFO) << "environ";
509     for (int i = 0; envp[i]; ++i) {
510       LOG(INFO) << i << ": " << envp[i];
511     }
512   }
513
514   // restores original stderr
515   restore_original_fds();
516
517   // reloading finished
518   shrpx_sd_notifyf(0, "READY=1");
519
520   if (execve(argv[0], argv.get(), envp.get()) == -1) {
521     auto error = errno;
522     LOG(ERROR) << "execve failed: errno=" << error;
523     nghttp2_Exit(EXIT_FAILURE);
524   }
525 }
526 } // namespace
527
528 namespace {
529 void ipc_send(WorkerProcess *wp, uint8_t ipc_event) {
530   std::array<char, STRERROR_BUFSIZE> errbuf;
531   ssize_t nwrite;
532   while ((nwrite = write(wp->ipc_fd, &ipc_event, 1)) == -1 && errno == EINTR)
533     ;
534
535   if (nwrite < 0) {
536     auto error = errno;
537     LOG(ERROR) << "Could not send IPC event to worker process: "
538                << xsi_strerror(error, errbuf.data(), errbuf.size());
539     return;
540   }
541
542   if (nwrite == 0) {
543     LOG(ERROR) << "Could not send IPC event due to pipe overflow";
544     return;
545   }
546 }
547 } // namespace
548
549 namespace {
550 void reopen_log(WorkerProcess *wp) {
551   LOG(NOTICE) << "Reopening log files: master process";
552
553   auto config = get_config();
554   auto &loggingconf = config->logging;
555
556   (void)reopen_log_files(loggingconf);
557   redirect_stderr_to_errorlog(loggingconf);
558   ipc_send(wp, SHRPX_IPC_REOPEN_LOG);
559 }
560 } // namespace
561
562 namespace {
563 void signal_cb(struct ev_loop *loop, ev_signal *w, int revents) {
564   auto wp = static_cast<WorkerProcess *>(w->data);
565   if (wp->worker_pid == -1) {
566     ev_break(loop);
567     return;
568   }
569
570   switch (w->signum) {
571   case REOPEN_LOG_SIGNAL:
572     reopen_log(wp);
573     return;
574   case EXEC_BINARY_SIGNAL:
575     exec_binary();
576     return;
577   case GRACEFUL_SHUTDOWN_SIGNAL: {
578     auto &listenerconf = get_config()->conn.listener;
579     for (auto &addr : listenerconf.addrs) {
580       close(addr.fd);
581     }
582     ipc_send(wp, SHRPX_IPC_GRACEFUL_SHUTDOWN);
583     return;
584   }
585   case RELOAD_SIGNAL:
586     reload_config(wp);
587     return;
588   default:
589     worker_process_kill(w->signum);
590     ev_break(loop);
591     return;
592   }
593 }
594 } // namespace
595
596 namespace {
597 void worker_process_child_cb(struct ev_loop *loop, ev_child *w, int revents) {
598   auto wp = static_cast<WorkerProcess *>(w->data);
599
600   log_chld(w->rpid, w->rstatus, "Worker process");
601
602   auto pid = wp->worker_pid;
603
604   worker_process_remove(wp);
605
606   if (worker_process_last_pid() == pid) {
607     ev_break(loop);
608   }
609 }
610 } // namespace
611
612 namespace {
613 int create_unix_domain_server_socket(UpstreamAddr &faddr,
614                                      std::vector<InheritedAddr> &iaddrs) {
615   std::array<char, STRERROR_BUFSIZE> errbuf;
616   auto found = std::find_if(
617       std::begin(iaddrs), std::end(iaddrs), [&faddr](const InheritedAddr &ia) {
618         return !ia.used && ia.host_unix && ia.host == faddr.host;
619       });
620
621   if (found != std::end(iaddrs)) {
622     LOG(NOTICE) << "Listening on UNIX domain socket " << faddr.host
623                 << (faddr.tls ? ", tls" : "");
624     (*found).used = true;
625     faddr.fd = (*found).fd;
626     faddr.hostport = StringRef::from_lit("localhost");
627
628     return 0;
629   }
630
631 #ifdef SOCK_NONBLOCK
632   auto fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
633   if (fd == -1) {
634     auto error = errno;
635     LOG(FATAL) << "socket() syscall failed: "
636                << xsi_strerror(error, errbuf.data(), errbuf.size());
637     return -1;
638   }
639 #else  // !SOCK_NONBLOCK
640   auto fd = socket(AF_UNIX, SOCK_STREAM, 0);
641   if (fd == -1) {
642     auto error = errno;
643     LOG(FATAL) << "socket() syscall failed: "
644                << xsi_strerror(error, errbuf.data(), errbuf.size());
645     return -1;
646   }
647   util::make_socket_nonblocking(fd);
648 #endif // !SOCK_NONBLOCK
649   int val = 1;
650   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val,
651                  static_cast<socklen_t>(sizeof(val))) == -1) {
652     auto error = errno;
653     LOG(FATAL) << "Failed to set SO_REUSEADDR option to listener socket: "
654                << xsi_strerror(error, errbuf.data(), errbuf.size());
655     close(fd);
656     return -1;
657   }
658
659   sockaddr_union addr;
660   addr.un.sun_family = AF_UNIX;
661   if (faddr.host.size() + 1 > sizeof(addr.un.sun_path)) {
662     LOG(FATAL) << "UNIX domain socket path " << faddr.host << " is too long > "
663                << sizeof(addr.un.sun_path);
664     close(fd);
665     return -1;
666   }
667   // copy path including terminal NULL
668   std::copy_n(faddr.host.c_str(), faddr.host.size() + 1, addr.un.sun_path);
669
670   // unlink (remove) already existing UNIX domain socket path
671   unlink(faddr.host.c_str());
672
673   if (bind(fd, &addr.sa, sizeof(addr.un)) != 0) {
674     auto error = errno;
675     LOG(FATAL) << "Failed to bind UNIX domain socket: "
676                << xsi_strerror(error, errbuf.data(), errbuf.size());
677     close(fd);
678     return -1;
679   }
680
681   auto &listenerconf = get_config()->conn.listener;
682
683   if (listen(fd, listenerconf.backlog) != 0) {
684     auto error = errno;
685     LOG(FATAL) << "Failed to listen to UNIX domain socket: "
686                << xsi_strerror(error, errbuf.data(), errbuf.size());
687     close(fd);
688     return -1;
689   }
690
691   LOG(NOTICE) << "Listening on UNIX domain socket " << faddr.host
692               << (faddr.tls ? ", tls" : "");
693
694   faddr.fd = fd;
695   faddr.hostport = StringRef::from_lit("localhost");
696
697   return 0;
698 }
699 } // namespace
700
701 namespace {
702 int create_tcp_server_socket(UpstreamAddr &faddr,
703                              std::vector<InheritedAddr> &iaddrs) {
704   std::array<char, STRERROR_BUFSIZE> errbuf;
705   int fd = -1;
706   int rv;
707
708   auto &listenerconf = get_config()->conn.listener;
709
710   auto service = util::utos(faddr.port);
711   addrinfo hints{};
712   hints.ai_family = faddr.family;
713   hints.ai_socktype = SOCK_STREAM;
714   hints.ai_flags = AI_PASSIVE;
715 #ifdef AI_ADDRCONFIG
716   hints.ai_flags |= AI_ADDRCONFIG;
717 #endif // AI_ADDRCONFIG
718
719   auto node =
720       faddr.host == StringRef::from_lit("*") ? nullptr : faddr.host.c_str();
721
722   addrinfo *res, *rp;
723   rv = getaddrinfo(node, service.c_str(), &hints, &res);
724 #ifdef AI_ADDRCONFIG
725   if (rv != 0) {
726     // Retry without AI_ADDRCONFIG
727     hints.ai_flags &= ~AI_ADDRCONFIG;
728     rv = getaddrinfo(node, service.c_str(), &hints, &res);
729   }
730 #endif // AI_ADDRCONFIG
731   if (rv != 0) {
732     LOG(FATAL) << "Unable to get IPv" << (faddr.family == AF_INET ? "4" : "6")
733                << " address for " << faddr.host << ", port " << faddr.port
734                << ": " << gai_strerror(rv);
735     return -1;
736   }
737
738   auto res_d = defer(freeaddrinfo, res);
739
740   std::array<char, NI_MAXHOST> host;
741
742   for (rp = res; rp; rp = rp->ai_next) {
743
744     rv = getnameinfo(rp->ai_addr, rp->ai_addrlen, host.data(), host.size(),
745                      nullptr, 0, NI_NUMERICHOST);
746
747     if (rv != 0) {
748       LOG(WARN) << "getnameinfo() failed: " << gai_strerror(rv);
749       continue;
750     }
751
752     auto found = std::find_if(std::begin(iaddrs), std::end(iaddrs),
753                               [&host, &faddr](const InheritedAddr &ia) {
754                                 return !ia.used && !ia.host_unix &&
755                                        ia.host == host.data() &&
756                                        ia.port == faddr.port;
757                               });
758
759     if (found != std::end(iaddrs)) {
760       (*found).used = true;
761       fd = (*found).fd;
762       break;
763     }
764
765 #ifdef SOCK_NONBLOCK
766     fd =
767         socket(rp->ai_family, rp->ai_socktype | SOCK_NONBLOCK, rp->ai_protocol);
768     if (fd == -1) {
769       auto error = errno;
770       LOG(WARN) << "socket() syscall failed: "
771                 << xsi_strerror(error, errbuf.data(), errbuf.size());
772       continue;
773     }
774 #else  // !SOCK_NONBLOCK
775     fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
776     if (fd == -1) {
777       auto error = errno;
778       LOG(WARN) << "socket() syscall failed: "
779                 << xsi_strerror(error, errbuf.data(), errbuf.size());
780       continue;
781     }
782     util::make_socket_nonblocking(fd);
783 #endif // !SOCK_NONBLOCK
784     int val = 1;
785     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val,
786                    static_cast<socklen_t>(sizeof(val))) == -1) {
787       auto error = errno;
788       LOG(WARN) << "Failed to set SO_REUSEADDR option to listener socket: "
789                 << xsi_strerror(error, errbuf.data(), errbuf.size());
790       close(fd);
791       continue;
792     }
793
794 #ifdef IPV6_V6ONLY
795     if (faddr.family == AF_INET6) {
796       if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val,
797                      static_cast<socklen_t>(sizeof(val))) == -1) {
798         auto error = errno;
799         LOG(WARN) << "Failed to set IPV6_V6ONLY option to listener socket: "
800                   << xsi_strerror(error, errbuf.data(), errbuf.size());
801         close(fd);
802         continue;
803       }
804     }
805 #endif // IPV6_V6ONLY
806
807 #ifdef TCP_DEFER_ACCEPT
808     val = 3;
809     if (setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &val,
810                    static_cast<socklen_t>(sizeof(val))) == -1) {
811       auto error = errno;
812       LOG(WARN) << "Failed to set TCP_DEFER_ACCEPT option to listener socket: "
813                 << xsi_strerror(error, errbuf.data(), errbuf.size());
814     }
815 #endif // TCP_DEFER_ACCEPT
816
817     // When we are executing new binary, and the old binary did not
818     // bind privileged port (< 1024) for some reason, binding to those
819     // ports will fail with permission denied error.
820     if (bind(fd, rp->ai_addr, rp->ai_addrlen) == -1) {
821       auto error = errno;
822       LOG(WARN) << "bind() syscall failed: "
823                 << xsi_strerror(error, errbuf.data(), errbuf.size());
824       close(fd);
825       continue;
826     }
827
828     if (listenerconf.fastopen > 0) {
829       val = listenerconf.fastopen;
830       if (setsockopt(fd, SOL_TCP, TCP_FASTOPEN, &val,
831                      static_cast<socklen_t>(sizeof(val))) == -1) {
832         auto error = errno;
833         LOG(WARN) << "Failed to set TCP_FASTOPEN option to listener socket: "
834                   << xsi_strerror(error, errbuf.data(), errbuf.size());
835       }
836     }
837
838     if (listen(fd, listenerconf.backlog) == -1) {
839       auto error = errno;
840       LOG(WARN) << "listen() syscall failed: "
841                 << xsi_strerror(error, errbuf.data(), errbuf.size());
842       close(fd);
843       continue;
844     }
845
846     break;
847   }
848
849   if (!rp) {
850     LOG(FATAL) << "Listening " << (faddr.family == AF_INET ? "IPv4" : "IPv6")
851                << " socket failed";
852
853     return -1;
854   }
855
856   faddr.fd = fd;
857   faddr.hostport = util::make_http_hostport(mod_config()->balloc,
858                                             StringRef{host.data()}, faddr.port);
859
860   LOG(NOTICE) << "Listening on " << faddr.hostport
861               << (faddr.tls ? ", tls" : "");
862
863   return 0;
864 }
865 } // namespace
866
867 namespace {
868 // Returns array of InheritedAddr constructed from |config|.  This
869 // function is intended to be used when reloading configuration, and
870 // |config| is usually a current configuration.
871 std::vector<InheritedAddr>
872 get_inherited_addr_from_config(BlockAllocator &balloc, Config *config) {
873   std::array<char, STRERROR_BUFSIZE> errbuf;
874   int rv;
875
876   auto &listenerconf = config->conn.listener;
877
878   std::vector<InheritedAddr> iaddrs(listenerconf.addrs.size());
879
880   size_t idx = 0;
881   for (auto &addr : listenerconf.addrs) {
882     auto &iaddr = iaddrs[idx++];
883
884     if (addr.host_unix) {
885       iaddr.host = addr.host;
886       iaddr.host_unix = true;
887       iaddr.fd = addr.fd;
888
889       continue;
890     }
891
892     iaddr.port = addr.port;
893     iaddr.fd = addr.fd;
894
895     // We have to getsockname/getnameinfo for fd, since we may have
896     // '*' appear in addr.host, which makes comparison against "real"
897     // address fail.
898
899     sockaddr_union su;
900     socklen_t salen = sizeof(su);
901
902     // We already added entry to iaddrs.  Even if we got errors, we
903     // don't remove it.  This is required because we have to close the
904     // socket if it is not reused.  The empty host name usually does
905     // not match anything.
906
907     if (getsockname(addr.fd, &su.sa, &salen) != 0) {
908       auto error = errno;
909       LOG(WARN) << "getsockname() syscall failed (fd=" << addr.fd
910                 << "): " << xsi_strerror(error, errbuf.data(), errbuf.size());
911       continue;
912     }
913
914     std::array<char, NI_MAXHOST> host;
915     rv = getnameinfo(&su.sa, salen, host.data(), host.size(), nullptr, 0,
916                      NI_NUMERICHOST);
917     if (rv != 0) {
918       LOG(WARN) << "getnameinfo() failed (fd=" << addr.fd
919                 << "): " << gai_strerror(rv);
920       continue;
921     }
922
923     iaddr.host = make_string_ref(balloc, StringRef{host.data()});
924   }
925
926   return iaddrs;
927 }
928 } // namespace
929
930 namespace {
931 // Returns array of InheritedAddr constructed from environment
932 // variables.  This function handles the old environment variable
933 // names used in 1.7.0 or earlier.
934 std::vector<InheritedAddr> get_inherited_addr_from_env(Config *config) {
935   std::array<char, STRERROR_BUFSIZE> errbuf;
936   int rv;
937   std::vector<InheritedAddr> iaddrs;
938
939   {
940     // Upgrade from 1.7.0 or earlier
941     auto portenv = getenv(ENV_PORT.c_str());
942     if (portenv) {
943       size_t i = 1;
944       for (auto env_name : {ENV_LISTENER4_FD, ENV_LISTENER6_FD}) {
945         auto fdenv = getenv(env_name.c_str());
946         if (fdenv) {
947           auto name = ENV_ACCEPT_PREFIX.str();
948           name += util::utos(i);
949           std::string value = "tcp,";
950           value += fdenv;
951           setenv(name.c_str(), value.c_str(), 0);
952           ++i;
953         }
954       }
955     } else {
956       // The return value of getenv may be allocated statically.
957       if (getenv(ENV_UNIX_PATH.c_str()) && getenv(ENV_UNIX_FD.c_str())) {
958         auto name = ENV_ACCEPT_PREFIX.str();
959         name += '1';
960         std::string value = "unix,";
961         value += getenv(ENV_UNIX_FD.c_str());
962         value += ',';
963         value += getenv(ENV_UNIX_PATH.c_str());
964         setenv(name.c_str(), value.c_str(), 0);
965       }
966     }
967   }
968
969   for (size_t i = 1;; ++i) {
970     auto name = ENV_ACCEPT_PREFIX.str();
971     name += util::utos(i);
972     auto env = getenv(name.c_str());
973     if (!env) {
974       break;
975     }
976
977     if (LOG_ENABLED(INFO)) {
978       LOG(INFO) << "Read env " << name << "=" << env;
979     }
980
981     auto end_type = strchr(env, ',');
982     if (!end_type) {
983       continue;
984     }
985
986     auto type = StringRef(env, end_type);
987     auto value = end_type + 1;
988
989     if (type == StringRef::from_lit("unix")) {
990       auto endfd = strchr(value, ',');
991       if (!endfd) {
992         continue;
993       }
994       auto fd = util::parse_uint(reinterpret_cast<const uint8_t *>(value),
995                                  endfd - value);
996       if (fd == -1) {
997         LOG(WARN) << "Could not parse file descriptor from "
998                   << std::string(value, endfd - value);
999         continue;
1000       }
1001
1002       auto path = endfd + 1;
1003       if (strlen(path) == 0) {
1004         LOG(WARN) << "Empty UNIX domain socket path (fd=" << fd << ")";
1005         close(fd);
1006         continue;
1007       }
1008
1009       if (LOG_ENABLED(INFO)) {
1010         LOG(INFO) << "Inherit UNIX domain socket fd=" << fd
1011                   << ", path=" << path;
1012       }
1013
1014       InheritedAddr addr{};
1015       addr.host = make_string_ref(config->balloc, StringRef{path});
1016       addr.host_unix = true;
1017       addr.fd = static_cast<int>(fd);
1018       iaddrs.push_back(std::move(addr));
1019     }
1020
1021     if (type == StringRef::from_lit("tcp")) {
1022       auto fd = util::parse_uint(value);
1023       if (fd == -1) {
1024         LOG(WARN) << "Could not parse file descriptor from " << value;
1025         continue;
1026       }
1027
1028       sockaddr_union su;
1029       socklen_t salen = sizeof(su);
1030
1031       if (getsockname(fd, &su.sa, &salen) != 0) {
1032         auto error = errno;
1033         LOG(WARN) << "getsockname() syscall failed (fd=" << fd
1034                   << "): " << xsi_strerror(error, errbuf.data(), errbuf.size());
1035         close(fd);
1036         continue;
1037       }
1038
1039       uint16_t port;
1040
1041       switch (su.storage.ss_family) {
1042       case AF_INET:
1043         port = ntohs(su.in.sin_port);
1044         break;
1045       case AF_INET6:
1046         port = ntohs(su.in6.sin6_port);
1047         break;
1048       default:
1049         close(fd);
1050         continue;
1051       }
1052
1053       std::array<char, NI_MAXHOST> host;
1054       rv = getnameinfo(&su.sa, salen, host.data(), host.size(), nullptr, 0,
1055                        NI_NUMERICHOST);
1056       if (rv != 0) {
1057         LOG(WARN) << "getnameinfo() failed (fd=" << fd
1058                   << "): " << gai_strerror(rv);
1059         close(fd);
1060         continue;
1061       }
1062
1063       if (LOG_ENABLED(INFO)) {
1064         LOG(INFO) << "Inherit TCP socket fd=" << fd
1065                   << ", address=" << host.data() << ", port=" << port;
1066       }
1067
1068       InheritedAddr addr{};
1069       addr.host = make_string_ref(config->balloc, StringRef{host.data()});
1070       addr.port = static_cast<uint16_t>(port);
1071       addr.fd = static_cast<int>(fd);
1072       iaddrs.push_back(std::move(addr));
1073       continue;
1074     }
1075   }
1076
1077   return iaddrs;
1078 }
1079 } // namespace
1080
1081 namespace {
1082 // Closes all sockets which are not reused.
1083 void close_unused_inherited_addr(const std::vector<InheritedAddr> &iaddrs) {
1084   for (auto &ia : iaddrs) {
1085     if (ia.used) {
1086       continue;
1087     }
1088
1089     close(ia.fd);
1090   }
1091 }
1092 } // namespace
1093
1094 namespace {
1095 // Returns the PID of the original master process from environment
1096 // variable ENV_ORIG_PID.
1097 pid_t get_orig_pid_from_env() {
1098   auto s = getenv(ENV_ORIG_PID.c_str());
1099   if (s == nullptr) {
1100     return -1;
1101   }
1102   return util::parse_uint(s);
1103 }
1104 } // namespace
1105
1106 namespace {
1107 int create_acceptor_socket(Config *config, std::vector<InheritedAddr> &iaddrs) {
1108   std::array<char, STRERROR_BUFSIZE> errbuf;
1109   auto &listenerconf = config->conn.listener;
1110
1111   for (auto &addr : listenerconf.addrs) {
1112     if (addr.host_unix) {
1113       if (create_unix_domain_server_socket(addr, iaddrs) != 0) {
1114         return -1;
1115       }
1116
1117       if (config->uid != 0) {
1118         // fd is not associated to inode, so we cannot use fchown(2)
1119         // here.  https://lkml.org/lkml/2004/11/1/84
1120         if (chown(addr.host.c_str(), config->uid, config->gid) == -1) {
1121           auto error = errno;
1122           LOG(WARN) << "Changing owner of UNIX domain socket " << addr.host
1123                     << " failed: "
1124                     << xsi_strerror(error, errbuf.data(), errbuf.size());
1125         }
1126       }
1127       continue;
1128     }
1129
1130     if (create_tcp_server_socket(addr, iaddrs) != 0) {
1131       return -1;
1132     }
1133   }
1134
1135   return 0;
1136 }
1137 } // namespace
1138
1139 namespace {
1140 int call_daemon() {
1141 #ifdef __sgi
1142   return _daemonize(0, 0, 0, 0);
1143 #else // !__sgi
1144 #  ifdef HAVE_LIBSYSTEMD
1145   if (sd_booted() && (getenv("NOTIFY_SOCKET") != nullptr)) {
1146     LOG(NOTICE) << "Daemonising disabled under systemd";
1147     chdir("/");
1148     return 0;
1149   }
1150 #  endif // HAVE_LIBSYSTEMD
1151   return util::daemonize(0, 0);
1152 #endif   // !__sgi
1153 }
1154 } // namespace
1155
1156 namespace {
1157 // Opens IPC socket used to communicate with worker proess.  The
1158 // communication is unidirectional; that is main process sends
1159 // messages to the worker process.  On success, ipc_fd[0] is for
1160 // reading, and ipc_fd[1] for writing, just like pipe(2).
1161 int create_ipc_socket(std::array<int, 2> &ipc_fd) {
1162   std::array<char, STRERROR_BUFSIZE> errbuf;
1163   int rv;
1164
1165   rv = pipe(ipc_fd.data());
1166   if (rv == -1) {
1167     auto error = errno;
1168     LOG(WARN) << "Failed to create pipe to communicate worker process: "
1169               << xsi_strerror(error, errbuf.data(), errbuf.size());
1170     return -1;
1171   }
1172
1173   for (int i = 0; i < 2; ++i) {
1174     auto fd = ipc_fd[i];
1175     util::make_socket_nonblocking(fd);
1176     util::make_socket_closeonexec(fd);
1177   }
1178
1179   return 0;
1180 }
1181 } // namespace
1182
1183 namespace {
1184 // Creates worker process, and returns PID of worker process.  On
1185 // success, file descriptor for IPC (send only) is assigned to
1186 // |main_ipc_fd|.  In child process, we will close file descriptors
1187 // which are inherited from previous configuration/process, but not
1188 // used in the current configuration.
1189 pid_t fork_worker_process(int &main_ipc_fd,
1190                           const std::vector<InheritedAddr> &iaddrs) {
1191   std::array<char, STRERROR_BUFSIZE> errbuf;
1192   int rv;
1193   sigset_t oldset;
1194
1195   std::array<int, 2> ipc_fd;
1196
1197   rv = create_ipc_socket(ipc_fd);
1198   if (rv != 0) {
1199     return -1;
1200   }
1201
1202   rv = shrpx_signal_block_all(&oldset);
1203   if (rv != 0) {
1204     auto error = errno;
1205     LOG(ERROR) << "Blocking all signals failed: "
1206                << xsi_strerror(error, errbuf.data(), errbuf.size());
1207
1208     close(ipc_fd[0]);
1209     close(ipc_fd[1]);
1210
1211     return -1;
1212   }
1213
1214   auto config = get_config();
1215
1216   pid_t pid = 0;
1217
1218   if (!config->single_process) {
1219     pid = fork();
1220   }
1221
1222   if (pid == 0) {
1223     ev_loop_fork(EV_DEFAULT);
1224
1225     for (auto &addr : config->conn.listener.addrs) {
1226       util::make_socket_closeonexec(addr.fd);
1227     }
1228
1229     // Remove all WorkerProcesses to stop any registered watcher on
1230     // default loop.
1231     worker_process_remove_all();
1232
1233     close_unused_inherited_addr(iaddrs);
1234
1235     shrpx_signal_set_worker_proc_ign_handler();
1236
1237     rv = shrpx_signal_unblock_all();
1238     if (rv != 0) {
1239       auto error = errno;
1240       LOG(FATAL) << "Unblocking all signals failed: "
1241                  << xsi_strerror(error, errbuf.data(), errbuf.size());
1242
1243       if (config->single_process) {
1244         exit(EXIT_FAILURE);
1245       } else {
1246         nghttp2_Exit(EXIT_FAILURE);
1247       }
1248     }
1249
1250     if (!config->single_process) {
1251       close(ipc_fd[1]);
1252     }
1253
1254     WorkerProcessConfig wpconf{ipc_fd[0]};
1255     rv = worker_process_event_loop(&wpconf);
1256     if (rv != 0) {
1257       LOG(FATAL) << "Worker process returned error";
1258
1259       if (config->single_process) {
1260         exit(EXIT_FAILURE);
1261       } else {
1262         nghttp2_Exit(EXIT_FAILURE);
1263       }
1264     }
1265
1266     LOG(NOTICE) << "Worker process shutting down momentarily";
1267
1268     // call exit(...) instead of nghttp2_Exit to get leak sanitizer report
1269     if (config->single_process) {
1270       exit(EXIT_SUCCESS);
1271     } else {
1272       nghttp2_Exit(EXIT_SUCCESS);
1273     }
1274   }
1275
1276   // parent process
1277   if (pid == -1) {
1278     auto error = errno;
1279     LOG(ERROR) << "Could not spawn worker process: "
1280                << xsi_strerror(error, errbuf.data(), errbuf.size());
1281   }
1282
1283   rv = shrpx_signal_set(&oldset);
1284   if (rv != 0) {
1285     auto error = errno;
1286     LOG(FATAL) << "Restoring signal mask failed: "
1287                << xsi_strerror(error, errbuf.data(), errbuf.size());
1288
1289     exit(EXIT_FAILURE);
1290   }
1291
1292   if (pid == -1) {
1293     close(ipc_fd[0]);
1294     close(ipc_fd[1]);
1295
1296     return -1;
1297   }
1298
1299   close(ipc_fd[0]);
1300
1301   main_ipc_fd = ipc_fd[1];
1302
1303   LOG(NOTICE) << "Worker process [" << pid << "] spawned";
1304
1305   return pid;
1306 }
1307 } // namespace
1308
1309 namespace {
1310 int event_loop() {
1311   std::array<char, STRERROR_BUFSIZE> errbuf;
1312
1313   shrpx_signal_set_master_proc_ign_handler();
1314
1315   auto config = mod_config();
1316
1317   if (config->daemon) {
1318     if (call_daemon() == -1) {
1319       auto error = errno;
1320       LOG(FATAL) << "Failed to daemonize: "
1321                  << xsi_strerror(error, errbuf.data(), errbuf.size());
1322       return -1;
1323     }
1324
1325     // We get new PID after successful daemon().
1326     mod_config()->pid = getpid();
1327
1328     // daemon redirects stderr file descriptor to /dev/null, so we
1329     // need this.
1330     redirect_stderr_to_errorlog(config->logging);
1331   }
1332
1333   // update systemd PID tracking
1334   shrpx_sd_notifyf(0, "MAINPID=%d\n", config->pid);
1335
1336   {
1337     auto iaddrs = get_inherited_addr_from_env(config);
1338
1339     if (create_acceptor_socket(config, iaddrs) != 0) {
1340       return -1;
1341     }
1342
1343     close_unused_inherited_addr(iaddrs);
1344   }
1345
1346   auto orig_pid = get_orig_pid_from_env();
1347
1348   auto loop = ev_default_loop(config->ev_loop_flags);
1349
1350   int ipc_fd = 0;
1351
1352   auto pid = fork_worker_process(ipc_fd, {});
1353
1354   if (pid == -1) {
1355     return -1;
1356   }
1357
1358   worker_process_add(std::make_unique<WorkerProcess>(loop, pid, ipc_fd));
1359
1360   // Write PID file when we are ready to accept connection from peer.
1361   // This makes easier to write restart script for nghttpx.  Because
1362   // when we know that PID file is recreated, it means we can send
1363   // QUIT signal to the old process to make it shutdown gracefully.
1364   if (!config->pid_file.empty()) {
1365     save_pid();
1366   }
1367
1368   // ready to serve requests
1369   shrpx_sd_notifyf(0, "READY=1");
1370
1371   if (orig_pid != -1) {
1372     LOG(NOTICE) << "Send QUIT signal to the original master process to tell "
1373                    "that we are ready to serve requests.";
1374     kill(orig_pid, SIGQUIT);
1375   }
1376
1377   ev_run(loop, 0);
1378
1379   return 0;
1380 }
1381 } // namespace
1382
1383 namespace {
1384 // Returns true if regular file or symbolic link |path| exists.
1385 bool conf_exists(const char *path) {
1386   struct stat buf;
1387   int rv = stat(path, &buf);
1388   return rv == 0 && (buf.st_mode & (S_IFREG | S_IFLNK));
1389 }
1390 } // namespace
1391
1392 namespace {
1393 constexpr auto DEFAULT_NPN_LIST =
1394     StringRef::from_lit("h2,h2-16,h2-14,http/1.1");
1395 } // namespace
1396
1397 namespace {
1398 constexpr auto DEFAULT_TLS_MIN_PROTO_VERSION = StringRef::from_lit("TLSv1.2");
1399 #ifdef TLS1_3_VERSION
1400 constexpr auto DEFAULT_TLS_MAX_PROTO_VERSION = StringRef::from_lit("TLSv1.3");
1401 #else  // !TLS1_3_VERSION
1402 constexpr auto DEFAULT_TLS_MAX_PROTO_VERSION = StringRef::from_lit("TLSv1.2");
1403 #endif // !TLS1_3_VERSION
1404 } // namespace
1405
1406 namespace {
1407 constexpr auto DEFAULT_ACCESSLOG_FORMAT =
1408     StringRef::from_lit(R"($remote_addr - - [$time_local] )"
1409                         R"("$request" $status $body_bytes_sent )"
1410                         R"("$http_referer" "$http_user_agent")");
1411 } // namespace
1412
1413 namespace {
1414 void fill_default_config(Config *config) {
1415   config->num_worker = 1;
1416   config->conf_path = StringRef::from_lit("/etc/nghttpx/nghttpx.conf");
1417   config->pid = getpid();
1418
1419 #ifdef NOTHREADS
1420   config->single_thread = true;
1421 #endif // NOTHREADS
1422
1423   if (ev_supported_backends() & ~ev_recommended_backends() & EVBACKEND_KQUEUE) {
1424     config->ev_loop_flags = ev_recommended_backends() | EVBACKEND_KQUEUE;
1425   }
1426
1427   auto &tlsconf = config->tls;
1428   {
1429     auto &ticketconf = tlsconf.ticket;
1430     {
1431       auto &memcachedconf = ticketconf.memcached;
1432       memcachedconf.max_retry = 3;
1433       memcachedconf.max_fail = 2;
1434       memcachedconf.interval = 10_min;
1435       memcachedconf.family = AF_UNSPEC;
1436     }
1437
1438     auto &session_cacheconf = tlsconf.session_cache;
1439     {
1440       auto &memcachedconf = session_cacheconf.memcached;
1441       memcachedconf.family = AF_UNSPEC;
1442     }
1443
1444     ticketconf.cipher = EVP_aes_128_cbc();
1445   }
1446
1447   {
1448     auto &ocspconf = tlsconf.ocsp;
1449     // ocsp update interval = 14400 secs = 4 hours, borrowed from h2o
1450     ocspconf.update_interval = 4_h;
1451     ocspconf.fetch_ocsp_response_file =
1452         StringRef::from_lit(PKGDATADIR "/fetch-ocsp-response");
1453   }
1454
1455   {
1456     auto &dyn_recconf = tlsconf.dyn_rec;
1457     dyn_recconf.warmup_threshold = 1_m;
1458     dyn_recconf.idle_timeout = 1_s;
1459   }
1460
1461   tlsconf.session_timeout = std::chrono::hours(12);
1462   tlsconf.ciphers = StringRef::from_lit(nghttp2::tls::DEFAULT_CIPHER_LIST);
1463   tlsconf.tls13_ciphers =
1464       StringRef::from_lit(nghttp2::tls::DEFAULT_TLS13_CIPHER_LIST);
1465   tlsconf.client.ciphers =
1466       StringRef::from_lit(nghttp2::tls::DEFAULT_CIPHER_LIST);
1467   tlsconf.client.tls13_ciphers =
1468       StringRef::from_lit(nghttp2::tls::DEFAULT_TLS13_CIPHER_LIST);
1469   tlsconf.min_proto_version =
1470       tls::proto_version_from_string(DEFAULT_TLS_MIN_PROTO_VERSION);
1471   tlsconf.max_proto_version =
1472       tls::proto_version_from_string(DEFAULT_TLS_MAX_PROTO_VERSION);
1473   tlsconf.max_early_data = 16_k;
1474 #if OPENSSL_1_1_API || defined(OPENSSL_IS_BORINGSSL)
1475   tlsconf.ecdh_curves = StringRef::from_lit("X25519:P-256:P-384:P-521");
1476 #else  // !OPENSSL_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
1477   tlsconf.ecdh_curves = StringRef::from_lit("P-256:P-384:P-521");
1478 #endif // !OPENSSL_1_1_API && !defined(OPENSSL_IS_BORINGSSL)
1479
1480   auto &httpconf = config->http;
1481   httpconf.server_name = StringRef::from_lit("nghttpx");
1482   httpconf.no_host_rewrite = true;
1483   httpconf.request_header_field_buffer = 64_k;
1484   httpconf.max_request_header_fields = 100;
1485   httpconf.response_header_field_buffer = 64_k;
1486   httpconf.max_response_header_fields = 500;
1487   httpconf.redirect_https_port = StringRef::from_lit("443");
1488   httpconf.max_requests = std::numeric_limits<size_t>::max();
1489   httpconf.xfp.add = true;
1490   httpconf.xfp.strip_incoming = true;
1491   httpconf.early_data.strip_incoming = true;
1492
1493   auto &http2conf = config->http2;
1494   {
1495     auto &upstreamconf = http2conf.upstream;
1496
1497     {
1498       auto &timeoutconf = upstreamconf.timeout;
1499       timeoutconf.settings = 10_s;
1500     }
1501
1502     // window size for HTTP/2 upstream connection per stream.  2**16-1
1503     // = 64KiB-1, which is HTTP/2 default.
1504     upstreamconf.window_size = 64_k - 1;
1505     // HTTP/2 has connection-level flow control. The default window
1506     // size for HTTP/2 is 64KiB - 1.
1507     upstreamconf.connection_window_size = 64_k - 1;
1508     upstreamconf.max_concurrent_streams = 100;
1509
1510     upstreamconf.encoder_dynamic_table_size = 4_k;
1511     upstreamconf.decoder_dynamic_table_size = 4_k;
1512
1513     nghttp2_option_new(&upstreamconf.option);
1514     nghttp2_option_set_no_auto_window_update(upstreamconf.option, 1);
1515     nghttp2_option_set_no_recv_client_magic(upstreamconf.option, 1);
1516     nghttp2_option_set_max_deflate_dynamic_table_size(
1517         upstreamconf.option, upstreamconf.encoder_dynamic_table_size);
1518
1519     // For API endpoint, we enable automatic window update.  This is
1520     // because we are a sink.
1521     nghttp2_option_new(&upstreamconf.alt_mode_option);
1522     nghttp2_option_set_no_recv_client_magic(upstreamconf.alt_mode_option, 1);
1523     nghttp2_option_set_max_deflate_dynamic_table_size(
1524         upstreamconf.alt_mode_option, upstreamconf.encoder_dynamic_table_size);
1525   }
1526
1527   http2conf.timeout.stream_write = 1_min;
1528
1529   {
1530     auto &downstreamconf = http2conf.downstream;
1531
1532     {
1533       auto &timeoutconf = downstreamconf.timeout;
1534       timeoutconf.settings = 10_s;
1535     }
1536
1537     downstreamconf.window_size = 64_k - 1;
1538     downstreamconf.connection_window_size = (1u << 31) - 1;
1539     downstreamconf.max_concurrent_streams = 100;
1540
1541     downstreamconf.encoder_dynamic_table_size = 4_k;
1542     downstreamconf.decoder_dynamic_table_size = 4_k;
1543
1544     nghttp2_option_new(&downstreamconf.option);
1545     nghttp2_option_set_no_auto_window_update(downstreamconf.option, 1);
1546     nghttp2_option_set_peer_max_concurrent_streams(downstreamconf.option, 100);
1547     nghttp2_option_set_max_deflate_dynamic_table_size(
1548         downstreamconf.option, downstreamconf.encoder_dynamic_table_size);
1549   }
1550
1551   auto &loggingconf = config->logging;
1552   {
1553     auto &accessconf = loggingconf.access;
1554     accessconf.format =
1555         parse_log_format(config->balloc, DEFAULT_ACCESSLOG_FORMAT);
1556
1557     auto &errorconf = loggingconf.error;
1558     errorconf.file = StringRef::from_lit("/dev/stderr");
1559   }
1560
1561   loggingconf.syslog_facility = LOG_DAEMON;
1562   loggingconf.severity = NOTICE;
1563
1564   auto &connconf = config->conn;
1565   {
1566     auto &listenerconf = connconf.listener;
1567     {
1568       // Default accept() backlog
1569       listenerconf.backlog = 65536;
1570       listenerconf.timeout.sleep = 30_s;
1571     }
1572   }
1573
1574   {
1575     auto &upstreamconf = connconf.upstream;
1576     {
1577       auto &timeoutconf = upstreamconf.timeout;
1578       // Read timeout for HTTP2 upstream connection
1579       timeoutconf.http2_read = 3_min;
1580
1581       // Read timeout for non-HTTP2 upstream connection
1582       timeoutconf.read = 1_min;
1583
1584       // Write timeout for HTTP2/non-HTTP2 upstream connection
1585       timeoutconf.write = 30_s;
1586
1587       // Keep alive timeout for HTTP/1 upstream connection
1588       timeoutconf.idle_read = 1_min;
1589     }
1590   }
1591
1592   {
1593     connconf.downstream = std::make_shared<DownstreamConfig>();
1594     auto &downstreamconf = *connconf.downstream;
1595     {
1596       auto &timeoutconf = downstreamconf.timeout;
1597       // Read/Write timeouts for downstream connection
1598       timeoutconf.read = 1_min;
1599       timeoutconf.write = 30_s;
1600       // Timeout for pooled (idle) connections
1601       timeoutconf.idle_read = 2_s;
1602       timeoutconf.connect = 30_s;
1603       timeoutconf.max_backoff = 120_s;
1604     }
1605
1606     downstreamconf.connections_per_host = 8;
1607     downstreamconf.request_buffer_size = 16_k;
1608     downstreamconf.response_buffer_size = 128_k;
1609     downstreamconf.family = AF_UNSPEC;
1610   }
1611
1612   auto &apiconf = config->api;
1613   apiconf.max_request_body = 32_m;
1614
1615   auto &dnsconf = config->dns;
1616   {
1617     auto &timeoutconf = dnsconf.timeout;
1618     timeoutconf.cache = 10_s;
1619     timeoutconf.lookup = 5_s;
1620   }
1621   dnsconf.max_try = 2;
1622 }
1623
1624 } // namespace
1625
1626 namespace {
1627 void print_version(std::ostream &out) {
1628   out << "nghttpx nghttp2/" NGHTTP2_VERSION << std::endl;
1629 }
1630 } // namespace
1631
1632 namespace {
1633 void print_usage(std::ostream &out) {
1634   out << R"(Usage: nghttpx [OPTIONS]... [<PRIVATE_KEY> <CERT>]
1635 A reverse proxy for HTTP/2, and HTTP/1.)"
1636       << std::endl;
1637 }
1638 } // namespace
1639
1640 namespace {
1641 void print_help(std::ostream &out) {
1642   auto config = get_config();
1643
1644   print_usage(out);
1645   out << R"(
1646   <PRIVATE_KEY>
1647               Set  path  to  server's private  key.   Required  unless
1648               "no-tls" parameter is used in --frontend option.
1649   <CERT>      Set  path  to  server's  certificate.   Required  unless
1650               "no-tls"  parameter is  used in  --frontend option.   To
1651               make OCSP stapling work, this must be an absolute path.
1652
1653 Options:
1654   The options are categorized into several groups.
1655
1656 Connections:
1657   -b, --backend=(<HOST>,<PORT>|unix:<PATH>)[;[<PATTERN>[:...]][[;<PARAM>]...]
1658
1659               Set  backend  host  and   port.   The  multiple  backend
1660               addresses are  accepted by repeating this  option.  UNIX
1661               domain socket  can be  specified by prefixing  path name
1662               with "unix:" (e.g., unix:/var/run/backend.sock).
1663
1664               Optionally, if <PATTERN>s are given, the backend address
1665               is  only  used  if  request matches  the  pattern.   The
1666               pattern  matching is  closely  designed  to ServeMux  in
1667               net/http package of  Go programming language.  <PATTERN>
1668               consists of  path, host +  path or just host.   The path
1669               must start  with "/".  If  it ends with "/",  it matches
1670               all  request path  in  its subtree.   To  deal with  the
1671               request  to the  directory without  trailing slash,  the
1672               path which ends  with "/" also matches  the request path
1673               which  only  lacks  trailing  '/'  (e.g.,  path  "/foo/"
1674               matches request path  "/foo").  If it does  not end with
1675               "/", it  performs exact match against  the request path.
1676               If  host  is given,  it  performs  a match  against  the
1677               request host.   For a  request received on  the frontend
1678               listener with  "sni-fwd" parameter enabled, SNI  host is
1679               used instead of a request host.  If host alone is given,
1680               "/" is  appended to it,  so that it matches  all request
1681               paths  under the  host  (e.g., specifying  "nghttp2.org"
1682               equals  to "nghttp2.org/").   CONNECT method  is treated
1683               specially.  It  does not have  path, and we  don't allow
1684               empty path.  To workaround  this, we assume that CONNECT
1685               method has "/" as path.
1686
1687               Patterns with  host take  precedence over  patterns with
1688               just path.   Then, longer patterns take  precedence over
1689               shorter ones.
1690
1691               Host  can  include "*"  in  the  left most  position  to
1692               indicate  wildcard match  (only suffix  match is  done).
1693               The "*" must match at least one character.  For example,
1694               host    pattern    "*.nghttp2.org"    matches    against
1695               "www.nghttp2.org"  and  "git.ngttp2.org", but  does  not
1696               match  against  "nghttp2.org".   The exact  hosts  match
1697               takes precedence over the wildcard hosts match.
1698
1699               If path  part ends with  "*", it is treated  as wildcard
1700               path.  The  wildcard path  behaves differently  from the
1701               normal path.  For normal path,  match is made around the
1702               boundary of path component  separator,"/".  On the other
1703               hand, the wildcard  path does not take  into account the
1704               path component  separator.  All paths which  include the
1705               wildcard  path  without  last  "*" as  prefix,  and  are
1706               strictly longer than wildcard  path without last "*" are
1707               matched.  "*"  must match  at least one  character.  For
1708               example,  the   pattern  "/foo*"  matches   "/foo/"  and
1709               "/foobar".  But it does not match "/foo", or "/fo".
1710
1711               If <PATTERN> is omitted or  empty string, "/" is used as
1712               pattern,  which  matches  all request  paths  (catch-all
1713               pattern).  The catch-all backend must be given.
1714
1715               When doing  a match, nghttpx made  some normalization to
1716               pattern, request host and path.  For host part, they are
1717               converted to lower case.  For path part, percent-encoded
1718               unreserved characters  defined in RFC 3986  are decoded,
1719               and any  dot-segments (".."  and ".")   are resolved and
1720               removed.
1721
1722               For   example,   -b'127.0.0.1,8080;nghttp2.org/httpbin/'
1723               matches the  request host "nghttp2.org" and  the request
1724               path "/httpbin/get", but does not match the request host
1725               "nghttp2.org" and the request path "/index.html".
1726
1727               The  multiple <PATTERN>s  can  be specified,  delimiting
1728               them            by           ":".             Specifying
1729               -b'127.0.0.1,8080;nghttp2.org:www.nghttp2.org'  has  the
1730               same  effect  to specify  -b'127.0.0.1,8080;nghttp2.org'
1731               and -b'127.0.0.1,8080;www.nghttp2.org'.
1732
1733               The backend addresses sharing same <PATTERN> are grouped
1734               together forming  load balancing  group.
1735
1736               Several parameters <PARAM> are accepted after <PATTERN>.
1737               The  parameters are  delimited  by  ";".  The  available
1738               parameters       are:      "proto=<PROTO>",       "tls",
1739               "sni=<SNI_HOST>",         "fall=<N>",        "rise=<N>",
1740               "affinity=<METHOD>",    "dns",    "redirect-if-not-tls",
1741               "upgrade-scheme",                        "mruby=<PATH>",
1742               "read-timeout=<DURATION>",   "write-timeout=<DURATION>",
1743               "group=<GROUP>",  "group-weight=<N>", and  "weight=<N>".
1744               The  parameter  consists   of  keyword,  and  optionally
1745               followed by  "=" and value.  For  example, the parameter
1746               "proto=h2"  consists of  the keyword  "proto" and  value
1747               "h2".  The parameter "tls" consists of the keyword "tls"
1748               without value.  Each parameter is described as follows.
1749
1750               The backend application protocol  can be specified using
1751               optional  "proto"   parameter,  and   in  the   form  of
1752               "proto=<PROTO>".  <PROTO> should be one of the following
1753               list  without  quotes:  "h2", "http/1.1".   The  default
1754               value of <PROTO> is  "http/1.1".  Note that usually "h2"
1755               refers to HTTP/2  over TLS.  But in this  option, it may
1756               mean HTTP/2  over cleartext TCP unless  "tls" keyword is
1757               used (see below).
1758
1759               TLS  can   be  enabled  by  specifying   optional  "tls"
1760               parameter.  TLS is not enabled by default.
1761
1762               With "sni=<SNI_HOST>" parameter, it can override the TLS
1763               SNI  field  value  with  given  <SNI_HOST>.   This  will
1764               default to the backend <HOST> name
1765
1766               The  feature  to detect  whether  backend  is online  or
1767               offline can be enabled  using optional "fall" and "rise"
1768               parameters.   Using  "fall=<N>"  parameter,  if  nghttpx
1769               cannot connect  to a  this backend <N>  times in  a row,
1770               this  backend  is  assumed  to be  offline,  and  it  is
1771               excluded from load balancing.  If <N> is 0, this backend
1772               never  be excluded  from load  balancing whatever  times
1773               nghttpx cannot connect  to it, and this  is the default.
1774               There is  also "rise=<N>" parameter.  After  backend was
1775               excluded from load balancing group, nghttpx periodically
1776               attempts to make a connection to the failed backend, and
1777               if the  connection is made  successfully <N> times  in a
1778               row, the backend is assumed to  be online, and it is now
1779               eligible  for load  balancing target.   If <N>  is 0,  a
1780               backend  is permanently  offline, once  it goes  in that
1781               state, and this is the default behaviour.
1782
1783               The     session     affinity    is     enabled     using
1784               "affinity=<METHOD>"  parameter.   If  "ip" is  given  in
1785               <METHOD>, client  IP based session affinity  is enabled.
1786               If "cookie"  is given in <METHOD>,  cookie based session
1787               affinity is  enabled.  If  "none" is given  in <METHOD>,
1788               session affinity  is disabled, and this  is the default.
1789               The session  affinity is  enabled per <PATTERN>.   If at
1790               least  one backend  has  "affinity"  parameter, and  its
1791               <METHOD> is not "none",  session affinity is enabled for
1792               all backend  servers sharing the same  <PATTERN>.  It is
1793               advised  to  set  "affinity" parameter  to  all  backend
1794               explicitly if session affinity  is desired.  The session
1795               affinity  may   break  if   one  of  the   backend  gets
1796               unreachable,  or   backend  settings  are   reloaded  or
1797               replaced by API.
1798
1799               If   "affinity=cookie"    is   used,    the   additional
1800               configuration                is                required.
1801               "affinity-cookie-name=<NAME>" must be  used to specify a
1802               name     of     cookie      to     use.      Optionally,
1803               "affinity-cookie-path=<PATH>" can  be used to  specify a
1804               path   which   cookie    is   applied.    The   optional
1805               "affinity-cookie-secure=<SECURE>"  controls  the  Secure
1806               attribute of a cookie.  The default value is "auto", and
1807               the Secure attribute is  determined by a request scheme.
1808               If a request scheme is "https", then Secure attribute is
1809               set.  Otherwise, it  is not set.  If  <SECURE> is "yes",
1810               the  Secure attribute  is  always set.   If <SECURE>  is
1811               "no", the Secure attribute is always omitted.
1812
1813               By default, name resolution of backend host name is done
1814               at  start  up,  or reloading  configuration.   If  "dns"
1815               parameter   is  given,   name  resolution   takes  place
1816               dynamically.  This is useful  if backend address changes
1817               frequently.   If  "dns"  is given,  name  resolution  of
1818               backend   host   name   at  start   up,   or   reloading
1819               configuration is skipped.
1820
1821               If "redirect-if-not-tls" parameter  is used, the matched
1822               backend  requires   that  frontend  connection   is  TLS
1823               encrypted.  If it isn't, nghttpx responds to the request
1824               with 308  status code, and  https URI the  client should
1825               use instead  is included in Location  header field.  The
1826               port number in  redirect URI is 443 by  default, and can
1827               be  changed using  --redirect-https-port option.   If at
1828               least one  backend has  "redirect-if-not-tls" parameter,
1829               this feature is enabled  for all backend servers sharing
1830               the   same   <PATTERN>.    It    is   advised   to   set
1831               "redirect-if-no-tls"    parameter   to    all   backends
1832               explicitly if this feature is desired.
1833
1834               If "upgrade-scheme"  parameter is used along  with "tls"
1835               parameter, HTTP/2 :scheme pseudo header field is changed
1836               to "https" from "http" when forwarding a request to this
1837               particular backend.  This is  a workaround for a backend
1838               server  which  requires  "https" :scheme  pseudo  header
1839               field on TLS encrypted connection.
1840
1841               "mruby=<PATH>"  parameter  specifies  a  path  to  mruby
1842               script  file  which  is  invoked when  this  pattern  is
1843               matched.  All backends which share the same pattern must
1844               have the same mruby path.
1845
1846               "read-timeout=<DURATION>" and "write-timeout=<DURATION>"
1847               parameters  specify the  read and  write timeout  of the
1848               backend connection  when this  pattern is  matched.  All
1849               backends which share the same pattern must have the same
1850               timeouts.  If these timeouts  are entirely omitted for a
1851               pattern,            --backend-read-timeout           and
1852               --backend-write-timeout are used.
1853
1854               "group=<GROUP>"  parameter specifies  the name  of group
1855               this backend address belongs to.  By default, it belongs
1856               to  the unnamed  default group.   The name  of group  is
1857               unique   per   pattern.   "group-weight=<N>"   parameter
1858               specifies the  weight of  the group.  The  higher weight
1859               gets  more frequently  selected  by  the load  balancing
1860               algorithm.  <N> must be  [1, 256] inclusive.  The weight
1861               8 has 4 times more weight  than 2.  <N> must be the same
1862               for  all addresses  which  share the  same <GROUP>.   If
1863               "group-weight" is  omitted in an address,  but the other
1864               address  which  belongs  to  the  same  group  specifies
1865               "group-weight",   its    weight   is   used.     If   no
1866               "group-weight"  is  specified  for  all  addresses,  the
1867               weight of a group becomes 1.  "group" and "group-weight"
1868               are ignored if session affinity is enabled.
1869
1870               "weight=<N>"  parameter  specifies  the  weight  of  the
1871               backend  address  inside  a  group  which  this  address
1872               belongs  to.  The  higher  weight  gets more  frequently
1873               selected by  the load balancing algorithm.   <N> must be
1874               [1,  256] inclusive.   The  weight 8  has  4 times  more
1875               weight  than weight  2.  If  this parameter  is omitted,
1876               weight  becomes  1.   "weight"  is  ignored  if  session
1877               affinity is enabled.
1878
1879               Since ";" and ":" are  used as delimiter, <PATTERN> must
1880               not  contain these  characters.  Since  ";" has  special
1881               meaning in shell, the option value must be quoted.
1882
1883               Default: )"
1884       << DEFAULT_DOWNSTREAM_HOST << "," << DEFAULT_DOWNSTREAM_PORT << R"(
1885   -f, --frontend=(<HOST>,<PORT>|unix:<PATH>)[[;<PARAM>]...]
1886               Set  frontend  host and  port.   If  <HOST> is  '*',  it
1887               assumes  all addresses  including  both  IPv4 and  IPv6.
1888               UNIX domain  socket can  be specified by  prefixing path
1889               name  with  "unix:" (e.g.,  unix:/var/run/nghttpx.sock).
1890               This  option can  be used  multiple times  to listen  to
1891               multiple addresses.
1892
1893               This option  can take  0 or  more parameters,  which are
1894               described  below.   Note   that  "api"  and  "healthmon"
1895               parameters are mutually exclusive.
1896
1897               Optionally, TLS  can be disabled by  specifying "no-tls"
1898               parameter.  TLS is enabled by default.
1899
1900               If "sni-fwd" parameter is  used, when performing a match
1901               to select a backend server,  SNI host name received from
1902               the client  is used  instead of  the request  host.  See
1903               --backend option about the pattern match.
1904
1905               To  make this  frontend as  API endpoint,  specify "api"
1906               parameter.   This   is  disabled  by  default.    It  is
1907               important  to  limit the  access  to  the API  frontend.
1908               Otherwise, someone  may change  the backend  server, and
1909               break your services,  or expose confidential information
1910               to the outside the world.
1911
1912               To  make  this  frontend  as  health  monitor  endpoint,
1913               specify  "healthmon"  parameter.   This is  disabled  by
1914               default.  Any  requests which come through  this address
1915               are replied with 200 HTTP status, without no body.
1916
1917               To accept  PROXY protocol  version 1  and 2  on frontend
1918               connection,  specify  "proxyproto" parameter.   This  is
1919               disabled by default.
1920
1921               Default: *,3000
1922   --backlog=<N>
1923               Set listen backlog size.
1924               Default: )"
1925       << config->conn.listener.backlog << R"(
1926   --backend-address-family=(auto|IPv4|IPv6)
1927               Specify  address  family  of  backend  connections.   If
1928               "auto" is given, both IPv4  and IPv6 are considered.  If
1929               "IPv4" is  given, only  IPv4 address is  considered.  If
1930               "IPv6" is given, only IPv6 address is considered.
1931               Default: auto
1932   --backend-http-proxy-uri=<URI>
1933               Specify      proxy       URI      in       the      form
1934               http://[<USER>:<PASS>@]<PROXY>:<PORT>.    If   a   proxy
1935               requires  authentication,  specify  <USER>  and  <PASS>.
1936               Note that  they must be properly  percent-encoded.  This
1937               proxy  is used  when the  backend connection  is HTTP/2.
1938               First,  make  a CONNECT  request  to  the proxy  and  it
1939               connects  to the  backend  on behalf  of nghttpx.   This
1940               forms  tunnel.   After  that, nghttpx  performs  SSL/TLS
1941               handshake with  the downstream through the  tunnel.  The
1942               timeouts when connecting and  making CONNECT request can
1943               be     specified    by     --backend-read-timeout    and
1944               --backend-write-timeout options.
1945
1946 Performance:
1947   -n, --workers=<N>
1948               Set the number of worker threads.
1949               Default: )"
1950       << config->num_worker << R"(
1951   --single-thread
1952               Run everything in one  thread inside the worker process.
1953               This   feature   is   provided  for   better   debugging
1954               experience,  or  for  the platforms  which  lack  thread
1955               support.   If  threading  is disabled,  this  option  is
1956               always enabled.
1957   --read-rate=<SIZE>
1958               Set maximum  average read  rate on  frontend connection.
1959               Setting 0 to this option means read rate is unlimited.
1960               Default: )"
1961       << config->conn.upstream.ratelimit.read.rate << R"(
1962   --read-burst=<SIZE>
1963               Set  maximum read  burst  size  on frontend  connection.
1964               Setting  0  to this  option  means  read burst  size  is
1965               unlimited.
1966               Default: )"
1967       << config->conn.upstream.ratelimit.read.burst << R"(
1968   --write-rate=<SIZE>
1969               Set maximum  average write rate on  frontend connection.
1970               Setting 0 to this option means write rate is unlimited.
1971               Default: )"
1972       << config->conn.upstream.ratelimit.write.rate << R"(
1973   --write-burst=<SIZE>
1974               Set  maximum write  burst size  on frontend  connection.
1975               Setting  0 to  this  option means  write  burst size  is
1976               unlimited.
1977               Default: )"
1978       << config->conn.upstream.ratelimit.write.burst << R"(
1979   --worker-read-rate=<SIZE>
1980               Set maximum average read rate on frontend connection per
1981               worker.  Setting  0 to  this option  means read  rate is
1982               unlimited.  Not implemented yet.
1983               Default: 0
1984   --worker-read-burst=<SIZE>
1985               Set maximum  read burst size on  frontend connection per
1986               worker.  Setting 0 to this  option means read burst size
1987               is unlimited.  Not implemented yet.
1988               Default: 0
1989   --worker-write-rate=<SIZE>
1990               Set maximum  average write  rate on  frontend connection
1991               per worker.  Setting  0 to this option  means write rate
1992               is unlimited.  Not implemented yet.
1993               Default: 0
1994   --worker-write-burst=<SIZE>
1995               Set maximum write burst  size on frontend connection per
1996               worker.  Setting 0 to this option means write burst size
1997               is unlimited.  Not implemented yet.
1998               Default: 0
1999   --worker-frontend-connections=<N>
2000               Set maximum number  of simultaneous connections frontend
2001               accepts.  Setting 0 means unlimited.
2002               Default: )"
2003       << config->conn.upstream.worker_connections << R"(
2004   --backend-connections-per-host=<N>
2005               Set  maximum number  of  backend concurrent  connections
2006               (and/or  streams in  case  of HTTP/2)  per origin  host.
2007               This option  is meaningful when --http2-proxy  option is
2008               used.   The  origin  host  is  determined  by  authority
2009               portion of  request URI (or :authority  header field for
2010               HTTP/2).   To  limit  the   number  of  connections  per
2011               frontend        for       default        mode,       use
2012               --backend-connections-per-frontend.
2013               Default: )"
2014       << config->conn.downstream->connections_per_host << R"(
2015   --backend-connections-per-frontend=<N>
2016               Set  maximum number  of  backend concurrent  connections
2017               (and/or streams  in case of HTTP/2)  per frontend.  This
2018               option  is   only  used  for  default   mode.   0  means
2019               unlimited.  To limit the  number of connections per host
2020               with          --http2-proxy         option,          use
2021               --backend-connections-per-host.
2022               Default: )"
2023       << config->conn.downstream->connections_per_frontend << R"(
2024   --rlimit-nofile=<N>
2025               Set maximum number of open files (RLIMIT_NOFILE) to <N>.
2026               If 0 is given, nghttpx does not set the limit.
2027               Default: )"
2028       << config->rlimit_nofile << R"(
2029   --backend-request-buffer=<SIZE>
2030               Set buffer size used to store backend request.
2031               Default: )"
2032       << util::utos_unit(config->conn.downstream->request_buffer_size) << R"(
2033   --backend-response-buffer=<SIZE>
2034               Set buffer size used to store backend response.
2035               Default: )"
2036       << util::utos_unit(config->conn.downstream->response_buffer_size) << R"(
2037   --fastopen=<N>
2038               Enables  "TCP Fast  Open" for  the listening  socket and
2039               limits the  maximum length for the  queue of connections
2040               that have not yet completed the three-way handshake.  If
2041               value is 0 then fast open is disabled.
2042               Default: )"
2043       << config->conn.listener.fastopen << R"(
2044   --no-kqueue Don't use  kqueue.  This  option is only  applicable for
2045               the platforms  which have kqueue.  For  other platforms,
2046               this option will be simply ignored.
2047
2048 Timeout:
2049   --frontend-http2-read-timeout=<DURATION>
2050               Specify read timeout for HTTP/2 frontend connection.
2051               Default: )"
2052       << util::duration_str(config->conn.upstream.timeout.http2_read) << R"(
2053   --frontend-read-timeout=<DURATION>
2054               Specify read timeout for HTTP/1.1 frontend connection.
2055               Default: )"
2056       << util::duration_str(config->conn.upstream.timeout.read) << R"(
2057   --frontend-write-timeout=<DURATION>
2058               Specify write timeout for all frontend connections.
2059               Default: )"
2060       << util::duration_str(config->conn.upstream.timeout.write) << R"(
2061   --frontend-keep-alive-timeout=<DURATION>
2062               Specify   keep-alive   timeout   for   frontend   HTTP/1
2063               connection.
2064               Default: )"
2065       << util::duration_str(config->conn.upstream.timeout.idle_read) << R"(
2066   --stream-read-timeout=<DURATION>
2067               Specify  read timeout  for HTTP/2  streams.  0  means no
2068               timeout.
2069               Default: )"
2070       << util::duration_str(config->http2.timeout.stream_read) << R"(
2071   --stream-write-timeout=<DURATION>
2072               Specify write  timeout for  HTTP/2 streams.  0  means no
2073               timeout.
2074               Default: )"
2075       << util::duration_str(config->http2.timeout.stream_write) << R"(
2076   --backend-read-timeout=<DURATION>
2077               Specify read timeout for backend connection.
2078               Default: )"
2079       << util::duration_str(config->conn.downstream->timeout.read) << R"(
2080   --backend-write-timeout=<DURATION>
2081               Specify write timeout for backend connection.
2082               Default: )"
2083       << util::duration_str(config->conn.downstream->timeout.write) << R"(
2084   --backend-connect-timeout=<DURATION>
2085               Specify  timeout before  establishing TCP  connection to
2086               backend.
2087               Default: )"
2088       << util::duration_str(config->conn.downstream->timeout.connect) << R"(
2089   --backend-keep-alive-timeout=<DURATION>
2090               Specify   keep-alive   timeout    for   backend   HTTP/1
2091               connection.
2092               Default: )"
2093       << util::duration_str(config->conn.downstream->timeout.idle_read) << R"(
2094   --listener-disable-timeout=<DURATION>
2095               After accepting  connection failed,  connection listener
2096               is disabled  for a given  amount of time.   Specifying 0
2097               disables this feature.
2098               Default: )"
2099       << util::duration_str(config->conn.listener.timeout.sleep) << R"(
2100   --frontend-http2-setting-timeout=<DURATION>
2101               Specify  timeout before  SETTINGS ACK  is received  from
2102               client.
2103               Default: )"
2104       << util::duration_str(config->http2.upstream.timeout.settings) << R"(
2105   --backend-http2-settings-timeout=<DURATION>
2106               Specify  timeout before  SETTINGS ACK  is received  from
2107               backend server.
2108               Default: )"
2109       << util::duration_str(config->http2.downstream.timeout.settings) << R"(
2110   --backend-max-backoff=<DURATION>
2111               Specify  maximum backoff  interval.  This  is used  when
2112               doing health  check against offline backend  (see "fail"
2113               parameter  in --backend  option).   It is  also used  to
2114               limit  the  maximum   interval  to  temporarily  disable
2115               backend  when nghttpx  failed to  connect to  it.  These
2116               intervals are calculated  using exponential backoff, and
2117               consecutive failed attempts increase the interval.  This
2118               option caps its maximum value.
2119               Default: )"
2120       << util::duration_str(config->conn.downstream->timeout.max_backoff) << R"(
2121
2122 SSL/TLS:
2123   --ciphers=<SUITE>
2124               Set allowed  cipher list  for frontend  connection.  The
2125               format of the string is described in OpenSSL ciphers(1).
2126               This option  sets cipher suites for  TLSv1.2 or earlier.
2127               Use --tls13-ciphers for TLSv1.3.
2128               Default: )"
2129       << config->tls.ciphers << R"(
2130   --tls13-ciphers=<SUITE>
2131               Set allowed  cipher list  for frontend  connection.  The
2132               format of the string is described in OpenSSL ciphers(1).
2133               This  option  sets  cipher   suites  for  TLSv1.3.   Use
2134               --ciphers for TLSv1.2 or earlier.
2135               Default: )"
2136       << config->tls.tls13_ciphers << R"(
2137   --client-ciphers=<SUITE>
2138               Set  allowed cipher  list for  backend connection.   The
2139               format of the string is described in OpenSSL ciphers(1).
2140               This option  sets cipher suites for  TLSv1.2 or earlier.
2141               Use --tls13-client-ciphers for TLSv1.3.
2142               Default: )"
2143       << config->tls.client.ciphers << R"(
2144   --tls13-client-ciphers=<SUITE>
2145               Set  allowed cipher  list for  backend connection.   The
2146               format of the string is described in OpenSSL ciphers(1).
2147               This  option  sets  cipher   suites  for  TLSv1.3.   Use
2148               --tls13-client-ciphers for TLSv1.2 or earlier.
2149               Default: )"
2150       << config->tls.client.tls13_ciphers << R"(
2151   --ecdh-curves=<LIST>
2152               Set  supported  curve  list  for  frontend  connections.
2153               <LIST> is a  colon separated list of curve  NID or names
2154               in the preference order.  The supported curves depend on
2155               the  linked  OpenSSL  library.  This  function  requires
2156               OpenSSL >= 1.0.2.
2157               Default: )"
2158       << config->tls.ecdh_curves << R"(
2159   -k, --insecure
2160               Don't  verify backend  server's  certificate  if TLS  is
2161               enabled for backend connections.
2162   --cacert=<PATH>
2163               Set path to trusted CA  certificate file.  It is used in
2164               backend  TLS connections  to verify  peer's certificate.
2165               It is also used to  verify OCSP response from the script
2166               set by --fetch-ocsp-response-file.  The  file must be in
2167               PEM format.   It can contain multiple  certificates.  If
2168               the  linked OpenSSL  is configured  to load  system wide
2169               certificates, they  are loaded at startup  regardless of
2170               this option.
2171   --private-key-passwd-file=<PATH>
2172               Path  to file  that contains  password for  the server's
2173               private key.   If none is  given and the private  key is
2174               password protected it'll be requested interactively.
2175   --subcert=<KEYPATH>:<CERTPATH>[[;<PARAM>]...]
2176               Specify  additional certificate  and  private key  file.
2177               nghttpx will  choose certificates based on  the hostname
2178               indicated by client using TLS SNI extension.  If nghttpx
2179               is  built with  OpenSSL  >= 1.0.2,  the shared  elliptic
2180               curves (e.g., P-256) between  client and server are also
2181               taken into  consideration.  This allows nghttpx  to send
2182               ECDSA certificate  to modern clients, while  sending RSA
2183               based certificate to older  clients.  This option can be
2184               used  multiple  times.   To  make  OCSP  stapling  work,
2185               <CERTPATH> must be absolute path.
2186
2187               Additional parameter  can be specified in  <PARAM>.  The
2188               available <PARAM> is "sct-dir=<DIR>".
2189
2190               "sct-dir=<DIR>"  specifies the  path to  directory which
2191               contains        *.sct        files        for        TLS
2192               signed_certificate_timestamp extension (RFC 6962).  This
2193               feature   requires   OpenSSL   >=   1.0.2.    See   also
2194               --tls-sct-dir option.
2195   --dh-param-file=<PATH>
2196               Path to file that contains  DH parameters in PEM format.
2197               Without  this   option,  DHE   cipher  suites   are  not
2198               available.
2199   --npn-list=<LIST>
2200               Comma delimited list of  ALPN protocol identifier sorted
2201               in the  order of preference.  That  means most desirable
2202               protocol comes  first.  This  is used  in both  ALPN and
2203               NPN.  The parameter must be  delimited by a single comma
2204               only  and any  white spaces  are  treated as  a part  of
2205               protocol string.
2206               Default: )"
2207       << DEFAULT_NPN_LIST
2208       << R"(
2209   --verify-client
2210               Require and verify client certificate.
2211   --verify-client-cacert=<PATH>
2212               Path  to file  that contains  CA certificates  to verify
2213               client certificate.  The file must be in PEM format.  It
2214               can contain multiple certificates.
2215   --verify-client-tolerate-expired
2216               Accept  expired  client  certificate.   Operator  should
2217               handle  the expired  client  certificate  by some  means
2218               (e.g.,  mruby  script).   Otherwise, this  option  might
2219               cause a security risk.
2220   --client-private-key-file=<PATH>
2221               Path to  file that contains  client private key  used in
2222               backend client authentication.
2223   --client-cert-file=<PATH>
2224               Path to  file that  contains client certificate  used in
2225               backend client authentication.
2226   --tls-min-proto-version=<VER>
2227               Specify minimum SSL/TLS protocol.   The name matching is
2228               done in  case-insensitive manner.  The  versions between
2229               --tls-min-proto-version and  --tls-max-proto-version are
2230               enabled.  If the protocol list advertised by client does
2231               not  overlap  this range,  you  will  receive the  error
2232               message "unknown protocol".  If a protocol version lower
2233               than TLSv1.2 is specified, make sure that the compatible
2234               ciphers are  included in --ciphers option.   The default
2235               cipher  list  only   includes  ciphers  compatible  with
2236               TLSv1.2 or above.  The available versions are:
2237               )"
2238 #ifdef TLS1_3_VERSION
2239          "TLSv1.3, "
2240 #endif // TLS1_3_VERSION
2241          "TLSv1.2, TLSv1.1, and TLSv1.0"
2242          R"(
2243               Default: )"
2244       << DEFAULT_TLS_MIN_PROTO_VERSION
2245       << R"(
2246   --tls-max-proto-version=<VER>
2247               Specify maximum SSL/TLS protocol.   The name matching is
2248               done in  case-insensitive manner.  The  versions between
2249               --tls-min-proto-version and  --tls-max-proto-version are
2250               enabled.  If the protocol list advertised by client does
2251               not  overlap  this range,  you  will  receive the  error
2252               message "unknown protocol".  The available versions are:
2253               )"
2254 #ifdef TLS1_3_VERSION
2255          "TLSv1.3, "
2256 #endif // TLS1_3_VERSION
2257          "TLSv1.2, TLSv1.1, and TLSv1.0"
2258          R"(
2259               Default: )"
2260       << DEFAULT_TLS_MAX_PROTO_VERSION << R"(
2261   --tls-ticket-key-file=<PATH>
2262               Path to file that contains  random data to construct TLS
2263               session ticket  parameters.  If aes-128-cbc is  given in
2264               --tls-ticket-key-cipher, the  file must  contain exactly
2265               48    bytes.     If     aes-256-cbc    is    given    in
2266               --tls-ticket-key-cipher, the  file must  contain exactly
2267               80  bytes.   This  options  can be  used  repeatedly  to
2268               specify  multiple ticket  parameters.  If  several files
2269               are given,  only the  first key is  used to  encrypt TLS
2270               session  tickets.  Other  keys are  accepted but  server
2271               will  issue new  session  ticket with  first key.   This
2272               allows  session  key  rotation.  Please  note  that  key
2273               rotation  does  not  occur automatically.   User  should
2274               rearrange  files or  change options  values and  restart
2275               nghttpx gracefully.   If opening  or reading  given file
2276               fails, all loaded  keys are discarded and  it is treated
2277               as if none  of this option is given.  If  this option is
2278               not given or an error  occurred while opening or reading
2279               a file,  key is  generated every  1 hour  internally and
2280               they are  valid for  12 hours.   This is  recommended if
2281               ticket  key sharing  between  nghttpx  instances is  not
2282               required.
2283   --tls-ticket-key-memcached=<HOST>,<PORT>[;tls]
2284               Specify address  of memcached  server to get  TLS ticket
2285               keys for  session resumption.   This enables  shared TLS
2286               ticket key between  multiple nghttpx instances.  nghttpx
2287               does not set TLS ticket  key to memcached.  The external
2288               ticket key generator is required.  nghttpx just gets TLS
2289               ticket  keys  from  memcached, and  use  them,  possibly
2290               replacing current set  of keys.  It is up  to extern TLS
2291               ticket  key generator  to rotate  keys frequently.   See
2292               "TLS SESSION  TICKET RESUMPTION" section in  manual page
2293               to know the data format in memcached entry.  Optionally,
2294               memcached  connection  can  be  encrypted  with  TLS  by
2295               specifying "tls" parameter.
2296   --tls-ticket-key-memcached-address-family=(auto|IPv4|IPv6)
2297               Specify address  family of memcached connections  to get
2298               TLS ticket keys.  If "auto" is given, both IPv4 and IPv6
2299               are considered.   If "IPv4" is given,  only IPv4 address
2300               is considered.  If "IPv6" is given, only IPv6 address is
2301               considered.
2302               Default: auto
2303   --tls-ticket-key-memcached-interval=<DURATION>
2304               Set interval to get TLS ticket keys from memcached.
2305               Default: )"
2306       << util::duration_str(config->tls.ticket.memcached.interval) << R"(
2307   --tls-ticket-key-memcached-max-retry=<N>
2308               Set  maximum   number  of  consecutive   retries  before
2309               abandoning TLS ticket key  retrieval.  If this number is
2310               reached,  the  attempt  is considered  as  failure,  and
2311               "failure" count  is incremented by 1,  which contributed
2312               to            the            value            controlled
2313               --tls-ticket-key-memcached-max-fail option.
2314               Default: )"
2315       << config->tls.ticket.memcached.max_retry << R"(
2316   --tls-ticket-key-memcached-max-fail=<N>
2317               Set  maximum   number  of  consecutive   failure  before
2318               disabling TLS ticket until next scheduled key retrieval.
2319               Default: )"
2320       << config->tls.ticket.memcached.max_fail << R"(
2321   --tls-ticket-key-cipher=<CIPHER>
2322               Specify cipher  to encrypt TLS session  ticket.  Specify
2323               either   aes-128-cbc   or  aes-256-cbc.    By   default,
2324               aes-128-cbc is used.
2325   --tls-ticket-key-memcached-cert-file=<PATH>
2326               Path to client certificate  for memcached connections to
2327               get TLS ticket keys.
2328   --tls-ticket-key-memcached-private-key-file=<PATH>
2329               Path to client private  key for memcached connections to
2330               get TLS ticket keys.
2331   --fetch-ocsp-response-file=<PATH>
2332               Path to  fetch-ocsp-response script file.  It  should be
2333               absolute path.
2334               Default: )"
2335       << config->tls.ocsp.fetch_ocsp_response_file << R"(
2336   --ocsp-update-interval=<DURATION>
2337               Set interval to update OCSP response cache.
2338               Default: )"
2339       << util::duration_str(config->tls.ocsp.update_interval) << R"(
2340   --ocsp-startup
2341               Start  accepting connections  after initial  attempts to
2342               get OCSP responses  finish.  It does not  matter some of
2343               the  attempts  fail.  This  feature  is  useful if  OCSP
2344               responses   must    be   available    before   accepting
2345               connections.
2346   --no-verify-ocsp
2347               nghttpx does not verify OCSP response.
2348   --no-ocsp   Disable OCSP stapling.
2349   --tls-session-cache-memcached=<HOST>,<PORT>[;tls]
2350               Specify  address of  memcached server  to store  session
2351               cache.   This  enables   shared  session  cache  between
2352               multiple   nghttpx  instances.    Optionally,  memcached
2353               connection can be encrypted with TLS by specifying "tls"
2354               parameter.
2355   --tls-session-cache-memcached-address-family=(auto|IPv4|IPv6)
2356               Specify address family of memcached connections to store
2357               session cache.  If  "auto" is given, both  IPv4 and IPv6
2358               are considered.   If "IPv4" is given,  only IPv4 address
2359               is considered.  If "IPv6" is given, only IPv6 address is
2360               considered.
2361               Default: auto
2362   --tls-session-cache-memcached-cert-file=<PATH>
2363               Path to client certificate  for memcached connections to
2364               store session cache.
2365   --tls-session-cache-memcached-private-key-file=<PATH>
2366               Path to client private  key for memcached connections to
2367               store session cache.
2368   --tls-dyn-rec-warmup-threshold=<SIZE>
2369               Specify the  threshold size for TLS  dynamic record size
2370               behaviour.  During  a TLS  session, after  the threshold
2371               number of bytes  have been written, the  TLS record size
2372               will be increased to the maximum allowed (16K).  The max
2373               record size will  continue to be used on  the active TLS
2374               session.  After  --tls-dyn-rec-idle-timeout has elapsed,
2375               the record size is reduced  to 1300 bytes.  Specify 0 to
2376               always use  the maximum record size,  regardless of idle
2377               period.   This  behaviour  applies   to  all  TLS  based
2378               frontends, and TLS HTTP/2 backends.
2379               Default: )"
2380       << util::utos_unit(config->tls.dyn_rec.warmup_threshold) << R"(
2381   --tls-dyn-rec-idle-timeout=<DURATION>
2382               Specify TLS dynamic record  size behaviour timeout.  See
2383               --tls-dyn-rec-warmup-threshold  for   more  information.
2384               This behaviour  applies to all TLS  based frontends, and
2385               TLS HTTP/2 backends.
2386               Default: )"
2387       << util::duration_str(config->tls.dyn_rec.idle_timeout) << R"(
2388   --no-http2-cipher-black-list
2389               Allow  black  listed  cipher suite  on  frontend  HTTP/2
2390               connection.                                          See
2391               https://tools.ietf.org/html/rfc7540#appendix-A  for  the
2392               complete HTTP/2 cipher suites black list.
2393   --client-no-http2-cipher-black-list
2394               Allow  black  listed  cipher  suite  on  backend  HTTP/2
2395               connection.                                          See
2396               https://tools.ietf.org/html/rfc7540#appendix-A  for  the
2397               complete HTTP/2 cipher suites black list.
2398   --tls-sct-dir=<DIR>
2399               Specifies the  directory where  *.sct files  exist.  All
2400               *.sct   files   in  <DIR>   are   read,   and  sent   as
2401               extension_data of  TLS signed_certificate_timestamp (RFC
2402               6962)  to  client.   These   *.sct  files  are  for  the
2403               certificate   specified   in   positional   command-line
2404               argument <CERT>, or  certificate option in configuration
2405               file.   For   additional  certificates,   use  --subcert
2406               option.  This option requires OpenSSL >= 1.0.2.
2407   --psk-secrets=<PATH>
2408               Read list of PSK identity and secrets from <PATH>.  This
2409               is used for frontend connection.  The each line of input
2410               file  is  formatted  as  <identity>:<hex-secret>,  where
2411               <identity> is  PSK identity, and <hex-secret>  is secret
2412               in hex.  An  empty line, and line which  starts with '#'
2413               are skipped.  The default  enabled cipher list might not
2414               contain any PSK cipher suite.  In that case, desired PSK
2415               cipher suites  must be  enabled using  --ciphers option.
2416               The  desired PSK  cipher suite  may be  black listed  by
2417               HTTP/2.   To  use  those   cipher  suites  with  HTTP/2,
2418               consider  to  use  --no-http2-cipher-black-list  option.
2419               But be aware its implications.
2420   --client-psk-secrets=<PATH>
2421               Read PSK identity and secrets from <PATH>.  This is used
2422               for backend connection.  The each  line of input file is
2423               formatted  as <identity>:<hex-secret>,  where <identity>
2424               is PSK identity, and <hex-secret>  is secret in hex.  An
2425               empty line, and line which  starts with '#' are skipped.
2426               The first identity and  secret pair encountered is used.
2427               The default  enabled cipher  list might not  contain any
2428               PSK  cipher suite.   In  that case,  desired PSK  cipher
2429               suites  must be  enabled using  --client-ciphers option.
2430               The  desired PSK  cipher suite  may be  black listed  by
2431               HTTP/2.   To  use  those   cipher  suites  with  HTTP/2,
2432               consider   to  use   --client-no-http2-cipher-black-list
2433               option.  But be aware its implications.
2434   --tls-no-postpone-early-data
2435               By default,  nghttpx postpones forwarding  HTTP requests
2436               sent in early data, including those sent in partially in
2437               it, until TLS handshake finishes.  If all backend server
2438               recognizes "Early-Data" header  field, using this option
2439               makes nghttpx  not postpone  forwarding request  and get
2440               full potential of 0-RTT data.
2441   --tls-max-early-data=<SIZE>
2442               Sets  the  maximum  amount  of 0-RTT  data  that  server
2443               accepts.
2444               Default: )"
2445       << util::utos_unit(config->tls.max_early_data) << R"(
2446
2447 HTTP/2:
2448   -c, --frontend-http2-max-concurrent-streams=<N>
2449               Set the maximum number of  the concurrent streams in one
2450               frontend HTTP/2 session.
2451               Default: )"
2452       << config->http2.upstream.max_concurrent_streams << R"(
2453   --backend-http2-max-concurrent-streams=<N>
2454               Set the maximum number of  the concurrent streams in one
2455               backend  HTTP/2 session.   This sets  maximum number  of
2456               concurrent opened pushed streams.  The maximum number of
2457               concurrent requests are set by a remote server.
2458               Default: )"
2459       << config->http2.downstream.max_concurrent_streams << R"(
2460   --frontend-http2-window-size=<SIZE>
2461               Sets  the  per-stream  initial  window  size  of  HTTP/2
2462               frontend connection.
2463               Default: )"
2464       << config->http2.upstream.window_size << R"(
2465   --frontend-http2-connection-window-size=<SIZE>
2466               Sets the  per-connection window size of  HTTP/2 frontend
2467               connection.
2468               Default: )"
2469       << config->http2.upstream.connection_window_size << R"(
2470   --backend-http2-window-size=<SIZE>
2471               Sets  the   initial  window   size  of   HTTP/2  backend
2472               connection.
2473               Default: )"
2474       << config->http2.downstream.window_size << R"(
2475   --backend-http2-connection-window-size=<SIZE>
2476               Sets the  per-connection window  size of  HTTP/2 backend
2477               connection.
2478               Default: )"
2479       << config->http2.downstream.connection_window_size << R"(
2480   --http2-no-cookie-crumbling
2481               Don't crumble cookie header field.
2482   --padding=<N>
2483               Add  at most  <N> bytes  to  a HTTP/2  frame payload  as
2484               padding.  Specify 0 to  disable padding.  This option is
2485               meant for debugging purpose  and not intended to enhance
2486               protocol security.
2487   --no-server-push
2488               Disable HTTP/2 server push.  Server push is supported by
2489               default mode and HTTP/2  frontend via Link header field.
2490               It is  also supported if  both frontend and  backend are
2491               HTTP/2 in default mode.  In  this case, server push from
2492               backend session is relayed  to frontend, and server push
2493               via Link header field is also supported.
2494   --frontend-http2-optimize-write-buffer-size
2495               (Experimental) Enable write  buffer size optimization in
2496               frontend HTTP/2 TLS  connection.  This optimization aims
2497               to reduce  write buffer  size so  that it  only contains
2498               bytes  which can  send immediately.   This makes  server
2499               more responsive to prioritized HTTP/2 stream because the
2500               buffering  of lower  priority stream  is reduced.   This
2501               option is only effective on recent Linux platform.
2502   --frontend-http2-optimize-window-size
2503               (Experimental)   Automatically  tune   connection  level
2504               window size of frontend  HTTP/2 TLS connection.  If this
2505               feature is  enabled, connection window size  starts with
2506               the   default  window   size,   65535  bytes.    nghttpx
2507               automatically  adjusts connection  window size  based on
2508               TCP receiving  window size.  The maximum  window size is
2509               capped      by      the     value      specified      by
2510               --frontend-http2-connection-window-size.     Since   the
2511               stream is subject to stream level window size, it should
2512               be adjusted using --frontend-http2-window-size option as
2513               well.   This option  is only  effective on  recent Linux
2514               platform.
2515   --frontend-http2-encoder-dynamic-table-size=<SIZE>
2516               Specify the maximum dynamic  table size of HPACK encoder
2517               in the frontend HTTP/2 connection.  The decoder (client)
2518               specifies  the maximum  dynamic table  size it  accepts.
2519               Then the negotiated dynamic table size is the minimum of
2520               this option value and the value which client specified.
2521               Default: )"
2522       << util::utos_unit(config->http2.upstream.encoder_dynamic_table_size)
2523       << R"(
2524   --frontend-http2-decoder-dynamic-table-size=<SIZE>
2525               Specify the maximum dynamic  table size of HPACK decoder
2526               in the frontend HTTP/2 connection.
2527               Default: )"
2528       << util::utos_unit(config->http2.upstream.decoder_dynamic_table_size)
2529       << R"(
2530   --backend-http2-encoder-dynamic-table-size=<SIZE>
2531               Specify the maximum dynamic  table size of HPACK encoder
2532               in the backend HTTP/2 connection.  The decoder (backend)
2533               specifies  the maximum  dynamic table  size it  accepts.
2534               Then the negotiated dynamic table size is the minimum of
2535               this option value and the value which backend specified.
2536               Default: )"
2537       << util::utos_unit(config->http2.downstream.encoder_dynamic_table_size)
2538       << R"(
2539   --backend-http2-decoder-dynamic-table-size=<SIZE>
2540               Specify the maximum dynamic  table size of HPACK decoder
2541               in the backend HTTP/2 connection.
2542               Default: )"
2543       << util::utos_unit(config->http2.downstream.decoder_dynamic_table_size)
2544       << R"(
2545
2546 Mode:
2547   (default mode)
2548               Accept  HTTP/2,  and  HTTP/1.1 over  SSL/TLS.   "no-tls"
2549               parameter is  used in  --frontend option,  accept HTTP/2
2550               and HTTP/1.1 over cleartext  TCP.  The incoming HTTP/1.1
2551               connection  can  be  upgraded  to  HTTP/2  through  HTTP
2552               Upgrade.
2553   -s, --http2-proxy
2554               Like default mode, but enable forward proxy.  This is so
2555               called HTTP/2 proxy mode.
2556
2557 Logging:
2558   -L, --log-level=<LEVEL>
2559               Set the severity  level of log output.   <LEVEL> must be
2560               one of INFO, NOTICE, WARN, ERROR and FATAL.
2561               Default: NOTICE
2562   --accesslog-file=<PATH>
2563               Set path to write access log.  To reopen file, send USR1
2564               signal to nghttpx.
2565   --accesslog-syslog
2566               Send  access log  to syslog.   If this  option is  used,
2567               --accesslog-file option is ignored.
2568   --accesslog-format=<FORMAT>
2569               Specify  format  string  for access  log.   The  default
2570               format is combined format.   The following variables are
2571               available:
2572
2573               * $remote_addr: client IP address.
2574               * $time_local: local time in Common Log format.
2575               * $time_iso8601: local time in ISO 8601 format.
2576               * $request: HTTP request line.
2577               * $status: HTTP response status code.
2578               * $body_bytes_sent: the  number of bytes sent  to client
2579                 as response body.
2580               * $http_<VAR>: value of HTTP  request header <VAR> where
2581                 '_' in <VAR> is replaced with '-'.
2582               * $remote_port: client  port.
2583               * $server_port: server port.
2584               * $request_time: request processing time in seconds with
2585                 milliseconds resolution.
2586               * $pid: PID of the running process.
2587               * $alpn: ALPN identifier of the protocol which generates
2588                 the response.   For HTTP/1,  ALPN is  always http/1.1,
2589                 regardless of minor version.
2590               * $tls_cipher: cipher used for SSL/TLS connection.
2591               * $tls_client_fingerprint_sha256: SHA-256 fingerprint of
2592                 client certificate.
2593               * $tls_client_fingerprint_sha1:  SHA-1   fingerprint  of
2594                 client certificate.
2595               * $tls_client_subject_name:   subject  name   in  client
2596                 certificate.
2597               * $tls_client_issuer_name:   issuer   name   in   client
2598                 certificate.
2599               * $tls_client_serial:    serial    number   in    client
2600                 certificate.
2601               * $tls_protocol: protocol for SSL/TLS connection.
2602               * $tls_session_id: session ID for SSL/TLS connection.
2603               * $tls_session_reused:  "r"   if  SSL/TLS   session  was
2604                 reused.  Otherwise, "."
2605               * $tls_sni: SNI server name for SSL/TLS connection.
2606               * $backend_host:  backend  host   used  to  fulfill  the
2607                 request.  "-" if backend host is not available.
2608               * $backend_port:  backend  port   used  to  fulfill  the
2609                 request.  "-" if backend host is not available.
2610
2611               The  variable  can  be  enclosed  by  "{"  and  "}"  for
2612               disambiguation (e.g., ${remote_addr}).
2613
2614               Default: )"
2615       << DEFAULT_ACCESSLOG_FORMAT << R"(
2616   --accesslog-write-early
2617               Write  access  log  when   response  header  fields  are
2618               received   from  backend   rather   than  when   request
2619               transaction finishes.
2620   --errorlog-file=<PATH>
2621               Set path to write error  log.  To reopen file, send USR1
2622               signal  to nghttpx.   stderr will  be redirected  to the
2623               error log file unless --errorlog-syslog is used.
2624               Default: )"
2625       << config->logging.error.file << R"(
2626   --errorlog-syslog
2627               Send  error log  to  syslog.  If  this  option is  used,
2628               --errorlog-file option is ignored.
2629   --syslog-facility=<FACILITY>
2630               Set syslog facility to <FACILITY>.
2631               Default: )"
2632       << str_syslog_facility(config->logging.syslog_facility) << R"(
2633
2634 HTTP:
2635   --add-x-forwarded-for
2636               Append  X-Forwarded-For header  field to  the downstream
2637               request.
2638   --strip-incoming-x-forwarded-for
2639               Strip X-Forwarded-For  header field from  inbound client
2640               requests.
2641   --no-add-x-forwarded-proto
2642               Don't append  additional X-Forwarded-Proto  header field
2643               to  the   backend  request.   If  inbound   client  sets
2644               X-Forwarded-Proto,                                   and
2645               --no-strip-incoming-x-forwarded-proto  option  is  used,
2646               they are passed to the backend.
2647   --no-strip-incoming-x-forwarded-proto
2648               Don't strip X-Forwarded-Proto  header field from inbound
2649               client requests.
2650   --add-forwarded=<LIST>
2651               Append RFC  7239 Forwarded header field  with parameters
2652               specified in comma delimited list <LIST>.  The supported
2653               parameters  are "by",  "for", "host",  and "proto".   By
2654               default,  the value  of  "by" and  "for" parameters  are
2655               obfuscated     string.     See     --forwarded-by    and
2656               --forwarded-for options respectively.  Note that nghttpx
2657               does  not  translate non-standard  X-Forwarded-*  header
2658               fields into Forwarded header field, and vice versa.
2659   --strip-incoming-forwarded
2660               Strip  Forwarded   header  field  from   inbound  client
2661               requests.
2662   --forwarded-by=(obfuscated|ip|<VALUE>)
2663               Specify the parameter value sent out with "by" parameter
2664               of Forwarded  header field.   If "obfuscated"  is given,
2665               the string is randomly generated at startup.  If "ip" is
2666               given,   the  interface   address  of   the  connection,
2667               including port number, is  sent with "by" parameter.  In
2668               case of UNIX domain  socket, "localhost" is used instead
2669               of address and  port.  User can also  specify the static
2670               obfuscated string.  The limitation is that it must start
2671               with   "_",  and   only   consists   of  character   set
2672               [A-Za-z0-9._-], as described in RFC 7239.
2673               Default: obfuscated
2674   --forwarded-for=(obfuscated|ip)
2675               Specify  the   parameter  value  sent  out   with  "for"
2676               parameter of Forwarded header field.  If "obfuscated" is
2677               given, the string is  randomly generated for each client
2678               connection.  If "ip" is given, the remote client address
2679               of  the connection,  without port  number, is  sent with
2680               "for"  parameter.   In  case   of  UNIX  domain  socket,
2681               "localhost" is used instead of address.
2682               Default: obfuscated
2683   --no-via    Don't append to  Via header field.  If  Via header field
2684               is received, it is left unaltered.
2685   --no-strip-incoming-early-data
2686               Don't strip Early-Data header  field from inbound client
2687               requests.
2688   --no-location-rewrite
2689               Don't  rewrite location  header field  in default  mode.
2690               When --http2-proxy  is used, location header  field will
2691               not be altered regardless of this option.
2692   --host-rewrite
2693               Rewrite  host and  :authority header  fields in  default
2694               mode.  When  --http2-proxy is  used, these  headers will
2695               not be altered regardless of this option.
2696   --altsvc=<PROTOID,PORT[,HOST,[ORIGIN]]>
2697               Specify   protocol  ID,   port,  host   and  origin   of
2698               alternative service.  <HOST>  and <ORIGIN> are optional.
2699               They  are advertised  in  alt-svc header  field only  in
2700               HTTP/1.1  frontend.  This  option can  be used  multiple
2701               times   to   specify  multiple   alternative   services.
2702               Example: --altsvc=h2,443
2703   --add-request-header=<HEADER>
2704               Specify additional header field to add to request header
2705               set.  This  option just  appends header field  and won't
2706               replace anything  already set.  This option  can be used
2707               several  times   to  specify  multiple   header  fields.
2708               Example: --add-request-header="foo: bar"
2709   --add-response-header=<HEADER>
2710               Specify  additional  header  field to  add  to  response
2711               header set.   This option just appends  header field and
2712               won't replace anything already  set.  This option can be
2713               used several  times to  specify multiple  header fields.
2714               Example: --add-response-header="foo: bar"
2715   --request-header-field-buffer=<SIZE>
2716               Set maximum buffer size for incoming HTTP request header
2717               field list.  This is the sum of header name and value in
2718               bytes.   If  trailer  fields  exist,  they  are  counted
2719               towards this number.
2720               Default: )"
2721       << util::utos_unit(config->http.request_header_field_buffer) << R"(
2722   --max-request-header-fields=<N>
2723               Set  maximum  number  of incoming  HTTP  request  header
2724               fields.   If  trailer  fields exist,  they  are  counted
2725               towards this number.
2726               Default: )"
2727       << config->http.max_request_header_fields << R"(
2728   --response-header-field-buffer=<SIZE>
2729               Set  maximum  buffer  size for  incoming  HTTP  response
2730               header field list.   This is the sum of  header name and
2731               value  in  bytes.  If  trailer  fields  exist, they  are
2732               counted towards this number.
2733               Default: )"
2734       << util::utos_unit(config->http.response_header_field_buffer) << R"(
2735   --max-response-header-fields=<N>
2736               Set  maximum number  of  incoming  HTTP response  header
2737               fields.   If  trailer  fields exist,  they  are  counted
2738               towards this number.
2739               Default: )"
2740       << config->http.max_response_header_fields << R"(
2741   --error-page=(<CODE>|*)=<PATH>
2742               Set file path  to custom error page  served when nghttpx
2743               originally  generates  HTTP  error status  code  <CODE>.
2744               <CODE> must be greater than or equal to 400, and at most
2745               599.  If "*"  is used instead of <CODE>,  it matches all
2746               HTTP  status  code.  If  error  status  code comes  from
2747               backend server, the custom error pages are not used.
2748   --server-name=<NAME>
2749               Change server response header field value to <NAME>.
2750               Default: )"
2751       << config->http.server_name << R"(
2752   --no-server-rewrite
2753               Don't rewrite server header field in default mode.  When
2754               --http2-proxy is used, these headers will not be altered
2755               regardless of this option.
2756   --redirect-https-port=<PORT>
2757               Specify the port number which appears in Location header
2758               field  when  redirect  to  HTTPS  URI  is  made  due  to
2759               "redirect-if-not-tls" parameter in --backend option.
2760               Default: )"
2761       << config->http.redirect_https_port << R"(
2762
2763 API:
2764   --api-max-request-body=<SIZE>
2765               Set the maximum size of request body for API request.
2766               Default: )"
2767       << util::utos_unit(config->api.max_request_body) << R"(
2768
2769 DNS:
2770   --dns-cache-timeout=<DURATION>
2771               Set duration that cached DNS results remain valid.  Note
2772               that nghttpx caches the unsuccessful results as well.
2773               Default: )"
2774       << util::duration_str(config->dns.timeout.cache) << R"(
2775   --dns-lookup-timeout=<DURATION>
2776               Set timeout that  DNS server is given to  respond to the
2777               initial  DNS  query.  For  the  2nd  and later  queries,
2778               server is  given time based  on this timeout, and  it is
2779               scaled linearly.
2780               Default: )"
2781       << util::duration_str(config->dns.timeout.lookup) << R"(
2782   --dns-max-try=<N>
2783               Set the number of DNS query before nghttpx gives up name
2784               lookup.
2785               Default: )"
2786       << config->dns.max_try << R"(
2787   --frontend-max-requests=<N>
2788               The number  of requests that single  frontend connection
2789               can process.  For HTTP/2, this  is the number of streams
2790               in  one  HTTP/2 connection.   For  HTTP/1,  this is  the
2791               number of keep alive requests.  This is hint to nghttpx,
2792               and it  may allow additional few  requests.  The default
2793               value is unlimited.
2794
2795 Debug:
2796   --frontend-http2-dump-request-header=<PATH>
2797               Dumps request headers received by HTTP/2 frontend to the
2798               file denoted  in <PATH>.  The  output is done  in HTTP/1
2799               header field format and each header block is followed by
2800               an empty line.  This option  is not thread safe and MUST
2801               NOT be used with option -n<N>, where <N> >= 2.
2802   --frontend-http2-dump-response-header=<PATH>
2803               Dumps response headers sent  from HTTP/2 frontend to the
2804               file denoted  in <PATH>.  The  output is done  in HTTP/1
2805               header field format and each header block is followed by
2806               an empty line.  This option  is not thread safe and MUST
2807               NOT be used with option -n<N>, where <N> >= 2.
2808   -o, --frontend-frame-debug
2809               Print HTTP/2 frames in  frontend to stderr.  This option
2810               is  not thread  safe and  MUST NOT  be used  with option
2811               -n=N, where N >= 2.
2812
2813 Process:
2814   -D, --daemon
2815               Run in a background.  If -D is used, the current working
2816               directory is changed to '/'.
2817   --pid-file=<PATH>
2818               Set path to save PID of this program.
2819   --user=<USER>
2820               Run this program as <USER>.   This option is intended to
2821               be used to drop root privileges.
2822   --single-process
2823               Run this program in a  single process mode for debugging
2824               purpose.  Without this option,  nghttpx creates at least
2825               2  processes:  master  and worker  processes.   If  this
2826               option is  used, master  and worker  are unified  into a
2827               single process.  nghttpx still spawns additional process
2828               if neverbleed is used.  In  the single process mode, the
2829               signal handling feature is disabled.
2830
2831 Scripting:
2832   --mruby-file=<PATH>
2833               Set mruby script file
2834   --ignore-per-pattern-mruby-error
2835               Ignore mruby compile error  for per-pattern mruby script
2836               file.  If error  occurred, it is treated as  if no mruby
2837               file were specified for the pattern.
2838
2839 Misc:
2840   --conf=<PATH>
2841               Load  configuration  from   <PATH>.   Please  note  that
2842               nghttpx always  tries to read the  default configuration
2843               file if --conf is not given.
2844               Default: )"
2845       << config->conf_path << R"(
2846   --include=<PATH>
2847               Load additional configurations from <PATH>.  File <PATH>
2848               is  read  when  configuration  parser  encountered  this
2849               option.  This option can be used multiple times, or even
2850               recursively.
2851   -v, --version
2852               Print version and exit.
2853   -h, --help  Print this help and exit.
2854
2855 --
2856
2857   The <SIZE> argument is an integer and an optional unit (e.g., 10K is
2858   10 * 1024).  Units are K, M and G (powers of 1024).
2859
2860   The <DURATION> argument is an integer and an optional unit (e.g., 1s
2861   is 1 second and 500ms is 500 milliseconds).  Units are h, m, s or ms
2862   (hours, minutes, seconds and milliseconds, respectively).  If a unit
2863   is omitted, a second is used as unit.)"
2864       << std::endl;
2865 }
2866 } // namespace
2867
2868 namespace {
2869 int process_options(Config *config,
2870                     std::vector<std::pair<StringRef, StringRef>> &cmdcfgs) {
2871   std::array<char, STRERROR_BUFSIZE> errbuf;
2872   std::map<StringRef, size_t> pattern_addr_indexer;
2873   if (conf_exists(config->conf_path.c_str())) {
2874     LOG(NOTICE) << "Loading configuration from " << config->conf_path;
2875     std::set<StringRef> include_set;
2876     if (load_config(config, config->conf_path.c_str(), include_set,
2877                     pattern_addr_indexer) == -1) {
2878       LOG(FATAL) << "Failed to load configuration from " << config->conf_path;
2879       return -1;
2880     }
2881     assert(include_set.empty());
2882   }
2883
2884   // Reopen log files using configurations in file
2885   reopen_log_files(config->logging);
2886
2887   {
2888     std::set<StringRef> include_set;
2889
2890     for (auto &p : cmdcfgs) {
2891       if (parse_config(config, p.first, p.second, include_set,
2892                        pattern_addr_indexer) == -1) {
2893         LOG(FATAL) << "Failed to parse command-line argument.";
2894         return -1;
2895       }
2896     }
2897
2898     assert(include_set.empty());
2899   }
2900
2901   Log::set_severity_level(config->logging.severity);
2902
2903   auto &loggingconf = config->logging;
2904
2905   if (loggingconf.access.syslog || loggingconf.error.syslog) {
2906     openlog("nghttpx", LOG_NDELAY | LOG_NOWAIT | LOG_PID,
2907             loggingconf.syslog_facility);
2908   }
2909
2910   if (reopen_log_files(config->logging) != 0) {
2911     LOG(FATAL) << "Failed to open log file";
2912     return -1;
2913   }
2914
2915   redirect_stderr_to_errorlog(loggingconf);
2916
2917   if (config->uid != 0) {
2918     if (log_config()->accesslog_fd != -1 &&
2919         fchown(log_config()->accesslog_fd, config->uid, config->gid) == -1) {
2920       auto error = errno;
2921       LOG(WARN) << "Changing owner of access log file failed: "
2922                 << xsi_strerror(error, errbuf.data(), errbuf.size());
2923     }
2924     if (log_config()->errorlog_fd != -1 &&
2925         fchown(log_config()->errorlog_fd, config->uid, config->gid) == -1) {
2926       auto error = errno;
2927       LOG(WARN) << "Changing owner of error log file failed: "
2928                 << xsi_strerror(error, errbuf.data(), errbuf.size());
2929     }
2930   }
2931
2932   if (config->single_thread) {
2933     LOG(WARN) << "single-thread: Set workers to 1";
2934     config->num_worker = 1;
2935   }
2936
2937   auto &http2conf = config->http2;
2938   {
2939     auto &dumpconf = http2conf.upstream.debug.dump;
2940
2941     if (!dumpconf.request_header_file.empty()) {
2942       auto path = dumpconf.request_header_file.c_str();
2943       auto f = open_file_for_write(path);
2944
2945       if (f == nullptr) {
2946         LOG(FATAL) << "Failed to open http2 upstream request header file: "
2947                    << path;
2948         return -1;
2949       }
2950
2951       dumpconf.request_header = f;
2952
2953       if (config->uid != 0) {
2954         if (chown(path, config->uid, config->gid) == -1) {
2955           auto error = errno;
2956           LOG(WARN) << "Changing owner of http2 upstream request header file "
2957                     << path << " failed: "
2958                     << xsi_strerror(error, errbuf.data(), errbuf.size());
2959         }
2960       }
2961     }
2962
2963     if (!dumpconf.response_header_file.empty()) {
2964       auto path = dumpconf.response_header_file.c_str();
2965       auto f = open_file_for_write(path);
2966
2967       if (f == nullptr) {
2968         LOG(FATAL) << "Failed to open http2 upstream response header file: "
2969                    << path;
2970         return -1;
2971       }
2972
2973       dumpconf.response_header = f;
2974
2975       if (config->uid != 0) {
2976         if (chown(path, config->uid, config->gid) == -1) {
2977           auto error = errno;
2978           LOG(WARN) << "Changing owner of http2 upstream response header file"
2979                     << " " << path << " failed: "
2980                     << xsi_strerror(error, errbuf.data(), errbuf.size());
2981         }
2982       }
2983     }
2984   }
2985
2986   auto &tlsconf = config->tls;
2987
2988   if (tlsconf.npn_list.empty()) {
2989     tlsconf.npn_list = util::split_str(DEFAULT_NPN_LIST, ',');
2990   }
2991
2992   if (!tlsconf.tls_proto_list.empty()) {
2993     tlsconf.tls_proto_mask = tls::create_tls_proto_mask(tlsconf.tls_proto_list);
2994   }
2995
2996   // TODO We depends on the ordering of protocol version macro in
2997   // OpenSSL.
2998   if (tlsconf.min_proto_version > tlsconf.max_proto_version) {
2999     LOG(ERROR) << "tls-max-proto-version must be equal to or larger than "
3000                   "tls-min-proto-version";
3001     return -1;
3002   }
3003
3004   if (tls::set_alpn_prefs(tlsconf.alpn_prefs, tlsconf.npn_list) != 0) {
3005     return -1;
3006   }
3007
3008   tlsconf.bio_method = create_bio_method();
3009
3010   auto &listenerconf = config->conn.listener;
3011   auto &upstreamconf = config->conn.upstream;
3012
3013   if (listenerconf.addrs.empty()) {
3014     UpstreamAddr addr{};
3015     addr.host = StringRef::from_lit("*");
3016     addr.port = 3000;
3017     addr.tls = true;
3018     addr.family = AF_INET;
3019     listenerconf.addrs.push_back(addr);
3020     addr.family = AF_INET6;
3021     listenerconf.addrs.push_back(std::move(addr));
3022   }
3023
3024   if (upstreamconf.worker_connections == 0) {
3025     upstreamconf.worker_connections = std::numeric_limits<size_t>::max();
3026   }
3027
3028   if (tls::upstream_tls_enabled(config->conn) &&
3029       (tlsconf.private_key_file.empty() || tlsconf.cert_file.empty())) {
3030     LOG(FATAL) << "TLS private key and certificate files are required.  "
3031                   "Specify them in command-line, or in configuration file "
3032                   "using private-key-file and certificate-file options.";
3033     return -1;
3034   }
3035
3036   if (tls::upstream_tls_enabled(config->conn) && !tlsconf.ocsp.disabled) {
3037     struct stat buf;
3038     if (stat(tlsconf.ocsp.fetch_ocsp_response_file.c_str(), &buf) != 0) {
3039       tlsconf.ocsp.disabled = true;
3040       LOG(WARN) << "--fetch-ocsp-response-file: "
3041                 << tlsconf.ocsp.fetch_ocsp_response_file
3042                 << " not found.  OCSP stapling has been disabled.";
3043     }
3044   }
3045
3046   if (configure_downstream_group(config, config->http2_proxy, false, tlsconf) !=
3047       0) {
3048     return -1;
3049   }
3050
3051   auto &proxy = config->downstream_http_proxy;
3052   if (!proxy.host.empty()) {
3053     auto hostport = util::make_hostport(StringRef{proxy.host}, proxy.port);
3054     if (resolve_hostname(&proxy.addr, proxy.host.c_str(), proxy.port,
3055                          AF_UNSPEC) == -1) {
3056       LOG(FATAL) << "Resolving backend HTTP proxy address failed: " << hostport;
3057       return -1;
3058     }
3059     LOG(NOTICE) << "Backend HTTP proxy address: " << hostport << " -> "
3060                 << util::to_numeric_addr(&proxy.addr);
3061   }
3062
3063   {
3064     auto &memcachedconf = tlsconf.session_cache.memcached;
3065     if (!memcachedconf.host.empty()) {
3066       auto hostport = util::make_hostport(StringRef{memcachedconf.host},
3067                                           memcachedconf.port);
3068       if (resolve_hostname(&memcachedconf.addr, memcachedconf.host.c_str(),
3069                            memcachedconf.port, memcachedconf.family) == -1) {
3070         LOG(FATAL)
3071             << "Resolving memcached address for TLS session cache failed: "
3072             << hostport;
3073         return -1;
3074       }
3075       LOG(NOTICE) << "Memcached address for TLS session cache: " << hostport
3076                   << " -> " << util::to_numeric_addr(&memcachedconf.addr);
3077       if (memcachedconf.tls) {
3078         LOG(NOTICE) << "Connection to memcached for TLS session cache will be "
3079                        "encrypted by TLS";
3080       }
3081     }
3082   }
3083
3084   {
3085     auto &memcachedconf = tlsconf.ticket.memcached;
3086     if (!memcachedconf.host.empty()) {
3087       auto hostport = util::make_hostport(StringRef{memcachedconf.host},
3088                                           memcachedconf.port);
3089       if (resolve_hostname(&memcachedconf.addr, memcachedconf.host.c_str(),
3090                            memcachedconf.port, memcachedconf.family) == -1) {
3091         LOG(FATAL) << "Resolving memcached address for TLS ticket key failed: "
3092                    << hostport;
3093         return -1;
3094       }
3095       LOG(NOTICE) << "Memcached address for TLS ticket key: " << hostport
3096                   << " -> " << util::to_numeric_addr(&memcachedconf.addr);
3097       if (memcachedconf.tls) {
3098         LOG(NOTICE) << "Connection to memcached for TLS ticket key will be "
3099                        "encrypted by TLS";
3100       }
3101     }
3102   }
3103
3104   if (config->rlimit_nofile) {
3105     struct rlimit lim = {static_cast<rlim_t>(config->rlimit_nofile),
3106                          static_cast<rlim_t>(config->rlimit_nofile)};
3107     if (setrlimit(RLIMIT_NOFILE, &lim) != 0) {
3108       auto error = errno;
3109       LOG(WARN) << "Setting rlimit-nofile failed: "
3110                 << xsi_strerror(error, errbuf.data(), errbuf.size());
3111     }
3112   }
3113
3114   auto &fwdconf = config->http.forwarded;
3115
3116   if (fwdconf.by_node_type == ForwardedNode::OBFUSCATED &&
3117       fwdconf.by_obfuscated.empty()) {
3118     // 2 for '_' and terminal NULL
3119     auto iov = make_byte_ref(config->balloc, SHRPX_OBFUSCATED_NODE_LENGTH + 2);
3120     auto p = iov.base;
3121     *p++ = '_';
3122     auto gen = util::make_mt19937();
3123     p = util::random_alpha_digit(p, p + SHRPX_OBFUSCATED_NODE_LENGTH, gen);
3124     *p = '\0';
3125     fwdconf.by_obfuscated = StringRef{iov.base, p};
3126   }
3127
3128   if (config->http2.upstream.debug.frame_debug) {
3129     // To make it sync to logging
3130     set_output(stderr);
3131     if (isatty(fileno(stdout))) {
3132       set_color_output(true);
3133     }
3134     reset_timer();
3135   }
3136
3137   config->http2.upstream.callbacks = create_http2_upstream_callbacks();
3138   config->http2.downstream.callbacks = create_http2_downstream_callbacks();
3139
3140   return 0;
3141 }
3142 } // namespace
3143
3144 namespace {
3145 // Closes file descriptor which are opened for listeners in config,
3146 // and are not inherited from |iaddrs|.
3147 void close_not_inherited_fd(Config *config,
3148                             const std::vector<InheritedAddr> &iaddrs) {
3149   auto &listenerconf = config->conn.listener;
3150
3151   for (auto &addr : listenerconf.addrs) {
3152     auto inherited = std::find_if(
3153         std::begin(iaddrs), std::end(iaddrs),
3154         [&addr](const InheritedAddr &iaddr) { return addr.fd == iaddr.fd; });
3155
3156     if (inherited != std::end(iaddrs)) {
3157       continue;
3158     }
3159
3160     close(addr.fd);
3161   }
3162 }
3163 } // namespace
3164
3165 namespace {
3166 void reload_config(WorkerProcess *wp) {
3167   int rv;
3168
3169   LOG(NOTICE) << "Reloading configuration";
3170
3171   auto cur_config = mod_config();
3172   auto new_config = std::make_unique<Config>();
3173
3174   fill_default_config(new_config.get());
3175
3176   new_config->conf_path =
3177       make_string_ref(new_config->balloc, cur_config->conf_path);
3178   // daemon option is ignored here.
3179   new_config->daemon = cur_config->daemon;
3180   // loop is reused, and ev_loop_flags gets ignored
3181   new_config->ev_loop_flags = cur_config->ev_loop_flags;
3182   new_config->config_revision = cur_config->config_revision + 1;
3183
3184   rv = process_options(new_config.get(), suconfig.cmdcfgs);
3185   if (rv != 0) {
3186     LOG(ERROR) << "Failed to process new configuration";
3187     return;
3188   }
3189
3190   auto iaddrs = get_inherited_addr_from_config(new_config->balloc, cur_config);
3191
3192   if (create_acceptor_socket(new_config.get(), iaddrs) != 0) {
3193     close_not_inherited_fd(new_config.get(), iaddrs);
3194     return;
3195   }
3196
3197   // According to libev documentation, flags are ignored since we have
3198   // already created first default loop.
3199   auto loop = ev_default_loop(new_config->ev_loop_flags);
3200
3201   int ipc_fd = 0;
3202
3203   // fork_worker_process and forked child process assumes new
3204   // configuration can be obtained from get_config().
3205
3206   auto old_config = replace_config(std::move(new_config));
3207
3208   auto pid = fork_worker_process(ipc_fd, iaddrs);
3209
3210   if (pid == -1) {
3211     LOG(ERROR) << "Failed to process new configuration";
3212
3213     new_config = replace_config(std::move(old_config));
3214     close_not_inherited_fd(new_config.get(), iaddrs);
3215
3216     return;
3217   }
3218
3219   close_unused_inherited_addr(iaddrs);
3220
3221   // Send last worker process a graceful shutdown notice
3222   auto &last_wp = worker_processes.back();
3223   ipc_send(last_wp.get(), SHRPX_IPC_GRACEFUL_SHUTDOWN);
3224   // We no longer use signals for this worker.
3225   last_wp->shutdown_signal_watchers();
3226
3227   worker_process_add(std::make_unique<WorkerProcess>(loop, pid, ipc_fd));
3228
3229   if (!get_config()->pid_file.empty()) {
3230     save_pid();
3231   }
3232 }
3233 } // namespace
3234
3235 int main(int argc, char **argv) {
3236   int rv;
3237   std::array<char, STRERROR_BUFSIZE> errbuf;
3238
3239   nghttp2::tls::libssl_init();
3240
3241 #ifndef NOTHREADS
3242   nghttp2::tls::LibsslGlobalLock lock;
3243 #endif // NOTHREADS
3244
3245   Log::set_severity_level(NOTICE);
3246   create_config();
3247   fill_default_config(mod_config());
3248
3249   // make copy of stderr
3250   store_original_fds();
3251
3252   // First open log files with default configuration, so that we can
3253   // log errors/warnings while reading configuration files.
3254   reopen_log_files(get_config()->logging);
3255
3256   suconfig.original_argv = argv;
3257
3258   // We have to copy argv, since getopt_long may change its content.
3259   suconfig.argc = argc;
3260   suconfig.argv = new char *[argc];
3261
3262   for (int i = 0; i < argc; ++i) {
3263     suconfig.argv[i] = strdup(argv[i]);
3264     if (suconfig.argv[i] == nullptr) {
3265       auto error = errno;
3266       LOG(FATAL) << "failed to copy argv: "
3267                  << xsi_strerror(error, errbuf.data(), errbuf.size());
3268       exit(EXIT_FAILURE);
3269     }
3270   }
3271
3272   suconfig.cwd = getcwd(nullptr, 0);
3273   if (suconfig.cwd == nullptr) {
3274     auto error = errno;
3275     LOG(FATAL) << "failed to get current working directory: errno=" << error;
3276     exit(EXIT_FAILURE);
3277   }
3278
3279   auto &cmdcfgs = suconfig.cmdcfgs;
3280
3281   while (1) {
3282     static int flag = 0;
3283     static constexpr option long_options[] = {
3284         {SHRPX_OPT_DAEMON.c_str(), no_argument, nullptr, 'D'},
3285         {SHRPX_OPT_LOG_LEVEL.c_str(), required_argument, nullptr, 'L'},
3286         {SHRPX_OPT_BACKEND.c_str(), required_argument, nullptr, 'b'},
3287         {SHRPX_OPT_HTTP2_MAX_CONCURRENT_STREAMS.c_str(), required_argument,
3288          nullptr, 'c'},
3289         {SHRPX_OPT_FRONTEND.c_str(), required_argument, nullptr, 'f'},
3290         {"help", no_argument, nullptr, 'h'},
3291         {SHRPX_OPT_INSECURE.c_str(), no_argument, nullptr, 'k'},
3292         {SHRPX_OPT_WORKERS.c_str(), required_argument, nullptr, 'n'},
3293         {SHRPX_OPT_CLIENT_PROXY.c_str(), no_argument, nullptr, 'p'},
3294         {SHRPX_OPT_HTTP2_PROXY.c_str(), no_argument, nullptr, 's'},
3295         {"version", no_argument, nullptr, 'v'},
3296         {SHRPX_OPT_FRONTEND_FRAME_DEBUG.c_str(), no_argument, nullptr, 'o'},
3297         {SHRPX_OPT_ADD_X_FORWARDED_FOR.c_str(), no_argument, &flag, 1},
3298         {SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT.c_str(), required_argument,
3299          &flag, 2},
3300         {SHRPX_OPT_FRONTEND_READ_TIMEOUT.c_str(), required_argument, &flag, 3},
3301         {SHRPX_OPT_FRONTEND_WRITE_TIMEOUT.c_str(), required_argument, &flag, 4},
3302         {SHRPX_OPT_BACKEND_READ_TIMEOUT.c_str(), required_argument, &flag, 5},
3303         {SHRPX_OPT_BACKEND_WRITE_TIMEOUT.c_str(), required_argument, &flag, 6},
3304         {SHRPX_OPT_ACCESSLOG_FILE.c_str(), required_argument, &flag, 7},
3305         {SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT.c_str(), required_argument, &flag,
3306          8},
3307         {SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS.c_str(), required_argument, &flag,
3308          9},
3309         {SHRPX_OPT_PID_FILE.c_str(), required_argument, &flag, 10},
3310         {SHRPX_OPT_USER.c_str(), required_argument, &flag, 11},
3311         {"conf", required_argument, &flag, 12},
3312         {SHRPX_OPT_SYSLOG_FACILITY.c_str(), required_argument, &flag, 14},
3313         {SHRPX_OPT_BACKLOG.c_str(), required_argument, &flag, 15},
3314         {SHRPX_OPT_CIPHERS.c_str(), required_argument, &flag, 16},
3315         {SHRPX_OPT_CLIENT.c_str(), no_argument, &flag, 17},
3316         {SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS.c_str(), required_argument, &flag,
3317          18},
3318         {SHRPX_OPT_CACERT.c_str(), required_argument, &flag, 19},
3319         {SHRPX_OPT_BACKEND_IPV4.c_str(), no_argument, &flag, 20},
3320         {SHRPX_OPT_BACKEND_IPV6.c_str(), no_argument, &flag, 21},
3321         {SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE.c_str(), required_argument, &flag,
3322          22},
3323         {SHRPX_OPT_NO_VIA.c_str(), no_argument, &flag, 23},
3324         {SHRPX_OPT_SUBCERT.c_str(), required_argument, &flag, 24},
3325         {SHRPX_OPT_HTTP2_BRIDGE.c_str(), no_argument, &flag, 25},
3326         {SHRPX_OPT_BACKEND_HTTP_PROXY_URI.c_str(), required_argument, &flag,
3327          26},
3328         {SHRPX_OPT_BACKEND_NO_TLS.c_str(), no_argument, &flag, 27},
3329         {SHRPX_OPT_OCSP_STARTUP.c_str(), no_argument, &flag, 28},
3330         {SHRPX_OPT_FRONTEND_NO_TLS.c_str(), no_argument, &flag, 29},
3331         {SHRPX_OPT_NO_VERIFY_OCSP.c_str(), no_argument, &flag, 30},
3332         {SHRPX_OPT_BACKEND_TLS_SNI_FIELD.c_str(), required_argument, &flag, 31},
3333         {SHRPX_OPT_DH_PARAM_FILE.c_str(), required_argument, &flag, 33},
3334         {SHRPX_OPT_READ_RATE.c_str(), required_argument, &flag, 34},
3335         {SHRPX_OPT_READ_BURST.c_str(), required_argument, &flag, 35},
3336         {SHRPX_OPT_WRITE_RATE.c_str(), required_argument, &flag, 36},
3337         {SHRPX_OPT_WRITE_BURST.c_str(), required_argument, &flag, 37},
3338         {SHRPX_OPT_NPN_LIST.c_str(), required_argument, &flag, 38},
3339         {SHRPX_OPT_VERIFY_CLIENT.c_str(), no_argument, &flag, 39},
3340         {SHRPX_OPT_VERIFY_CLIENT_CACERT.c_str(), required_argument, &flag, 40},
3341         {SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE.c_str(), required_argument, &flag,
3342          41},
3343         {SHRPX_OPT_CLIENT_CERT_FILE.c_str(), required_argument, &flag, 42},
3344         {SHRPX_OPT_FRONTEND_HTTP2_DUMP_REQUEST_HEADER.c_str(),
3345          required_argument, &flag, 43},
3346         {SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER.c_str(),
3347          required_argument, &flag, 44},
3348         {SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING.c_str(), no_argument, &flag, 45},
3349         {SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS.c_str(),
3350          required_argument, &flag, 46},
3351         {SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_BITS.c_str(),
3352          required_argument, &flag, 47},
3353         {SHRPX_OPT_TLS_PROTO_LIST.c_str(), required_argument, &flag, 48},
3354         {SHRPX_OPT_PADDING.c_str(), required_argument, &flag, 49},
3355         {SHRPX_OPT_WORKER_READ_RATE.c_str(), required_argument, &flag, 50},
3356         {SHRPX_OPT_WORKER_READ_BURST.c_str(), required_argument, &flag, 51},
3357         {SHRPX_OPT_WORKER_WRITE_RATE.c_str(), required_argument, &flag, 52},
3358         {SHRPX_OPT_WORKER_WRITE_BURST.c_str(), required_argument, &flag, 53},
3359         {SHRPX_OPT_ALTSVC.c_str(), required_argument, &flag, 54},
3360         {SHRPX_OPT_ADD_RESPONSE_HEADER.c_str(), required_argument, &flag, 55},
3361         {SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS.c_str(), required_argument,
3362          &flag, 56},
3363         {SHRPX_OPT_ACCESSLOG_SYSLOG.c_str(), no_argument, &flag, 57},
3364         {SHRPX_OPT_ERRORLOG_FILE.c_str(), required_argument, &flag, 58},
3365         {SHRPX_OPT_ERRORLOG_SYSLOG.c_str(), no_argument, &flag, 59},
3366         {SHRPX_OPT_STREAM_READ_TIMEOUT.c_str(), required_argument, &flag, 60},
3367         {SHRPX_OPT_STREAM_WRITE_TIMEOUT.c_str(), required_argument, &flag, 61},
3368         {SHRPX_OPT_NO_LOCATION_REWRITE.c_str(), no_argument, &flag, 62},
3369         {SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_HOST.c_str(),
3370          required_argument, &flag, 63},
3371         {SHRPX_OPT_LISTENER_DISABLE_TIMEOUT.c_str(), required_argument, &flag,
3372          64},
3373         {SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR.c_str(), no_argument, &flag,
3374          65},
3375         {SHRPX_OPT_ACCESSLOG_FORMAT.c_str(), required_argument, &flag, 66},
3376         {SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND.c_str(),
3377          required_argument, &flag, 67},
3378         {SHRPX_OPT_TLS_TICKET_KEY_FILE.c_str(), required_argument, &flag, 68},
3379         {SHRPX_OPT_RLIMIT_NOFILE.c_str(), required_argument, &flag, 69},
3380         {SHRPX_OPT_BACKEND_RESPONSE_BUFFER.c_str(), required_argument, &flag,
3381          71},
3382         {SHRPX_OPT_BACKEND_REQUEST_BUFFER.c_str(), required_argument, &flag,
3383          72},
3384         {SHRPX_OPT_NO_HOST_REWRITE.c_str(), no_argument, &flag, 73},
3385         {SHRPX_OPT_NO_SERVER_PUSH.c_str(), no_argument, &flag, 74},
3386         {SHRPX_OPT_BACKEND_HTTP2_CONNECTIONS_PER_WORKER.c_str(),
3387          required_argument, &flag, 76},
3388         {SHRPX_OPT_FETCH_OCSP_RESPONSE_FILE.c_str(), required_argument, &flag,
3389          77},
3390         {SHRPX_OPT_OCSP_UPDATE_INTERVAL.c_str(), required_argument, &flag, 78},
3391         {SHRPX_OPT_NO_OCSP.c_str(), no_argument, &flag, 79},
3392         {SHRPX_OPT_HEADER_FIELD_BUFFER.c_str(), required_argument, &flag, 80},
3393         {SHRPX_OPT_MAX_HEADER_FIELDS.c_str(), required_argument, &flag, 81},
3394         {SHRPX_OPT_ADD_REQUEST_HEADER.c_str(), required_argument, &flag, 82},
3395         {SHRPX_OPT_INCLUDE.c_str(), required_argument, &flag, 83},
3396         {SHRPX_OPT_TLS_TICKET_KEY_CIPHER.c_str(), required_argument, &flag, 84},
3397         {SHRPX_OPT_HOST_REWRITE.c_str(), no_argument, &flag, 85},
3398         {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED.c_str(), required_argument,
3399          &flag, 86},
3400         {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED.c_str(), required_argument, &flag,
3401          87},
3402         {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_INTERVAL.c_str(), required_argument,
3403          &flag, 88},
3404         {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY.c_str(),
3405          required_argument, &flag, 89},
3406         {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL.c_str(), required_argument,
3407          &flag, 90},
3408         {SHRPX_OPT_MRUBY_FILE.c_str(), required_argument, &flag, 91},
3409         {SHRPX_OPT_ACCEPT_PROXY_PROTOCOL.c_str(), no_argument, &flag, 93},
3410         {SHRPX_OPT_FASTOPEN.c_str(), required_argument, &flag, 94},
3411         {SHRPX_OPT_TLS_DYN_REC_WARMUP_THRESHOLD.c_str(), required_argument,
3412          &flag, 95},
3413         {SHRPX_OPT_TLS_DYN_REC_IDLE_TIMEOUT.c_str(), required_argument, &flag,
3414          96},
3415         {SHRPX_OPT_ADD_FORWARDED.c_str(), required_argument, &flag, 97},
3416         {SHRPX_OPT_STRIP_INCOMING_FORWARDED.c_str(), no_argument, &flag, 98},
3417         {SHRPX_OPT_FORWARDED_BY.c_str(), required_argument, &flag, 99},
3418         {SHRPX_OPT_FORWARDED_FOR.c_str(), required_argument, &flag, 100},
3419         {SHRPX_OPT_RESPONSE_HEADER_FIELD_BUFFER.c_str(), required_argument,
3420          &flag, 101},
3421         {SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS.c_str(), required_argument, &flag,
3422          102},
3423         {SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST.c_str(), no_argument, &flag, 103},
3424         {SHRPX_OPT_REQUEST_HEADER_FIELD_BUFFER.c_str(), required_argument,
3425          &flag, 104},
3426         {SHRPX_OPT_MAX_REQUEST_HEADER_FIELDS.c_str(), required_argument, &flag,
3427          105},
3428         {SHRPX_OPT_BACKEND_HTTP1_TLS.c_str(), no_argument, &flag, 106},
3429         {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS.c_str(), no_argument, &flag,
3430          108},
3431         {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE.c_str(),
3432          required_argument, &flag, 109},
3433         {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE.c_str(),
3434          required_argument, &flag, 110},
3435         {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_TLS.c_str(), no_argument, &flag,
3436          111},
3437         {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_CERT_FILE.c_str(),
3438          required_argument, &flag, 112},
3439         {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE.c_str(),
3440          required_argument, &flag, 113},
3441         {SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY.c_str(),
3442          required_argument, &flag, 114},
3443         {SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY.c_str(),
3444          required_argument, &flag, 115},
3445         {SHRPX_OPT_BACKEND_ADDRESS_FAMILY.c_str(), required_argument, &flag,
3446          116},
3447         {SHRPX_OPT_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS.c_str(),
3448          required_argument, &flag, 117},
3449         {SHRPX_OPT_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS.c_str(),
3450          required_argument, &flag, 118},
3451         {SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND.c_str(), required_argument,
3452          &flag, 119},
3453         {SHRPX_OPT_BACKEND_TLS.c_str(), no_argument, &flag, 120},
3454         {SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST.c_str(), required_argument,
3455          &flag, 121},
3456         {SHRPX_OPT_ERROR_PAGE.c_str(), required_argument, &flag, 122},
3457         {SHRPX_OPT_NO_KQUEUE.c_str(), no_argument, &flag, 123},
3458         {SHRPX_OPT_FRONTEND_HTTP2_SETTINGS_TIMEOUT.c_str(), required_argument,
3459          &flag, 124},
3460         {SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT.c_str(), required_argument,
3461          &flag, 125},
3462         {SHRPX_OPT_API_MAX_REQUEST_BODY.c_str(), required_argument, &flag, 126},
3463         {SHRPX_OPT_BACKEND_MAX_BACKOFF.c_str(), required_argument, &flag, 127},
3464         {SHRPX_OPT_SERVER_NAME.c_str(), required_argument, &flag, 128},
3465         {SHRPX_OPT_NO_SERVER_REWRITE.c_str(), no_argument, &flag, 129},
3466         {SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE.c_str(),
3467          no_argument, &flag, 130},
3468         {SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE.c_str(), no_argument,
3469          &flag, 131},
3470         {SHRPX_OPT_FRONTEND_HTTP2_WINDOW_SIZE.c_str(), required_argument, &flag,
3471          132},
3472         {SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE.c_str(),
3473          required_argument, &flag, 133},
3474         {SHRPX_OPT_BACKEND_HTTP2_WINDOW_SIZE.c_str(), required_argument, &flag,
3475          134},
3476         {SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE.c_str(),
3477          required_argument, &flag, 135},
3478         {SHRPX_OPT_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE.c_str(),
3479          required_argument, &flag, 136},
3480         {SHRPX_OPT_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE.c_str(),
3481          required_argument, &flag, 137},
3482         {SHRPX_OPT_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE.c_str(),
3483          required_argument, &flag, 138},
3484         {SHRPX_OPT_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE.c_str(),
3485          required_argument, &flag, 139},
3486         {SHRPX_OPT_ECDH_CURVES.c_str(), required_argument, &flag, 140},
3487         {SHRPX_OPT_TLS_SCT_DIR.c_str(), required_argument, &flag, 141},
3488         {SHRPX_OPT_BACKEND_CONNECT_TIMEOUT.c_str(), required_argument, &flag,
3489          142},
3490         {SHRPX_OPT_DNS_CACHE_TIMEOUT.c_str(), required_argument, &flag, 143},
3491         {SHRPX_OPT_DNS_LOOKUP_TIMEOUT.c_str(), required_argument, &flag, 144},
3492         {SHRPX_OPT_DNS_MAX_TRY.c_str(), required_argument, &flag, 145},
3493         {SHRPX_OPT_FRONTEND_KEEP_ALIVE_TIMEOUT.c_str(), required_argument,
3494          &flag, 146},
3495         {SHRPX_OPT_PSK_SECRETS.c_str(), required_argument, &flag, 147},
3496         {SHRPX_OPT_CLIENT_PSK_SECRETS.c_str(), required_argument, &flag, 148},
3497         {SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST.c_str(), no_argument,
3498          &flag, 149},
3499         {SHRPX_OPT_CLIENT_CIPHERS.c_str(), required_argument, &flag, 150},
3500         {SHRPX_OPT_ACCESSLOG_WRITE_EARLY.c_str(), no_argument, &flag, 151},
3501         {SHRPX_OPT_TLS_MIN_PROTO_VERSION.c_str(), required_argument, &flag,
3502          152},
3503         {SHRPX_OPT_TLS_MAX_PROTO_VERSION.c_str(), required_argument, &flag,
3504          153},
3505         {SHRPX_OPT_REDIRECT_HTTPS_PORT.c_str(), required_argument, &flag, 154},
3506         {SHRPX_OPT_FRONTEND_MAX_REQUESTS.c_str(), required_argument, &flag,
3507          155},
3508         {SHRPX_OPT_SINGLE_THREAD.c_str(), no_argument, &flag, 156},
3509         {SHRPX_OPT_NO_ADD_X_FORWARDED_PROTO.c_str(), no_argument, &flag, 157},
3510         {SHRPX_OPT_NO_STRIP_INCOMING_X_FORWARDED_PROTO.c_str(), no_argument,
3511          &flag, 158},
3512         {SHRPX_OPT_SINGLE_PROCESS.c_str(), no_argument, &flag, 159},
3513         {SHRPX_OPT_VERIFY_CLIENT_TOLERATE_EXPIRED.c_str(), no_argument, &flag,
3514          160},
3515         {SHRPX_OPT_IGNORE_PER_PATTERN_MRUBY_ERROR.c_str(), no_argument, &flag,
3516          161},
3517         {SHRPX_OPT_TLS_NO_POSTPONE_EARLY_DATA.c_str(), no_argument, &flag, 162},
3518         {SHRPX_OPT_TLS_MAX_EARLY_DATA.c_str(), required_argument, &flag, 163},
3519         {SHRPX_OPT_TLS13_CIPHERS.c_str(), required_argument, &flag, 164},
3520         {SHRPX_OPT_TLS13_CLIENT_CIPHERS.c_str(), required_argument, &flag, 165},
3521         {SHRPX_OPT_NO_STRIP_INCOMING_EARLY_DATA.c_str(), no_argument, &flag,
3522          166},
3523         {nullptr, 0, nullptr, 0}};
3524
3525     int option_index = 0;
3526     int c = getopt_long(argc, argv, "DL:b:c:f:hkn:opsv", long_options,
3527                         &option_index);
3528     if (c == -1) {
3529       break;
3530     }
3531     switch (c) {
3532     case 'D':
3533       cmdcfgs.emplace_back(SHRPX_OPT_DAEMON, StringRef::from_lit("yes"));
3534       break;
3535     case 'L':
3536       cmdcfgs.emplace_back(SHRPX_OPT_LOG_LEVEL, StringRef{optarg});
3537       break;
3538     case 'b':
3539       cmdcfgs.emplace_back(SHRPX_OPT_BACKEND, StringRef{optarg});
3540       break;
3541     case 'c':
3542       cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_MAX_CONCURRENT_STREAMS,
3543                            StringRef{optarg});
3544       break;
3545     case 'f':
3546       cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND, StringRef{optarg});
3547       break;
3548     case 'h':
3549       print_help(std::cout);
3550       exit(EXIT_SUCCESS);
3551     case 'k':
3552       cmdcfgs.emplace_back(SHRPX_OPT_INSECURE, StringRef::from_lit("yes"));
3553       break;
3554     case 'n':
3555       cmdcfgs.emplace_back(SHRPX_OPT_WORKERS, StringRef{optarg});
3556       break;
3557     case 'o':
3558       cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_FRAME_DEBUG,
3559                            StringRef::from_lit("yes"));
3560       break;
3561     case 'p':
3562       cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_PROXY, StringRef::from_lit("yes"));
3563       break;
3564     case 's':
3565       cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_PROXY, StringRef::from_lit("yes"));
3566       break;
3567     case 'v':
3568       print_version(std::cout);
3569       exit(EXIT_SUCCESS);
3570     case '?':
3571       util::show_candidates(argv[optind - 1], long_options);
3572       exit(EXIT_FAILURE);
3573     case 0:
3574       switch (flag) {
3575       case 1:
3576         // --add-x-forwarded-for
3577         cmdcfgs.emplace_back(SHRPX_OPT_ADD_X_FORWARDED_FOR,
3578                              StringRef::from_lit("yes"));
3579         break;
3580       case 2:
3581         // --frontend-http2-read-timeout
3582         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT,
3583                              StringRef{optarg});
3584         break;
3585       case 3:
3586         // --frontend-read-timeout
3587         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_READ_TIMEOUT,
3588                              StringRef{optarg});
3589         break;
3590       case 4:
3591         // --frontend-write-timeout
3592         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_WRITE_TIMEOUT,
3593                              StringRef{optarg});
3594         break;
3595       case 5:
3596         // --backend-read-timeout
3597         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_READ_TIMEOUT, StringRef{optarg});
3598         break;
3599       case 6:
3600         // --backend-write-timeout
3601         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_WRITE_TIMEOUT,
3602                              StringRef{optarg});
3603         break;
3604       case 7:
3605         cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_FILE, StringRef{optarg});
3606         break;
3607       case 8:
3608         // --backend-keep-alive-timeout
3609         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT,
3610                              StringRef{optarg});
3611         break;
3612       case 9:
3613         // --frontend-http2-window-bits
3614         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS,
3615                              StringRef{optarg});
3616         break;
3617       case 10:
3618         cmdcfgs.emplace_back(SHRPX_OPT_PID_FILE, StringRef{optarg});
3619         break;
3620       case 11:
3621         cmdcfgs.emplace_back(SHRPX_OPT_USER, StringRef{optarg});
3622         break;
3623       case 12:
3624         // --conf
3625         mod_config()->conf_path =
3626             make_string_ref(mod_config()->balloc, StringRef{optarg});
3627         break;
3628       case 14:
3629         // --syslog-facility
3630         cmdcfgs.emplace_back(SHRPX_OPT_SYSLOG_FACILITY, StringRef{optarg});
3631         break;
3632       case 15:
3633         // --backlog
3634         cmdcfgs.emplace_back(SHRPX_OPT_BACKLOG, StringRef{optarg});
3635         break;
3636       case 16:
3637         // --ciphers
3638         cmdcfgs.emplace_back(SHRPX_OPT_CIPHERS, StringRef{optarg});
3639         break;
3640       case 17:
3641         // --client
3642         cmdcfgs.emplace_back(SHRPX_OPT_CLIENT, StringRef::from_lit("yes"));
3643         break;
3644       case 18:
3645         // --backend-http2-window-bits
3646         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS,
3647                              StringRef{optarg});
3648         break;
3649       case 19:
3650         // --cacert
3651         cmdcfgs.emplace_back(SHRPX_OPT_CACERT, StringRef{optarg});
3652         break;
3653       case 20:
3654         // --backend-ipv4
3655         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_IPV4,
3656                              StringRef::from_lit("yes"));
3657         break;
3658       case 21:
3659         // --backend-ipv6
3660         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_IPV6,
3661                              StringRef::from_lit("yes"));
3662         break;
3663       case 22:
3664         // --private-key-passwd-file
3665         cmdcfgs.emplace_back(SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE,
3666                              StringRef{optarg});
3667         break;
3668       case 23:
3669         // --no-via
3670         cmdcfgs.emplace_back(SHRPX_OPT_NO_VIA, StringRef::from_lit("yes"));
3671         break;
3672       case 24:
3673         // --subcert
3674         cmdcfgs.emplace_back(SHRPX_OPT_SUBCERT, StringRef{optarg});
3675         break;
3676       case 25:
3677         // --http2-bridge
3678         cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_BRIDGE,
3679                              StringRef::from_lit("yes"));
3680         break;
3681       case 26:
3682         // --backend-http-proxy-uri
3683         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP_PROXY_URI,
3684                              StringRef{optarg});
3685         break;
3686       case 27:
3687         // --backend-no-tls
3688         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_NO_TLS,
3689                              StringRef::from_lit("yes"));
3690         break;
3691       case 28:
3692         // --ocsp-startup
3693         cmdcfgs.emplace_back(SHRPX_OPT_OCSP_STARTUP,
3694                              StringRef::from_lit("yes"));
3695         break;
3696       case 29:
3697         // --frontend-no-tls
3698         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_NO_TLS,
3699                              StringRef::from_lit("yes"));
3700         break;
3701       case 30:
3702         // --no-verify-ocsp
3703         cmdcfgs.emplace_back(SHRPX_OPT_NO_VERIFY_OCSP,
3704                              StringRef::from_lit("yes"));
3705         break;
3706       case 31:
3707         // --backend-tls-sni-field
3708         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_TLS_SNI_FIELD,
3709                              StringRef{optarg});
3710         break;
3711       case 33:
3712         // --dh-param-file
3713         cmdcfgs.emplace_back(SHRPX_OPT_DH_PARAM_FILE, StringRef{optarg});
3714         break;
3715       case 34:
3716         // --read-rate
3717         cmdcfgs.emplace_back(SHRPX_OPT_READ_RATE, StringRef{optarg});
3718         break;
3719       case 35:
3720         // --read-burst
3721         cmdcfgs.emplace_back(SHRPX_OPT_READ_BURST, StringRef{optarg});
3722         break;
3723       case 36:
3724         // --write-rate
3725         cmdcfgs.emplace_back(SHRPX_OPT_WRITE_RATE, StringRef{optarg});
3726         break;
3727       case 37:
3728         // --write-burst
3729         cmdcfgs.emplace_back(SHRPX_OPT_WRITE_BURST, StringRef{optarg});
3730         break;
3731       case 38:
3732         // --npn-list
3733         cmdcfgs.emplace_back(SHRPX_OPT_NPN_LIST, StringRef{optarg});
3734         break;
3735       case 39:
3736         // --verify-client
3737         cmdcfgs.emplace_back(SHRPX_OPT_VERIFY_CLIENT,
3738                              StringRef::from_lit("yes"));
3739         break;
3740       case 40:
3741         // --verify-client-cacert
3742         cmdcfgs.emplace_back(SHRPX_OPT_VERIFY_CLIENT_CACERT, StringRef{optarg});
3743         break;
3744       case 41:
3745         // --client-private-key-file
3746         cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE,
3747                              StringRef{optarg});
3748         break;
3749       case 42:
3750         // --client-cert-file
3751         cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_CERT_FILE, StringRef{optarg});
3752         break;
3753       case 43:
3754         // --frontend-http2-dump-request-header
3755         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_DUMP_REQUEST_HEADER,
3756                              StringRef{optarg});
3757         break;
3758       case 44:
3759         // --frontend-http2-dump-response-header
3760         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER,
3761                              StringRef{optarg});
3762         break;
3763       case 45:
3764         // --http2-no-cookie-crumbling
3765         cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING,
3766                              StringRef::from_lit("yes"));
3767         break;
3768       case 46:
3769         // --frontend-http2-connection-window-bits
3770         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS,
3771                              StringRef{optarg});
3772         break;
3773       case 47:
3774         // --backend-http2-connection-window-bits
3775         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_BITS,
3776                              StringRef{optarg});
3777         break;
3778       case 48:
3779         // --tls-proto-list
3780         cmdcfgs.emplace_back(SHRPX_OPT_TLS_PROTO_LIST, StringRef{optarg});
3781         break;
3782       case 49:
3783         // --padding
3784         cmdcfgs.emplace_back(SHRPX_OPT_PADDING, StringRef{optarg});
3785         break;
3786       case 50:
3787         // --worker-read-rate
3788         cmdcfgs.emplace_back(SHRPX_OPT_WORKER_READ_RATE, StringRef{optarg});
3789         break;
3790       case 51:
3791         // --worker-read-burst
3792         cmdcfgs.emplace_back(SHRPX_OPT_WORKER_READ_BURST, StringRef{optarg});
3793         break;
3794       case 52:
3795         // --worker-write-rate
3796         cmdcfgs.emplace_back(SHRPX_OPT_WORKER_WRITE_RATE, StringRef{optarg});
3797         break;
3798       case 53:
3799         // --worker-write-burst
3800         cmdcfgs.emplace_back(SHRPX_OPT_WORKER_WRITE_BURST, StringRef{optarg});
3801         break;
3802       case 54:
3803         // --altsvc
3804         cmdcfgs.emplace_back(SHRPX_OPT_ALTSVC, StringRef{optarg});
3805         break;
3806       case 55:
3807         // --add-response-header
3808         cmdcfgs.emplace_back(SHRPX_OPT_ADD_RESPONSE_HEADER, StringRef{optarg});
3809         break;
3810       case 56:
3811         // --worker-frontend-connections
3812         cmdcfgs.emplace_back(SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS,
3813                              StringRef{optarg});
3814         break;
3815       case 57:
3816         // --accesslog-syslog
3817         cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_SYSLOG,
3818                              StringRef::from_lit("yes"));
3819         break;
3820       case 58:
3821         // --errorlog-file
3822         cmdcfgs.emplace_back(SHRPX_OPT_ERRORLOG_FILE, StringRef{optarg});
3823         break;
3824       case 59:
3825         // --errorlog-syslog
3826         cmdcfgs.emplace_back(SHRPX_OPT_ERRORLOG_SYSLOG,
3827                              StringRef::from_lit("yes"));
3828         break;
3829       case 60:
3830         // --stream-read-timeout
3831         cmdcfgs.emplace_back(SHRPX_OPT_STREAM_READ_TIMEOUT, StringRef{optarg});
3832         break;
3833       case 61:
3834         // --stream-write-timeout
3835         cmdcfgs.emplace_back(SHRPX_OPT_STREAM_WRITE_TIMEOUT, StringRef{optarg});
3836         break;
3837       case 62:
3838         // --no-location-rewrite
3839         cmdcfgs.emplace_back(SHRPX_OPT_NO_LOCATION_REWRITE,
3840                              StringRef::from_lit("yes"));
3841         break;
3842       case 63:
3843         // --backend-http1-connections-per-host
3844         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_HOST,
3845                              StringRef{optarg});
3846         break;
3847       case 64:
3848         // --listener-disable-timeout
3849         cmdcfgs.emplace_back(SHRPX_OPT_LISTENER_DISABLE_TIMEOUT,
3850                              StringRef{optarg});
3851         break;
3852       case 65:
3853         // --strip-incoming-x-forwarded-for
3854         cmdcfgs.emplace_back(SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR,
3855                              StringRef::from_lit("yes"));
3856         break;
3857       case 66:
3858         // --accesslog-format
3859         cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_FORMAT, StringRef{optarg});
3860         break;
3861       case 67:
3862         // --backend-http1-connections-per-frontend
3863         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND,
3864                              StringRef{optarg});
3865         break;
3866       case 68:
3867         // --tls-ticket-key-file
3868         cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_FILE, StringRef{optarg});
3869         break;
3870       case 69:
3871         // --rlimit-nofile
3872         cmdcfgs.emplace_back(SHRPX_OPT_RLIMIT_NOFILE, StringRef{optarg});
3873         break;
3874       case 71:
3875         // --backend-response-buffer
3876         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_RESPONSE_BUFFER,
3877                              StringRef{optarg});
3878         break;
3879       case 72:
3880         // --backend-request-buffer
3881         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_REQUEST_BUFFER,
3882                              StringRef{optarg});
3883         break;
3884       case 73:
3885         // --no-host-rewrite
3886         cmdcfgs.emplace_back(SHRPX_OPT_NO_HOST_REWRITE,
3887                              StringRef::from_lit("yes"));
3888         break;
3889       case 74:
3890         // --no-server-push
3891         cmdcfgs.emplace_back(SHRPX_OPT_NO_SERVER_PUSH,
3892                              StringRef::from_lit("yes"));
3893         break;
3894       case 76:
3895         // --backend-http2-connections-per-worker
3896         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_CONNECTIONS_PER_WORKER,
3897                              StringRef{optarg});
3898         break;
3899       case 77:
3900         // --fetch-ocsp-response-file
3901         cmdcfgs.emplace_back(SHRPX_OPT_FETCH_OCSP_RESPONSE_FILE,
3902                              StringRef{optarg});
3903         break;
3904       case 78:
3905         // --ocsp-update-interval
3906         cmdcfgs.emplace_back(SHRPX_OPT_OCSP_UPDATE_INTERVAL, StringRef{optarg});
3907         break;
3908       case 79:
3909         // --no-ocsp
3910         cmdcfgs.emplace_back(SHRPX_OPT_NO_OCSP, StringRef::from_lit("yes"));
3911         break;
3912       case 80:
3913         // --header-field-buffer
3914         cmdcfgs.emplace_back(SHRPX_OPT_HEADER_FIELD_BUFFER, StringRef{optarg});
3915         break;
3916       case 81:
3917         // --max-header-fields
3918         cmdcfgs.emplace_back(SHRPX_OPT_MAX_HEADER_FIELDS, StringRef{optarg});
3919         break;
3920       case 82:
3921         // --add-request-header
3922         cmdcfgs.emplace_back(SHRPX_OPT_ADD_REQUEST_HEADER, StringRef{optarg});
3923         break;
3924       case 83:
3925         // --include
3926         cmdcfgs.emplace_back(SHRPX_OPT_INCLUDE, StringRef{optarg});
3927         break;
3928       case 84:
3929         // --tls-ticket-key-cipher
3930         cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_CIPHER,
3931                              StringRef{optarg});
3932         break;
3933       case 85:
3934         // --host-rewrite
3935         cmdcfgs.emplace_back(SHRPX_OPT_HOST_REWRITE,
3936                              StringRef::from_lit("yes"));
3937         break;
3938       case 86:
3939         // --tls-session-cache-memcached
3940         cmdcfgs.emplace_back(SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED,
3941                              StringRef{optarg});
3942         break;
3943       case 87:
3944         // --tls-ticket-key-memcached
3945         cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED,
3946                              StringRef{optarg});
3947         break;
3948       case 88:
3949         // --tls-ticket-key-memcached-interval
3950         cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_INTERVAL,
3951                              StringRef{optarg});
3952         break;
3953       case 89:
3954         // --tls-ticket-key-memcached-max-retry
3955         cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_RETRY,
3956                              StringRef{optarg});
3957         break;
3958       case 90:
3959         // --tls-ticket-key-memcached-max-fail
3960         cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_MAX_FAIL,
3961                              StringRef{optarg});
3962         break;
3963       case 91:
3964         // --mruby-file
3965         cmdcfgs.emplace_back(SHRPX_OPT_MRUBY_FILE, StringRef{optarg});
3966         break;
3967       case 93:
3968         // --accept-proxy-protocol
3969         cmdcfgs.emplace_back(SHRPX_OPT_ACCEPT_PROXY_PROTOCOL,
3970                              StringRef::from_lit("yes"));
3971         break;
3972       case 94:
3973         // --fastopen
3974         cmdcfgs.emplace_back(SHRPX_OPT_FASTOPEN, StringRef{optarg});
3975         break;
3976       case 95:
3977         // --tls-dyn-rec-warmup-threshold
3978         cmdcfgs.emplace_back(SHRPX_OPT_TLS_DYN_REC_WARMUP_THRESHOLD,
3979                              StringRef{optarg});
3980         break;
3981       case 96:
3982         // --tls-dyn-rec-idle-timeout
3983         cmdcfgs.emplace_back(SHRPX_OPT_TLS_DYN_REC_IDLE_TIMEOUT,
3984                              StringRef{optarg});
3985         break;
3986       case 97:
3987         // --add-forwarded
3988         cmdcfgs.emplace_back(SHRPX_OPT_ADD_FORWARDED, StringRef{optarg});
3989         break;
3990       case 98:
3991         // --strip-incoming-forwarded
3992         cmdcfgs.emplace_back(SHRPX_OPT_STRIP_INCOMING_FORWARDED,
3993                              StringRef::from_lit("yes"));
3994         break;
3995       case 99:
3996         // --forwarded-by
3997         cmdcfgs.emplace_back(SHRPX_OPT_FORWARDED_BY, StringRef{optarg});
3998         break;
3999       case 100:
4000         // --forwarded-for
4001         cmdcfgs.emplace_back(SHRPX_OPT_FORWARDED_FOR, StringRef{optarg});
4002         break;
4003       case 101:
4004         // --response-header-field-buffer
4005         cmdcfgs.emplace_back(SHRPX_OPT_RESPONSE_HEADER_FIELD_BUFFER,
4006                              StringRef{optarg});
4007         break;
4008       case 102:
4009         // --max-response-header-fields
4010         cmdcfgs.emplace_back(SHRPX_OPT_MAX_RESPONSE_HEADER_FIELDS,
4011                              StringRef{optarg});
4012         break;
4013       case 103:
4014         // --no-http2-cipher-black-list
4015         cmdcfgs.emplace_back(SHRPX_OPT_NO_HTTP2_CIPHER_BLACK_LIST,
4016                              StringRef::from_lit("yes"));
4017         break;
4018       case 104:
4019         // --request-header-field-buffer
4020         cmdcfgs.emplace_back(SHRPX_OPT_REQUEST_HEADER_FIELD_BUFFER,
4021                              StringRef{optarg});
4022         break;
4023       case 105:
4024         // --max-request-header-fields
4025         cmdcfgs.emplace_back(SHRPX_OPT_MAX_REQUEST_HEADER_FIELDS,
4026                              StringRef{optarg});
4027         break;
4028       case 106:
4029         // --backend-http1-tls
4030         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP1_TLS,
4031                              StringRef::from_lit("yes"));
4032         break;
4033       case 108:
4034         // --tls-session-cache-memcached-tls
4035         cmdcfgs.emplace_back(SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_TLS,
4036                              StringRef::from_lit("yes"));
4037         break;
4038       case 109:
4039         // --tls-session-cache-memcached-cert-file
4040         cmdcfgs.emplace_back(SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE,
4041                              StringRef{optarg});
4042         break;
4043       case 110:
4044         // --tls-session-cache-memcached-private-key-file
4045         cmdcfgs.emplace_back(
4046             SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_PRIVATE_KEY_FILE,
4047             StringRef{optarg});
4048         break;
4049       case 111:
4050         // --tls-ticket-key-memcached-tls
4051         cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_TLS,
4052                              StringRef::from_lit("yes"));
4053         break;
4054       case 112:
4055         // --tls-ticket-key-memcached-cert-file
4056         cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_CERT_FILE,
4057                              StringRef{optarg});
4058         break;
4059       case 113:
4060         // --tls-ticket-key-memcached-private-key-file
4061         cmdcfgs.emplace_back(
4062             SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_PRIVATE_KEY_FILE,
4063             StringRef{optarg});
4064         break;
4065       case 114:
4066         // --tls-ticket-key-memcached-address-family
4067         cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_MEMCACHED_ADDRESS_FAMILY,
4068                              StringRef{optarg});
4069         break;
4070       case 115:
4071         // --tls-session-cache-memcached-address-family
4072         cmdcfgs.emplace_back(
4073             SHRPX_OPT_TLS_SESSION_CACHE_MEMCACHED_ADDRESS_FAMILY,
4074             StringRef{optarg});
4075         break;
4076       case 116:
4077         // --backend-address-family
4078         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_ADDRESS_FAMILY,
4079                              StringRef{optarg});
4080         break;
4081       case 117:
4082         // --frontend-http2-max-concurrent-streams
4083         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS,
4084                              StringRef{optarg});
4085         break;
4086       case 118:
4087         // --backend-http2-max-concurrent-streams
4088         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS,
4089                              StringRef{optarg});
4090         break;
4091       case 119:
4092         // --backend-connections-per-frontend
4093         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND,
4094                              StringRef{optarg});
4095         break;
4096       case 120:
4097         // --backend-tls
4098         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_TLS, StringRef::from_lit("yes"));
4099         break;
4100       case 121:
4101         // --backend-connections-per-host
4102         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST,
4103                              StringRef{optarg});
4104         break;
4105       case 122:
4106         // --error-page
4107         cmdcfgs.emplace_back(SHRPX_OPT_ERROR_PAGE, StringRef{optarg});
4108         break;
4109       case 123:
4110         // --no-kqueue
4111         cmdcfgs.emplace_back(SHRPX_OPT_NO_KQUEUE, StringRef::from_lit("yes"));
4112         break;
4113       case 124:
4114         // --frontend-http2-settings-timeout
4115         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_SETTINGS_TIMEOUT,
4116                              StringRef{optarg});
4117         break;
4118       case 125:
4119         // --backend-http2-settings-timeout
4120         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_SETTINGS_TIMEOUT,
4121                              StringRef{optarg});
4122         break;
4123       case 126:
4124         // --api-max-request-body
4125         cmdcfgs.emplace_back(SHRPX_OPT_API_MAX_REQUEST_BODY, StringRef{optarg});
4126         break;
4127       case 127:
4128         // --backend-max-backoff
4129         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_MAX_BACKOFF, StringRef{optarg});
4130         break;
4131       case 128:
4132         // --server-name
4133         cmdcfgs.emplace_back(SHRPX_OPT_SERVER_NAME, StringRef{optarg});
4134         break;
4135       case 129:
4136         // --no-server-rewrite
4137         cmdcfgs.emplace_back(SHRPX_OPT_NO_SERVER_REWRITE,
4138                              StringRef::from_lit("yes"));
4139         break;
4140       case 130:
4141         // --frontend-http2-optimize-write-buffer-size
4142         cmdcfgs.emplace_back(
4143             SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE,
4144             StringRef::from_lit("yes"));
4145         break;
4146       case 131:
4147         // --frontend-http2-optimize-window-size
4148         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE,
4149                              StringRef::from_lit("yes"));
4150         break;
4151       case 132:
4152         // --frontend-http2-window-size
4153         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_WINDOW_SIZE,
4154                              StringRef{optarg});
4155         break;
4156       case 133:
4157         // --frontend-http2-connection-window-size
4158         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE,
4159                              StringRef{optarg});
4160         break;
4161       case 134:
4162         // --backend-http2-window-size
4163         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_WINDOW_SIZE,
4164                              StringRef{optarg});
4165         break;
4166       case 135:
4167         // --backend-http2-connection-window-size
4168         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE,
4169                              StringRef{optarg});
4170         break;
4171       case 136:
4172         // --frontend-http2-encoder-dynamic-table-size
4173         cmdcfgs.emplace_back(
4174             SHRPX_OPT_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE,
4175             StringRef{optarg});
4176         break;
4177       case 137:
4178         // --frontend-http2-decoder-dynamic-table-size
4179         cmdcfgs.emplace_back(
4180             SHRPX_OPT_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE,
4181             StringRef{optarg});
4182         break;
4183       case 138:
4184         // --backend-http2-encoder-dynamic-table-size
4185         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE,
4186                              StringRef{optarg});
4187         break;
4188       case 139:
4189         // --backend-http2-decoder-dynamic-table-size
4190         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE,
4191                              StringRef{optarg});
4192         break;
4193       case 140:
4194         // --ecdh-curves
4195         cmdcfgs.emplace_back(SHRPX_OPT_ECDH_CURVES, StringRef{optarg});
4196         break;
4197       case 141:
4198         // --tls-sct-dir
4199         cmdcfgs.emplace_back(SHRPX_OPT_TLS_SCT_DIR, StringRef{optarg});
4200         break;
4201       case 142:
4202         // --backend-connect-timeout
4203         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_CONNECT_TIMEOUT,
4204                              StringRef{optarg});
4205         break;
4206       case 143:
4207         // --dns-cache-timeout
4208         cmdcfgs.emplace_back(SHRPX_OPT_DNS_CACHE_TIMEOUT, StringRef{optarg});
4209         break;
4210       case 144:
4211         // --dns-lookup-timeou
4212         cmdcfgs.emplace_back(SHRPX_OPT_DNS_LOOKUP_TIMEOUT, StringRef{optarg});
4213         break;
4214       case 145:
4215         // --dns-max-try
4216         cmdcfgs.emplace_back(SHRPX_OPT_DNS_MAX_TRY, StringRef{optarg});
4217         break;
4218       case 146:
4219         // --frontend-keep-alive-timeout
4220         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_KEEP_ALIVE_TIMEOUT,
4221                              StringRef{optarg});
4222         break;
4223       case 147:
4224         // --psk-secrets
4225         cmdcfgs.emplace_back(SHRPX_OPT_PSK_SECRETS, StringRef{optarg});
4226         break;
4227       case 148:
4228         // --client-psk-secrets
4229         cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_PSK_SECRETS, StringRef{optarg});
4230         break;
4231       case 149:
4232         // --client-no-http2-cipher-black-list
4233         cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST,
4234                              StringRef::from_lit("yes"));
4235         break;
4236       case 150:
4237         // --client-ciphers
4238         cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_CIPHERS, StringRef{optarg});
4239         break;
4240       case 151:
4241         // --accesslog-write-early
4242         cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_WRITE_EARLY,
4243                              StringRef::from_lit("yes"));
4244         break;
4245       case 152:
4246         // --tls-min-proto-version
4247         cmdcfgs.emplace_back(SHRPX_OPT_TLS_MIN_PROTO_VERSION,
4248                              StringRef{optarg});
4249         break;
4250       case 153:
4251         // --tls-max-proto-version
4252         cmdcfgs.emplace_back(SHRPX_OPT_TLS_MAX_PROTO_VERSION,
4253                              StringRef{optarg});
4254         break;
4255       case 154:
4256         // --redirect-https-port
4257         cmdcfgs.emplace_back(SHRPX_OPT_REDIRECT_HTTPS_PORT, StringRef{optarg});
4258         break;
4259       case 155:
4260         // --frontend-max-requests
4261         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_MAX_REQUESTS,
4262                              StringRef{optarg});
4263         break;
4264       case 156:
4265         // --single-thread
4266         cmdcfgs.emplace_back(SHRPX_OPT_SINGLE_THREAD,
4267                              StringRef::from_lit("yes"));
4268         break;
4269       case 157:
4270         // --no-add-x-forwarded-proto
4271         cmdcfgs.emplace_back(SHRPX_OPT_NO_ADD_X_FORWARDED_PROTO,
4272                              StringRef::from_lit("yes"));
4273         break;
4274       case 158:
4275         // --no-strip-incoming-x-forwarded-proto
4276         cmdcfgs.emplace_back(SHRPX_OPT_NO_STRIP_INCOMING_X_FORWARDED_PROTO,
4277                              StringRef::from_lit("yes"));
4278         break;
4279       case 159:
4280         // --single-process
4281         cmdcfgs.emplace_back(SHRPX_OPT_SINGLE_PROCESS,
4282                              StringRef::from_lit("yes"));
4283         break;
4284       case 160:
4285         // --verify-client-tolerate-expired
4286         cmdcfgs.emplace_back(SHRPX_OPT_VERIFY_CLIENT_TOLERATE_EXPIRED,
4287                              StringRef::from_lit("yes"));
4288         break;
4289       case 161:
4290         // --ignore-per-pattern-mruby-error
4291         cmdcfgs.emplace_back(SHRPX_OPT_IGNORE_PER_PATTERN_MRUBY_ERROR,
4292                              StringRef::from_lit("yes"));
4293         break;
4294       case 162:
4295         // --tls-no-postpone-early-data
4296         cmdcfgs.emplace_back(SHRPX_OPT_TLS_NO_POSTPONE_EARLY_DATA,
4297                              StringRef::from_lit("yes"));
4298         break;
4299       case 163:
4300         // --tls-max-early-data
4301         cmdcfgs.emplace_back(SHRPX_OPT_TLS_MAX_EARLY_DATA, StringRef{optarg});
4302         break;
4303       case 164:
4304         // --tls13-ciphers
4305         cmdcfgs.emplace_back(SHRPX_OPT_TLS13_CIPHERS, StringRef{optarg});
4306         break;
4307       case 165:
4308         // --tls13-client-ciphers
4309         cmdcfgs.emplace_back(SHRPX_OPT_TLS13_CLIENT_CIPHERS, StringRef{optarg});
4310         break;
4311       case 166:
4312         // --no-strip-incoming-early-data
4313         cmdcfgs.emplace_back(SHRPX_OPT_NO_STRIP_INCOMING_EARLY_DATA,
4314                              StringRef::from_lit("yes"));
4315         break;
4316       default:
4317         break;
4318       }
4319       break;
4320     default:
4321       break;
4322     }
4323   }
4324
4325   if (argc - optind >= 2) {
4326     cmdcfgs.emplace_back(SHRPX_OPT_PRIVATE_KEY_FILE, StringRef{argv[optind++]});
4327     cmdcfgs.emplace_back(SHRPX_OPT_CERTIFICATE_FILE, StringRef{argv[optind++]});
4328   }
4329
4330   rv = process_options(mod_config(), cmdcfgs);
4331   if (rv != 0) {
4332     return -1;
4333   }
4334
4335   if (event_loop() != 0) {
4336     return -1;
4337   }
4338
4339   LOG(NOTICE) << "Shutdown momentarily";
4340
4341   delete_log_config();
4342
4343   return 0;
4344 }
4345
4346 } // namespace shrpx
4347
4348 int main(int argc, char **argv) { return run_app(shrpx::main, argc, argv); }