OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "tools/android/forwarder2/device_controller.h" |
| 6 |
| 7 #include <errno.h> |
| 8 #include <stdlib.h> |
| 9 |
| 10 #include "base/logging.h" |
| 11 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/safe_strerror_posix.h" |
| 13 #include "tools/android/forwarder2/command.h" |
| 14 #include "tools/android/forwarder2/device_listener.h" |
| 15 #include "tools/android/forwarder2/socket.h" |
| 16 |
| 17 namespace forwarder { |
| 18 |
| 19 DeviceController::DeviceController(int notifier_fd) |
| 20 : exit_notifier_fd_(notifier_fd) { |
| 21 kickstart_adb_socket_.set_notifier_fd(notifier_fd); |
| 22 } |
| 23 |
| 24 DeviceController::~DeviceController() { |
| 25 KillAllListeners(); |
| 26 CleanUpDeadListeners(); |
| 27 CHECK_EQ(0, listeners_.size()); |
| 28 } |
| 29 |
| 30 void DeviceController::CleanUpDeadListeners() { |
| 31 // Clean up dead listeners. |
| 32 for (ListenersMap::iterator it = listeners_.begin(); |
| 33 it != listeners_.end();) { |
| 34 if (!it->second->is_alive()) { |
| 35 ListenersMap::iterator to_erase(it); |
| 36 to_erase->second.reset(); |
| 37 ++it; |
| 38 listeners_.erase(to_erase); |
| 39 } else { |
| 40 ++it; |
| 41 } |
| 42 } |
| 43 } |
| 44 |
| 45 void DeviceController::KillAllListeners() { |
| 46 ListenersMap::iterator it; |
| 47 for (it = listeners_.begin(); it != listeners_.end(); ++it) { |
| 48 it->second->ForceExit(); |
| 49 } |
| 50 for (it = listeners_.begin(); it != listeners_.end(); ++it) { |
| 51 it->second->Join(); |
| 52 CHECK(!it->second->is_alive()); |
| 53 } |
| 54 } |
| 55 |
| 56 bool DeviceController::Start(const string& adb_unix_socket) { |
| 57 if (!kickstart_adb_socket_.BindUnix(adb_unix_socket, |
| 58 /* abstract = */ true)) { |
| 59 LOG(ERROR) << "Could not BindAndListen DeviceController socket on port: " |
| 60 << adb_unix_socket; |
| 61 return false; |
| 62 } |
| 63 while (true) { |
| 64 CleanUpDeadListeners(); |
| 65 scoped_ptr<Socket> socket(new Socket); |
| 66 if (!kickstart_adb_socket_.Accept(socket.get())) { |
| 67 LOG(ERROR) << "Could not Accept DeviceController socket: " |
| 68 << safe_strerror(errno); |
| 69 break; |
| 70 } |
| 71 // So that |socket| doesn't block on read if it has notifications. |
| 72 socket->set_notifier_fd(exit_notifier_fd_); |
| 73 int port; |
| 74 command::Type command; |
| 75 if (!ReadCommand(socket.get(), &port, &command)) { |
| 76 LOG(ERROR) << "Invalid command received."; |
| 77 socket->Close(); |
| 78 continue; |
| 79 } |
| 80 ListenersMap::iterator listener_it(listeners_.find(port)); |
| 81 switch (command) { |
| 82 case command::LISTEN: |
| 83 if (listener_it != listeners_.end()) { |
| 84 LOG(WARNING) << "Already forwarding port " << port |
| 85 << ". Attempting to restart the listener.\n"; |
| 86 listener_it->second->ForceExit(); |
| 87 listener_it->second->Join(); |
| 88 CHECK(!listener_it->second->is_alive()); |
| 89 } else { |
| 90 // Listener object will be deleted by the CleanUpDeadListeners method. |
| 91 DeviceListener* listener = new DeviceListener(socket.Pass(), port); |
| 92 listeners_[port].reset(listener); |
| 93 listener->Start(); |
| 94 } |
| 95 break; |
| 96 case command::DATA_CONNECTION: |
| 97 if (listener_it == listeners_.end()) { |
| 98 LOG(ERROR) << "Data Connection command received, but " |
| 99 << "listener has not been set up yet for port " << port; |
| 100 // After this point it is assumed that, once we close our Adb Data |
| 101 // socket, the Adb forwarder command will propagate the closing of |
| 102 // sockets all the way to the host side. |
| 103 socket->Close(); |
| 104 continue; |
| 105 } else if (!listener_it->second->SetAdbDataSocket(socket.Pass())) { |
| 106 LOG(ERROR) << "Could not set Adb Data Socket for port: " << port; |
| 107 // Same assumption as above, but in this case the socket is closed |
| 108 // inside SetAdbDataSocket. |
| 109 continue; |
| 110 } |
| 111 break; |
| 112 default: |
| 113 // TODO(felipeg): add a KillAllListeners command. |
| 114 LOG(ERROR) << "Invalid command received."; |
| 115 socket->Close(); |
| 116 continue; |
| 117 } |
| 118 } |
| 119 KillAllListeners(); |
| 120 CleanUpDeadListeners(); |
| 121 kickstart_adb_socket_.Close(); |
| 122 } |
| 123 |
| 124 } // namespace forwarder |
OLD | NEW |