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..82bb7a841b7fba5db25de5fe28f8e51758e410f3 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,21 @@ 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; |
+ if (!pickle_it.ReadInt(&device_port)) { |
+ SendMessage("ERROR: missing device port", client_socket.get()); |
+ return; |
+ } |
+ 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) { |
@@ -156,10 +129,15 @@ class ServerDelegate : public Daemon::ServerDelegate { |
client_socket.get()); |
return; |
} |
+ int host_port; |
+ if (!pickle_it.ReadInt(&host_port)) { |
+ SendMessage("ERROR: missing host port", client_socket.get()); |
+ return; |
+ } |
// 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 +145,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 +178,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() ? "" : 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 +209,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 +218,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 +228,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 +247,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; |