| Index: tools/android/forwarder2/host_forwarder_main.cc | 
| diff --git a/tools/android/forwarder2/host_forwarder_main.cc b/tools/android/forwarder2/host_forwarder_main.cc | 
| index d7f52d157e033815dc8f00aaab0809b68e51dde5..435cae43194dd449c8dcbce8c080e339fb73229d 100644 | 
| --- a/tools/android/forwarder2/host_forwarder_main.cc | 
| +++ b/tools/android/forwarder2/host_forwarder_main.cc | 
| @@ -4,14 +4,15 @@ | 
|  | 
| #include <errno.h> | 
| #include <signal.h> | 
| -#include <stdio.h> | 
| -#include <stdlib.h> | 
| #include <unistd.h> | 
|  | 
| -#include <vector> | 
| +#include <cstdio> | 
| +#include <cstring> | 
| #include <string> | 
| +#include <vector> | 
|  | 
| #include "base/command_line.h" | 
| +#include "base/compiler_specific.h" | 
| #include "base/file_path.h" | 
| #include "base/file_util.h" | 
| #include "base/logging.h" | 
| @@ -29,26 +30,36 @@ | 
| #include "tools/android/forwarder2/pipe_notifier.h" | 
| #include "tools/android/forwarder2/socket.h" | 
|  | 
| -using base::StringToInt; | 
| - | 
| namespace forwarder2 { | 
| namespace { | 
|  | 
| +const char kLogFilePath[] = "/tmp/host_forwarder_log"; | 
| const char kPIDFilePath[] = "/tmp/host_forwarder_pid"; | 
| -const char kCommandSocketPath[] = "host_forwarder_command_socket"; | 
| -const char kWelcomeMessage[] = "forwarder2"; | 
| +const char kDaemonIdentifier[] = "chrome_host_forwarder_daemon"; | 
| + | 
| +const char kKillServerCommand[] = "kill-server"; | 
| +const char kForwardCommand[] = "forward"; | 
| + | 
| const int kBufSize = 256; | 
|  | 
| -// Need to be global to be able to accessed from the signal handler. | 
| -PipeNotifier* g_notifier; | 
| +// Needs to be global to be able to be accessed from the signal handler. | 
| +PipeNotifier* g_notifier = NULL; | 
| + | 
| +// Lets the daemon fetch the exit notifier file descriptor. | 
| +int GetExitNotifierFD() { | 
| +  DCHECK(g_notifier); | 
| +  return g_notifier->receiver_fd(); | 
| +} | 
|  | 
| void KillHandler(int signal_number) { | 
| +  char buf[kBufSize]; | 
| if (signal_number != SIGTERM && signal_number != SIGINT) { | 
| -    char buf[kBufSize]; | 
| snprintf(buf, sizeof(buf), "Ignoring unexpected signal %d.", signal_number); | 
| SIGNAL_SAFE_LOG(WARNING, buf); | 
| return; | 
| } | 
| +  snprintf(buf, sizeof(buf), "Received signal %d.", signal_number); | 
| +  SIGNAL_SAFE_LOG(WARNING, buf); | 
| static int s_kill_handler_count = 0; | 
| CHECK(g_notifier); | 
| // If for some reason the forwarder get stuck in any socket waiting forever, | 
| @@ -59,34 +70,6 @@ void KillHandler(int signal_number) { | 
| exit(1); | 
| } | 
|  | 
| -enum { | 
| -  kConnectSingleTry = 1, | 
| -  kConnectNoIdleTime = 0, | 
| -}; | 
| - | 
| -scoped_ptr<Socket> ConnectToDaemon(int tries_count, int idle_time_msec) { | 
| -  for (int i = 0; i < tries_count; ++i) { | 
| -    scoped_ptr<Socket> socket(new Socket()); | 
| -    if (!socket->ConnectUnix(kCommandSocketPath, true)) { | 
| -      if (idle_time_msec) | 
| -        usleep(idle_time_msec * 1000); | 
| -      continue; | 
| -    } | 
| -    char buf[sizeof(kWelcomeMessage)]; | 
| -    memset(buf, 0, sizeof(buf)); | 
| -    if (socket->Read(buf, sizeof(buf)) < 0) { | 
| -      perror("read"); | 
| -      continue; | 
| -    } | 
| -    if (strcmp(buf, kWelcomeMessage)) { | 
| -      LOG(ERROR) << "Unexpected message read from daemon: " << buf; | 
| -      break; | 
| -    } | 
| -    return socket.Pass(); | 
| -  } | 
| -  return scoped_ptr<Socket>(NULL); | 
| -} | 
| - | 
| // Format of |command|: | 
| //   <ADB port>:<Device port>[:<Forward to port>:<Forward to address>]. | 
| bool ParseForwardCommand(const std::string& command, | 
| @@ -98,12 +81,12 @@ bool ParseForwardCommand(const std::string& command, | 
| base::SplitString(command, ':', &command_pieces); | 
|  | 
| if (command_pieces.size() < 2 || | 
| -      !StringToInt(command_pieces[0], adb_port) || | 
| -      !StringToInt(command_pieces[1], device_port)) | 
| +      !base::StringToInt(command_pieces[0], adb_port) || | 
| +      !base::StringToInt(command_pieces[1], device_port)) | 
| return false; | 
|  | 
| if (command_pieces.size() > 2) { | 
| -    if (!StringToInt(command_pieces[2], forward_to_port)) | 
| +    if (!base::StringToInt(command_pieces[2], forward_to_port)) | 
| return false; | 
| if (command_pieces.size() > 3) | 
| *forward_to_host = command_pieces[3]; | 
| @@ -121,44 +104,30 @@ bool IsForwardCommandValid(const std::string& command) { | 
| command, &adb_port, &device_port, &forward_to_host, &forward_to_port); | 
| } | 
|  | 
| -bool DaemonHandler() { | 
| -  LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")"; | 
| -  DCHECK(!g_notifier); | 
| -  g_notifier = new PipeNotifier(); | 
| - | 
| -  const int notifier_fd = g_notifier->receiver_fd(); | 
| -  Socket command_socket; | 
| -  if (!command_socket.BindUnix(kCommandSocketPath, true)) { | 
| -    LOG(ERROR) << "Could not bind Unix Domain Socket"; | 
| -    return false; | 
| -  } | 
| -  command_socket.set_exit_notifier_fd(notifier_fd); | 
| +class ServerDelegate : public Daemon::ServerDelegate { | 
| + public: | 
| +  ServerDelegate() : has_failed_(false) {} | 
|  | 
| -  signal(SIGTERM, KillHandler); | 
| -  signal(SIGINT, KillHandler); | 
| +  bool has_failed() const { return has_failed_; } | 
|  | 
| -  ScopedVector<HostController> controllers; | 
| -  int failed_count = 0; | 
| +  // Daemon::ServerDelegate: | 
| +  virtual void Init() OVERRIDE { | 
| +    LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")"; | 
| +    DCHECK(!g_notifier); | 
| +    g_notifier = new PipeNotifier(); | 
| +    signal(SIGTERM, KillHandler); | 
| +    signal(SIGINT, KillHandler); | 
| +  } | 
|  | 
| -  for (;;) { | 
| -    Socket client_socket; | 
| -    if (!command_socket.Accept(&client_socket)) { | 
| -      if (command_socket.exited()) | 
| -        return true; | 
| -      PError("Accept()"); | 
| -      return false; | 
| -    } | 
| -    if (!client_socket.Write(kWelcomeMessage, sizeof(kWelcomeMessage))) { | 
| -      PError("Write()"); | 
| -      continue; | 
| -    } | 
| +  virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE { | 
| char buf[kBufSize]; | 
| -    const int bytes_read = client_socket.Read(buf, sizeof(buf)); | 
| +    const int bytes_read = client_socket->Read(buf, sizeof(buf)); | 
| if (bytes_read <= 0) { | 
| -      if (client_socket.exited()) | 
| -        break; | 
| +      if (client_socket->exited()) | 
| +        return; | 
| PError("Read()"); | 
| -      ++failed_count; | 
| +      has_failed_ = true; | 
| +      return; | 
| } | 
| const std::string command(buf, bytes_read); | 
| int adb_port = 0; | 
| @@ -168,41 +137,81 @@ bool DaemonHandler() { | 
| const bool succeeded = ParseForwardCommand( | 
| command, &adb_port, &device_port, &forward_to_host, &forward_to_port); | 
| if (!succeeded) { | 
| -      ++failed_count; | 
| -      client_socket.WriteString( | 
| +      has_failed_ = true; | 
| +      client_socket->WriteString( | 
| base::StringPrintf("ERROR: Could not parse forward command '%s'", | 
| command.c_str())); | 
| -      continue; | 
| +      return; | 
| } | 
| scoped_ptr<HostController> host_controller( | 
| new HostController(device_port, forward_to_host, forward_to_port, | 
| -                           adb_port, notifier_fd)); | 
| +                           adb_port, GetExitNotifierFD())); | 
| if (!host_controller->Connect()) { | 
| -      ++failed_count; | 
| -      client_socket.WriteString("ERROR: Connection to device failed."); | 
| -      continue; | 
| +      has_failed_ = true; | 
| +      client_socket->WriteString("ERROR: Connection to device failed."); | 
| +      return; | 
| } | 
| // Get the current allocated port. | 
| device_port = host_controller->device_port(); | 
| LOG(INFO) << "Forwarding device port " << device_port << " to host " | 
| << forward_to_host << ":" << forward_to_port; | 
| -    if (!client_socket.WriteString( | 
| +    if (!client_socket->WriteString( | 
| base::StringPrintf("%d:%d", device_port, forward_to_port))) { | 
| -      ++failed_count; | 
| -      continue; | 
| +      has_failed_ = true; | 
| +      return; | 
| } | 
| host_controller->Start(); | 
| -    controllers.push_back(host_controller.release()); | 
| +    controllers_.push_back(host_controller.release()); | 
| } | 
| -  for (int i = 0; i < controllers.size(); ++i) | 
| -    controllers[i]->Join(); | 
|  | 
| -  if (controllers.size() == 0) { | 
| -    LOG(ERROR) << "No forwarder servers could be started. Exiting."; | 
| -    return false; | 
| +  virtual void OnServerExited() OVERRIDE { | 
| +    for (int i = 0; i < controllers_.size(); ++i) | 
| +      controllers_[i]->Join(); | 
| +    if (controllers_.size() == 0) { | 
| +      LOG(ERROR) << "No forwarder servers could be started. Exiting."; | 
| +      has_failed_ = true; | 
| +    } | 
| +  } | 
| + | 
| + private: | 
| +  ScopedVector<HostController> controllers_; | 
| +  bool has_failed_; | 
| + | 
| +  DISALLOW_COPY_AND_ASSIGN(ServerDelegate); | 
| +}; | 
| + | 
| +class ClientDelegate : public Daemon::ClientDelegate { | 
| + public: | 
| +  ClientDelegate(const std::string& forward_command) | 
| +      : forward_command_(forward_command), | 
| +        has_failed_(false) { | 
| } | 
| -  return true; | 
| -} | 
| + | 
| +  bool has_failed() const { return has_failed_; } | 
| + | 
| +  // Daemon::ClientDelegate: | 
| +  virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE { | 
| +    // Send the forward command to the daemon. | 
| +    CHECK(daemon_socket->WriteString(forward_command_)); | 
| +    char buf[kBufSize]; | 
| +    const int bytes_read = daemon_socket->Read( | 
| +        buf, sizeof(buf) - 1 /* leave space for null terminator */); | 
| +    CHECK_GT(bytes_read, 0); | 
| +    DCHECK(bytes_read < sizeof(buf)); | 
| +    buf[bytes_read] = 0; | 
| +    base::StringPiece msg(buf, bytes_read); | 
| +    if (msg.starts_with("ERROR")) { | 
| +      LOG(ERROR) << msg; | 
| +      has_failed_ = true; | 
| +      return; | 
| +    } | 
| +    printf("%s\n", buf); | 
| +  } | 
| + | 
| + private: | 
| +  const std::string forward_command_; | 
| +  bool has_failed_; | 
| +}; | 
|  | 
| void PrintUsage(const char* program_name) { | 
| LOG(ERROR) << program_name << " adb_port:from_port:to_port:to_host\n" | 
| @@ -215,63 +224,36 @@ int RunHostForwarder(int argc, char** argv) { | 
| return 1; | 
| } | 
| const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | 
| -  std::string command; | 
| +  const char* command = NULL; | 
| int adb_port = 0; | 
| if (argc != 2) { | 
| PrintUsage(argv[0]); | 
| return 1; | 
| } | 
| -  if (!strcmp(argv[1], "kill-server")) { | 
| -    command = "kill-server"; | 
| +  if (!strcmp(argv[1], kKillServerCommand)) { | 
| +    command = kKillServerCommand; | 
| } else { | 
| -    command = "forward"; | 
| +    command = kForwardCommand; | 
| if (!IsForwardCommandValid(argv[1])) { | 
| PrintUsage(argv[0]); | 
| return 1; | 
| } | 
| } | 
|  | 
| -  Daemon daemon(kPIDFilePath); | 
| +  ClientDelegate client_delegate(argv[1]); | 
| +  ServerDelegate daemon_delegate; | 
| +  Daemon daemon( | 
| +      kLogFilePath, kPIDFilePath, kDaemonIdentifier, &client_delegate, | 
| +      &daemon_delegate, &GetExitNotifierFD); | 
|  | 
| -  if (command == "kill-server") | 
| +  if (command == kKillServerCommand) | 
| return !daemon.Kill(); | 
|  | 
| -  bool is_daemon = false; | 
| -  scoped_ptr<Socket> daemon_socket = ConnectToDaemon( | 
| -      kConnectSingleTry, kConnectNoIdleTime); | 
| -  if (!daemon_socket) { | 
| -    if (!daemon.Spawn(&is_daemon)) | 
| -      return 1; | 
| -  } | 
| - | 
| -  if (is_daemon) | 
| -    return !DaemonHandler(); | 
| - | 
| -  if (!daemon_socket) { | 
| -    const int kTries = 10; | 
| -    const int kIdleTimeMsec = 10; | 
| -    daemon_socket = ConnectToDaemon(kTries, kIdleTimeMsec); | 
| -    if (!daemon_socket) { | 
| -      LOG(ERROR) << "Could not connect to daemon."; | 
| -      return 1; | 
| -    } | 
| -  } | 
| - | 
| -  // Send the forward command to the daemon. | 
| -  CHECK(daemon_socket->Write(argv[1], strlen(argv[1]))); | 
| -  char buf[kBufSize]; | 
| -  const int bytes_read = daemon_socket->Read( | 
| -      buf, sizeof(buf) - 1 /* leave space for null terminator */); | 
| -  CHECK_GT(bytes_read, 0); | 
| -  DCHECK(bytes_read < sizeof(buf)); | 
| -  buf[bytes_read] = 0; | 
| -  base::StringPiece msg(buf, bytes_read); | 
| -  if (msg.starts_with("ERROR")) { | 
| -    LOG(ERROR) << msg; | 
| +  DCHECK(command == kForwardCommand); | 
| +  if (!daemon.SpawnIfNeeded()) | 
| return 1; | 
| -  } | 
| -  printf("%s\n", buf); | 
| -  return 0; | 
| + | 
| +  return client_delegate.has_failed() || daemon_delegate.has_failed(); | 
| } | 
|  | 
| }  // namespace | 
|  |