15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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>
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <sys/types.h>
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <sys/wait.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <cstdio>
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <iostream>
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <limits>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <utility>
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/at_exit.h"
19d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/basictypes.h"
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/bind.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h"
237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/containers/hash_tables.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/memory/linked_ptr.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h"
29d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/memory/weak_ptr.h"
307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/pickle.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/safe_strerror_posix.h"
325e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
355e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
365e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/task_runner.h"
387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/threading/thread.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/forwarder2/common.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/forwarder2/daemon.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/forwarder2/host_controller.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/forwarder2/pipe_notifier.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/forwarder2/socket.h"
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "tools/android/forwarder2/util.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace forwarder2 {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kLogFilePath[] = "/tmp/host_forwarder_log";
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kDaemonIdentifier[] = "chrome_host_forwarder_daemon";
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kKillServerCommand[] = "kill-server";
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kForwardCommand[] = "forward";
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kBufSize = 256;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Needs to be global to be able to be accessed from the signal handler.
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PipeNotifier* g_notifier = NULL;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Lets the daemon fetch the exit notifier file descriptor.
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int GetExitNotifierFD() {
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(g_notifier);
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return g_notifier->receiver_fd();
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void KillHandler(int signal_number) {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char buf[kBufSize];
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (signal_number != SIGTERM && signal_number != SIGINT) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    snprintf(buf, sizeof(buf), "Ignoring unexpected signal %d.", signal_number);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SIGNAL_SAFE_LOG(WARNING, buf);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  snprintf(buf, sizeof(buf), "Received signal %d.", signal_number);
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SIGNAL_SAFE_LOG(WARNING, buf);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int s_kill_handler_count = 0;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(g_notifier);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If for some reason the forwarder get stuck in any socket waiting forever,
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we can send a SIGKILL or SIGINT three times to force it die
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (non-nicely). This is useful when debugging.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++s_kill_handler_count;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!g_notifier->Notify() || s_kill_handler_count > 2)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exit(1);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// Manages HostController instances. There is one HostController instance for
86d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// each connection being forwarded. Note that forwarding can happen with many
87d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// devices (identified with a serial id).
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochclass HostControllersManager {
897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch public:
90d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  HostControllersManager()
91d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      : weak_ptr_factory_(this),
92d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        controllers_(new HostControllerMap()),
93d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        has_failed_(false) {
94d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
95d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
96d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  ~HostControllersManager() {
97d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (!thread_.get())
98d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      return;
99d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // Delete the controllers on the thread they were created on.
100d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    thread_->message_loop_proxy()->DeleteSoon(
101d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        FROM_HERE, controllers_.release());
102d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void HandleRequest(const std::string& device_serial,
1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                     int device_port,
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                     int host_port,
1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                     scoped_ptr<Socket> client_socket) {
1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // Lazy initialize so that the CLI process doesn't get this thread created.
1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    InitOnce();
1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    thread_->message_loop_proxy()->PostTask(
1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        FROM_HERE,
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        base::Bind(
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            &HostControllersManager::HandleRequestOnInternalThread,
1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            base::Unretained(this), device_serial, device_port, host_port,
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            base::Passed(&client_socket)));
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  bool has_failed() const { return has_failed_; }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch private:
1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  typedef base::hash_map<
1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      std::string, linked_ptr<HostController> > HostControllerMap;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  static std::string MakeHostControllerMapKey(int adb_port, int device_port) {
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return base::StringPrintf("%d:%d", adb_port, device_port);
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void InitOnce() {
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (thread_.get())
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return;
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    at_exit_manager_.reset(new base::AtExitManager());
1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    thread_.reset(new base::Thread("HostControllersManagerThread"));
1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    thread_->Start();
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Invoked when a HostController instance reports an error (e.g. due to a
137d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // device connectivity issue). Note that this could be called after the
138d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // controller manager was destroyed which is why a weak pointer is used.
139d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  static void DeleteHostController(
140d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      const base::WeakPtr<HostControllersManager>& manager_ptr,
141d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      scoped_ptr<HostController> host_controller) {
142d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    HostController* const controller = host_controller.release();
143d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    HostControllersManager* const manager = manager_ptr.get();
144d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (!manager) {
145d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // Note that |controller| is not leaked in this case since the host
146d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // controllers manager owns the controllers. If the manager was deleted
147d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // then all the controllers (including |controller|) were also deleted.
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
150d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    DCHECK(manager->thread_->message_loop_proxy()->RunsTasksOnCurrentThread());
151d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    // Note that this will delete |controller| which is owned by the map.
152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DeleteRefCountedValueInMap(
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        MakeHostControllerMapKey(
154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            controller->adb_port(), controller->device_port()),
155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        manager->controllers_.get());
1567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  void HandleRequestOnInternalThread(const std::string& device_serial,
1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                     int device_port,
1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                     int host_port,
1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                     scoped_ptr<Socket> client_socket) {
1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const int adb_port = GetAdbPortForDevice(device_serial);
1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (adb_port < 0) {
1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      SendMessage(
1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          "ERROR: could not get adb port for device. You might need to add "
1667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          "'adb' to your PATH or provide the device serial id.",
1677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          client_socket.get());
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (device_port < 0) {
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Remove the previously created host controller.
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const std::string controller_key = MakeHostControllerMapKey(
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          adb_port, -device_port);
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      const bool controller_did_exist = DeleteRefCountedValueInMap(
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          controller_key, controllers_.get());
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      SendMessage(
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          !controller_did_exist ? "ERROR: could not unmap port" : "OK",
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          client_socket.get());
1798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      RemoveAdbPortForDeviceIfNeeded(device_serial);
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return;
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
1837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (host_port < 0) {
1847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      SendMessage("ERROR: missing host port", client_socket.get());
1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return;
1867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
1877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const bool use_dynamic_port_allocation = device_port == 0;
1887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (!use_dynamic_port_allocation) {
1897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      const std::string controller_key = MakeHostControllerMapKey(
1907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          adb_port, device_port);
191d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      if (controllers_->find(controller_key) != controllers_->end()) {
1927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        LOG(INFO) << "Already forwarding device port " << device_port
1937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                  << " to host port " << host_port;
1947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        SendMessage(base::StringPrintf("%d:%d", device_port, host_port),
1957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                    client_socket.get());
1967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        return;
1977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      }
1987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Create a new host controller.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HostController> host_controller(
201d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        HostController::Create(
202d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch            device_port, host_port, adb_port, GetExitNotifierFD(),
2037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            base::Bind(&HostControllersManager::DeleteHostController,
204d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                       weak_ptr_factory_.GetWeakPtr())));
205d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (!host_controller.get()) {
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      has_failed_ = true;
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      SendMessage("ERROR: Connection to device failed.", client_socket.get());
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Get the current allocated port.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device_port = host_controller->device_port();
2127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    LOG(INFO) << "Forwarding device port " << device_port << " to host port "
2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              << host_port;
2147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string msg = base::StringPrintf("%d:%d", device_port, host_port);
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!SendMessage(msg, client_socket.get()))
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_controller->Start();
218d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    controllers_->insert(
2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        std::make_pair(MakeHostControllerMapKey(adb_port, device_port),
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                       linked_ptr<HostController>(host_controller.release())));
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  void RemoveAdbPortForDeviceIfNeeded(const std::string& device_serial) {
2248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    base::hash_map<std::string, int>::const_iterator it =
2258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        device_serial_to_adb_port_map_.find(device_serial);
2268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (it == device_serial_to_adb_port_map_.end())
2278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return;
2288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    int port = it->second;
2308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const std::string prefix = base::StringPrintf("%d:", port);
2318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    for (HostControllerMap::const_iterator others = controllers_->begin();
2328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)         others != controllers_->end(); ++others) {
2338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      if (others->first.find(prefix) == 0U)
2348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        return;
2358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
2368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // No other port is being forwarded to this device:
2378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // - Remove it from our internal serial -> adb port map.
2388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // - Remove from "adb forward" command.
239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    LOG(INFO) << "Device " << device_serial << " has no more ports.";
2408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    device_serial_to_adb_port_map_.erase(device_serial);
2418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const std::string serial_part = device_serial.empty() ?
2428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        std::string() : std::string("-s ") + device_serial;
2438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const std::string command = base::StringPrintf(
2448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        "adb %s forward --remove tcp:%d",
2458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        serial_part.c_str(),
2468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        port);
2478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const int ret = system(command.c_str());
248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    LOG(INFO) << command << " ret: " << ret;
249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Wait for the socket to be fully unmapped.
250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string port_mapped_cmd = base::StringPrintf(
251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        "lsof -nPi:%d",
252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        port);
253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const int poll_interval_us = 500 * 1000;
254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    int retries = 3;
255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    while (retries) {
256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      const int port_unmapped = system(port_mapped_cmd.c_str());
257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      LOG(INFO) << "Device " << device_serial << " port " << port << " unmap "
258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                << port_unmapped;
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (port_unmapped)
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        break;
261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      --retries;
262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      usleep(poll_interval_us);
263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
2648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
2658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int GetAdbPortForDevice(const std::string& device_serial) {
2677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    base::hash_map<std::string, int>::const_iterator it =
2687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        device_serial_to_adb_port_map_.find(device_serial);
2697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (it != device_serial_to_adb_port_map_.end())
2707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return it->second;
2717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    Socket bind_socket;
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    CHECK(bind_socket.BindTcp("127.0.0.1", 0));
2737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const int port = bind_socket.GetPort();
2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    bind_socket.Close();
2757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string serial_part = device_serial.empty() ?
2767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        std::string() : std::string("-s ") + device_serial;
2777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string command = base::StringPrintf(
2787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "adb %s forward tcp:%d localabstract:chrome_device_forwarder",
2798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        serial_part.c_str(),
2807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        port);
2817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    LOG(INFO) << command;
2827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const int ret = system(command.c_str());
2837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (ret < 0 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0)
2847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return -1;
2857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    device_serial_to_adb_port_map_[device_serial] = port;
2867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return port;
28790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool SendMessage(const std::string& msg, Socket* client_socket) {
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    bool result = client_socket->WriteString(msg);
29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DCHECK(result);
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!result)
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      has_failed_ = true;
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return result;
29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
297d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  base::WeakPtrFactory<HostControllersManager> weak_ptr_factory_;
2987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::hash_map<std::string, int> device_serial_to_adb_port_map_;
299d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  scoped_ptr<HostControllerMap> controllers_;
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool has_failed_;
3017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<base::AtExitManager> at_exit_manager_;  // Needed by base::Thread.
3027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<base::Thread> thread_;
3037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch};
3047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochclass ServerDelegate : public Daemon::ServerDelegate {
3067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch public:
3077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ServerDelegate() : has_failed_(false) {}
3087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  bool has_failed() const {
3107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return has_failed_ || controllers_manager_.has_failed();
3117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
3127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Daemon::ServerDelegate:
3147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual void Init() OVERRIDE {
3157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")";
3167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    DCHECK(!g_notifier);
3177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    g_notifier = new PipeNotifier();
3187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    signal(SIGTERM, KillHandler);
3197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    signal(SIGINT, KillHandler);
3207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
3217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE {
3237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    char buf[kBufSize];
3247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const int bytes_read = client_socket->Read(buf, sizeof(buf));
3257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (bytes_read <= 0) {
3267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      if (client_socket->DidReceiveEvent())
3277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        return;
3287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      PError("Read()");
3297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      has_failed_ = true;
3307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return;
3317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
3327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const Pickle command_pickle(buf, bytes_read);
3337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    PickleIterator pickle_it(command_pickle);
3347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    std::string device_serial;
3357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    CHECK(pickle_it.ReadString(&device_serial));
3367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int device_port;
3377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (!pickle_it.ReadInt(&device_port)) {
3387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      client_socket->WriteString("ERROR: missing device port");
3397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return;
3407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
3417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int host_port;
3427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (!pickle_it.ReadInt(&host_port))
3437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      host_port = -1;
3447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    controllers_manager_.HandleRequest(
3457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        device_serial, device_port, host_port, client_socket.Pass());
3467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
3477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch private:
3497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  bool has_failed_;
3507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  HostControllersManager controllers_manager_;
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ServerDelegate);
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ClientDelegate : public Daemon::ClientDelegate {
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
3577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ClientDelegate(const Pickle& command_pickle)
3587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      : command_pickle_(command_pickle),
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        has_failed_(false) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool has_failed() const { return has_failed_; }
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Daemon::ClientDelegate:
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE {
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Send the forward command to the daemon.
3677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    CHECK_EQ(command_pickle_.size(),
3687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch             daemon_socket->WriteNumBytes(command_pickle_.data(),
3697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                          command_pickle_.size()));
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    char buf[kBufSize];
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const int bytes_read = daemon_socket->Read(
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        buf, sizeof(buf) - 1 /* leave space for null terminator */);
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK_GT(bytes_read, 0);
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(bytes_read < sizeof(buf));
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    buf[bytes_read] = 0;
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::StringPiece msg(buf, bytes_read);
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (msg.starts_with("ERROR")) {
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      LOG(ERROR) << msg;
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      has_failed_ = true;
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    printf("%s\n", buf);
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
3867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const Pickle command_pickle_;
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool has_failed_;
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid ExitWithUsage() {
3917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::cerr << "Usage: host_forwarder [options]\n\n"
3927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch               "Options:\n"
3937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch               "  --serial-id=[0-9A-Z]{16}]\n"
3947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch               "  --map DEVICE_PORT HOST_PORT\n"
3957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch               "  --unmap DEVICE_PORT\n"
3967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch               "  --kill-server\n";
3977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  exit(1);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint PortToInt(const std::string& s) {
4017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int value;
4027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Note that 0 is a valid port (used for dynamic port allocation).
4037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!base::StringToInt(s, &value) || value < 0 ||
4047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      value > std::numeric_limits<uint16>::max()) {
4057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    LOG(ERROR) << "Could not convert string " << s << " to port";
4067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ExitWithUsage();
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return value;
4097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
4107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochint RunHostForwarder(int argc, char** argv) {
4127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  CommandLine::Init(argc, argv);
4137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
4147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  bool kill_server = false;
4157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Pickle pickle;
4177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  pickle.WriteString(
4187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      cmd_line.HasSwitch("serial-id") ?
4197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          cmd_line.GetSwitchValueASCII("serial-id") : std::string());
4207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const std::vector<std::string> args = cmd_line.GetArgs();
4227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (cmd_line.HasSwitch("kill-server")) {
4237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    kill_server = true;
4247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } else if (cmd_line.HasSwitch("unmap")) {
4257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (args.size() != 1)
4267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      ExitWithUsage();
4277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // Note the minus sign below.
4287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    pickle.WriteInt(-PortToInt(args[0]));
4297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } else if (cmd_line.HasSwitch("map")) {
4307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (args.size() != 2)
4317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      ExitWithUsage();
4327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    pickle.WriteInt(PortToInt(args[0]));
4337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    pickle.WriteInt(PortToInt(args[1]));
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ExitWithUsage();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (kill_server && args.size() > 0)
4397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ExitWithUsage();
4407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ClientDelegate client_delegate(pickle);
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ServerDelegate daemon_delegate;
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Daemon daemon(
444a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      kLogFilePath, kDaemonIdentifier, &client_delegate, &daemon_delegate,
445a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      &GetExitNotifierFD);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (kill_server)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !daemon.Kill();
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!daemon.SpawnIfNeeded())
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1;
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_delegate.has_failed() || daemon_delegate.has_failed();
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace forwarder2
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc, char** argv) {
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return forwarder2::RunHostForwarder(argc, argv);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
461