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