Imported Upstream version 1.0.0
[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/stat.h>
29 #ifdef HAVE_SYS_SOCKET_H
30 #include <sys/socket.h>
31 #endif // HAVE_SYS_SOCKET_H
32 #include <sys/un.h>
33 #ifdef HAVE_NETDB_H
34 #include <netdb.h>
35 #endif // HAVE_NETDB_H
36 #include <signal.h>
37 #ifdef HAVE_NETINET_IN_H
38 #include <netinet/in.h>
39 #endif // HAVE_NETINET_IN_H
40 #include <netinet/tcp.h>
41 #ifdef HAVE_ARPA_INET_H
42 #include <arpa/inet.h>
43 #endif // HAVE_ARPA_INET_H
44 #ifdef HAVE_UNISTD_H
45 #include <unistd.h>
46 #endif // HAVE_UNISTD_H
47 #include <getopt.h>
48 #ifdef HAVE_SYSLOG_H
49 #include <syslog.h>
50 #endif // HAVE_SYSLOG_H
51 #include <signal.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 #include <grp.h>
60
61 #include <cinttypes>
62 #include <limits>
63 #include <cstdlib>
64 #include <iostream>
65 #include <fstream>
66 #include <vector>
67 #include <initializer_list>
68
69 #include <openssl/ssl.h>
70 #include <openssl/err.h>
71 #include <openssl/conf.h>
72 #include <openssl/rand.h>
73
74 #include <ev.h>
75
76 #include <nghttp2/nghttp2.h>
77
78 #include "shrpx_config.h"
79 #include "shrpx_connection_handler.h"
80 #include "shrpx_ssl.h"
81 #include "shrpx_log_config.h"
82 #include "shrpx_worker.h"
83 #include "shrpx_accept_handler.h"
84 #include "shrpx_http2_upstream.h"
85 #include "shrpx_http2_session.h"
86 #include "util.h"
87 #include "app_helper.h"
88 #include "ssl.h"
89 #include "template.h"
90
91 extern char **environ;
92
93 using namespace nghttp2;
94
95 namespace shrpx {
96
97 namespace {
98 const int REOPEN_LOG_SIGNAL = SIGUSR1;
99 const int EXEC_BINARY_SIGNAL = SIGUSR2;
100 const int GRACEFUL_SHUTDOWN_SIGNAL = SIGQUIT;
101 } // namespace
102
103 // Environment variables to tell new binary the listening socket's
104 // file descriptors.  They are not close-on-exec.
105 #define ENV_LISTENER4_FD "NGHTTPX_LISTENER4_FD"
106 #define ENV_LISTENER6_FD "NGHTTPX_LISTENER6_FD"
107
108 // Environment variable to tell new binary the port number the current
109 // binary is listening to.
110 #define ENV_PORT "NGHTTPX_PORT"
111
112 // Environment variable to tell new binary the listening socket's file
113 // descriptor if frontend listens UNIX domain socket.
114 #define ENV_UNIX_FD "NGHTTP2_UNIX_FD"
115 // Environment variable to tell new binary the UNIX domain socket
116 // path.
117 #define ENV_UNIX_PATH "NGHTTP2_UNIX_PATH"
118
119 namespace {
120 int resolve_hostname(sockaddr_union *addr, size_t *addrlen,
121                      const char *hostname, uint16_t port, int family) {
122   addrinfo hints;
123   int rv;
124
125   auto service = util::utos(port);
126   memset(&hints, 0, sizeof(addrinfo));
127
128   hints.ai_family = family;
129   hints.ai_socktype = SOCK_STREAM;
130 #ifdef AI_ADDRCONFIG
131   hints.ai_flags |= AI_ADDRCONFIG;
132 #endif // AI_ADDRCONFIG
133   addrinfo *res;
134
135   rv = getaddrinfo(hostname, service.c_str(), &hints, &res);
136   if (rv != 0) {
137     LOG(FATAL) << "Unable to resolve address for " << hostname << ": "
138                << gai_strerror(rv);
139     return -1;
140   }
141
142   char host[NI_MAXHOST];
143   rv = getnameinfo(res->ai_addr, res->ai_addrlen, host, sizeof(host), 0, 0,
144                    NI_NUMERICHOST);
145   if (rv != 0) {
146     LOG(FATAL) << "Address resolution for " << hostname
147                << " failed: " << gai_strerror(rv);
148
149     freeaddrinfo(res);
150
151     return -1;
152   }
153
154   if (LOG_ENABLED(INFO)) {
155     LOG(INFO) << "Address resolution for " << hostname
156               << " succeeded: " << host;
157   }
158
159   memcpy(addr, res->ai_addr, res->ai_addrlen);
160   *addrlen = res->ai_addrlen;
161   freeaddrinfo(res);
162   return 0;
163 }
164 } // namespace
165
166 namespace {
167 void close_env_fd(std::initializer_list<const char *> envnames) {
168   for (auto envname : envnames) {
169     auto envfd = getenv(envname);
170     if (!envfd) {
171       continue;
172     }
173     auto fd = strtol(envfd, nullptr, 10);
174     close(fd);
175   }
176 }
177 } // namespace
178
179 namespace {
180 std::unique_ptr<AcceptHandler>
181 create_unix_domain_acceptor(ConnectionHandler *handler) {
182   auto path = get_config()->host.get();
183   auto pathlen = strlen(path);
184   {
185     auto envfd = getenv(ENV_UNIX_FD);
186     auto envpath = getenv(ENV_UNIX_PATH);
187     if (envfd && envpath) {
188       auto fd = strtoul(envfd, nullptr, 10);
189
190       if (util::streq(envpath, path)) {
191         LOG(NOTICE) << "Listening on UNIX domain socket " << path;
192
193         return make_unique<AcceptHandler>(fd, handler);
194       }
195
196       LOG(WARN) << "UNIX domain socket path was changed between old binary ("
197                 << envpath << ") and new binary (" << path << ")";
198       close(fd);
199     }
200   }
201
202 #ifdef SOCK_NONBLOCK
203   auto fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
204   if (fd == -1) {
205     return nullptr;
206   }
207 #else  // !SOCK_NONBLOCK
208   auto fd = socket(AF_UNIX, SOCK_STREAM, 0);
209   if (fd == -1) {
210     return nullptr;
211   }
212   util::make_socket_nonblocking(fd);
213 #endif // !SOCK_NONBLOCK
214   int val = 1;
215   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val,
216                  static_cast<socklen_t>(sizeof(val))) == -1) {
217     close(fd);
218     return nullptr;
219   }
220
221   sockaddr_union addr;
222   addr.un.sun_family = AF_UNIX;
223   if (pathlen + 1 > sizeof(addr.un.sun_path)) {
224     LOG(FATAL) << "UNIX domain socket path " << path << " is too long > "
225                << sizeof(addr.un.sun_path);
226     close(fd);
227     return nullptr;
228   }
229   // copy path including terminal NULL
230   std::copy_n(path, pathlen + 1, addr.un.sun_path);
231
232   // unlink (remove) already existing UNIX domain socket path
233   unlink(path);
234
235   if (bind(fd, &addr.sa, sizeof(addr.un)) != 0) {
236     auto error = errno;
237     LOG(FATAL) << "Failed to bind UNIX domain socket, error=" << error;
238     close(fd);
239     return nullptr;
240   }
241
242   if (listen(fd, get_config()->backlog) != 0) {
243     auto error = errno;
244     LOG(FATAL) << "Failed to listen to UNIX domain socket, error=" << error;
245     close(fd);
246     return nullptr;
247   }
248
249   LOG(NOTICE) << "Listening on UNIX domain socket " << path;
250
251   return make_unique<AcceptHandler>(fd, handler);
252 }
253 } // namespace
254
255 namespace {
256 std::unique_ptr<AcceptHandler> create_acceptor(ConnectionHandler *handler,
257                                                int family) {
258   {
259     auto envfd =
260         getenv(family == AF_INET ? ENV_LISTENER4_FD : ENV_LISTENER6_FD);
261     auto envport = getenv(ENV_PORT);
262
263     if (envfd && envport) {
264       auto fd = strtoul(envfd, nullptr, 10);
265       auto port = strtoul(envport, nullptr, 10);
266
267       // Only do this iff NGHTTPX_PORT == get_config()->port.
268       // Otherwise, close fd, and create server socket as usual.
269
270       if (port == get_config()->port) {
271         LOG(NOTICE) << "Listening on port " << get_config()->port;
272
273         return make_unique<AcceptHandler>(fd, handler);
274       }
275
276       LOG(WARN) << "Port was changed between old binary (" << port
277                 << ") and new binary (" << get_config()->port << ")";
278       close(fd);
279     }
280   }
281
282   addrinfo hints;
283   int fd = -1;
284   int rv;
285
286   auto service = util::utos(get_config()->port);
287   memset(&hints, 0, sizeof(addrinfo));
288   hints.ai_family = family;
289   hints.ai_socktype = SOCK_STREAM;
290   hints.ai_flags = AI_PASSIVE;
291 #ifdef AI_ADDRCONFIG
292   hints.ai_flags |= AI_ADDRCONFIG;
293 #endif // AI_ADDRCONFIG
294
295   auto node = strcmp("*", get_config()->host.get()) == 0
296                   ? nullptr
297                   : get_config()->host.get();
298
299   addrinfo *res, *rp;
300   rv = getaddrinfo(node, service.c_str(), &hints, &res);
301   if (rv != 0) {
302     if (LOG_ENABLED(INFO)) {
303       LOG(INFO) << "Unable to get IPv" << (family == AF_INET ? "4" : "6")
304                 << " address for " << get_config()->host.get() << ": "
305                 << gai_strerror(rv);
306     }
307     return nullptr;
308   }
309   for (rp = res; rp; rp = rp->ai_next) {
310 #ifdef SOCK_NONBLOCK
311     fd =
312         socket(rp->ai_family, rp->ai_socktype | SOCK_NONBLOCK, rp->ai_protocol);
313     if (fd == -1) {
314       continue;
315     }
316 #else  // !SOCK_NONBLOCK
317     fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
318     if (fd == -1) {
319       continue;
320     }
321     util::make_socket_nonblocking(fd);
322 #endif // !SOCK_NONBLOCK
323     int val = 1;
324     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val,
325                    static_cast<socklen_t>(sizeof(val))) == -1) {
326       close(fd);
327       continue;
328     }
329
330 #ifdef IPV6_V6ONLY
331     if (family == AF_INET6) {
332       if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val,
333                      static_cast<socklen_t>(sizeof(val))) == -1) {
334         close(fd);
335         continue;
336       }
337     }
338 #endif // IPV6_V6ONLY
339
340 #ifdef TCP_DEFER_ACCEPT
341     val = 3;
342     if (setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &val,
343                    static_cast<socklen_t>(sizeof(val))) == -1) {
344       LOG(WARN) << "Failed to set TCP_DEFER_ACCEPT option to listener socket";
345     }
346 #endif // TCP_DEFER_ACCEPT
347
348     if (bind(fd, rp->ai_addr, rp->ai_addrlen) == 0 &&
349         listen(fd, get_config()->backlog) == 0) {
350       break;
351     }
352     close(fd);
353   }
354
355   if (!rp) {
356     LOG(WARN) << "Listening " << (family == AF_INET ? "IPv4" : "IPv6")
357               << " socket failed";
358
359     freeaddrinfo(res);
360
361     return nullptr;
362   }
363
364   char host[NI_MAXHOST];
365   rv = getnameinfo(rp->ai_addr, rp->ai_addrlen, host, sizeof(host), nullptr, 0,
366                    NI_NUMERICHOST);
367
368   freeaddrinfo(res);
369
370   if (rv != 0) {
371     LOG(WARN) << gai_strerror(rv);
372
373     close(fd);
374
375     return nullptr;
376   }
377
378   LOG(NOTICE) << "Listening on " << host << ", port " << get_config()->port;
379
380   return make_unique<AcceptHandler>(fd, handler);
381 }
382 } // namespace
383
384 namespace {
385 void drop_privileges() {
386   if (getuid() == 0 && get_config()->uid != 0) {
387     if (initgroups(get_config()->user.get(), get_config()->gid) != 0) {
388       auto error = errno;
389       LOG(FATAL) << "Could not change supplementary groups: "
390                  << strerror(error);
391       exit(EXIT_FAILURE);
392     }
393     if (setgid(get_config()->gid) != 0) {
394       auto error = errno;
395       LOG(FATAL) << "Could not change gid: " << strerror(error);
396       exit(EXIT_FAILURE);
397     }
398     if (setuid(get_config()->uid) != 0) {
399       auto error = errno;
400       LOG(FATAL) << "Could not change uid: " << strerror(error);
401       exit(EXIT_FAILURE);
402     }
403     if (setuid(0) != -1) {
404       LOG(FATAL) << "Still have root privileges?";
405       exit(EXIT_FAILURE);
406     }
407   }
408 }
409 } // namespace
410
411 namespace {
412 void save_pid() {
413   std::ofstream out(get_config()->pid_file.get(), std::ios::binary);
414   out << get_config()->pid << "\n";
415   out.close();
416   if (!out) {
417     LOG(ERROR) << "Could not save PID to file " << get_config()->pid_file.get();
418     exit(EXIT_FAILURE);
419   }
420
421   if (get_config()->uid != 0) {
422     if (chown(get_config()->pid_file.get(), get_config()->uid,
423               get_config()->gid) == -1) {
424       auto error = errno;
425       LOG(WARN) << "Changing owner of pid file " << get_config()->pid_file.get()
426                 << " failed: " << strerror(error);
427     }
428   }
429 }
430 } // namespace
431
432 namespace {
433 void reopen_log_signal_cb(struct ev_loop *loop, ev_signal *w, int revents) {
434   auto conn_handler = static_cast<ConnectionHandler *>(w->data);
435
436   LOG(NOTICE) << "Reopening log files: main";
437
438   (void)reopen_log_files();
439   redirect_stderr_to_errorlog();
440
441   if (get_config()->num_worker > 1) {
442     conn_handler->worker_reopen_log_files();
443   }
444 }
445 } // namespace
446
447 namespace {
448 void exec_binary_signal_cb(struct ev_loop *loop, ev_signal *w, int revents) {
449   auto conn_handler = static_cast<ConnectionHandler *>(w->data);
450
451   LOG(NOTICE) << "Executing new binary";
452
453   auto pid = fork();
454
455   if (pid == -1) {
456     auto error = errno;
457     LOG(ERROR) << "fork() failed errno=" << error;
458     return;
459   }
460
461   if (pid != 0) {
462     return;
463   }
464
465   auto exec_path = util::get_exec_path(get_config()->argc, get_config()->argv,
466                                        get_config()->cwd);
467
468   if (!exec_path) {
469     LOG(ERROR) << "Could not resolve the executable path";
470     return;
471   }
472
473   auto argv = make_unique<char *[]>(get_config()->argc + 1);
474
475   argv[0] = exec_path;
476   for (int i = 1; i < get_config()->argc; ++i) {
477     argv[i] = strdup(get_config()->argv[i]);
478   }
479   argv[get_config()->argc] = nullptr;
480
481   size_t envlen = 0;
482   for (char **p = environ; *p; ++p, ++envlen)
483     ;
484   // 3 for missing (fd4, fd6 and port) or (unix fd and unix path)
485   auto envp = make_unique<char *[]>(envlen + 3 + 1);
486   size_t envidx = 0;
487
488   if (get_config()->host_unix) {
489     auto acceptor = conn_handler->get_acceptor();
490     std::string fd = ENV_UNIX_FD "=";
491     fd += util::utos(acceptor->get_fd());
492     envp[envidx++] = strdup(fd.c_str());
493
494     std::string path = ENV_UNIX_PATH "=";
495     path += get_config()->host.get();
496     envp[envidx++] = strdup(path.c_str());
497   } else {
498     auto acceptor4 = conn_handler->get_acceptor();
499     if (acceptor4) {
500       std::string fd4 = ENV_LISTENER4_FD "=";
501       fd4 += util::utos(acceptor4->get_fd());
502       envp[envidx++] = strdup(fd4.c_str());
503     }
504
505     auto acceptor6 = conn_handler->get_acceptor6();
506     if (acceptor6) {
507       std::string fd6 = ENV_LISTENER6_FD "=";
508       fd6 += util::utos(acceptor6->get_fd());
509       envp[envidx++] = strdup(fd6.c_str());
510     }
511
512     std::string port = ENV_PORT "=";
513     port += util::utos(get_config()->port);
514     envp[envidx++] = strdup(port.c_str());
515   }
516
517   for (size_t i = 0; i < envlen; ++i) {
518     if (util::startsWith(environ[i], ENV_LISTENER4_FD) ||
519         util::startsWith(environ[i], ENV_LISTENER6_FD) ||
520         util::startsWith(environ[i], ENV_PORT) ||
521         util::startsWith(environ[i], ENV_UNIX_FD) ||
522         util::startsWith(environ[i], ENV_UNIX_PATH)) {
523       continue;
524     }
525
526     envp[envidx++] = environ[i];
527   }
528
529   envp[envidx++] = nullptr;
530
531   if (LOG_ENABLED(INFO)) {
532     LOG(INFO) << "cmdline";
533     for (int i = 0; argv[i]; ++i) {
534       LOG(INFO) << i << ": " << argv[i];
535     }
536     LOG(INFO) << "environ";
537     for (int i = 0; envp[i]; ++i) {
538       LOG(INFO) << i << ": " << envp[i];
539     }
540   }
541
542   if (execve(argv[0], argv.get(), envp.get()) == -1) {
543     auto error = errno;
544     LOG(ERROR) << "execve failed: errno=" << error;
545     _Exit(EXIT_FAILURE);
546   }
547 }
548 } // namespace
549
550 namespace {
551 void graceful_shutdown_signal_cb(struct ev_loop *loop, ev_signal *w,
552                                  int revents) {
553   auto conn_handler = static_cast<ConnectionHandler *>(w->data);
554
555   if (conn_handler->get_graceful_shutdown()) {
556     return;
557   }
558
559   LOG(NOTICE) << "Graceful shutdown signal received";
560
561   conn_handler->set_graceful_shutdown(true);
562
563   conn_handler->disable_acceptor();
564
565   // After disabling accepting new connection, disptach incoming
566   // connection in backlog.
567
568   conn_handler->accept_pending_connection();
569
570   conn_handler->graceful_shutdown_worker();
571
572   if (get_config()->num_worker == 1 &&
573       conn_handler->get_single_worker()->get_worker_stat()->num_connections >
574           0) {
575     return;
576   }
577
578   // We have accepted all pending connections.  Shutdown main event
579   // loop.
580   ev_break(loop);
581 }
582 } // namespace
583
584 namespace {
585 void renew_ticket_key_cb(struct ev_loop *loop, ev_timer *w, int revents) {
586   auto conn_handler = static_cast<ConnectionHandler *>(w->data);
587   const auto &old_ticket_keys = conn_handler->get_ticket_keys();
588
589   auto ticket_keys = std::make_shared<TicketKeys>();
590   LOG(NOTICE) << "Renew ticket keys: main";
591
592   // We store at most 2 ticket keys
593   if (old_ticket_keys) {
594     auto &old_keys = old_ticket_keys->keys;
595     auto &new_keys = ticket_keys->keys;
596
597     assert(!old_keys.empty());
598
599     new_keys.resize(2);
600     new_keys[1] = old_keys[0];
601   } else {
602     ticket_keys->keys.resize(1);
603   }
604
605   if (RAND_bytes(reinterpret_cast<unsigned char *>(&ticket_keys->keys[0]),
606                  sizeof(ticket_keys->keys[0])) == 0) {
607     if (LOG_ENABLED(INFO)) {
608       LOG(INFO) << "failed to renew ticket key";
609     }
610     return;
611   }
612
613   if (LOG_ENABLED(INFO)) {
614     LOG(INFO) << "ticket keys generation done";
615     for (auto &key : ticket_keys->keys) {
616       LOG(INFO) << "name: " << util::format_hex(key.name, sizeof(key.name));
617     }
618   }
619
620   conn_handler->set_ticket_keys(ticket_keys);
621   conn_handler->worker_renew_ticket_keys(ticket_keys);
622 }
623 } // namespace
624
625 namespace {
626 int event_loop() {
627   auto loop = EV_DEFAULT;
628
629   auto conn_handler = make_unique<ConnectionHandler>(loop);
630   if (get_config()->daemon) {
631     if (daemon(0, 0) == -1) {
632       auto error = errno;
633       LOG(FATAL) << "Failed to daemonize: " << strerror(error);
634       exit(EXIT_FAILURE);
635     }
636
637     // We get new PID after successful daemon().
638     mod_config()->pid = getpid();
639
640     // daemon redirects stderr file descriptor to /dev/null, so we
641     // need this.
642     redirect_stderr_to_errorlog();
643   }
644
645   if (get_config()->pid_file) {
646     save_pid();
647   }
648
649   if (get_config()->host_unix) {
650     close_env_fd({ENV_LISTENER4_FD, ENV_LISTENER6_FD});
651     auto acceptor = create_unix_domain_acceptor(conn_handler.get());
652     if (!acceptor) {
653       LOG(FATAL) << "Failed to listen on UNIX domain socket "
654                  << get_config()->host.get();
655       exit(EXIT_FAILURE);
656     }
657
658     conn_handler->set_acceptor(std::move(acceptor));
659   } else {
660     close_env_fd({ENV_UNIX_FD});
661     auto acceptor6 = create_acceptor(conn_handler.get(), AF_INET6);
662     auto acceptor4 = create_acceptor(conn_handler.get(), AF_INET);
663     if (!acceptor6 && !acceptor4) {
664       LOG(FATAL) << "Failed to listen on address " << get_config()->host.get()
665                  << ", port " << get_config()->port;
666       exit(EXIT_FAILURE);
667     }
668
669     conn_handler->set_acceptor(std::move(acceptor4));
670     conn_handler->set_acceptor6(std::move(acceptor6));
671   }
672
673   ev_timer renew_ticket_key_timer;
674   if (!get_config()->upstream_no_tls) {
675     bool auto_tls_ticket_key = true;
676     if (!get_config()->tls_ticket_key_files.empty()) {
677       auto ticket_keys =
678           read_tls_ticket_key_file(get_config()->tls_ticket_key_files);
679       if (!ticket_keys) {
680         LOG(WARN) << "Use internal session ticket key generator";
681       } else {
682         conn_handler->set_ticket_keys(std::move(ticket_keys));
683         auto_tls_ticket_key = false;
684       }
685     }
686     if (auto_tls_ticket_key) {
687       // Renew ticket key every 12hrs
688       ev_timer_init(&renew_ticket_key_timer, renew_ticket_key_cb, 0.,
689                     12 * 3600.);
690       renew_ticket_key_timer.data = conn_handler.get();
691       ev_timer_again(loop, &renew_ticket_key_timer);
692
693       // Generate first session ticket key before running workers.
694       renew_ticket_key_cb(loop, &renew_ticket_key_timer, 0);
695     }
696   }
697
698   // ListenHandler loads private key, and we listen on a priveleged port.
699   // After that, we drop the root privileges if needed.
700   drop_privileges();
701
702 #ifndef NOTHREADS
703   int rv;
704   sigset_t signals;
705   sigemptyset(&signals);
706   sigaddset(&signals, REOPEN_LOG_SIGNAL);
707   sigaddset(&signals, EXEC_BINARY_SIGNAL);
708   sigaddset(&signals, GRACEFUL_SHUTDOWN_SIGNAL);
709   rv = pthread_sigmask(SIG_BLOCK, &signals, nullptr);
710   if (rv != 0) {
711     LOG(ERROR) << "Blocking signals failed: " << strerror(rv);
712   }
713 #endif // !NOTHREADS
714
715   if (get_config()->num_worker == 1) {
716     conn_handler->create_single_worker();
717   } else {
718     conn_handler->create_worker_thread(get_config()->num_worker);
719   }
720
721 #ifndef NOTHREADS
722   rv = pthread_sigmask(SIG_UNBLOCK, &signals, nullptr);
723   if (rv != 0) {
724     LOG(ERROR) << "Unblocking signals failed: " << strerror(rv);
725   }
726 #endif // !NOTHREADS
727
728   ev_signal reopen_log_sig;
729   ev_signal_init(&reopen_log_sig, reopen_log_signal_cb, REOPEN_LOG_SIGNAL);
730   reopen_log_sig.data = conn_handler.get();
731   ev_signal_start(loop, &reopen_log_sig);
732
733   ev_signal exec_bin_sig;
734   ev_signal_init(&exec_bin_sig, exec_binary_signal_cb, EXEC_BINARY_SIGNAL);
735   exec_bin_sig.data = conn_handler.get();
736   ev_signal_start(loop, &exec_bin_sig);
737
738   ev_signal graceful_shutdown_sig;
739   ev_signal_init(&graceful_shutdown_sig, graceful_shutdown_signal_cb,
740                  GRACEFUL_SHUTDOWN_SIGNAL);
741   graceful_shutdown_sig.data = conn_handler.get();
742   ev_signal_start(loop, &graceful_shutdown_sig);
743
744   if (!get_config()->upstream_no_tls && !get_config()->no_ocsp) {
745     conn_handler->proceed_next_cert_ocsp();
746   }
747
748   if (LOG_ENABLED(INFO)) {
749     LOG(INFO) << "Entering event loop";
750   }
751
752   ev_run(loop, 0);
753
754   conn_handler->join_worker();
755   conn_handler->cancel_ocsp_update();
756
757   return 0;
758 }
759 } // namespace
760
761 namespace {
762 // Returns true if regular file or symbolic link |path| exists.
763 bool conf_exists(const char *path) {
764   struct stat buf;
765   int rv = stat(path, &buf);
766   return rv == 0 && (buf.st_mode & (S_IFREG | S_IFLNK));
767 }
768 } // namespace
769
770 namespace {
771 const char *DEFAULT_NPN_LIST = "h2,h2-16,h2-14,"
772 #ifdef HAVE_SPDYLAY
773                                "spdy/3.1,"
774 #endif // HAVE_SPDYLAY
775                                "http/1.1";
776 } // namespace
777
778 namespace {
779 const char *DEFAULT_TLS_PROTO_LIST = "TLSv1.2,TLSv1.1";
780 } // namespace
781
782 namespace {
783 const char *DEFAULT_ACCESSLOG_FORMAT = "$remote_addr - - [$time_local] "
784                                        "\"$request\" $status $body_bytes_sent "
785                                        "\"$http_referer\" \"$http_user_agent\"";
786 } // namespace
787
788 namespace {
789 auto DEFAULT_DOWNSTREAM_HOST = "127.0.0.1";
790 int16_t DEFAULT_DOWNSTREAM_PORT = 80;
791 } // namespace;
792
793 namespace {
794 void fill_default_config() {
795   memset(mod_config(), 0, sizeof(*mod_config()));
796
797   mod_config()->verbose = false;
798   mod_config()->daemon = false;
799
800   mod_config()->server_name = "nghttpx nghttp2/" NGHTTP2_VERSION;
801   mod_config()->host = strcopy("*");
802   mod_config()->port = 3000;
803   mod_config()->private_key_file = nullptr;
804   mod_config()->private_key_passwd = nullptr;
805   mod_config()->cert_file = nullptr;
806
807   // Read timeout for HTTP2 upstream connection
808   mod_config()->http2_upstream_read_timeout = 180.;
809
810   // Read timeout for non-HTTP2 upstream connection
811   mod_config()->upstream_read_timeout = 180.;
812
813   // Write timeout for HTTP2/non-HTTP2 upstream connection
814   mod_config()->upstream_write_timeout = 30.;
815
816   // Read/Write timeouts for downstream connection
817   mod_config()->downstream_read_timeout = 180.;
818   mod_config()->downstream_write_timeout = 30.;
819
820   // Read timeout for HTTP/2 stream
821   mod_config()->stream_read_timeout = 0.;
822
823   // Write timeout for HTTP/2 stream
824   mod_config()->stream_write_timeout = 0.;
825
826   // Timeout for pooled (idle) connections
827   mod_config()->downstream_idle_read_timeout = 2.;
828
829   // window bits for HTTP/2 and SPDY upstream/downstream connection
830   // per stream. 2**16-1 = 64KiB-1, which is HTTP/2 default. Please
831   // note that SPDY/3 default is 64KiB.
832   mod_config()->http2_upstream_window_bits = 16;
833   mod_config()->http2_downstream_window_bits = 16;
834
835   // HTTP/2 SPDY/3.1 has connection-level flow control. The default
836   // window size for HTTP/2 is 64KiB - 1. SPDY/3's default is 64KiB
837   mod_config()->http2_upstream_connection_window_bits = 16;
838   mod_config()->http2_downstream_connection_window_bits = 16;
839
840   mod_config()->upstream_no_tls = false;
841   mod_config()->downstream_no_tls = false;
842
843   mod_config()->num_worker = 1;
844   mod_config()->http2_max_concurrent_streams = 100;
845   mod_config()->add_x_forwarded_for = false;
846   mod_config()->strip_incoming_x_forwarded_for = false;
847   mod_config()->no_via = false;
848   mod_config()->accesslog_file = nullptr;
849   mod_config()->accesslog_syslog = false;
850   mod_config()->accesslog_format = parse_log_format(DEFAULT_ACCESSLOG_FORMAT);
851 #if defined(__ANDROID__) || defined(ANDROID)
852   // Android does not have /dev/stderr.  Use /proc/self/fd/2 instead.
853   mod_config()->errorlog_file = strcopy("/proc/self/fd/2");
854 #else  // !__ANDROID__ && ANDROID
855   mod_config()->errorlog_file = strcopy("/dev/stderr");
856 #endif // !__ANDROID__ && ANDROID
857   mod_config()->errorlog_syslog = false;
858   mod_config()->conf_path = strcopy("/etc/nghttpx/nghttpx.conf");
859   mod_config()->syslog_facility = LOG_DAEMON;
860   // Default accept() backlog
861   mod_config()->backlog = 512;
862   mod_config()->ciphers = nullptr;
863   mod_config()->http2_proxy = false;
864   mod_config()->http2_bridge = false;
865   mod_config()->client_proxy = false;
866   mod_config()->client = false;
867   mod_config()->client_mode = false;
868   mod_config()->insecure = false;
869   mod_config()->cacert = nullptr;
870   mod_config()->pid_file = nullptr;
871   mod_config()->user = nullptr;
872   mod_config()->uid = 0;
873   mod_config()->gid = 0;
874   mod_config()->pid = getpid();
875   mod_config()->backend_ipv4 = false;
876   mod_config()->backend_ipv6 = false;
877   mod_config()->downstream_http_proxy_userinfo = nullptr;
878   mod_config()->downstream_http_proxy_host = nullptr;
879   mod_config()->downstream_http_proxy_port = 0;
880   mod_config()->downstream_http_proxy_addrlen = 0;
881   mod_config()->read_rate = 0;
882   mod_config()->read_burst = 0;
883   mod_config()->write_rate = 0;
884   mod_config()->write_burst = 0;
885   mod_config()->worker_read_rate = 0;
886   mod_config()->worker_read_burst = 0;
887   mod_config()->worker_write_rate = 0;
888   mod_config()->worker_write_burst = 0;
889   mod_config()->verify_client = false;
890   mod_config()->verify_client_cacert = nullptr;
891   mod_config()->client_private_key_file = nullptr;
892   mod_config()->client_cert_file = nullptr;
893   mod_config()->http2_upstream_dump_request_header = nullptr;
894   mod_config()->http2_upstream_dump_response_header = nullptr;
895   mod_config()->http2_no_cookie_crumbling = false;
896   mod_config()->upstream_frame_debug = false;
897   mod_config()->padding = 0;
898   mod_config()->worker_frontend_connections = 0;
899
900   mod_config()->http2_upstream_callbacks = create_http2_upstream_callbacks();
901   mod_config()->http2_downstream_callbacks =
902       create_http2_downstream_callbacks();
903
904   nghttp2_option_new(&mod_config()->http2_option);
905   nghttp2_option_set_no_auto_window_update(get_config()->http2_option, 1);
906   nghttp2_option_set_no_recv_client_magic(get_config()->http2_option, 1);
907
908   nghttp2_option_new(&mod_config()->http2_client_option);
909   nghttp2_option_set_no_auto_window_update(get_config()->http2_client_option,
910                                            1);
911   nghttp2_option_set_peer_max_concurrent_streams(
912       get_config()->http2_client_option, 100);
913
914   mod_config()->tls_proto_mask = 0;
915   mod_config()->no_location_rewrite = false;
916   mod_config()->no_host_rewrite = false;
917   mod_config()->argc = 0;
918   mod_config()->argv = nullptr;
919   mod_config()->downstream_connections_per_host = 8;
920   mod_config()->downstream_connections_per_frontend = 0;
921   mod_config()->listener_disable_timeout = 0.;
922   mod_config()->downstream_request_buffer_size = 16 * 1024;
923   mod_config()->downstream_response_buffer_size = 16 * 1024;
924   mod_config()->no_server_push = false;
925   mod_config()->host_unix = false;
926   mod_config()->http2_downstream_connections_per_worker = 0;
927   // ocsp update interval = 14400 secs = 4 hours, borrowed from h2o
928   mod_config()->ocsp_update_interval = 14400.;
929   mod_config()->fetch_ocsp_response_file =
930       strcopy(PKGDATADIR "/fetch-ocsp-response");
931   mod_config()->no_ocsp = false;
932   mod_config()->header_field_buffer = 64 * 1024;
933   mod_config()->max_header_fields = 100;
934 }
935 } // namespace
936
937 namespace {
938 void print_version(std::ostream &out) {
939   out << get_config()->server_name << std::endl;
940 }
941 } // namespace
942
943 namespace {
944 void print_usage(std::ostream &out) {
945   out << R"(Usage: nghttpx [OPTIONS]... [<PRIVATE_KEY> <CERT>]
946 A reverse proxy for HTTP/2, HTTP/1 and SPDY.)" << std::endl;
947 }
948 } // namespace
949
950 namespace {
951 void print_help(std::ostream &out) {
952   print_usage(out);
953   out << R"(
954   <PRIVATE_KEY>
955               Set path  to server's private key.   Required unless -p,
956               --client or --frontend-no-tls are given.
957   <CERT>      Set path  to server's certificate.  Required  unless -p,
958               --client or  --frontend-no-tls are given.  To  make OCSP
959               stapling work, this must be absolute path.
960
961 Options:
962   The options are categorized into several groups.
963
964 Connections:
965   -b, --backend=<HOST,PORT>
966               Set  backend  host  and   port.   The  multiple  backend
967               addresses are  accepted by repeating this  option.  UNIX
968               domain socket  can be  specified by prefixing  path name
969               with "unix:" (e.g., unix:/var/run/backend.sock)
970               Default: )" << DEFAULT_DOWNSTREAM_HOST << ","
971       << DEFAULT_DOWNSTREAM_PORT << R"(
972   -f, --frontend=<HOST,PORT>
973               Set  frontend  host and  port.   If  <HOST> is  '*',  it
974               assumes  all addresses  including  both  IPv4 and  IPv6.
975               UNIX domain  socket can  be specified by  prefixing path
976               name with "unix:" (e.g., unix:/var/run/nghttpx.sock)
977               Default: )" << get_config()->host.get() << ","
978       << get_config()->port << R"(
979   --backlog=<N>
980               Set listen backlog size.
981               Default: )" << get_config()->backlog << R"(
982   --backend-ipv4
983               Resolve backend hostname to IPv4 address only.
984   --backend-ipv6
985               Resolve backend hostname to IPv6 address only.
986   --backend-http-proxy-uri=<URI>
987               Specify      proxy       URI      in       the      form
988               http://[<USER>:<PASS>@]<PROXY>:<PORT>.    If   a   proxy
989               requires  authentication,  specify  <USER>  and  <PASS>.
990               Note that  they must be properly  percent-encoded.  This
991               proxy  is used  when the  backend connection  is HTTP/2.
992               First,  make  a CONNECT  request  to  the proxy  and  it
993               connects  to the  backend  on behalf  of nghttpx.   This
994               forms  tunnel.   After  that, nghttpx  performs  SSL/TLS
995               handshake with  the downstream through the  tunnel.  The
996               timeouts when connecting and  making CONNECT request can
997               be     specified    by     --backend-read-timeout    and
998               --backend-write-timeout options.
999
1000 Performance:
1001   -n, --workers=<N>
1002               Set the number of worker threads.
1003               Default: )" << get_config()->num_worker << R"(
1004   --read-rate=<SIZE>
1005               Set maximum  average read  rate on  frontend connection.
1006               Setting 0 to this option means read rate is unlimited.
1007               Default: )" << get_config()->read_rate << R"(
1008   --read-burst=<SIZE>
1009               Set  maximum read  burst  size  on frontend  connection.
1010               Setting  0  to this  option  means  read burst  size  is
1011               unlimited.
1012               Default: )" << get_config()->read_burst << R"(
1013   --write-rate=<SIZE>
1014               Set maximum  average write rate on  frontend connection.
1015               Setting 0 to this option means write rate is unlimited.
1016               Default: )" << get_config()->write_rate << R"(
1017   --write-burst=<SIZE>
1018               Set  maximum write  burst size  on frontend  connection.
1019               Setting  0 to  this  option means  write  burst size  is
1020               unlimited.
1021               Default: )" << get_config()->write_burst << R"(
1022   --worker-read-rate=<SIZE>
1023               Set maximum average read rate on frontend connection per
1024               worker.  Setting  0 to  this option  means read  rate is
1025               unlimited.  Not implemented yet.
1026               Default: )" << get_config()->worker_read_rate << R"(
1027   --worker-read-burst=<SIZE>
1028               Set maximum  read burst size on  frontend connection per
1029               worker.  Setting 0 to this  option means read burst size
1030               is unlimited.  Not implemented yet.
1031               Default: )" << get_config()->worker_read_burst << R"(
1032   --worker-write-rate=<SIZE>
1033               Set maximum  average write  rate on  frontend connection
1034               per worker.  Setting  0 to this option  means write rate
1035               is unlimited.  Not implemented yet.
1036               Default: )" << get_config()->worker_write_rate << R"(
1037   --worker-write-burst=<SIZE>
1038               Set maximum write burst  size on frontend connection per
1039               worker.  Setting 0 to this option means write burst size
1040               is unlimited.  Not implemented yet.
1041               Default: )" << get_config()->worker_write_burst << R"(
1042   --worker-frontend-connections=<N>
1043               Set maximum number  of simultaneous connections frontend
1044               accepts.  Setting 0 means unlimited.
1045               Default: )" << get_config()->worker_frontend_connections << R"(
1046   --backend-http2-connections-per-worker=<N>
1047               Set  maximum number  of HTTP/2  connections per  worker.
1048               The  default  value is  0,  which  means the  number  of
1049               backend addresses specified by -b option.
1050   --backend-http1-connections-per-host=<N>
1051               Set   maximum  number   of  backend   concurrent  HTTP/1
1052               connections per host.  This option is meaningful when -s
1053               option is used.  To limit  the number of connections per
1054               frontend        for       default        mode,       use
1055               --backend-http1-connections-per-frontend.
1056               Default: )" << get_config()->downstream_connections_per_host
1057       << R"(
1058   --backend-http1-connections-per-frontend=<N>
1059               Set   maximum  number   of  backend   concurrent  HTTP/1
1060               connections per frontend.  This  option is only used for
1061               default mode.   0 means unlimited.  To  limit the number
1062               of connections  per host for  HTTP/2 or SPDY  proxy mode
1063               (-s option), use --backend-http1-connections-per-host.
1064               Default: )" << get_config()->downstream_connections_per_frontend
1065       << R"(
1066   --rlimit-nofile=<N>
1067               Set maximum number of open files (RLIMIT_NOFILE) to <N>.
1068               If 0 is given, nghttpx does not set the limit.
1069               Default: )" << get_config()->rlimit_nofile << R"(
1070   --backend-request-buffer=<SIZE>
1071               Set buffer size used to store backend request.
1072               Default: )"
1073       << util::utos_with_unit(get_config()->downstream_request_buffer_size)
1074       << R"(
1075   --backend-response-buffer=<SIZE>
1076               Set buffer size used to store backend response.
1077               Default: )"
1078       << util::utos_with_unit(get_config()->downstream_response_buffer_size)
1079       << R"(
1080
1081 Timeout:
1082   --frontend-http2-read-timeout=<DURATION>
1083               Specify  read  timeout  for  HTTP/2  and  SPDY  frontend
1084               connection.
1085               Default: )"
1086       << util::duration_str(get_config()->http2_upstream_read_timeout) << R"(
1087   --frontend-read-timeout=<DURATION>
1088               Specify read timeout for HTTP/1.1 frontend connection.
1089               Default: )"
1090       << util::duration_str(get_config()->upstream_read_timeout) << R"(
1091   --frontend-write-timeout=<DURATION>
1092               Specify write timeout for all frontend connections.
1093               Default: )"
1094       << util::duration_str(get_config()->upstream_write_timeout) << R"(
1095   --stream-read-timeout=<DURATION>
1096               Specify  read timeout  for HTTP/2  and SPDY  streams.  0
1097               means no timeout.
1098               Default: )"
1099       << util::duration_str(get_config()->stream_read_timeout) << R"(
1100   --stream-write-timeout=<DURATION>
1101               Specify write  timeout for  HTTP/2 and SPDY  streams.  0
1102               means no timeout.
1103               Default: )"
1104       << util::duration_str(get_config()->stream_write_timeout) << R"(
1105   --backend-read-timeout=<DURATION>
1106               Specify read timeout for backend connection.
1107               Default: )"
1108       << util::duration_str(get_config()->downstream_read_timeout) << R"(
1109   --backend-write-timeout=<DURATION>
1110               Specify write timeout for backend connection.
1111               Default: )"
1112       << util::duration_str(get_config()->downstream_write_timeout) << R"(
1113   --backend-keep-alive-timeout=<DURATION>
1114               Specify keep-alive timeout for backend connection.
1115               Default: )"
1116       << util::duration_str(get_config()->downstream_idle_read_timeout) << R"(
1117   --listener-disable-timeout=<DURATION>
1118               After accepting  connection failed,  connection listener
1119               is disabled  for a given  amount of time.   Specifying 0
1120               disables this feature.
1121               Default: )"
1122       << util::duration_str(get_config()->listener_disable_timeout) << R"(
1123
1124 SSL/TLS:
1125   --ciphers=<SUITE>
1126               Set allowed  cipher list.  The  format of the  string is
1127               described in OpenSSL ciphers(1).
1128   -k, --insecure
1129               Don't  verify   backend  server's  certificate   if  -p,
1130               --client    or    --http2-bridge     are    given    and
1131               --backend-no-tls is not given.
1132   --cacert=<PATH>
1133               Set path to trusted CA  certificate file if -p, --client
1134               or --http2-bridge are given  and --backend-no-tls is not
1135               given.  The file must be  in PEM format.  It can contain
1136               multiple  certificates.    If  the  linked   OpenSSL  is
1137               configured to  load system  wide certificates,  they are
1138               loaded at startup regardless of this option.
1139   --private-key-passwd-file=<PATH>
1140               Path  to file  that contains  password for  the server's
1141               private key.   If none is  given and the private  key is
1142               password protected it'll be requested interactively.
1143   --subcert=<KEYPATH>:<CERTPATH>
1144               Specify  additional certificate  and  private key  file.
1145               nghttpx will  choose certificates based on  the hostname
1146               indicated  by  client  using TLS  SNI  extension.   This
1147               option  can  be  used  multiple  times.   To  make  OCSP
1148               stapling work, <CERTPATH> must be absolute path.
1149   --backend-tls-sni-field=<HOST>
1150               Explicitly  set the  content of  the TLS  SNI extension.
1151               This will default to the backend HOST name.
1152   --dh-param-file=<PATH>
1153               Path to file that contains  DH parameters in PEM format.
1154               Without  this   option,  DHE   cipher  suites   are  not
1155               available.
1156   --npn-list=<LIST>
1157               Comma delimited list of  ALPN protocol identifier sorted
1158               in the  order of preference.  That  means most desirable
1159               protocol comes  first.  This  is used  in both  ALPN and
1160               NPN.  The parameter must be  delimited by a single comma
1161               only  and any  white spaces  are  treated as  a part  of
1162               protocol string.
1163               Default: )" << DEFAULT_NPN_LIST << R"(
1164   --verify-client
1165               Require and verify client certificate.
1166   --verify-client-cacert=<PATH>
1167               Path  to file  that contains  CA certificates  to verify
1168               client certificate.  The file must be in PEM format.  It
1169               can contain multiple certificates.
1170   --client-private-key-file=<PATH>
1171               Path to  file that contains  client private key  used in
1172               backend client authentication.
1173   --client-cert-file=<PATH>
1174               Path to  file that  contains client certificate  used in
1175               backend client authentication.
1176   --tls-proto-list=<LIST>
1177               Comma delimited list of  SSL/TLS protocol to be enabled.
1178               The following protocols  are available: TLSv1.2, TLSv1.1
1179               and   TLSv1.0.    The   name   matching   is   done   in
1180               case-insensitive   manner.    The  parameter   must   be
1181               delimited by  a single comma  only and any  white spaces
1182               are treated as a part of protocol string.
1183               Default: )" << DEFAULT_TLS_PROTO_LIST << R"(
1184   --tls-ticket-key-file=<PATH>
1185               Path  to file  that  contains 48  bytes  random data  to
1186               construct TLS  session ticket parameters.   This options
1187               can  be  used  repeatedly  to  specify  multiple  ticket
1188               parameters.  If several files  are given, only the first
1189               key is used to encrypt  TLS session tickets.  Other keys
1190               are accepted  but server  will issue new  session ticket
1191               with  first  key.   This allows  session  key  rotation.
1192               Please   note  that   key   rotation   does  not   occur
1193               automatically.   User should  rearrange files  or change
1194               options  values  and  restart  nghttpx  gracefully.   If
1195               opening or reading given file fails, all loaded keys are
1196               discarded and it is treated as if none of this option is
1197               given.  If this option is not given or an error occurred
1198               while  opening  or  reading  a file,  key  is  generated
1199               automatically and  renewed every 12hrs.  At  most 2 keys
1200               are stored in memory.
1201   --fetch-ocsp-response-file=<PATH>
1202               Path to  fetch-ocsp-response script file.  It  should be
1203               absolute path.
1204               Default: )" << get_config()->fetch_ocsp_response_file.get() << R"(
1205   --ocsp-update-interval=<DURATION>
1206               Set interval to update OCSP response cache.
1207               Default: )"
1208       << util::duration_str(get_config()->ocsp_update_interval) << R"(
1209   --no-ocsp   Disable OCSP stapling.
1210
1211 HTTP/2 and SPDY:
1212   -c, --http2-max-concurrent-streams=<N>
1213               Set the maximum number of  the concurrent streams in one
1214               HTTP/2 and SPDY session.
1215               Default: )" << get_config()->http2_max_concurrent_streams << R"(
1216   --frontend-http2-window-bits=<N>
1217               Sets the  per-stream initial window size  of HTTP/2 SPDY
1218               frontend connection.  For HTTP/2,  the size is 2**<N>-1.
1219               For SPDY, the size is 2**<N>.
1220               Default: )" << get_config()->http2_upstream_window_bits << R"(
1221   --frontend-http2-connection-window-bits=<N>
1222               Sets the  per-connection window size of  HTTP/2 and SPDY
1223               frontend   connection.    For   HTTP/2,  the   size   is
1224               2**<N>-1. For SPDY, the size is 2**<N>.
1225               Default: )" << get_config()->http2_upstream_connection_window_bits
1226       << R"(
1227   --frontend-no-tls
1228               Disable SSL/TLS on frontend connections.
1229   --backend-http2-window-bits=<N>
1230               Sets  the   initial  window   size  of   HTTP/2  backend
1231               connection to 2**<N>-1.
1232               Default: )" << get_config()->http2_downstream_window_bits << R"(
1233   --backend-http2-connection-window-bits=<N>
1234               Sets the  per-connection window  size of  HTTP/2 backend
1235               connection to 2**<N>-1.
1236               Default: )"
1237       << get_config()->http2_downstream_connection_window_bits << R"(
1238   --backend-no-tls
1239               Disable SSL/TLS on backend connections.
1240   --http2-no-cookie-crumbling
1241               Don't crumble cookie header field.
1242   --padding=<N>
1243               Add  at most  <N> bytes  to  a HTTP/2  frame payload  as
1244               padding.  Specify 0 to  disable padding.  This option is
1245               meant for debugging purpose  and not intended to enhance
1246               protocol security.
1247   --no-server-push
1248               Disable  HTTP/2  server  push.    Server  push  is  only
1249               supported  by default  mode and  HTTP/2 frontend.   SPDY
1250               frontend does not support server push.
1251
1252 Mode:
1253   (default mode)
1254               Accept  HTTP/2,  SPDY  and HTTP/1.1  over  SSL/TLS.   If
1255               --frontend-no-tls is  used, accept HTTP/2  and HTTP/1.1.
1256               The  incoming HTTP/1.1  connection  can  be upgraded  to
1257               HTTP/2  through  HTTP  Upgrade.   The  protocol  to  the
1258               backend is HTTP/1.1.
1259   -s, --http2-proxy
1260               Like default mode, but enable secure proxy mode.
1261   --http2-bridge
1262               Like default  mode, but communicate with  the backend in
1263               HTTP/2 over SSL/TLS.  Thus  the incoming all connections
1264               are converted  to HTTP/2  connection and relayed  to the
1265               backend.  See --backend-http-proxy-uri option if you are
1266               behind  the proxy  and want  to connect  to the  outside
1267               HTTP/2 proxy.
1268   --client    Accept  HTTP/2   and  HTTP/1.1  without   SSL/TLS.   The
1269               incoming HTTP/1.1  connection can be upgraded  to HTTP/2
1270               connection through  HTTP Upgrade.   The protocol  to the
1271               backend is HTTP/2.   To use nghttpx as  a forward proxy,
1272               use -p option instead.
1273   -p, --client-proxy
1274               Like --client  option, but it also  requires the request
1275               path from frontend must be an absolute URI, suitable for
1276               use as a forward proxy.
1277
1278 Logging:
1279   -L, --log-level=<LEVEL>
1280               Set the severity  level of log output.   <LEVEL> must be
1281               one of INFO, NOTICE, WARN, ERROR and FATAL.
1282               Default: NOTICE
1283   --accesslog-file=<PATH>
1284               Set path to write access log.  To reopen file, send USR1
1285               signal to nghttpx.
1286   --accesslog-syslog
1287               Send  access log  to syslog.   If this  option is  used,
1288               --accesslog-file option is ignored.
1289   --accesslog-format=<FORMAT>
1290               Specify  format  string  for access  log.   The  default
1291               format is combined format.   The following variables are
1292               available:
1293
1294               * $remote_addr: client IP address.
1295               * $time_local: local time in Common Log format.
1296               * $time_iso8601: local time in ISO 8601 format.
1297               * $request: HTTP request line.
1298               * $status: HTTP response status code.
1299               * $body_bytes_sent: the  number of bytes sent  to client
1300                 as response body.
1301               * $http_<VAR>: value of HTTP  request header <VAR> where
1302                 '_' in <VAR> is replaced with '-'.
1303               * $remote_port: client  port.
1304               * $server_port: server port.
1305               * $request_time: request processing time in seconds with
1306                 milliseconds resolution.
1307               * $pid: PID of the running process.
1308               * $alpn: ALPN identifier of the protocol which generates
1309                 the response.   For HTTP/1,  ALPN is  always http/1.1,
1310                 regardless of minor version.
1311
1312               Default: )" << DEFAULT_ACCESSLOG_FORMAT << R"(
1313   --errorlog-file=<PATH>
1314               Set path to write error  log.  To reopen file, send USR1
1315               signal  to nghttpx.   stderr will  be redirected  to the
1316               error log file unless --errorlog-syslog is used.
1317               Default: )" << get_config()->errorlog_file.get() << R"(
1318   --errorlog-syslog
1319               Send  error log  to  syslog.  If  this  option is  used,
1320               --errorlog-file option is ignored.
1321   --syslog-facility=<FACILITY>
1322               Set syslog facility to <FACILITY>.
1323               Default: )" << str_syslog_facility(get_config()->syslog_facility)
1324       << R"(
1325
1326 HTTP:
1327   --add-x-forwarded-for
1328               Append  X-Forwarded-For header  field to  the downstream
1329               request.
1330   --strip-incoming-x-forwarded-for
1331               Strip X-Forwarded-For  header field from  inbound client
1332               requests.
1333   --no-via    Don't append to  Via header field.  If  Via header field
1334               is received, it is left unaltered.
1335   --no-location-rewrite
1336               Don't rewrite  location header field  on --http2-bridge,
1337               --client  and  default   mode.   For  --http2-proxy  and
1338               --client-proxy mode,  location header field will  not be
1339               altered regardless of this option.
1340   --no-host-rewrite
1341               Don't  rewrite  host  and :authority  header  fields  on
1342               --http2-bridge,   --client   and  default   mode.    For
1343               --http2-proxy  and  --client-proxy mode,  these  headers
1344               will not be altered regardless of this option.
1345   --altsvc=<PROTOID,PORT[,HOST,[ORIGIN]]>
1346               Specify   protocol  ID,   port,  host   and  origin   of
1347               alternative service.  <HOST>  and <ORIGIN> are optional.
1348               They  are advertised  in  alt-svc header  field only  in
1349               HTTP/1.1  frontend.  This  option can  be used  multiple
1350               times   to   specify  multiple   alternative   services.
1351               Example: --altsvc=h2,443
1352   --add-response-header=<HEADER>
1353               Specify  additional  header  field to  add  to  response
1354               header set.   This option just appends  header field and
1355               won't replace anything already  set.  This option can be
1356               used several  times to  specify multiple  header fields.
1357               Example: --add-response-header="foo: bar"
1358   --header-field-buffer=<SIZE>
1359               Set maximum  buffer size for incoming  HTTP header field
1360               list.   This is  the sum  of  header name  and value  in
1361               bytes.
1362               Default: )"
1363       << util::utos_with_unit(get_config()->header_field_buffer) << R"(
1364   --max-header-fields=<N>
1365               Set maximum number of incoming HTTP header fields, which
1366               appear in one request or response header field list.
1367               Default: )" << get_config()->max_header_fields << R"(
1368
1369 Debug:
1370   --frontend-http2-dump-request-header=<PATH>
1371               Dumps request headers received by HTTP/2 frontend to the
1372               file denoted  in <PATH>.  The  output is done  in HTTP/1
1373               header field format and each header block is followed by
1374               an empty line.  This option  is not thread safe and MUST
1375               NOT be used with option -n<N>, where <N> >= 2.
1376   --frontend-http2-dump-response-header=<PATH>
1377               Dumps response headers sent  from HTTP/2 frontend to the
1378               file denoted  in <PATH>.  The  output is done  in HTTP/1
1379               header field format and each header block is followed by
1380               an empty line.  This option  is not thread safe and MUST
1381               NOT be used with option -n<N>, where <N> >= 2.
1382   -o, --frontend-frame-debug
1383               Print HTTP/2 frames in  frontend to stderr.  This option
1384               is  not thread  safe and  MUST NOT  be used  with option
1385               -n=N, where N >= 2.
1386
1387 Process:
1388   -D, --daemon
1389               Run in a background.  If -D is used, the current working
1390               directory is changed to '/'.
1391   --pid-file=<PATH>
1392               Set path to save PID of this program.
1393   --user=<USER>
1394               Run this program as <USER>.   This option is intended to
1395               be used to drop root privileges.
1396
1397 Misc:
1398   --conf=<PATH>
1399               Load configuration from <PATH>.
1400               Default: )" << get_config()->conf_path.get() << R"(
1401   -v, --version
1402               Print version and exit.
1403   -h, --help  Print this help and exit.
1404
1405 --
1406
1407   The <SIZE> argument is an integer and an optional unit (e.g., 10K is
1408   10 * 1024).  Units are K, M and G (powers of 1024).
1409
1410   The <DURATION> argument is an integer and an optional unit (e.g., 1s
1411   is 1 second and 500ms is 500 milliseconds).  Units are h, m, s or ms
1412   (hours, minutes, seconds and milliseconds, respectively).  If a unit
1413   is omitted, a second is used as unit.)" << std::endl;
1414 }
1415 } // namespace
1416
1417 int main(int argc, char **argv) {
1418   Log::set_severity_level(NOTICE);
1419   create_config();
1420   fill_default_config();
1421
1422   // We have to copy argv, since getopt_long may change its content.
1423   mod_config()->argc = argc;
1424   mod_config()->argv = new char *[argc];
1425
1426   for (int i = 0; i < argc; ++i) {
1427     mod_config()->argv[i] = strdup(argv[i]);
1428   }
1429
1430   mod_config()->cwd = getcwd(nullptr, 0);
1431   if (mod_config()->cwd == nullptr) {
1432     auto error = errno;
1433     LOG(FATAL) << "failed to get current working directory: errno=" << error;
1434     exit(EXIT_FAILURE);
1435   }
1436
1437   std::vector<std::pair<const char *, const char *>> cmdcfgs;
1438   while (1) {
1439     static int flag = 0;
1440     static option long_options[] = {
1441         {"daemon", no_argument, nullptr, 'D'},
1442         {"log-level", required_argument, nullptr, 'L'},
1443         {"backend", required_argument, nullptr, 'b'},
1444         {"http2-max-concurrent-streams", required_argument, nullptr, 'c'},
1445         {"frontend", required_argument, nullptr, 'f'},
1446         {"help", no_argument, nullptr, 'h'},
1447         {"insecure", no_argument, nullptr, 'k'},
1448         {"workers", required_argument, nullptr, 'n'},
1449         {"client-proxy", no_argument, nullptr, 'p'},
1450         {"http2-proxy", no_argument, nullptr, 's'},
1451         {"version", no_argument, nullptr, 'v'},
1452         {"frontend-frame-debug", no_argument, nullptr, 'o'},
1453         {"add-x-forwarded-for", no_argument, &flag, 1},
1454         {"frontend-http2-read-timeout", required_argument, &flag, 2},
1455         {"frontend-read-timeout", required_argument, &flag, 3},
1456         {"frontend-write-timeout", required_argument, &flag, 4},
1457         {"backend-read-timeout", required_argument, &flag, 5},
1458         {"backend-write-timeout", required_argument, &flag, 6},
1459         {"accesslog-file", required_argument, &flag, 7},
1460         {"backend-keep-alive-timeout", required_argument, &flag, 8},
1461         {"frontend-http2-window-bits", required_argument, &flag, 9},
1462         {"pid-file", required_argument, &flag, 10},
1463         {"user", required_argument, &flag, 11},
1464         {"conf", required_argument, &flag, 12},
1465         {"syslog-facility", required_argument, &flag, 14},
1466         {"backlog", required_argument, &flag, 15},
1467         {"ciphers", required_argument, &flag, 16},
1468         {"client", no_argument, &flag, 17},
1469         {"backend-http2-window-bits", required_argument, &flag, 18},
1470         {"cacert", required_argument, &flag, 19},
1471         {"backend-ipv4", no_argument, &flag, 20},
1472         {"backend-ipv6", no_argument, &flag, 21},
1473         {"private-key-passwd-file", required_argument, &flag, 22},
1474         {"no-via", no_argument, &flag, 23},
1475         {"subcert", required_argument, &flag, 24},
1476         {"http2-bridge", no_argument, &flag, 25},
1477         {"backend-http-proxy-uri", required_argument, &flag, 26},
1478         {"backend-no-tls", no_argument, &flag, 27},
1479         {"frontend-no-tls", no_argument, &flag, 29},
1480         {"backend-tls-sni-field", required_argument, &flag, 31},
1481         {"dh-param-file", required_argument, &flag, 33},
1482         {"read-rate", required_argument, &flag, 34},
1483         {"read-burst", required_argument, &flag, 35},
1484         {"write-rate", required_argument, &flag, 36},
1485         {"write-burst", required_argument, &flag, 37},
1486         {"npn-list", required_argument, &flag, 38},
1487         {"verify-client", no_argument, &flag, 39},
1488         {"verify-client-cacert", required_argument, &flag, 40},
1489         {"client-private-key-file", required_argument, &flag, 41},
1490         {"client-cert-file", required_argument, &flag, 42},
1491         {"frontend-http2-dump-request-header", required_argument, &flag, 43},
1492         {"frontend-http2-dump-response-header", required_argument, &flag, 44},
1493         {"http2-no-cookie-crumbling", no_argument, &flag, 45},
1494         {"frontend-http2-connection-window-bits", required_argument, &flag, 46},
1495         {"backend-http2-connection-window-bits", required_argument, &flag, 47},
1496         {"tls-proto-list", required_argument, &flag, 48},
1497         {"padding", required_argument, &flag, 49},
1498         {"worker-read-rate", required_argument, &flag, 50},
1499         {"worker-read-burst", required_argument, &flag, 51},
1500         {"worker-write-rate", required_argument, &flag, 52},
1501         {"worker-write-burst", required_argument, &flag, 53},
1502         {"altsvc", required_argument, &flag, 54},
1503         {"add-response-header", required_argument, &flag, 55},
1504         {"worker-frontend-connections", required_argument, &flag, 56},
1505         {"accesslog-syslog", no_argument, &flag, 57},
1506         {"errorlog-file", required_argument, &flag, 58},
1507         {"errorlog-syslog", no_argument, &flag, 59},
1508         {"stream-read-timeout", required_argument, &flag, 60},
1509         {"stream-write-timeout", required_argument, &flag, 61},
1510         {"no-location-rewrite", no_argument, &flag, 62},
1511         {"backend-http1-connections-per-host", required_argument, &flag, 63},
1512         {"listener-disable-timeout", required_argument, &flag, 64},
1513         {"strip-incoming-x-forwarded-for", no_argument, &flag, 65},
1514         {"accesslog-format", required_argument, &flag, 66},
1515         {"backend-http1-connections-per-frontend", required_argument, &flag,
1516          67},
1517         {"tls-ticket-key-file", required_argument, &flag, 68},
1518         {"rlimit-nofile", required_argument, &flag, 69},
1519         {"tls-ctx-per-worker", no_argument, &flag, 70},
1520         {"backend-response-buffer", required_argument, &flag, 71},
1521         {"backend-request-buffer", required_argument, &flag, 72},
1522         {"no-host-rewrite", no_argument, &flag, 73},
1523         {"no-server-push", no_argument, &flag, 74},
1524         {"backend-http2-connections-per-worker", required_argument, &flag, 76},
1525         {"fetch-ocsp-response-file", required_argument, &flag, 77},
1526         {"ocsp-update-interval", required_argument, &flag, 78},
1527         {"no-ocsp", no_argument, &flag, 79},
1528         {"header-field-buffer", required_argument, &flag, 80},
1529         {"max-header-fields", required_argument, &flag, 81},
1530         {nullptr, 0, nullptr, 0}};
1531
1532     int option_index = 0;
1533     int c = getopt_long(argc, argv, "DL:b:c:f:hkn:opsv", long_options,
1534                         &option_index);
1535     if (c == -1) {
1536       break;
1537     }
1538     switch (c) {
1539     case 'D':
1540       cmdcfgs.emplace_back(SHRPX_OPT_DAEMON, "yes");
1541       break;
1542     case 'L':
1543       cmdcfgs.emplace_back(SHRPX_OPT_LOG_LEVEL, optarg);
1544       break;
1545     case 'b':
1546       cmdcfgs.emplace_back(SHRPX_OPT_BACKEND, optarg);
1547       break;
1548     case 'c':
1549       cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_MAX_CONCURRENT_STREAMS, optarg);
1550       break;
1551     case 'f':
1552       cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND, optarg);
1553       break;
1554     case 'h':
1555       print_help(std::cout);
1556       exit(EXIT_SUCCESS);
1557     case 'k':
1558       cmdcfgs.emplace_back(SHRPX_OPT_INSECURE, "yes");
1559       break;
1560     case 'n':
1561 #ifdef NOTHREADS
1562       LOG(WARN) << "Threading disabled at build time, no threads created.";
1563 #else
1564       cmdcfgs.emplace_back(SHRPX_OPT_WORKERS, optarg);
1565 #endif // NOTHREADS
1566       break;
1567     case 'o':
1568       cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_FRAME_DEBUG, "yes");
1569       break;
1570     case 'p':
1571       cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_PROXY, "yes");
1572       break;
1573     case 's':
1574       cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_PROXY, "yes");
1575       break;
1576     case 'v':
1577       print_version(std::cout);
1578       exit(EXIT_SUCCESS);
1579     case '?':
1580       util::show_candidates(argv[optind - 1], long_options);
1581       exit(EXIT_FAILURE);
1582     case 0:
1583       switch (flag) {
1584       case 1:
1585         // --add-x-forwarded-for
1586         cmdcfgs.emplace_back(SHRPX_OPT_ADD_X_FORWARDED_FOR, "yes");
1587         break;
1588       case 2:
1589         // --frontend-http2-read-timeout
1590         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_READ_TIMEOUT, optarg);
1591         break;
1592       case 3:
1593         // --frontend-read-timeout
1594         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_READ_TIMEOUT, optarg);
1595         break;
1596       case 4:
1597         // --frontend-write-timeout
1598         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_WRITE_TIMEOUT, optarg);
1599         break;
1600       case 5:
1601         // --backend-read-timeout
1602         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_READ_TIMEOUT, optarg);
1603         break;
1604       case 6:
1605         // --backend-write-timeout
1606         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_WRITE_TIMEOUT, optarg);
1607         break;
1608       case 7:
1609         cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_FILE, optarg);
1610         break;
1611       case 8:
1612         // --backend-keep-alive-timeout
1613         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT, optarg);
1614         break;
1615       case 9:
1616         // --frontend-http2-window-bits
1617         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS, optarg);
1618         break;
1619       case 10:
1620         cmdcfgs.emplace_back(SHRPX_OPT_PID_FILE, optarg);
1621         break;
1622       case 11:
1623         cmdcfgs.emplace_back(SHRPX_OPT_USER, optarg);
1624         break;
1625       case 12:
1626         // --conf
1627         mod_config()->conf_path = strcopy(optarg);
1628         break;
1629       case 14:
1630         // --syslog-facility
1631         cmdcfgs.emplace_back(SHRPX_OPT_SYSLOG_FACILITY, optarg);
1632         break;
1633       case 15:
1634         // --backlog
1635         cmdcfgs.emplace_back(SHRPX_OPT_BACKLOG, optarg);
1636         break;
1637       case 16:
1638         // --ciphers
1639         cmdcfgs.emplace_back(SHRPX_OPT_CIPHERS, optarg);
1640         break;
1641       case 17:
1642         // --client
1643         cmdcfgs.emplace_back(SHRPX_OPT_CLIENT, "yes");
1644         break;
1645       case 18:
1646         // --backend-http2-window-bits
1647         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS, optarg);
1648         break;
1649       case 19:
1650         // --cacert
1651         cmdcfgs.emplace_back(SHRPX_OPT_CACERT, optarg);
1652         break;
1653       case 20:
1654         // --backend-ipv4
1655         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_IPV4, "yes");
1656         break;
1657       case 21:
1658         // --backend-ipv6
1659         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_IPV6, "yes");
1660         break;
1661       case 22:
1662         // --private-key-passwd-file
1663         cmdcfgs.emplace_back(SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE, optarg);
1664         break;
1665       case 23:
1666         // --no-via
1667         cmdcfgs.emplace_back(SHRPX_OPT_NO_VIA, "yes");
1668         break;
1669       case 24:
1670         // --subcert
1671         cmdcfgs.emplace_back(SHRPX_OPT_SUBCERT, optarg);
1672         break;
1673       case 25:
1674         // --http2-bridge
1675         cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_BRIDGE, "yes");
1676         break;
1677       case 26:
1678         // --backend-http-proxy-uri
1679         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP_PROXY_URI, optarg);
1680         break;
1681       case 27:
1682         // --backend-no-tls
1683         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_NO_TLS, "yes");
1684         break;
1685       case 29:
1686         // --frontend-no-tls
1687         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_NO_TLS, "yes");
1688         break;
1689       case 31:
1690         // --backend-tls-sni-field
1691         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_TLS_SNI_FIELD, optarg);
1692         break;
1693       case 33:
1694         // --dh-param-file
1695         cmdcfgs.emplace_back(SHRPX_OPT_DH_PARAM_FILE, optarg);
1696         break;
1697       case 34:
1698         // --read-rate
1699         cmdcfgs.emplace_back(SHRPX_OPT_READ_RATE, optarg);
1700         break;
1701       case 35:
1702         // --read-burst
1703         cmdcfgs.emplace_back(SHRPX_OPT_READ_BURST, optarg);
1704         break;
1705       case 36:
1706         // --write-rate
1707         cmdcfgs.emplace_back(SHRPX_OPT_WRITE_RATE, optarg);
1708         break;
1709       case 37:
1710         // --write-burst
1711         cmdcfgs.emplace_back(SHRPX_OPT_WRITE_BURST, optarg);
1712         break;
1713       case 38:
1714         // --npn-list
1715         cmdcfgs.emplace_back(SHRPX_OPT_NPN_LIST, optarg);
1716         break;
1717       case 39:
1718         // --verify-client
1719         cmdcfgs.emplace_back(SHRPX_OPT_VERIFY_CLIENT, "yes");
1720         break;
1721       case 40:
1722         // --verify-client-cacert
1723         cmdcfgs.emplace_back(SHRPX_OPT_VERIFY_CLIENT_CACERT, optarg);
1724         break;
1725       case 41:
1726         // --client-private-key-file
1727         cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_PRIVATE_KEY_FILE, optarg);
1728         break;
1729       case 42:
1730         // --client-cert-file
1731         cmdcfgs.emplace_back(SHRPX_OPT_CLIENT_CERT_FILE, optarg);
1732         break;
1733       case 43:
1734         // --frontend-http2-dump-request-header
1735         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_DUMP_REQUEST_HEADER,
1736                              optarg);
1737         break;
1738       case 44:
1739         // --frontend-http2-dump-response-header
1740         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER,
1741                              optarg);
1742         break;
1743       case 45:
1744         // --http2-no-cookie-crumbling
1745         cmdcfgs.emplace_back(SHRPX_OPT_HTTP2_NO_COOKIE_CRUMBLING, "yes");
1746         break;
1747       case 46:
1748         // --frontend-http2-connection-window-bits
1749         cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS,
1750                              optarg);
1751         break;
1752       case 47:
1753         // --backend-http2-connection-window-bits
1754         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_BITS,
1755                              optarg);
1756         break;
1757       case 48:
1758         // --tls-proto-list
1759         cmdcfgs.emplace_back(SHRPX_OPT_TLS_PROTO_LIST, optarg);
1760         break;
1761       case 49:
1762         // --padding
1763         cmdcfgs.emplace_back(SHRPX_OPT_PADDING, optarg);
1764         break;
1765       case 50:
1766         // --worker-read-rate
1767         cmdcfgs.emplace_back(SHRPX_OPT_WORKER_READ_RATE, optarg);
1768         break;
1769       case 51:
1770         // --worker-read-burst
1771         cmdcfgs.emplace_back(SHRPX_OPT_WORKER_READ_BURST, optarg);
1772         break;
1773       case 52:
1774         // --worker-write-rate
1775         cmdcfgs.emplace_back(SHRPX_OPT_WORKER_WRITE_RATE, optarg);
1776         break;
1777       case 53:
1778         // --worker-write-burst
1779         cmdcfgs.emplace_back(SHRPX_OPT_WORKER_WRITE_BURST, optarg);
1780         break;
1781       case 54:
1782         // --altsvc
1783         cmdcfgs.emplace_back(SHRPX_OPT_ALTSVC, optarg);
1784         break;
1785       case 55:
1786         // --add-response-header
1787         cmdcfgs.emplace_back(SHRPX_OPT_ADD_RESPONSE_HEADER, optarg);
1788         break;
1789       case 56:
1790         // --worker-frontend-connections
1791         cmdcfgs.emplace_back(SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS, optarg);
1792         break;
1793       case 57:
1794         // --accesslog-syslog
1795         cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_SYSLOG, "yes");
1796         break;
1797       case 58:
1798         // --errorlog-file
1799         cmdcfgs.emplace_back(SHRPX_OPT_ERRORLOG_FILE, optarg);
1800         break;
1801       case 59:
1802         // --errorlog-syslog
1803         cmdcfgs.emplace_back(SHRPX_OPT_ERRORLOG_SYSLOG, "yes");
1804         break;
1805       case 60:
1806         // --stream-read-timeout
1807         cmdcfgs.emplace_back(SHRPX_OPT_STREAM_READ_TIMEOUT, optarg);
1808         break;
1809       case 61:
1810         // --stream-write-timeout
1811         cmdcfgs.emplace_back(SHRPX_OPT_STREAM_WRITE_TIMEOUT, optarg);
1812         break;
1813       case 62:
1814         // --no-location-rewrite
1815         cmdcfgs.emplace_back(SHRPX_OPT_NO_LOCATION_REWRITE, "yes");
1816         break;
1817       case 63:
1818         // --backend-http1-connections-per-host
1819         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_HOST,
1820                              optarg);
1821         break;
1822       case 64:
1823         // --listener-disable-timeout
1824         cmdcfgs.emplace_back(SHRPX_OPT_LISTENER_DISABLE_TIMEOUT, optarg);
1825         break;
1826       case 65:
1827         // --strip-incoming-x-forwarded-for
1828         cmdcfgs.emplace_back(SHRPX_OPT_STRIP_INCOMING_X_FORWARDED_FOR, "yes");
1829         break;
1830       case 66:
1831         // --accesslog-format
1832         cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_FORMAT, optarg);
1833         break;
1834       case 67:
1835         // --backend-http1-connections-per-frontend
1836         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP1_CONNECTIONS_PER_FRONTEND,
1837                              optarg);
1838         break;
1839       case 68:
1840         // --tls-ticket-key-file
1841         cmdcfgs.emplace_back(SHRPX_OPT_TLS_TICKET_KEY_FILE, optarg);
1842         break;
1843       case 69:
1844         // --rlimit-nofile
1845         cmdcfgs.emplace_back(SHRPX_OPT_RLIMIT_NOFILE, optarg);
1846         break;
1847       case 71:
1848         // --backend-response-buffer
1849         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_RESPONSE_BUFFER, optarg);
1850         break;
1851       case 72:
1852         // --backend-request-buffer
1853         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_REQUEST_BUFFER, optarg);
1854         break;
1855       case 73:
1856         // --no-host-rewrite
1857         cmdcfgs.emplace_back(SHRPX_OPT_NO_HOST_REWRITE, "yes");
1858         break;
1859       case 74:
1860         // --no-server-push
1861         cmdcfgs.emplace_back(SHRPX_OPT_NO_SERVER_PUSH, "yes");
1862         break;
1863       case 76:
1864         // --backend-http2-connections-per-worker
1865         cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_CONNECTIONS_PER_WORKER,
1866                              optarg);
1867         break;
1868       case 77:
1869         // --fetch-ocsp-response-file
1870         cmdcfgs.emplace_back(SHRPX_OPT_FETCH_OCSP_RESPONSE_FILE, optarg);
1871         break;
1872       case 78:
1873         // --ocsp-update-interval
1874         cmdcfgs.emplace_back(SHRPX_OPT_OCSP_UPDATE_INTERVAL, optarg);
1875         break;
1876       case 79:
1877         // --no-ocsp
1878         cmdcfgs.emplace_back(SHRPX_OPT_NO_OCSP, "yes");
1879         break;
1880       case 80:
1881         // --header-field-buffer
1882         cmdcfgs.emplace_back(SHRPX_OPT_HEADER_FIELD_BUFFER, optarg);
1883         break;
1884       case 81:
1885         // --max-header-fields
1886         cmdcfgs.emplace_back(SHRPX_OPT_MAX_HEADER_FIELDS, optarg);
1887         break;
1888       default:
1889         break;
1890       }
1891       break;
1892     default:
1893       break;
1894     }
1895   }
1896
1897   // Initialize OpenSSL before parsing options because we create
1898   // SSL_CTX there.
1899   OPENSSL_config(nullptr);
1900   OpenSSL_add_all_algorithms();
1901   SSL_load_error_strings();
1902   SSL_library_init();
1903
1904   if (conf_exists(get_config()->conf_path.get())) {
1905     if (load_config(get_config()->conf_path.get()) == -1) {
1906       LOG(FATAL) << "Failed to load configuration from "
1907                  << get_config()->conf_path.get();
1908       exit(EXIT_FAILURE);
1909     }
1910   }
1911
1912   if (argc - optind >= 2) {
1913     cmdcfgs.emplace_back(SHRPX_OPT_PRIVATE_KEY_FILE, argv[optind++]);
1914     cmdcfgs.emplace_back(SHRPX_OPT_CERTIFICATE_FILE, argv[optind++]);
1915   }
1916
1917   // First open default log files to deal with errors occurred while
1918   // parsing option values.
1919   reopen_log_files();
1920
1921   for (size_t i = 0, len = cmdcfgs.size(); i < len; ++i) {
1922     if (parse_config(cmdcfgs[i].first, cmdcfgs[i].second) == -1) {
1923       LOG(FATAL) << "Failed to parse command-line argument.";
1924       exit(EXIT_FAILURE);
1925     }
1926   }
1927
1928 #ifndef NOTHREADS
1929   auto lock = make_unique<nghttp2::ssl::LibsslGlobalLock>();
1930 #endif // NOTHREADS
1931
1932   if (get_config()->accesslog_syslog || get_config()->errorlog_syslog) {
1933     openlog("nghttpx", LOG_NDELAY | LOG_NOWAIT | LOG_PID,
1934             get_config()->syslog_facility);
1935   }
1936
1937   if (reopen_log_files() != 0) {
1938     LOG(FATAL) << "Failed to open log file";
1939     exit(EXIT_FAILURE);
1940   }
1941
1942   redirect_stderr_to_errorlog();
1943
1944   if (get_config()->uid != 0) {
1945     if (log_config()->accesslog_fd != -1 &&
1946         fchown(log_config()->accesslog_fd, get_config()->uid,
1947                get_config()->gid) == -1) {
1948       auto error = errno;
1949       LOG(WARN) << "Changing owner of access log file failed: "
1950                 << strerror(error);
1951     }
1952     if (log_config()->errorlog_fd != -1 &&
1953         fchown(log_config()->errorlog_fd, get_config()->uid,
1954                get_config()->gid) == -1) {
1955       auto error = errno;
1956       LOG(WARN) << "Changing owner of error log file failed: "
1957                 << strerror(error);
1958     }
1959   }
1960
1961   if (get_config()->http2_upstream_dump_request_header_file) {
1962     auto path = get_config()->http2_upstream_dump_request_header_file.get();
1963     auto f = open_file_for_write(path);
1964
1965     if (f == nullptr) {
1966       LOG(FATAL) << "Failed to open http2 upstream request header file: "
1967                  << path;
1968       exit(EXIT_FAILURE);
1969     }
1970
1971     mod_config()->http2_upstream_dump_request_header = f;
1972
1973     if (get_config()->uid != 0) {
1974       if (chown(path, get_config()->uid, get_config()->gid) == -1) {
1975         auto error = errno;
1976         LOG(WARN) << "Changing owner of http2 upstream request header file "
1977                   << path << " failed: " << strerror(error);
1978       }
1979     }
1980   }
1981
1982   if (get_config()->http2_upstream_dump_response_header_file) {
1983     auto path = get_config()->http2_upstream_dump_response_header_file.get();
1984     auto f = open_file_for_write(path);
1985
1986     if (f == nullptr) {
1987       LOG(FATAL) << "Failed to open http2 upstream response header file: "
1988                  << path;
1989       exit(EXIT_FAILURE);
1990     }
1991
1992     mod_config()->http2_upstream_dump_response_header = f;
1993
1994     if (get_config()->uid != 0) {
1995       if (chown(path, get_config()->uid, get_config()->gid) == -1) {
1996         auto error = errno;
1997         LOG(WARN) << "Changing owner of http2 upstream response header file"
1998                   << " " << path << " failed: " << strerror(error);
1999       }
2000     }
2001   }
2002
2003   if (get_config()->npn_list.empty()) {
2004     mod_config()->npn_list = parse_config_str_list(DEFAULT_NPN_LIST);
2005   }
2006   if (get_config()->tls_proto_list.empty()) {
2007     mod_config()->tls_proto_list =
2008         parse_config_str_list(DEFAULT_TLS_PROTO_LIST);
2009   }
2010
2011   mod_config()->tls_proto_mask =
2012       ssl::create_tls_proto_mask(get_config()->tls_proto_list);
2013
2014   mod_config()->alpn_prefs = ssl::set_alpn_prefs(get_config()->npn_list);
2015
2016   if (get_config()->backend_ipv4 && get_config()->backend_ipv6) {
2017     LOG(FATAL) << "--backend-ipv4 and --backend-ipv6 cannot be used at the "
2018                << "same time.";
2019     exit(EXIT_FAILURE);
2020   }
2021
2022   if (get_config()->worker_frontend_connections == 0) {
2023     mod_config()->worker_frontend_connections =
2024         std::numeric_limits<size_t>::max();
2025   }
2026
2027   if (get_config()->http2_proxy + get_config()->http2_bridge +
2028           get_config()->client_proxy + get_config()->client >
2029       1) {
2030     LOG(FATAL) << "--http2-proxy, --http2-bridge, --client-proxy and --client "
2031                << "cannot be used at the same time.";
2032     exit(EXIT_FAILURE);
2033   }
2034
2035   if (get_config()->client || get_config()->client_proxy) {
2036     mod_config()->client_mode = true;
2037     mod_config()->upstream_no_tls = true;
2038   }
2039
2040   if (get_config()->client_mode || get_config()->http2_bridge) {
2041     mod_config()->downstream_proto = PROTO_HTTP2;
2042   } else {
2043     mod_config()->downstream_proto = PROTO_HTTP;
2044   }
2045
2046   if (!get_config()->upstream_no_tls &&
2047       (!get_config()->private_key_file || !get_config()->cert_file)) {
2048     print_usage(std::cerr);
2049     LOG(FATAL) << "Too few arguments";
2050     exit(EXIT_FAILURE);
2051   }
2052
2053   if (!get_config()->upstream_no_tls && !get_config()->no_ocsp) {
2054     struct stat buf;
2055     if (stat(get_config()->fetch_ocsp_response_file.get(), &buf) != 0) {
2056       mod_config()->no_ocsp = true;
2057       LOG(WARN) << "--fetch-ocsp-response-file: "
2058                 << get_config()->fetch_ocsp_response_file.get()
2059                 << " not found.  OCSP stapling has been disabled.";
2060     }
2061   }
2062
2063   if (get_config()->downstream_addrs.empty()) {
2064     DownstreamAddr addr;
2065     addr.host = strcopy(DEFAULT_DOWNSTREAM_HOST);
2066     addr.port = DEFAULT_DOWNSTREAM_PORT;
2067
2068     mod_config()->downstream_addrs.push_back(std::move(addr));
2069   }
2070
2071   if (LOG_ENABLED(INFO)) {
2072     LOG(INFO) << "Resolving backend address";
2073   }
2074
2075   for (auto &addr : mod_config()->downstream_addrs) {
2076
2077     if (addr.host_unix) {
2078       // for AF_UNIX socket, we use "localhost" as host for backend
2079       // hostport.  This is used as Host header field to backend and
2080       // not going to be passed to any syscalls.
2081       addr.hostport =
2082           strcopy(util::make_hostport("localhost", get_config()->port));
2083
2084       auto path = addr.host.get();
2085       auto pathlen = strlen(path);
2086
2087       if (pathlen + 1 > sizeof(addr.addr.un.sun_path)) {
2088         LOG(FATAL) << "UNIX domain socket path " << path << " is too long > "
2089                    << sizeof(addr.addr.un.sun_path);
2090         exit(EXIT_FAILURE);
2091       }
2092
2093       LOG(INFO) << "Use UNIX domain socket path " << path
2094                 << " for backend connection";
2095
2096       addr.addr.un.sun_family = AF_UNIX;
2097       // copy path including terminal NULL
2098       std::copy_n(path, pathlen + 1, addr.addr.un.sun_path);
2099       addr.addrlen = sizeof(addr.addr.un);
2100
2101       continue;
2102     }
2103
2104     addr.hostport = strcopy(util::make_hostport(addr.host.get(), addr.port));
2105
2106     if (resolve_hostname(
2107             &addr.addr, &addr.addrlen, addr.host.get(), addr.port,
2108             get_config()->backend_ipv4
2109                 ? AF_INET
2110                 : (get_config()->backend_ipv6 ? AF_INET6 : AF_UNSPEC)) == -1) {
2111       exit(EXIT_FAILURE);
2112     }
2113   }
2114
2115   if (get_config()->downstream_http_proxy_host) {
2116     if (LOG_ENABLED(INFO)) {
2117       LOG(INFO) << "Resolving backend http proxy address";
2118     }
2119     if (resolve_hostname(&mod_config()->downstream_http_proxy_addr,
2120                          &mod_config()->downstream_http_proxy_addrlen,
2121                          get_config()->downstream_http_proxy_host.get(),
2122                          get_config()->downstream_http_proxy_port,
2123                          AF_UNSPEC) == -1) {
2124       exit(EXIT_FAILURE);
2125     }
2126   }
2127
2128   if (get_config()->http2_downstream_connections_per_worker == 0) {
2129     mod_config()->http2_downstream_connections_per_worker =
2130         get_config()->downstream_addrs.size();
2131   }
2132
2133   if (get_config()->rlimit_nofile) {
2134     struct rlimit lim = {static_cast<rlim_t>(get_config()->rlimit_nofile),
2135                          static_cast<rlim_t>(get_config()->rlimit_nofile)};
2136     if (setrlimit(RLIMIT_NOFILE, &lim) != 0) {
2137       auto error = errno;
2138       LOG(WARN) << "Setting rlimit-nofile failed: " << strerror(error);
2139     }
2140   }
2141
2142   if (get_config()->upstream_frame_debug) {
2143     // To make it sync to logging
2144     set_output(stderr);
2145     if (isatty(fileno(stdout))) {
2146       set_color_output(true);
2147     }
2148     reset_timer();
2149   }
2150
2151   struct sigaction act;
2152   memset(&act, 0, sizeof(struct sigaction));
2153   act.sa_handler = SIG_IGN;
2154   sigaction(SIGPIPE, &act, nullptr);
2155
2156   event_loop();
2157
2158   LOG(NOTICE) << "Shutdown momentarily";
2159
2160   return 0;
2161 }
2162
2163 } // namespace shrpx
2164
2165 int main(int argc, char **argv) { return shrpx::main(argc, argv); }