Chromium Code Reviews| 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 0f0ca68d79e403c7b898fa53f58362889884c951..ae169b1dfddd941bdc67a3691da6d7a32be2f595 100644 |
| --- a/tools/android/forwarder2/host_forwarder_main.cc |
| +++ b/tools/android/forwarder2/host_forwarder_main.cc |
| @@ -4,10 +4,13 @@ |
| #include <errno.h> |
| #include <signal.h> |
| +#include <sys/types.h> |
| +#include <sys/wait.h> |
| #include <unistd.h> |
| #include <cstdio> |
| -#include <cstring> |
| +#include <iostream> |
| +#include <limits> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| @@ -20,6 +23,7 @@ |
| #include "base/logging.h" |
| #include "base/memory/linked_ptr.h" |
| #include "base/memory/scoped_vector.h" |
| +#include "base/pickle.h" |
| #include "base/posix/eintr_wrapper.h" |
| #include "base/safe_strerror_posix.h" |
| #include "base/strings/string_number_conversions.h" |
| @@ -72,40 +76,6 @@ void KillHandler(int signal_number) { |
| exit(1); |
| } |
| -// Format of |command|: |
| -// <ADB port>:<Device port>[:<Forward to port>:<Forward to address>]. |
| -bool ParseForwardCommand(const std::string& command, |
| - int* adb_port, |
| - int* device_port, |
| - std::string* forward_to_host, |
| - int* forward_to_port) { |
| - std::vector<std::string> command_pieces; |
| - base::SplitString(command, ':', &command_pieces); |
| - |
| - if (command_pieces.size() < 2 || |
| - !base::StringToInt(command_pieces[0], adb_port) || |
| - !base::StringToInt(command_pieces[1], device_port)) |
| - return false; |
| - |
| - if (command_pieces.size() > 2) { |
| - if (!base::StringToInt(command_pieces[2], forward_to_port)) |
| - return false; |
| - if (command_pieces.size() > 3) |
| - *forward_to_host = command_pieces[3]; |
| - } else { |
| - *forward_to_port = *device_port; |
| - } |
| - return true; |
| -} |
| - |
| -bool IsForwardCommandValid(const std::string& command) { |
| - int adb_port, device_port, forward_to_port; |
| - std::string forward_to_host; |
| - std::vector<std::string> command_pieces; |
| - return ParseForwardCommand( |
| - command, &adb_port, &device_port, &forward_to_host, &forward_to_port); |
| -} |
| - |
| class ServerDelegate : public Daemon::ServerDelegate { |
| public: |
| ServerDelegate() : has_failed_(false) {} |
| @@ -131,18 +101,27 @@ class ServerDelegate : public Daemon::ServerDelegate { |
| has_failed_ = true; |
| return; |
| } |
| - const std::string command(buf, bytes_read); |
| - int adb_port = 0; |
| - int device_port = 0; |
| - std::string forward_to_host; |
| - int forward_to_port = 0; |
| - const bool succeeded = ParseForwardCommand( |
| - command, &adb_port, &device_port, &forward_to_host, &forward_to_port); |
| - if (!succeeded) { |
| - has_failed_ = true; |
| - const std::string msg = base::StringPrintf( |
| - "ERROR: Could not parse forward command '%s'", command.c_str()); |
| - SendMessage(msg, client_socket.get()); |
| + const Pickle command_pickle(buf, bytes_read); |
| + PickleIterator pickle_it(command_pickle); |
| + std::string device_serial; |
| + CHECK(pickle_it.ReadString(&device_serial)); |
| + int device_port, host_port = -1; |
| + if (!pickle_it.ReadInt(&device_port)) { |
| + SendMessage("ERROR: missing device port", client_socket.get()); |
| + return; |
| + } |
| + if (device_port >= 0) { |
| + if (!pickle_it.ReadInt(&host_port)) { |
| + SendMessage("ERROR: missing host port", client_socket.get()); |
| + return; |
| + } |
| + } |
|
bulach
2013/07/02 16:12:38
nit: 113-118 could be moved down to 137, with a CH
Philippe
2013/07/02 16:24:20
Yes, good idea.
|
| + const int adb_port = GetAdbPortForDevice(device_serial); |
| + if (adb_port < 0) { |
| + SendMessage( |
| + "ERROR: could not get adb port for device. You might need to add " |
| + "'adb' to your PATH or provide the device serial id.", |
| + client_socket.get()); |
| return; |
| } |
| if (device_port < 0) { |
| @@ -158,8 +137,8 @@ class ServerDelegate : public Daemon::ServerDelegate { |
| } |
| // Create a new host controller. |
| scoped_ptr<HostController> host_controller( |
| - new HostController(device_port, forward_to_host, forward_to_port, |
| - adb_port, GetExitNotifierFD())); |
| + new HostController(device_port, "127.0.0.1", host_port, adb_port, |
| + GetExitNotifierFD())); |
| if (!host_controller->Connect()) { |
| has_failed_ = true; |
| SendMessage("ERROR: Connection to device failed.", client_socket.get()); |
| @@ -167,10 +146,9 @@ class ServerDelegate : public Daemon::ServerDelegate { |
| } |
| // 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; |
| - const std::string msg = base::StringPrintf( |
| - "%d:%d", device_port, forward_to_port); |
| + LOG(INFO) << "Forwarding device port " << device_port << " to host port " |
| + << host_port; |
| + const std::string msg = base::StringPrintf("%d:%d", device_port, host_port); |
| if (!SendMessage(msg, client_socket.get())) |
| return; |
| host_controller->Start(); |
| @@ -201,6 +179,29 @@ class ServerDelegate : public Daemon::ServerDelegate { |
| return base::StringPrintf("%d:%d", adb_port, device_port); |
| } |
| + int GetAdbPortForDevice(const std::string& device_serial) { |
| + base::hash_map<std::string, int>::const_iterator it = |
| + device_serial_to_adb_port_map_.find(device_serial); |
| + if (it != device_serial_to_adb_port_map_.end()) |
| + return it->second; |
| + Socket bind_socket; |
| + CHECK(bind_socket.BindTcp("127.0.0.1", 0)); |
| + const int port = bind_socket.GetPort(); |
| + bind_socket.Close(); |
| + const std::string serial_part = device_serial.empty() ? |
| + std::string() : std::string("-s ") + device_serial; |
| + const std::string command = base::StringPrintf( |
| + "adb %s forward tcp:%d localabstract:chrome_device_forwarder", |
| + device_serial.empty() ? std::string() : serial_part.c_str(), |
| + port); |
| + LOG(INFO) << command; |
| + const int ret = system(command.c_str()); |
| + if (ret < 0 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0) |
| + return -1; |
| + device_serial_to_adb_port_map_[device_serial] = port; |
| + return port; |
| + } |
| + |
| bool SendMessage(const std::string& msg, Socket* client_socket) { |
| bool result = client_socket->WriteString(msg); |
| DCHECK(result); |
| @@ -209,6 +210,7 @@ class ServerDelegate : public Daemon::ServerDelegate { |
| return result; |
| } |
| + base::hash_map<std::string, int> device_serial_to_adb_port_map_; |
| HostControllerMap controllers_; |
| bool has_failed_; |
| @@ -217,8 +219,8 @@ class ServerDelegate : public Daemon::ServerDelegate { |
| class ClientDelegate : public Daemon::ClientDelegate { |
| public: |
| - ClientDelegate(const std::string& forward_command) |
| - : forward_command_(forward_command), |
| + ClientDelegate(const Pickle& command_pickle) |
| + : command_pickle_(command_pickle), |
| has_failed_(false) { |
| } |
| @@ -227,7 +229,9 @@ class ClientDelegate : public Daemon::ClientDelegate { |
| // Daemon::ClientDelegate: |
| virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE { |
| // Send the forward command to the daemon. |
| - CHECK(daemon_socket->WriteString(forward_command_)); |
| + CHECK_EQ(command_pickle_.size(), |
| + daemon_socket->WriteNumBytes(command_pickle_.data(), |
| + command_pickle_.size())); |
| char buf[kBufSize]; |
| const int bytes_read = daemon_socket->Read( |
| buf, sizeof(buf) - 1 /* leave space for null terminator */); |
| @@ -244,49 +248,69 @@ class ClientDelegate : public Daemon::ClientDelegate { |
| } |
| private: |
| - const std::string forward_command_; |
| + const Pickle command_pickle_; |
| bool has_failed_; |
| }; |
| -void PrintUsage(const char* program_name) { |
| - LOG(ERROR) << program_name |
| - << " adb_port:from_port:to_port:to_host\n" |
| - "<adb port> is the TCP port Adb is configured to forward to.\n" |
| - "Note that <from_port> can be unmapped by making it negative."; |
| +void ExitWithUsage() { |
| + std::cerr << "Usage: host_forwarder [options]\n\n" |
| + "Options:\n" |
| + " --serial-id=[0-9A-Z]{16}]\n" |
| + " --map DEVICE_PORT HOST_PORT\n" |
| + " --unmap DEVICE_PORT\n" |
| + " --kill-server\n"; |
| + exit(1); |
| } |
| -int RunHostForwarder(int argc, char** argv) { |
| - if (!CommandLine::Init(argc, argv)) { |
| - LOG(ERROR) << "Could not initialize command line"; |
| - return 1; |
| - } |
| - const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| - const char* command = NULL; |
| - int adb_port = 0; |
| - if (argc != 2) { |
| - PrintUsage(argv[0]); |
| - return 1; |
| +int PortToInt(const std::string& s) { |
| + int value; |
| + // Note that 0 is a valid port (used for dynamic port allocation). |
| + if (!base::StringToInt(s, &value) || value < 0 || |
| + value > std::numeric_limits<uint16>::max()) { |
| + LOG(ERROR) << "Could not convert string " << s << " to port"; |
| + ExitWithUsage(); |
| } |
| - if (!strcmp(argv[1], kKillServerCommand)) { |
| - command = kKillServerCommand; |
| + return value; |
| +} |
| + |
| +int RunHostForwarder(int argc, char** argv) { |
| + CommandLine::Init(argc, argv); |
| + const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); |
| + bool kill_server = false; |
| + |
| + Pickle pickle; |
| + pickle.WriteString( |
| + cmd_line.HasSwitch("serial-id") ? |
| + cmd_line.GetSwitchValueASCII("serial-id") : std::string()); |
| + |
| + const std::vector<std::string> args = cmd_line.GetArgs(); |
| + if (cmd_line.HasSwitch("kill-server")) { |
| + kill_server = true; |
| + } else if (cmd_line.HasSwitch("unmap")) { |
| + if (args.size() != 1) |
| + ExitWithUsage(); |
| + // Note the minus sign below. |
| + pickle.WriteInt(-PortToInt(args[0])); |
| + } else if (cmd_line.HasSwitch("map")) { |
| + if (args.size() != 2) |
| + ExitWithUsage(); |
| + pickle.WriteInt(PortToInt(args[0])); |
| + pickle.WriteInt(PortToInt(args[1])); |
| } else { |
| - command = kForwardCommand; |
| - if (!IsForwardCommandValid(argv[1])) { |
| - PrintUsage(argv[0]); |
| - return 1; |
| - } |
| + ExitWithUsage(); |
| } |
| - ClientDelegate client_delegate(argv[1]); |
| + if (kill_server && args.size() > 0) |
| + ExitWithUsage(); |
| + |
| + ClientDelegate client_delegate(pickle); |
| ServerDelegate daemon_delegate; |
| Daemon daemon( |
| kLogFilePath, kDaemonIdentifier, &client_delegate, &daemon_delegate, |
| &GetExitNotifierFD); |
| - if (command == kKillServerCommand) |
| + if (kill_server) |
| return !daemon.Kill(); |
| - |
| - DCHECK(command == kForwardCommand); |
| if (!daemon.SpawnIfNeeded()) |
| return 1; |