Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1150)

Side by Side Diff: tools/android/forwarder2/host_forwarder_main.cc

Issue 18354005: Add --serial-id option to host_forwarder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address Marcus and Digit's comments Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/android/forwarder2/device_forwarder_main.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <errno.h> 5 #include <errno.h>
6 #include <signal.h> 6 #include <signal.h>
7 #include <sys/types.h>
8 #include <sys/wait.h>
7 #include <unistd.h> 9 #include <unistd.h>
8 10
9 #include <cstdio> 11 #include <cstdio>
10 #include <cstring> 12 #include <iostream>
13 #include <limits>
11 #include <string> 14 #include <string>
12 #include <utility> 15 #include <utility>
13 #include <vector> 16 #include <vector>
14 17
15 #include "base/command_line.h" 18 #include "base/command_line.h"
16 #include "base/compiler_specific.h" 19 #include "base/compiler_specific.h"
17 #include "base/containers/hash_tables.h" 20 #include "base/containers/hash_tables.h"
18 #include "base/file_util.h" 21 #include "base/file_util.h"
19 #include "base/files/file_path.h" 22 #include "base/files/file_path.h"
20 #include "base/logging.h" 23 #include "base/logging.h"
21 #include "base/memory/linked_ptr.h" 24 #include "base/memory/linked_ptr.h"
22 #include "base/memory/scoped_vector.h" 25 #include "base/memory/scoped_vector.h"
26 #include "base/pickle.h"
23 #include "base/posix/eintr_wrapper.h" 27 #include "base/posix/eintr_wrapper.h"
24 #include "base/safe_strerror_posix.h" 28 #include "base/safe_strerror_posix.h"
25 #include "base/strings/string_number_conversions.h" 29 #include "base/strings/string_number_conversions.h"
26 #include "base/strings/string_piece.h" 30 #include "base/strings/string_piece.h"
27 #include "base/strings/string_split.h" 31 #include "base/strings/string_split.h"
28 #include "base/strings/string_util.h" 32 #include "base/strings/string_util.h"
29 #include "base/strings/stringprintf.h" 33 #include "base/strings/stringprintf.h"
30 #include "tools/android/forwarder2/common.h" 34 #include "tools/android/forwarder2/common.h"
31 #include "tools/android/forwarder2/daemon.h" 35 #include "tools/android/forwarder2/daemon.h"
32 #include "tools/android/forwarder2/host_controller.h" 36 #include "tools/android/forwarder2/host_controller.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 static int s_kill_handler_count = 0; 69 static int s_kill_handler_count = 0;
66 CHECK(g_notifier); 70 CHECK(g_notifier);
67 // If for some reason the forwarder get stuck in any socket waiting forever, 71 // If for some reason the forwarder get stuck in any socket waiting forever,
68 // we can send a SIGKILL or SIGINT three times to force it die 72 // we can send a SIGKILL or SIGINT three times to force it die
69 // (non-nicely). This is useful when debugging. 73 // (non-nicely). This is useful when debugging.
70 ++s_kill_handler_count; 74 ++s_kill_handler_count;
71 if (!g_notifier->Notify() || s_kill_handler_count > 2) 75 if (!g_notifier->Notify() || s_kill_handler_count > 2)
72 exit(1); 76 exit(1);
73 } 77 }
74 78
75 // Format of |command|:
76 // <ADB port>:<Device port>[:<Forward to port>:<Forward to address>].
77 bool ParseForwardCommand(const std::string& command,
78 int* adb_port,
79 int* device_port,
80 std::string* forward_to_host,
81 int* forward_to_port) {
82 std::vector<std::string> command_pieces;
83 base::SplitString(command, ':', &command_pieces);
84
85 if (command_pieces.size() < 2 ||
86 !base::StringToInt(command_pieces[0], adb_port) ||
87 !base::StringToInt(command_pieces[1], device_port))
88 return false;
89
90 if (command_pieces.size() > 2) {
91 if (!base::StringToInt(command_pieces[2], forward_to_port))
92 return false;
93 if (command_pieces.size() > 3)
94 *forward_to_host = command_pieces[3];
95 } else {
96 *forward_to_port = *device_port;
97 }
98 return true;
99 }
100
101 bool IsForwardCommandValid(const std::string& command) {
102 int adb_port, device_port, forward_to_port;
103 std::string forward_to_host;
104 std::vector<std::string> command_pieces;
105 return ParseForwardCommand(
106 command, &adb_port, &device_port, &forward_to_host, &forward_to_port);
107 }
108
109 class ServerDelegate : public Daemon::ServerDelegate { 79 class ServerDelegate : public Daemon::ServerDelegate {
110 public: 80 public:
111 ServerDelegate() : has_failed_(false) {} 81 ServerDelegate() : has_failed_(false) {}
112 82
113 bool has_failed() const { return has_failed_; } 83 bool has_failed() const { return has_failed_; }
114 84
115 // Daemon::ServerDelegate: 85 // Daemon::ServerDelegate:
116 virtual void Init() OVERRIDE { 86 virtual void Init() OVERRIDE {
117 LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")"; 87 LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")";
118 DCHECK(!g_notifier); 88 DCHECK(!g_notifier);
119 g_notifier = new PipeNotifier(); 89 g_notifier = new PipeNotifier();
120 signal(SIGTERM, KillHandler); 90 signal(SIGTERM, KillHandler);
121 signal(SIGINT, KillHandler); 91 signal(SIGINT, KillHandler);
122 } 92 }
123 93
124 virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE { 94 virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE {
125 char buf[kBufSize]; 95 char buf[kBufSize];
126 const int bytes_read = client_socket->Read(buf, sizeof(buf)); 96 const int bytes_read = client_socket->Read(buf, sizeof(buf));
127 if (bytes_read <= 0) { 97 if (bytes_read <= 0) {
128 if (client_socket->DidReceiveEvent()) 98 if (client_socket->DidReceiveEvent())
129 return; 99 return;
130 PError("Read()"); 100 PError("Read()");
131 has_failed_ = true; 101 has_failed_ = true;
132 return; 102 return;
133 } 103 }
134 const std::string command(buf, bytes_read); 104 const Pickle command_pickle(buf, bytes_read);
135 int adb_port = 0; 105 PickleIterator pickle_it(command_pickle);
136 int device_port = 0; 106 std::string device_serial;
137 std::string forward_to_host; 107 CHECK(pickle_it.ReadString(&device_serial));
138 int forward_to_port = 0; 108 int device_port, host_port = -1;
139 const bool succeeded = ParseForwardCommand( 109 if (!pickle_it.ReadInt(&device_port)) {
140 command, &adb_port, &device_port, &forward_to_host, &forward_to_port); 110 SendMessage("ERROR: missing device port", client_socket.get());
141 if (!succeeded) { 111 return;
142 has_failed_ = true; 112 }
143 const std::string msg = base::StringPrintf( 113 if (device_port >= 0) {
144 "ERROR: Could not parse forward command '%s'", command.c_str()); 114 if (!pickle_it.ReadInt(&host_port)) {
145 SendMessage(msg, client_socket.get()); 115 SendMessage("ERROR: missing host port", client_socket.get());
116 return;
117 }
118 }
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.
119 const int adb_port = GetAdbPortForDevice(device_serial);
120 if (adb_port < 0) {
121 SendMessage(
122 "ERROR: could not get adb port for device. You might need to add "
123 "'adb' to your PATH or provide the device serial id.",
124 client_socket.get());
146 return; 125 return;
147 } 126 }
148 if (device_port < 0) { 127 if (device_port < 0) {
149 // Remove the previously created host controller. 128 // Remove the previously created host controller.
150 const std::string controller_key = MakeHostControllerMapKey( 129 const std::string controller_key = MakeHostControllerMapKey(
151 adb_port, -device_port); 130 adb_port, -device_port);
152 const HostControllerMap::size_type removed_elements = controllers_.erase( 131 const HostControllerMap::size_type removed_elements = controllers_.erase(
153 controller_key); 132 controller_key);
154 SendMessage( 133 SendMessage(
155 !removed_elements ? "ERROR: could not unmap port" : "OK", 134 !removed_elements ? "ERROR: could not unmap port" : "OK",
156 client_socket.get()); 135 client_socket.get());
157 return; 136 return;
158 } 137 }
159 // Create a new host controller. 138 // Create a new host controller.
160 scoped_ptr<HostController> host_controller( 139 scoped_ptr<HostController> host_controller(
161 new HostController(device_port, forward_to_host, forward_to_port, 140 new HostController(device_port, "127.0.0.1", host_port, adb_port,
162 adb_port, GetExitNotifierFD())); 141 GetExitNotifierFD()));
163 if (!host_controller->Connect()) { 142 if (!host_controller->Connect()) {
164 has_failed_ = true; 143 has_failed_ = true;
165 SendMessage("ERROR: Connection to device failed.", client_socket.get()); 144 SendMessage("ERROR: Connection to device failed.", client_socket.get());
166 return; 145 return;
167 } 146 }
168 // Get the current allocated port. 147 // Get the current allocated port.
169 device_port = host_controller->device_port(); 148 device_port = host_controller->device_port();
170 LOG(INFO) << "Forwarding device port " << device_port << " to host " 149 LOG(INFO) << "Forwarding device port " << device_port << " to host port "
171 << forward_to_host << ":" << forward_to_port; 150 << host_port;
172 const std::string msg = base::StringPrintf( 151 const std::string msg = base::StringPrintf("%d:%d", device_port, host_port);
173 "%d:%d", device_port, forward_to_port);
174 if (!SendMessage(msg, client_socket.get())) 152 if (!SendMessage(msg, client_socket.get()))
175 return; 153 return;
176 host_controller->Start(); 154 host_controller->Start();
177 const std::string controller_key = MakeHostControllerMapKey( 155 const std::string controller_key = MakeHostControllerMapKey(
178 adb_port, device_port); 156 adb_port, device_port);
179 controllers_.insert( 157 controllers_.insert(
180 std::make_pair(controller_key, 158 std::make_pair(controller_key,
181 linked_ptr<HostController>(host_controller.release()))); 159 linked_ptr<HostController>(host_controller.release())));
182 } 160 }
183 161
(...skipping 10 matching lines...) Expand all
194 } 172 }
195 173
196 private: 174 private:
197 typedef base::hash_map< 175 typedef base::hash_map<
198 std::string, linked_ptr<HostController> > HostControllerMap; 176 std::string, linked_ptr<HostController> > HostControllerMap;
199 177
200 static std::string MakeHostControllerMapKey(int adb_port, int device_port) { 178 static std::string MakeHostControllerMapKey(int adb_port, int device_port) {
201 return base::StringPrintf("%d:%d", adb_port, device_port); 179 return base::StringPrintf("%d:%d", adb_port, device_port);
202 } 180 }
203 181
182 int GetAdbPortForDevice(const std::string& device_serial) {
183 base::hash_map<std::string, int>::const_iterator it =
184 device_serial_to_adb_port_map_.find(device_serial);
185 if (it != device_serial_to_adb_port_map_.end())
186 return it->second;
187 Socket bind_socket;
188 CHECK(bind_socket.BindTcp("127.0.0.1", 0));
189 const int port = bind_socket.GetPort();
190 bind_socket.Close();
191 const std::string serial_part = device_serial.empty() ?
192 std::string() : std::string("-s ") + device_serial;
193 const std::string command = base::StringPrintf(
194 "adb %s forward tcp:%d localabstract:chrome_device_forwarder",
195 device_serial.empty() ? std::string() : serial_part.c_str(),
196 port);
197 LOG(INFO) << command;
198 const int ret = system(command.c_str());
199 if (ret < 0 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0)
200 return -1;
201 device_serial_to_adb_port_map_[device_serial] = port;
202 return port;
203 }
204
204 bool SendMessage(const std::string& msg, Socket* client_socket) { 205 bool SendMessage(const std::string& msg, Socket* client_socket) {
205 bool result = client_socket->WriteString(msg); 206 bool result = client_socket->WriteString(msg);
206 DCHECK(result); 207 DCHECK(result);
207 if (!result) 208 if (!result)
208 has_failed_ = true; 209 has_failed_ = true;
209 return result; 210 return result;
210 } 211 }
211 212
213 base::hash_map<std::string, int> device_serial_to_adb_port_map_;
212 HostControllerMap controllers_; 214 HostControllerMap controllers_;
213 bool has_failed_; 215 bool has_failed_;
214 216
215 DISALLOW_COPY_AND_ASSIGN(ServerDelegate); 217 DISALLOW_COPY_AND_ASSIGN(ServerDelegate);
216 }; 218 };
217 219
218 class ClientDelegate : public Daemon::ClientDelegate { 220 class ClientDelegate : public Daemon::ClientDelegate {
219 public: 221 public:
220 ClientDelegate(const std::string& forward_command) 222 ClientDelegate(const Pickle& command_pickle)
221 : forward_command_(forward_command), 223 : command_pickle_(command_pickle),
222 has_failed_(false) { 224 has_failed_(false) {
223 } 225 }
224 226
225 bool has_failed() const { return has_failed_; } 227 bool has_failed() const { return has_failed_; }
226 228
227 // Daemon::ClientDelegate: 229 // Daemon::ClientDelegate:
228 virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE { 230 virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE {
229 // Send the forward command to the daemon. 231 // Send the forward command to the daemon.
230 CHECK(daemon_socket->WriteString(forward_command_)); 232 CHECK_EQ(command_pickle_.size(),
233 daemon_socket->WriteNumBytes(command_pickle_.data(),
234 command_pickle_.size()));
231 char buf[kBufSize]; 235 char buf[kBufSize];
232 const int bytes_read = daemon_socket->Read( 236 const int bytes_read = daemon_socket->Read(
233 buf, sizeof(buf) - 1 /* leave space for null terminator */); 237 buf, sizeof(buf) - 1 /* leave space for null terminator */);
234 CHECK_GT(bytes_read, 0); 238 CHECK_GT(bytes_read, 0);
235 DCHECK(bytes_read < sizeof(buf)); 239 DCHECK(bytes_read < sizeof(buf));
236 buf[bytes_read] = 0; 240 buf[bytes_read] = 0;
237 base::StringPiece msg(buf, bytes_read); 241 base::StringPiece msg(buf, bytes_read);
238 if (msg.starts_with("ERROR")) { 242 if (msg.starts_with("ERROR")) {
239 LOG(ERROR) << msg; 243 LOG(ERROR) << msg;
240 has_failed_ = true; 244 has_failed_ = true;
241 return; 245 return;
242 } 246 }
243 printf("%s\n", buf); 247 printf("%s\n", buf);
244 } 248 }
245 249
246 private: 250 private:
247 const std::string forward_command_; 251 const Pickle command_pickle_;
248 bool has_failed_; 252 bool has_failed_;
249 }; 253 };
250 254
251 void PrintUsage(const char* program_name) { 255 void ExitWithUsage() {
252 LOG(ERROR) << program_name 256 std::cerr << "Usage: host_forwarder [options]\n\n"
253 << " adb_port:from_port:to_port:to_host\n" 257 "Options:\n"
254 "<adb port> is the TCP port Adb is configured to forward to.\n" 258 " --serial-id=[0-9A-Z]{16}]\n"
255 "Note that <from_port> can be unmapped by making it negative."; 259 " --map DEVICE_PORT HOST_PORT\n"
260 " --unmap DEVICE_PORT\n"
261 " --kill-server\n";
262 exit(1);
263 }
264
265 int PortToInt(const std::string& s) {
266 int value;
267 // Note that 0 is a valid port (used for dynamic port allocation).
268 if (!base::StringToInt(s, &value) || value < 0 ||
269 value > std::numeric_limits<uint16>::max()) {
270 LOG(ERROR) << "Could not convert string " << s << " to port";
271 ExitWithUsage();
272 }
273 return value;
256 } 274 }
257 275
258 int RunHostForwarder(int argc, char** argv) { 276 int RunHostForwarder(int argc, char** argv) {
259 if (!CommandLine::Init(argc, argv)) { 277 CommandLine::Init(argc, argv);
260 LOG(ERROR) << "Could not initialize command line"; 278 const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
261 return 1; 279 bool kill_server = false;
262 } 280
263 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 281 Pickle pickle;
264 const char* command = NULL; 282 pickle.WriteString(
265 int adb_port = 0; 283 cmd_line.HasSwitch("serial-id") ?
266 if (argc != 2) { 284 cmd_line.GetSwitchValueASCII("serial-id") : std::string());
267 PrintUsage(argv[0]); 285
268 return 1; 286 const std::vector<std::string> args = cmd_line.GetArgs();
269 } 287 if (cmd_line.HasSwitch("kill-server")) {
270 if (!strcmp(argv[1], kKillServerCommand)) { 288 kill_server = true;
271 command = kKillServerCommand; 289 } else if (cmd_line.HasSwitch("unmap")) {
290 if (args.size() != 1)
291 ExitWithUsage();
292 // Note the minus sign below.
293 pickle.WriteInt(-PortToInt(args[0]));
294 } else if (cmd_line.HasSwitch("map")) {
295 if (args.size() != 2)
296 ExitWithUsage();
297 pickle.WriteInt(PortToInt(args[0]));
298 pickle.WriteInt(PortToInt(args[1]));
272 } else { 299 } else {
273 command = kForwardCommand; 300 ExitWithUsage();
274 if (!IsForwardCommandValid(argv[1])) {
275 PrintUsage(argv[0]);
276 return 1;
277 }
278 } 301 }
279 302
280 ClientDelegate client_delegate(argv[1]); 303 if (kill_server && args.size() > 0)
304 ExitWithUsage();
305
306 ClientDelegate client_delegate(pickle);
281 ServerDelegate daemon_delegate; 307 ServerDelegate daemon_delegate;
282 Daemon daemon( 308 Daemon daemon(
283 kLogFilePath, kDaemonIdentifier, &client_delegate, &daemon_delegate, 309 kLogFilePath, kDaemonIdentifier, &client_delegate, &daemon_delegate,
284 &GetExitNotifierFD); 310 &GetExitNotifierFD);
285 311
286 if (command == kKillServerCommand) 312 if (kill_server)
287 return !daemon.Kill(); 313 return !daemon.Kill();
288
289 DCHECK(command == kForwardCommand);
290 if (!daemon.SpawnIfNeeded()) 314 if (!daemon.SpawnIfNeeded())
291 return 1; 315 return 1;
292 316
293 return client_delegate.has_failed() || daemon_delegate.has_failed(); 317 return client_delegate.has_failed() || daemon_delegate.has_failed();
294 } 318 }
295 319
296 } // namespace 320 } // namespace
297 } // namespace forwarder2 321 } // namespace forwarder2
298 322
299 int main(int argc, char** argv) { 323 int main(int argc, char** argv) {
300 return forwarder2::RunHostForwarder(argc, argv); 324 return forwarder2::RunHostForwarder(argc, argv);
301 } 325 }
OLDNEW
« no previous file with comments | « tools/android/forwarder2/device_forwarder_main.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698