15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <signal.h>
7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include <stdio.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/file.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/stat.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h"
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/tools/balsa/split.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/acceptor_thread.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/constants.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/flip_config.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/output_ordering.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/sm_connection.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/sm_interface.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/spdy_interface.h"
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/tools/flip_server/streamer_interface.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If true, then disables the nagle algorithm);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FLAGS_disable_nagle = true;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The number of times that accept() will be called when the
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  alarm goes off when the accept_using_alarm flag is set to true.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  If set to 0, accept() will be performed until the accept queue
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  is completely drained and the accept() call returns an error);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32 FLAGS_accepts_per_wake = 0;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The size of the TCP accept backlog);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32 FLAGS_accept_backlog_size = 1024;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If set to false a single socket will be used. If set to true
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  then a new socket will be created for each accept thread.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  Note that this only works with kernels that support
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  SO_REUSEPORT);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FLAGS_reuseport = false;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Flag to force spdy, even if NPN is not negotiated.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FLAGS_force_spdy = false;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The amount of time the server delays before sending back the
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  reply);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double FLAGS_server_think_time_in_s = 0;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)net::FlipConfig g_proxy_config;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)std::vector<std::string>& split(const std::string& s,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                char delim,
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                std::vector<std::string>& elems) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::stringstream ss(s);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string item;
60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  while (std::getline(ss, item, delim)) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elems.push_back(item);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return elems;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)std::vector<std::string> split(const std::string& s, char delim) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> elems;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return split(s, delim, elems);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GotQuitFromStdin() {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make stdin nonblocking. Yes this is done each time. Oh well.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fcntl(0, F_SETFL, O_NONBLOCK);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char c;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string maybequit;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (read(0, &c, 1) > 0) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    maybequit += c;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (maybequit.size()) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "scanning string: \"" << maybequit << "\"";
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (maybequit.size() > 1 &&
83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          (maybequit.c_str()[0] == 'q' || maybequit.c_str()[0] == 'Q'));
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BoolToStr(bool b) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (b)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "true";
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "false";
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool wantExit = false;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool wantLogClose = false;
94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SignalHandler(int signum) {
95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  switch (signum) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SIGTERM:
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SIGINT:
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wantExit = true;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SIGHUP:
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wantLogClose = true;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)static int OpenPidFile(const char* pidfile) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fd;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct stat pid_stat;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ret;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fd = open(pidfile, O_RDWR | O_CREAT, 0600);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fd == -1) {
113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    fprintf(stderr, "Could not open pid file '%s' for reading.\n", pidfile);
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    exit(1);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ret = flock(fd, LOCK_EX | LOCK_NB);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ret == -1) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (errno == EWOULDBLOCK) {
120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      fprintf(stderr, "Flip server is already running.\n");
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      perror("Error getting lock on pid file");
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exit(1);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (fstat(fd, &pid_stat) == -1) {
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    fprintf(
129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        stderr, "Could not stat pid file '%s': %s\n", pidfile, strerror(errno));
130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    exit(1);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pid_stat.st_size != 0) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ftruncate(fd, pid_stat.st_size) == -1) {
134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      fprintf(stderr,
135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              "Could not truncate pid file '%s': %s\n",
136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              pidfile,
137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              strerror(errno));
138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      exit(1);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char pid_str[8];
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  snprintf(pid_str, sizeof(pid_str), "%d", getpid());
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bytes = static_cast<int>(strlen(pid_str));
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (write(fd, pid_str, strlen(pid_str)) != bytes) {
146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    perror("Could not write pid file");
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    close(fd);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exit(1);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return fd;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)int main(int argc, char** argv) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int i = 0;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool wait_for_iface = false;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pidfile_fd;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal(SIGPIPE, SIG_IGN);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal(SIGTERM, SignalHandler);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal(SIGINT, SignalHandler);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal(SIGHUP, SignalHandler);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::CommandLine::Init(argc, argv);
16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::CommandLine cl(argc, argv);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cl.HasSwitch("help") || argc < 2) {
168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    printf("%s <options>\n", argv[0]);
169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    printf("  Proxy options:\n");
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    printf(
171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t--proxy<1..n>=\"<listen ip>,<listen port>,"
172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "<ssl cert filename>,\n"
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t               <ssl key filename>,<http server ip>,"
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "<http server port>,\n"
175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t               [https server ip],[https server port],"
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "<spdy only 0|1>\"\n"
177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t  * The https server ip and port may be left empty if they are"
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        " the same as\n"
179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t    the http server fields.\n"
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t  * spdy only prevents non-spdy https connections from being"
181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        " passed\n"
182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t    through the proxy listen ip:port.\n"
183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t--forward-ip-header=<header name>\n"
184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\n  Server options:\n"
185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t--spdy-server=\"<listen ip>,<listen port>,[ssl cert filename],"
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\n\t               [ssl key filename]\"\n"
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t--http-server=\"<listen ip>,<listen port>,[ssl cert filename],"
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\n\t               [ssl key filename]\"\n"
189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t  * Leaving the ssl cert and key fields empty will disable ssl"
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        " for the\n"
191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t    http and spdy flip servers\n"
192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\n  Global options:\n"
193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t--logdest=<file|system|both>\n"
194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t--logfile=<logfile>\n"
195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t--wait-for-iface\n"
196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t  * The flip server will block until the listen ip has been"
197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        " raised.\n"
198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t--ssl-session-expiry=<seconds> (default is 300)\n"
199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t--ssl-disable-compression\n"
200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t--idle-timeout=<seconds> (default is 300)\n"
201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t--pidfile=<filepath> (default /var/run/flip-server.pid)\n"
202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        "\t--help\n");
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exit(0);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cl.HasSwitch("pidfile")) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pidfile_fd = OpenPidFile(cl.GetSwitchValueASCII("pidfile").c_str());
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pidfile_fd = OpenPidFile(PIDFILE);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::OutputOrdering::set_server_think_time_in_s(FLAGS_server_think_time_in_s);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cl.HasSwitch("forward-ip-header")) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::SpdySM::set_forward_ip_header(
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cl.GetSwitchValueASCII("forward-ip-header"));
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::StreamerSM::set_forward_ip_header(
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cl.GetSwitchValueASCII("forward-ip-header"));
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cl.HasSwitch("logdest")) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string log_dest_value = cl.GetSwitchValueASCII("logdest");
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (log_dest_value.compare("file") == 0) {
224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      g_proxy_config.log_destination_ = logging::LOG_TO_FILE;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (log_dest_value.compare("system") == 0) {
226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      g_proxy_config.log_destination_ = logging::LOG_TO_SYSTEM_DEBUG_LOG;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (log_dest_value.compare("both") == 0) {
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      g_proxy_config.log_destination_ = logging::LOG_TO_ALL;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(FATAL) << "Invalid logging destination value: " << log_dest_value;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_proxy_config.log_destination_ = logging::LOG_NONE;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cl.HasSwitch("logfile")) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_proxy_config.log_filename_ = cl.GetSwitchValueASCII("logfile");
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (g_proxy_config.log_destination_ == logging::LOG_NONE) {
239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      g_proxy_config.log_destination_ = logging::LOG_TO_FILE;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } else if ((g_proxy_config.log_destination_ & logging::LOG_TO_FILE) != 0) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(FATAL) << "Logging destination requires a log file to be specified.";
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cl.HasSwitch("wait-for-iface")) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wait_for_iface = true;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cl.HasSwitch("ssl-session-expiry")) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string session_expiry = cl.GetSwitchValueASCII("ssl-session-expiry");
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_proxy_config.ssl_session_expiry_ = atoi(session_expiry.c_str());
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cl.HasSwitch("ssl-disable-compression")) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_proxy_config.ssl_disable_compression_ = true;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cl.HasSwitch("idle-timeout")) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_proxy_config.idle_socket_timeout_s_ =
260a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        atoi(cl.GetSwitchValueASCII("idle-timeout").c_str());
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cl.HasSwitch("force_spdy"))
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::SMConnection::set_force_spdy(true);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
266eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  logging::LoggingSettings settings;
267eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  settings.logging_dest = g_proxy_config.log_destination_;
268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  settings.log_file = g_proxy_config.log_filename_.c_str();
269eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  settings.lock_log = logging::DONT_LOCK_LOG_FILE;
270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  logging::InitLogging(settings);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "Flip SPDY proxy started with configuration:";
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "Logging destination     : " << g_proxy_config.log_destination_;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "Log file                : " << g_proxy_config.log_filename_;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "Forward IP Header       : "
276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            << (net::SpdySM::forward_ip_header().length()
277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                    ? net::SpdySM::forward_ip_header()
278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                    : "<disabled>");
279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LOG(INFO) << "Wait for interfaces     : " << (wait_for_iface ? "true"
280a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                               : "false");
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "Accept backlog size     : " << FLAGS_accept_backlog_size;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "Accepts per wake        : " << FLAGS_accepts_per_wake;
283a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LOG(INFO) << "Disable nagle           : " << (FLAGS_disable_nagle ? "true"
284a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                                    : "false");
285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LOG(INFO) << "Reuseport               : " << (FLAGS_reuseport ? "true"
286a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                                : "false");
287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  LOG(INFO) << "Force SPDY              : " << (FLAGS_force_spdy ? "true"
288a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                                 : "false");
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "SSL session expiry      : "
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << g_proxy_config.ssl_session_expiry_;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "SSL disable compression : "
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << g_proxy_config.ssl_disable_compression_;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "Connection idle timeout : "
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << g_proxy_config.idle_socket_timeout_s_;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Proxy Acceptors
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i += 1;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::stringstream name;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    name << "proxy" << i;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!cl.HasSwitch(name.str())) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string value = cl.GetSwitchValueASCII(name.str());
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string> valueArgs = split(value, ',');
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_EQ((unsigned int)9, valueArgs.size());
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int spdy_only = atoi(valueArgs[8].c_str());
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If wait_for_iface is enabled, then this call will block
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // indefinitely until the interface is raised.
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_proxy_config.AddAcceptor(net::FLIP_HANDLER_PROXY,
311a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               valueArgs[0],
312a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               valueArgs[1],
313a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               valueArgs[2],
314a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               valueArgs[3],
315a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               valueArgs[4],
316a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               valueArgs[5],
317a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               valueArgs[6],
318a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               valueArgs[7],
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               spdy_only,
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               FLAGS_accept_backlog_size,
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               FLAGS_disable_nagle,
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               FLAGS_accepts_per_wake,
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               FLAGS_reuseport,
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               wait_for_iface,
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               NULL);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Spdy Server Acceptor
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::MemoryCache spdy_memory_cache;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cl.HasSwitch("spdy-server")) {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    spdy_memory_cache.AddFiles();
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string value = cl.GetSwitchValueASCII("spdy-server");
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string> valueArgs = split(value, ',');
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (valueArgs.size() < 4)
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      valueArgs.push_back(std::string());
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_proxy_config.AddAcceptor(net::FLIP_HANDLER_SPDY_SERVER,
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               valueArgs[0],
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               valueArgs[1],
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               valueArgs[2],
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               valueArgs[3],
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               std::string(),
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               std::string(),
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               std::string(),
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               std::string(),
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               0,
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               FLAGS_accept_backlog_size,
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               FLAGS_disable_nagle,
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               FLAGS_accepts_per_wake,
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               FLAGS_reuseport,
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               wait_for_iface,
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               &spdy_memory_cache);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Spdy Server Acceptor
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::MemoryCache http_memory_cache;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cl.HasSwitch("http-server")) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    http_memory_cache.AddFiles();
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string value = cl.GetSwitchValueASCII("http-server");
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string> valueArgs = split(value, ',');
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (valueArgs.size() < 4)
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      valueArgs.push_back(std::string());
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_proxy_config.AddAcceptor(net::FLIP_HANDLER_HTTP_SERVER,
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               valueArgs[0],
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               valueArgs[1],
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               valueArgs[2],
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               valueArgs[3],
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               std::string(),
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               std::string(),
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               std::string(),
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               std::string(),
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               0,
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               FLAGS_accept_backlog_size,
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               FLAGS_disable_nagle,
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               FLAGS_accepts_per_wake,
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               FLAGS_reuseport,
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               wait_for_iface,
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               &http_memory_cache);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<net::SMAcceptorThread*> sm_worker_threads_;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < g_proxy_config.acceptors_.size(); i++) {
383a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    net::FlipAcceptor* acceptor = g_proxy_config.acceptors_[i];
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    sm_worker_threads_.push_back(new net::SMAcceptorThread(
386a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        acceptor, (net::MemoryCache*)acceptor->memory_cache_));
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that spdy_memory_cache is not threadsafe, it is merely
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // thread compatible. Thus, if ever we are to spawn multiple threads,
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we either must make the MemoryCache threadsafe, or use
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // a separate MemoryCache for each thread.
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The latter is what is currently being done as we spawn
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // a separate thread for each http and spdy server acceptor.
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sm_worker_threads_.back()->InitWorker();
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sm_worker_threads_.back()->Start();
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!wantExit) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Close logfile when HUP signal is received. Logging system will
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // automatically reopen on next log message.
402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (wantLogClose) {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wantLogClose = false;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << "HUP received, reopening log file.";
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging::CloseLogFile();
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (GotQuitFromStdin()) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (unsigned int i = 0; i < sm_worker_threads_.size(); ++i) {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sm_worker_threads_[i]->Quit();
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (unsigned int i = 0; i < sm_worker_threads_.size(); ++i) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sm_worker_threads_[i]->Join();
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
416a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    usleep(1000 * 10);  // 10 ms
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unlink(PIDFILE);
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  close(pidfile_fd);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
423