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