1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <errno.h>
6201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include <signal.h>
772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <sys/file.h>
8dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <sys/stat.h>
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <iostream>
1172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <string>
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <vector>
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "base/command_line.h"
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h"
1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/synchronization/lock.h"
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/timer.h"
1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/tools/flip_server/acceptor_thread.h"
1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/tools/flip_server/constants.h"
2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/tools/flip_server/flip_config.h"
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/tools/flip_server/output_ordering.h"
2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/tools/flip_server/sm_connection.h"
2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/tools/flip_server/sm_interface.h"
2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/tools/flip_server/spdy_interface.h"
25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/streamer_interface.h"
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/tools/flip_server/split.h"
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenusing std::cout;
2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenusing std::cerr;
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// If true, then disables the nagle algorithm);
3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool FLAGS_disable_nagle = true;
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// The number of times that accept() will be called when the
3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen//  alarm goes off when the accept_using_alarm flag is set to true.
3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen//  If set to 0, accept() will be performed until the accept queue
3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen//  is completely drained and the accept() call returns an error);
3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint32 FLAGS_accepts_per_wake = 0;
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// The size of the TCP accept backlog);
4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint32 FLAGS_accept_backlog_size = 1024;
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// If set to false a single socket will be used. If set to true
4472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen//  then a new socket will be created for each accept thread.
4572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen//  Note that this only works with kernels that support
4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen//  SO_REUSEPORT);
4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool FLAGS_reuseport = false;
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Flag to force spdy, even if NPN is not negotiated.
5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool FLAGS_force_spdy = false;
51201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// The amount of time the server delays before sending back the
5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen//  reply);
5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsendouble FLAGS_server_think_time_in_s = 0;
55201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsennet::FlipConfig g_proxy_config;
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott////////////////////////////////////////////////////////////////////////////////
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
60201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochstd::vector<std::string> &split(const std::string &s,
61201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                char delim,
62201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                std::vector<std::string> &elems) {
63201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::stringstream ss(s);
64201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::string item;
65201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  while(std::getline(ss, item, delim)) {
66201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    elems.push_back(item);
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
68201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return elems;
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
71201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochstd::vector<std::string> split(const std::string &s, char delim) {
72201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  std::vector<std::string> elems;
73201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return split(s, delim, elems);
74201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool GotQuitFromStdin() {
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Make stdin nonblocking. Yes this is done each time. Oh well.
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  fcntl(0, F_SETFL, O_NONBLOCK);
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char c;
8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string maybequit;
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  while (read(0, &c, 1) > 0) {
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    maybequit += c;
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (maybequit.size()) {
85201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    VLOG(1) << "scanning string: \"" << maybequit << "\"";
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return (maybequit.size() > 1 &&
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          (maybequit.c_str()[0] == 'q' ||
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott           maybequit.c_str()[0] == 'Q'));
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char* BoolToStr(bool b) {
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (b)
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return "true";
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return "false";
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott////////////////////////////////////////////////////////////////////////////////
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic bool wantExit = false;
10172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic bool wantLogClose = false;
10272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SignalHandler(int signum)
10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen{
10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  switch(signum) {
10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case SIGTERM:
10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case SIGINT:
10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      wantExit = true;
10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case SIGHUP:
11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      wantLogClose = true;
11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
11572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic int OpenPidFile(const char *pidfile)
11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen{
11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int fd;
11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  struct stat pid_stat;
11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int ret;
12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  fd = open(pidfile, O_RDWR | O_CREAT, 0600);
12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (fd == -1) {
12372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      cerr << "Could not open pid file '" << pidfile << "' for reading.\n";
12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      exit(1);
12572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
12672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ret = flock(fd, LOCK_EX | LOCK_NB);
12872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (ret == -1) {
12972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (errno == EWOULDBLOCK) {
13072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      cerr << "Flip server is already running.\n";
13172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    } else {
13272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      cerr << "Error getting lock on pid file: " << strerror(errno) << "\n";
13372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
13472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    exit(1);
13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
13672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
13772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (fstat(fd, &pid_stat) == -1) {
13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    cerr << "Could not stat pid file '" << pidfile << "': " << strerror(errno)
13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen         << "\n";
14072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
14172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (pid_stat.st_size != 0) {
14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (ftruncate(fd, pid_stat.st_size) == -1) {
14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      cerr << "Could not truncate pid file '" << pidfile << "': "
14472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen           << strerror(errno) << "\n";
14572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
14672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
14772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  char pid_str[8];
14972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  snprintf(pid_str, sizeof(pid_str), "%d", getpid());
15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int bytes = static_cast<int>(strlen(pid_str));
15172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (write(fd, pid_str, strlen(pid_str)) != bytes) {
15272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    cerr << "Could not write pid file: " << strerror(errno) << "\n";
15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    close(fd);
15472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    exit(1);
15572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
15672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
15772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return fd;
15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
160201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochint main (int argc, char**argv)
161201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch{
162201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  unsigned int i = 0;
163201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  bool wait_for_iface = false;
16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int pidfile_fd;
165201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
16621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  signal(SIGPIPE, SIG_IGN);
16772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  signal(SIGTERM, SignalHandler);
16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  signal(SIGINT, SignalHandler);
16972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  signal(SIGHUP, SignalHandler);
17021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
171201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  CommandLine::Init(argc, argv);
172201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  CommandLine cl(argc, argv);
173201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
17421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (cl.HasSwitch("help") || argc < 2) {
175201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    cout << argv[0] << " <options>\n";
17621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    cout << "  Proxy options:\n";
17721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    cout << "\t--proxy<1..n>=\"<listen ip>,<listen port>,"
17821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         << "<ssl cert filename>,\n"
17921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         << "\t               <ssl key filename>,<http server ip>,"
18021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         << "<http server port>,\n"
18121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         << "\t               [https server ip],[https server port],"
18221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         << "<spdy only 0|1>\"\n";
18321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    cout << "\t  * The https server ip and port may be left empty if they are"
18421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         << " the same as\n"
18521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         << "\t    the http server fields.\n";
18621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    cout << "\t  * spdy only prevents non-spdy https connections from being"
18721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         << " passed\n"
18821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         << "\t    through the proxy listen ip:port.\n";
189201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    cout << "\t--forward-ip-header=<header name>\n";
19021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    cout << "\n  Server options:\n";
19172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    cout << "\t--spdy-server=\"<listen ip>,<listen port>,[ssl cert filename],"
19272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen         << "\n\t               [ssl key filename]\"\n";
19372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    cout << "\t--http-server=\"<listen ip>,<listen port>,[ssl cert filename],"
19472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen         << "\n\t               [ssl key filename]\"\n";
19521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    cout << "\t  * Leaving the ssl cert and key fields empty will disable ssl"
19621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         << " for the\n"
19721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         << "\t    http and spdy flip servers\n";
19821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    cout << "\n  Global options:\n";
19921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    cout << "\t--logdest=<file|system|both>\n";
200201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    cout << "\t--logfile=<logfile>\n";
201201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    cout << "\t--wait-for-iface\n";
20221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    cout << "\t  * The flip server will block until the listen ip has been"
20321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         << " raised.\n";
204201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    cout << "\t--ssl-session-expiry=<seconds> (default is 300)\n";
20521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    cout << "\t--ssl-disable-compression\n";
20672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    cout << "\t--idle-timeout=<seconds> (default is 300)\n";
20772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    cout << "\t--pidfile=<filepath> (default /var/run/flip-server.pid)\n";
208201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    cout << "\t--help\n";
209201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    exit(0);
210201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
211201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
21272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (cl.HasSwitch("pidfile")) {
21372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    pidfile_fd = OpenPidFile(cl.GetSwitchValueASCII("pidfile").c_str());
21472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else {
21572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    pidfile_fd = OpenPidFile(PIDFILE);
21672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
21772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
21872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  net::OutputOrdering::set_server_think_time_in_s(FLAGS_server_think_time_in_s);
219201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
220201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (cl.HasSwitch("forward-ip-header")) {
22172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    net::SpdySM::set_forward_ip_header(
22272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        cl.GetSwitchValueASCII("forward-ip-header"));
223dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    net::StreamerSM::set_forward_ip_header(
224dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        cl.GetSwitchValueASCII("forward-ip-header"));
225201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
226201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
227201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (cl.HasSwitch("logdest")) {
22872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::string log_dest_value = cl.GetSwitchValueASCII("logdest");
229201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (log_dest_value.compare("file") == 0) {
230201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      g_proxy_config.log_destination_ = logging::LOG_ONLY_TO_FILE;
231201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    } else if (log_dest_value.compare("system") == 0) {
232201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      g_proxy_config.log_destination_ = logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG;
233201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    } else if (log_dest_value.compare("both") == 0) {
234201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      g_proxy_config.log_destination_ =
235201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG;
236201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    } else {
237201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      LOG(FATAL) << "Invalid logging destination value: " << log_dest_value;
238201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
239201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  } else {
240201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    g_proxy_config.log_destination_ = logging::LOG_NONE;
241201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
243201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (cl.HasSwitch("logfile")) {
244201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    g_proxy_config.log_filename_ = cl.GetSwitchValueASCII("logfile");
245201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (g_proxy_config.log_destination_ == logging::LOG_NONE) {
246201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      g_proxy_config.log_destination_ = logging::LOG_ONLY_TO_FILE;
247201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
248201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  } else if (g_proxy_config.log_destination_ == logging::LOG_ONLY_TO_FILE ||
249201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch             g_proxy_config.log_destination_ ==
250201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch             logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG) {
251201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    LOG(FATAL) << "Logging destination requires a log file to be specified.";
252201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
254201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (cl.HasSwitch("wait-for-iface")) {
255201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    wait_for_iface = true;
256201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
258201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (cl.HasSwitch("ssl-session-expiry")) {
25972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::string session_expiry = cl.GetSwitchValueASCII("ssl-session-expiry");
26072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    g_proxy_config.ssl_session_expiry_ = atoi(session_expiry.c_str());
261201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
262201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
26321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (cl.HasSwitch("ssl-disable-compression")) {
26421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    g_proxy_config.ssl_disable_compression_ = true;
26521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
26621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
26772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (cl.HasSwitch("idle-timeout")) {
26872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    g_proxy_config.idle_socket_timeout_s_ =
26972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      atoi(cl.GetSwitchValueASCII("idle-timeout").c_str());
27072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
27172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
27272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (cl.HasSwitch("force_spdy"))
27372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    net::SMConnection::set_force_spdy(true);
27472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
275201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  InitLogging(g_proxy_config.log_filename_.c_str(),
276201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch              g_proxy_config.log_destination_,
277201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch              logging::DONT_LOCK_LOG_FILE,
27872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              logging::APPEND_TO_OLD_LOG_FILE,
27972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen              logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS);
280201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
281201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  LOG(INFO) << "Flip SPDY proxy started with configuration:";
28221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  LOG(INFO) << "Logging destination     : " << g_proxy_config.log_destination_;
28321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  LOG(INFO) << "Log file                : " << g_proxy_config.log_filename_;
28421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  LOG(INFO) << "Forward IP Header       : "
28572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            << (net::SpdySM::forward_ip_header().length() ?
28672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen               net::SpdySM::forward_ip_header() : "<disabled>");
28721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  LOG(INFO) << "Wait for interfaces     : " << (wait_for_iface?"true":"false");
28821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  LOG(INFO) << "Accept backlog size     : " << FLAGS_accept_backlog_size;
28921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  LOG(INFO) << "Accepts per wake        : " << FLAGS_accepts_per_wake;
29021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  LOG(INFO) << "Disable nagle           : "
291201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch            << (FLAGS_disable_nagle?"true":"false");
29272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  LOG(INFO) << "Reuseport               : "
29372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            << (FLAGS_reuseport?"true":"false");
29472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  LOG(INFO) << "Force SPDY              : "
29572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            << (FLAGS_force_spdy?"true":"false");
29621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  LOG(INFO) << "SSL session expiry      : "
29721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            << g_proxy_config.ssl_session_expiry_;
29821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  LOG(INFO) << "SSL disable compression : "
29921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            << g_proxy_config.ssl_disable_compression_;
30072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  LOG(INFO) << "Connection idle timeout : "
30172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            << g_proxy_config.idle_socket_timeout_s_;
302201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
303201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Proxy Acceptors
304201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  while (true) {
305201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    i += 1;
306201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    std::stringstream name;
307201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    name << "proxy" << i;
308201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (!cl.HasSwitch(name.str())) {
309201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      break;
310201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
31172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::string value = cl.GetSwitchValueASCII(name.str());
31272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::vector<std::string> valueArgs = split(value, ',');
31321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    CHECK_EQ((unsigned int)9, valueArgs.size());
31421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    int spdy_only = atoi(valueArgs[8].c_str());
315201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // If wait_for_iface is enabled, then this call will block
316201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // indefinitely until the interface is raised.
31772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    g_proxy_config.AddAcceptor(net::FLIP_HANDLER_PROXY,
318201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               valueArgs[0], valueArgs[1],
319201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               valueArgs[2], valueArgs[3],
320201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               valueArgs[4], valueArgs[5],
32121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                               valueArgs[6], valueArgs[7],
32221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                               spdy_only,
323201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               FLAGS_accept_backlog_size,
324201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               FLAGS_disable_nagle,
325201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               FLAGS_accepts_per_wake,
326201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               FLAGS_reuseport,
327201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               wait_for_iface,
328201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               NULL);
329201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
330201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
331201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Spdy Server Acceptor
33272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  net::MemoryCache spdy_memory_cache;
333201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (cl.HasSwitch("spdy-server")) {
334201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    spdy_memory_cache.AddFiles();
33572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::string value = cl.GetSwitchValueASCII("spdy-server");
33672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::vector<std::string> valueArgs = split(value, ',');
33772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    g_proxy_config.AddAcceptor(net::FLIP_HANDLER_SPDY_SERVER,
338201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               valueArgs[0], valueArgs[1],
339201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               valueArgs[2], valueArgs[3],
34021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                               "", "", "", "",
34121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                               0,
342201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               FLAGS_accept_backlog_size,
343201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               FLAGS_disable_nagle,
344201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               FLAGS_accepts_per_wake,
345201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               FLAGS_reuseport,
346201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               wait_for_iface,
347201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               &spdy_memory_cache);
348201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
349201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
350201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Spdy Server Acceptor
35172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  net::MemoryCache http_memory_cache;
352201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (cl.HasSwitch("http-server")) {
353201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    http_memory_cache.AddFiles();
35472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::string value = cl.GetSwitchValueASCII("http-server");
35572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::vector<std::string> valueArgs = split(value, ',');
35672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    g_proxy_config.AddAcceptor(net::FLIP_HANDLER_HTTP_SERVER,
357201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               valueArgs[0], valueArgs[1],
358201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               valueArgs[2], valueArgs[3],
35921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                               "", "", "", "",
36021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                               0,
361201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               FLAGS_accept_backlog_size,
362201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               FLAGS_disable_nagle,
363201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               FLAGS_accepts_per_wake,
364201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               FLAGS_reuseport,
365201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               wait_for_iface,
366201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                               &http_memory_cache);
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
368201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
36972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::vector<net::SMAcceptorThread*> sm_worker_threads_;
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
371201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  for (i = 0; i < g_proxy_config.acceptors_.size(); i++) {
37272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    net::FlipAcceptor *acceptor = g_proxy_config.acceptors_[i];
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
37472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    sm_worker_threads_.push_back(
37572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        new net::SMAcceptorThread(acceptor,
37672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                  (net::MemoryCache *)acceptor->memory_cache_));
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Note that spdy_memory_cache is not threadsafe, it is merely
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // thread compatible. Thus, if ever we are to spawn multiple threads,
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // we either must make the MemoryCache threadsafe, or use
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // a separate MemoryCache for each thread.
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    //
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // The latter is what is currently being done as we spawn
383201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // a separate thread for each http and spdy server acceptor.
384201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    sm_worker_threads_.back()->InitWorker();
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    sm_worker_threads_.back()->Start();
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
38972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  while (!wantExit) {
39072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Close logfile when HUP signal is received. Logging system will
39172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // automatically reopen on next log message.
39272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if ( wantLogClose ) {
39372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      wantLogClose = false;
39472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      VLOG(1) << "HUP received, reopening log file.";
39572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      logging::CloseLogFile();
39672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (GotQuitFromStdin()) {
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      for (unsigned int i = 0; i < sm_worker_threads_.size(); ++i) {
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        sm_worker_threads_[i]->Quit();
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      for (unsigned int i = 0; i < sm_worker_threads_.size(); ++i) {
402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        sm_worker_threads_[i]->Join();
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
40472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    usleep(1000*10);  // 10 ms
407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
408201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
40972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  unlink(PIDFILE);
41072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  close(pidfile_fd);
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return 0;
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
41372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
414