OLD | NEW |
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> | 7 #include <sys/types.h> |
8 #include <sys/wait.h> | 8 #include <sys/wait.h> |
9 #include <unistd.h> | 9 #include <unistd.h> |
10 | 10 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 } | 91 } |
92 | 92 |
93 ~HostControllersManager() { | 93 ~HostControllersManager() { |
94 if (!thread_.get()) | 94 if (!thread_.get()) |
95 return; | 95 return; |
96 // Delete the controllers on the thread they were created on. | 96 // Delete the controllers on the thread they were created on. |
97 thread_->message_loop_proxy()->DeleteSoon( | 97 thread_->message_loop_proxy()->DeleteSoon( |
98 FROM_HERE, controllers_.release()); | 98 FROM_HERE, controllers_.release()); |
99 } | 99 } |
100 | 100 |
101 void HandleRequest(const std::string& device_serial, | 101 void HandleRequest(const std::string& adb_path, |
| 102 const std::string& device_serial, |
102 int device_port, | 103 int device_port, |
103 int host_port, | 104 int host_port, |
104 scoped_ptr<Socket> client_socket) { | 105 scoped_ptr<Socket> client_socket) { |
105 // Lazy initialize so that the CLI process doesn't get this thread created. | 106 // Lazy initialize so that the CLI process doesn't get this thread created. |
106 InitOnce(); | 107 InitOnce(); |
107 thread_->message_loop_proxy()->PostTask( | 108 thread_->message_loop_proxy()->PostTask( |
108 FROM_HERE, | 109 FROM_HERE, |
109 base::Bind( | 110 base::Bind(&HostControllersManager::HandleRequestOnInternalThread, |
110 &HostControllersManager::HandleRequestOnInternalThread, | 111 base::Unretained(this), adb_path, device_serial, device_port, |
111 base::Unretained(this), device_serial, device_port, host_port, | 112 host_port, base::Passed(&client_socket))); |
112 base::Passed(&client_socket))); | |
113 } | 113 } |
114 | 114 |
115 bool has_failed() const { return has_failed_; } | 115 bool has_failed() const { return has_failed_; } |
116 | 116 |
117 private: | 117 private: |
118 typedef base::hash_map< | 118 typedef base::hash_map< |
119 std::string, linked_ptr<HostController> > HostControllerMap; | 119 std::string, linked_ptr<HostController> > HostControllerMap; |
120 | 120 |
121 static std::string MakeHostControllerMapKey(int adb_port, int device_port) { | 121 static std::string MakeHostControllerMapKey(int adb_port, int device_port) { |
122 return base::StringPrintf("%d:%d", adb_port, device_port); | 122 return base::StringPrintf("%d:%d", adb_port, device_port); |
(...skipping 22 matching lines...) Expand all Loading... |
145 return; | 145 return; |
146 } | 146 } |
147 DCHECK(manager->thread_->message_loop_proxy()->RunsTasksOnCurrentThread()); | 147 DCHECK(manager->thread_->message_loop_proxy()->RunsTasksOnCurrentThread()); |
148 // Note that this will delete |controller| which is owned by the map. | 148 // Note that this will delete |controller| which is owned by the map. |
149 DeleteRefCountedValueInMap( | 149 DeleteRefCountedValueInMap( |
150 MakeHostControllerMapKey( | 150 MakeHostControllerMapKey( |
151 controller->adb_port(), controller->device_port()), | 151 controller->adb_port(), controller->device_port()), |
152 manager->controllers_.get()); | 152 manager->controllers_.get()); |
153 } | 153 } |
154 | 154 |
155 void HandleRequestOnInternalThread(const std::string& device_serial, | 155 void HandleRequestOnInternalThread(const std::string& adb_path, |
| 156 const std::string& device_serial, |
156 int device_port, | 157 int device_port, |
157 int host_port, | 158 int host_port, |
158 scoped_ptr<Socket> client_socket) { | 159 scoped_ptr<Socket> client_socket) { |
159 const int adb_port = GetAdbPortForDevice(device_serial); | 160 const int adb_port = GetAdbPortForDevice(adb_path, device_serial); |
160 if (adb_port < 0) { | 161 if (adb_port < 0) { |
161 SendMessage( | 162 SendMessage( |
162 "ERROR: could not get adb port for device. You might need to add " | 163 "ERROR: could not get adb port for device. You might need to add " |
163 "'adb' to your PATH or provide the device serial id.", | 164 "'adb' to your PATH or provide the device serial id.", |
164 client_socket.get()); | 165 client_socket.get()); |
165 return; | 166 return; |
166 } | 167 } |
167 if (device_port < 0) { | 168 if (device_port < 0) { |
168 // Remove the previously created host controller. | 169 // Remove the previously created host controller. |
169 const std::string controller_key = MakeHostControllerMapKey( | 170 const std::string controller_key = MakeHostControllerMapKey( |
170 adb_port, -device_port); | 171 adb_port, -device_port); |
171 const bool controller_did_exist = DeleteRefCountedValueInMap( | 172 const bool controller_did_exist = DeleteRefCountedValueInMap( |
172 controller_key, controllers_.get()); | 173 controller_key, controllers_.get()); |
173 SendMessage( | 174 SendMessage( |
174 !controller_did_exist ? "ERROR: could not unmap port" : "OK", | 175 !controller_did_exist ? "ERROR: could not unmap port" : "OK", |
175 client_socket.get()); | 176 client_socket.get()); |
176 | 177 |
177 RemoveAdbPortForDeviceIfNeeded(device_serial); | 178 RemoveAdbPortForDeviceIfNeeded(adb_path, device_serial); |
178 return; | 179 return; |
179 } | 180 } |
180 if (host_port < 0) { | 181 if (host_port < 0) { |
181 SendMessage("ERROR: missing host port", client_socket.get()); | 182 SendMessage("ERROR: missing host port", client_socket.get()); |
182 return; | 183 return; |
183 } | 184 } |
184 const bool use_dynamic_port_allocation = device_port == 0; | 185 const bool use_dynamic_port_allocation = device_port == 0; |
185 if (!use_dynamic_port_allocation) { | 186 if (!use_dynamic_port_allocation) { |
186 const std::string controller_key = MakeHostControllerMapKey( | 187 const std::string controller_key = MakeHostControllerMapKey( |
187 adb_port, device_port); | 188 adb_port, device_port); |
(...skipping 22 matching lines...) Expand all Loading... |
210 << host_port; | 211 << host_port; |
211 const std::string msg = base::StringPrintf("%d:%d", device_port, host_port); | 212 const std::string msg = base::StringPrintf("%d:%d", device_port, host_port); |
212 if (!SendMessage(msg, client_socket.get())) | 213 if (!SendMessage(msg, client_socket.get())) |
213 return; | 214 return; |
214 host_controller->Start(); | 215 host_controller->Start(); |
215 controllers_->insert( | 216 controllers_->insert( |
216 std::make_pair(MakeHostControllerMapKey(adb_port, device_port), | 217 std::make_pair(MakeHostControllerMapKey(adb_port, device_port), |
217 linked_ptr<HostController>(host_controller.release()))); | 218 linked_ptr<HostController>(host_controller.release()))); |
218 } | 219 } |
219 | 220 |
220 void RemoveAdbPortForDeviceIfNeeded(const std::string& device_serial) { | 221 void RemoveAdbPortForDeviceIfNeeded(const std::string& adb_path, |
| 222 const std::string& device_serial) { |
221 base::hash_map<std::string, int>::const_iterator it = | 223 base::hash_map<std::string, int>::const_iterator it = |
222 device_serial_to_adb_port_map_.find(device_serial); | 224 device_serial_to_adb_port_map_.find(device_serial); |
223 if (it == device_serial_to_adb_port_map_.end()) | 225 if (it == device_serial_to_adb_port_map_.end()) |
224 return; | 226 return; |
225 | 227 |
226 int port = it->second; | 228 int port = it->second; |
227 const std::string prefix = base::StringPrintf("%d:", port); | 229 const std::string prefix = base::StringPrintf("%d:", port); |
228 for (HostControllerMap::const_iterator others = controllers_->begin(); | 230 for (HostControllerMap::const_iterator others = controllers_->begin(); |
229 others != controllers_->end(); ++others) { | 231 others != controllers_->end(); ++others) { |
230 if (others->first.find(prefix) == 0U) | 232 if (others->first.find(prefix) == 0U) |
231 return; | 233 return; |
232 } | 234 } |
233 // No other port is being forwarded to this device: | 235 // No other port is being forwarded to this device: |
234 // - Remove it from our internal serial -> adb port map. | 236 // - Remove it from our internal serial -> adb port map. |
235 // - Remove from "adb forward" command. | 237 // - Remove from "adb forward" command. |
236 LOG(INFO) << "Device " << device_serial << " has no more ports."; | 238 LOG(INFO) << "Device " << device_serial << " has no more ports."; |
237 device_serial_to_adb_port_map_.erase(device_serial); | 239 device_serial_to_adb_port_map_.erase(device_serial); |
238 const std::string serial_part = device_serial.empty() ? | 240 const std::string serial_part = device_serial.empty() ? |
239 std::string() : std::string("-s ") + device_serial; | 241 std::string() : std::string("-s ") + device_serial; |
240 const std::string command = base::StringPrintf( | 242 const std::string command = base::StringPrintf( |
241 "adb %s forward --remove tcp:%d", | 243 "%s %s forward --remove tcp:%d", |
| 244 adb_path.c_str(), |
242 serial_part.c_str(), | 245 serial_part.c_str(), |
243 port); | 246 port); |
244 const int ret = system(command.c_str()); | 247 const int ret = system(command.c_str()); |
245 LOG(INFO) << command << " ret: " << ret; | 248 LOG(INFO) << command << " ret: " << ret; |
246 // Wait for the socket to be fully unmapped. | 249 // Wait for the socket to be fully unmapped. |
247 const std::string port_mapped_cmd = base::StringPrintf( | 250 const std::string port_mapped_cmd = base::StringPrintf( |
248 "lsof -nPi:%d", | 251 "lsof -nPi:%d", |
249 port); | 252 port); |
250 const int poll_interval_us = 500 * 1000; | 253 const int poll_interval_us = 500 * 1000; |
251 int retries = 3; | 254 int retries = 3; |
252 while (retries) { | 255 while (retries) { |
253 const int port_unmapped = system(port_mapped_cmd.c_str()); | 256 const int port_unmapped = system(port_mapped_cmd.c_str()); |
254 LOG(INFO) << "Device " << device_serial << " port " << port << " unmap " | 257 LOG(INFO) << "Device " << device_serial << " port " << port << " unmap " |
255 << port_unmapped; | 258 << port_unmapped; |
256 if (port_unmapped) | 259 if (port_unmapped) |
257 break; | 260 break; |
258 --retries; | 261 --retries; |
259 usleep(poll_interval_us); | 262 usleep(poll_interval_us); |
260 } | 263 } |
261 } | 264 } |
262 | 265 |
263 int GetAdbPortForDevice(const std::string& device_serial) { | 266 int GetAdbPortForDevice(const std::string adb_path, |
| 267 const std::string& device_serial) { |
264 base::hash_map<std::string, int>::const_iterator it = | 268 base::hash_map<std::string, int>::const_iterator it = |
265 device_serial_to_adb_port_map_.find(device_serial); | 269 device_serial_to_adb_port_map_.find(device_serial); |
266 if (it != device_serial_to_adb_port_map_.end()) | 270 if (it != device_serial_to_adb_port_map_.end()) |
267 return it->second; | 271 return it->second; |
268 Socket bind_socket; | 272 Socket bind_socket; |
269 CHECK(bind_socket.BindTcp("127.0.0.1", 0)); | 273 CHECK(bind_socket.BindTcp("127.0.0.1", 0)); |
270 const int port = bind_socket.GetPort(); | 274 const int port = bind_socket.GetPort(); |
271 bind_socket.Close(); | 275 bind_socket.Close(); |
272 const std::string serial_part = device_serial.empty() ? | 276 const std::string serial_part = device_serial.empty() ? |
273 std::string() : std::string("-s ") + device_serial; | 277 std::string() : std::string("-s ") + device_serial; |
274 const std::string command = base::StringPrintf( | 278 const std::string command = base::StringPrintf( |
275 "adb %s forward tcp:%d localabstract:chrome_device_forwarder", | 279 "%s %s forward tcp:%d localabstract:chrome_device_forwarder", |
| 280 adb_path.c_str(), |
276 serial_part.c_str(), | 281 serial_part.c_str(), |
277 port); | 282 port); |
278 LOG(INFO) << command; | 283 LOG(INFO) << command; |
279 const int ret = system(command.c_str()); | 284 const int ret = system(command.c_str()); |
280 if (ret < 0 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0) | 285 if (ret < 0 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0) |
281 return -1; | 286 return -1; |
282 device_serial_to_adb_port_map_[device_serial] = port; | 287 device_serial_to_adb_port_map_[device_serial] = port; |
283 return port; | 288 return port; |
284 } | 289 } |
285 | 290 |
286 bool SendMessage(const std::string& msg, Socket* client_socket) { | 291 bool SendMessage(const std::string& msg, Socket* client_socket) { |
287 bool result = client_socket->WriteString(msg); | 292 bool result = client_socket->WriteString(msg); |
288 DCHECK(result); | 293 DCHECK(result); |
289 if (!result) | 294 if (!result) |
290 has_failed_ = true; | 295 has_failed_ = true; |
291 return result; | 296 return result; |
292 } | 297 } |
293 | 298 |
294 base::hash_map<std::string, int> device_serial_to_adb_port_map_; | 299 base::hash_map<std::string, int> device_serial_to_adb_port_map_; |
295 scoped_ptr<HostControllerMap> controllers_; | 300 scoped_ptr<HostControllerMap> controllers_; |
296 bool has_failed_; | 301 bool has_failed_; |
297 scoped_ptr<base::AtExitManager> at_exit_manager_; // Needed by base::Thread. | 302 scoped_ptr<base::AtExitManager> at_exit_manager_; // Needed by base::Thread. |
298 scoped_ptr<base::Thread> thread_; | 303 scoped_ptr<base::Thread> thread_; |
299 base::WeakPtrFactory<HostControllersManager> weak_ptr_factory_; | 304 base::WeakPtrFactory<HostControllersManager> weak_ptr_factory_; |
300 }; | 305 }; |
301 | 306 |
302 class ServerDelegate : public Daemon::ServerDelegate { | 307 class ServerDelegate : public Daemon::ServerDelegate { |
303 public: | 308 public: |
304 ServerDelegate() : has_failed_(false) {} | 309 ServerDelegate(const std::string& adb_path) |
| 310 : adb_path_(adb_path), has_failed_(false) {} |
305 | 311 |
306 bool has_failed() const { | 312 bool has_failed() const { |
307 return has_failed_ || controllers_manager_.has_failed(); | 313 return has_failed_ || controllers_manager_.has_failed(); |
308 } | 314 } |
309 | 315 |
310 // Daemon::ServerDelegate: | 316 // Daemon::ServerDelegate: |
311 virtual void Init() override { | 317 virtual void Init() override { |
312 LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")"; | 318 LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")"; |
313 DCHECK(!g_notifier); | 319 DCHECK(!g_notifier); |
314 g_notifier = new PipeNotifier(); | 320 g_notifier = new PipeNotifier(); |
(...skipping 16 matching lines...) Expand all Loading... |
331 std::string device_serial; | 337 std::string device_serial; |
332 CHECK(pickle_it.ReadString(&device_serial)); | 338 CHECK(pickle_it.ReadString(&device_serial)); |
333 int device_port; | 339 int device_port; |
334 if (!pickle_it.ReadInt(&device_port)) { | 340 if (!pickle_it.ReadInt(&device_port)) { |
335 client_socket->WriteString("ERROR: missing device port"); | 341 client_socket->WriteString("ERROR: missing device port"); |
336 return; | 342 return; |
337 } | 343 } |
338 int host_port; | 344 int host_port; |
339 if (!pickle_it.ReadInt(&host_port)) | 345 if (!pickle_it.ReadInt(&host_port)) |
340 host_port = -1; | 346 host_port = -1; |
341 controllers_manager_.HandleRequest( | 347 controllers_manager_.HandleRequest(adb_path_, device_serial, device_port, |
342 device_serial, device_port, host_port, client_socket.Pass()); | 348 host_port, client_socket.Pass()); |
343 } | 349 } |
344 | 350 |
345 private: | 351 private: |
| 352 std::string adb_path_; |
346 bool has_failed_; | 353 bool has_failed_; |
347 HostControllersManager controllers_manager_; | 354 HostControllersManager controllers_manager_; |
348 | 355 |
349 DISALLOW_COPY_AND_ASSIGN(ServerDelegate); | 356 DISALLOW_COPY_AND_ASSIGN(ServerDelegate); |
350 }; | 357 }; |
351 | 358 |
352 class ClientDelegate : public Daemon::ClientDelegate { | 359 class ClientDelegate : public Daemon::ClientDelegate { |
353 public: | 360 public: |
354 ClientDelegate(const Pickle& command_pickle) | 361 ClientDelegate(const Pickle& command_pickle) |
355 : command_pickle_(command_pickle), | 362 : command_pickle_(command_pickle), |
(...skipping 27 matching lines...) Expand all Loading... |
383 const Pickle command_pickle_; | 390 const Pickle command_pickle_; |
384 bool has_failed_; | 391 bool has_failed_; |
385 }; | 392 }; |
386 | 393 |
387 void ExitWithUsage() { | 394 void ExitWithUsage() { |
388 std::cerr << "Usage: host_forwarder [options]\n\n" | 395 std::cerr << "Usage: host_forwarder [options]\n\n" |
389 "Options:\n" | 396 "Options:\n" |
390 " --serial-id=[0-9A-Z]{16}]\n" | 397 " --serial-id=[0-9A-Z]{16}]\n" |
391 " --map DEVICE_PORT HOST_PORT\n" | 398 " --map DEVICE_PORT HOST_PORT\n" |
392 " --unmap DEVICE_PORT\n" | 399 " --unmap DEVICE_PORT\n" |
| 400 " --adb PATH_TO_ADB\n" |
393 " --kill-server\n"; | 401 " --kill-server\n"; |
394 exit(1); | 402 exit(1); |
395 } | 403 } |
396 | 404 |
397 int PortToInt(const std::string& s) { | 405 int PortToInt(const std::string& s) { |
398 int value; | 406 int value; |
399 // Note that 0 is a valid port (used for dynamic port allocation). | 407 // Note that 0 is a valid port (used for dynamic port allocation). |
400 if (!base::StringToInt(s, &value) || value < 0 || | 408 if (!base::StringToInt(s, &value) || value < 0 || |
401 value > std::numeric_limits<uint16>::max()) { | 409 value > std::numeric_limits<uint16>::max()) { |
402 LOG(ERROR) << "Could not convert string " << s << " to port"; | 410 LOG(ERROR) << "Could not convert string " << s << " to port"; |
403 ExitWithUsage(); | 411 ExitWithUsage(); |
404 } | 412 } |
405 return value; | 413 return value; |
406 } | 414 } |
407 | 415 |
408 int RunHostForwarder(int argc, char** argv) { | 416 int RunHostForwarder(int argc, char** argv) { |
409 base::CommandLine::Init(argc, argv); | 417 base::CommandLine::Init(argc, argv); |
410 const base::CommandLine& cmd_line = *base::CommandLine::ForCurrentProcess(); | 418 const base::CommandLine& cmd_line = *base::CommandLine::ForCurrentProcess(); |
| 419 std::string adb_path = "adb"; |
411 bool kill_server = false; | 420 bool kill_server = false; |
412 | 421 |
413 Pickle pickle; | 422 Pickle pickle; |
414 pickle.WriteString( | 423 pickle.WriteString( |
415 cmd_line.HasSwitch("serial-id") ? | 424 cmd_line.HasSwitch("serial-id") ? |
416 cmd_line.GetSwitchValueASCII("serial-id") : std::string()); | 425 cmd_line.GetSwitchValueASCII("serial-id") : std::string()); |
417 | 426 |
418 const std::vector<std::string> args = cmd_line.GetArgs(); | 427 const std::vector<std::string> args = cmd_line.GetArgs(); |
419 if (cmd_line.HasSwitch("kill-server")) { | 428 if (cmd_line.HasSwitch("kill-server")) { |
420 kill_server = true; | 429 kill_server = true; |
421 } else if (cmd_line.HasSwitch("unmap")) { | 430 } else if (cmd_line.HasSwitch("unmap")) { |
422 if (args.size() != 1) | 431 if (args.size() != 1) |
423 ExitWithUsage(); | 432 ExitWithUsage(); |
424 // Note the minus sign below. | 433 // Note the minus sign below. |
425 pickle.WriteInt(-PortToInt(args[0])); | 434 pickle.WriteInt(-PortToInt(args[0])); |
426 } else if (cmd_line.HasSwitch("map")) { | 435 } else if (cmd_line.HasSwitch("map")) { |
427 if (args.size() != 2) | 436 if (args.size() != 2) |
428 ExitWithUsage(); | 437 ExitWithUsage(); |
429 pickle.WriteInt(PortToInt(args[0])); | 438 pickle.WriteInt(PortToInt(args[0])); |
430 pickle.WriteInt(PortToInt(args[1])); | 439 pickle.WriteInt(PortToInt(args[1])); |
431 } else { | 440 } else { |
432 ExitWithUsage(); | 441 ExitWithUsage(); |
433 } | 442 } |
434 | 443 |
| 444 if (cmd_line.HasSwitch("adb")) { |
| 445 adb_path = cmd_line.GetSwitchValueASCII("adb"); |
| 446 } |
| 447 |
435 if (kill_server && args.size() > 0) | 448 if (kill_server && args.size() > 0) |
436 ExitWithUsage(); | 449 ExitWithUsage(); |
437 | 450 |
438 ClientDelegate client_delegate(pickle); | 451 ClientDelegate client_delegate(pickle); |
439 ServerDelegate daemon_delegate; | 452 ServerDelegate daemon_delegate(adb_path); |
440 Daemon daemon( | 453 Daemon daemon( |
441 kLogFilePath, kDaemonIdentifier, &client_delegate, &daemon_delegate, | 454 kLogFilePath, kDaemonIdentifier, &client_delegate, &daemon_delegate, |
442 &GetExitNotifierFD); | 455 &GetExitNotifierFD); |
443 | 456 |
444 if (kill_server) | 457 if (kill_server) |
445 return !daemon.Kill(); | 458 return !daemon.Kill(); |
446 if (!daemon.SpawnIfNeeded()) | 459 if (!daemon.SpawnIfNeeded()) |
447 return 1; | 460 return 1; |
448 | 461 |
449 return client_delegate.has_failed() || daemon_delegate.has_failed(); | 462 return client_delegate.has_failed() || daemon_delegate.has_failed(); |
450 } | 463 } |
451 | 464 |
452 } // namespace | 465 } // namespace |
453 } // namespace forwarder2 | 466 } // namespace forwarder2 |
454 | 467 |
455 int main(int argc, char** argv) { | 468 int main(int argc, char** argv) { |
456 return forwarder2::RunHostForwarder(argc, argv); | 469 return forwarder2::RunHostForwarder(argc, argv); |
457 } | 470 } |
OLD | NEW |