Chromium Code Reviews| 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 |
| 11 #include <cstdio> | 11 #include <cstdio> |
| 12 #include <iostream> | 12 #include <iostream> |
| 13 #include <limits> | 13 #include <limits> |
| 14 #include <string> | 14 #include <string> |
| 15 #include <utility> | 15 #include <utility> |
| 16 #include <vector> | 16 #include <vector> |
| 17 | 17 |
| 18 #include "base/at_exit.h" | 18 #include "base/at_exit.h" |
| 19 #include "base/basictypes.h" | |
| 19 #include "base/bind.h" | 20 #include "base/bind.h" |
| 20 #include "base/command_line.h" | 21 #include "base/command_line.h" |
| 21 #include "base/compiler_specific.h" | 22 #include "base/compiler_specific.h" |
| 22 #include "base/containers/hash_tables.h" | 23 #include "base/containers/hash_tables.h" |
| 23 #include "base/file_util.h" | 24 #include "base/file_util.h" |
| 24 #include "base/files/file_path.h" | 25 #include "base/files/file_path.h" |
| 25 #include "base/logging.h" | 26 #include "base/logging.h" |
| 26 #include "base/memory/linked_ptr.h" | 27 #include "base/memory/linked_ptr.h" |
| 27 #include "base/memory/scoped_vector.h" | 28 #include "base/memory/scoped_vector.h" |
| 29 #include "base/memory/weak_ptr.h" | |
| 28 #include "base/pickle.h" | 30 #include "base/pickle.h" |
| 29 #include "base/posix/eintr_wrapper.h" | 31 #include "base/posix/eintr_wrapper.h" |
| 30 #include "base/safe_strerror_posix.h" | 32 #include "base/safe_strerror_posix.h" |
| 31 #include "base/strings/string_number_conversions.h" | 33 #include "base/strings/string_number_conversions.h" |
| 32 #include "base/strings/string_piece.h" | 34 #include "base/strings/string_piece.h" |
| 33 #include "base/strings/string_split.h" | 35 #include "base/strings/string_split.h" |
| 34 #include "base/strings/string_util.h" | 36 #include "base/strings/string_util.h" |
| 35 #include "base/strings/stringprintf.h" | 37 #include "base/strings/stringprintf.h" |
| 36 #include "base/task_runner.h" | 38 #include "base/task_runner.h" |
| 37 #include "base/threading/thread.h" | 39 #include "base/threading/thread.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 static int s_kill_handler_count = 0; | 75 static int s_kill_handler_count = 0; |
| 74 CHECK(g_notifier); | 76 CHECK(g_notifier); |
| 75 // If for some reason the forwarder get stuck in any socket waiting forever, | 77 // If for some reason the forwarder get stuck in any socket waiting forever, |
| 76 // we can send a SIGKILL or SIGINT three times to force it die | 78 // we can send a SIGKILL or SIGINT three times to force it die |
| 77 // (non-nicely). This is useful when debugging. | 79 // (non-nicely). This is useful when debugging. |
| 78 ++s_kill_handler_count; | 80 ++s_kill_handler_count; |
| 79 if (!g_notifier->Notify() || s_kill_handler_count > 2) | 81 if (!g_notifier->Notify() || s_kill_handler_count > 2) |
| 80 exit(1); | 82 exit(1); |
| 81 } | 83 } |
| 82 | 84 |
| 85 // Manages HostController instances. There is one HostController instance for | |
| 86 // each redirection. Note that redirections can happen with many devices | |
|
bulach
2013/07/30 11:11:37
nit: is "redirection" the same as "forwarding" her
pliard
2013/07/30 11:50:20
Yeah :) Done.
| |
| 87 // (identified with a serial id). | |
| 83 class HostControllersManager { | 88 class HostControllersManager { |
| 84 public: | 89 public: |
| 85 HostControllersManager() : has_failed_(false) {} | 90 HostControllersManager() |
| 91 : weak_ptr_factory_(this), | |
| 92 controllers_(new HostControllerMap()), | |
| 93 has_failed_(false) { | |
| 94 } | |
| 95 | |
| 96 ~HostControllersManager() { | |
| 97 if (!thread_.get()) | |
| 98 return; | |
| 99 // Delete the controllers on the thread they were created on. | |
| 100 thread_->message_loop_proxy()->DeleteSoon( | |
| 101 FROM_HERE, controllers_.release()); | |
| 102 } | |
| 86 | 103 |
| 87 void HandleRequest(const std::string& device_serial, | 104 void HandleRequest(const std::string& device_serial, |
| 88 int device_port, | 105 int device_port, |
| 89 int host_port, | 106 int host_port, |
| 90 scoped_ptr<Socket> client_socket) { | 107 scoped_ptr<Socket> client_socket) { |
| 91 // Lazy initialize so that the CLI process doesn't get this thread created. | 108 // Lazy initialize so that the CLI process doesn't get this thread created. |
| 92 InitOnce(); | 109 InitOnce(); |
| 93 thread_->message_loop_proxy()->PostTask( | 110 thread_->message_loop_proxy()->PostTask( |
| 94 FROM_HERE, | 111 FROM_HERE, |
| 95 base::Bind( | 112 base::Bind( |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 110 | 127 |
| 111 void InitOnce() { | 128 void InitOnce() { |
| 112 if (thread_.get()) | 129 if (thread_.get()) |
| 113 return; | 130 return; |
| 114 at_exit_manager_.reset(new base::AtExitManager()); | 131 at_exit_manager_.reset(new base::AtExitManager()); |
| 115 thread_.reset(new base::Thread("HostControllersManagerThread")); | 132 thread_.reset(new base::Thread("HostControllersManagerThread")); |
| 116 thread_->Start(); | 133 thread_->Start(); |
| 117 } | 134 } |
| 118 | 135 |
| 119 // Invoked when a HostController instance reports an error (e.g. due to a | 136 // Invoked when a HostController instance reports an error (e.g. due to a |
| 120 // device connectivity issue). | 137 // device connectivity issue). Note that this could be called after the |
| 121 void DeleteHostController(HostController* host_controller) { | 138 // controller manager was destroyed which is why a weak pointer is used. |
| 122 if (!thread_->message_loop_proxy()->RunsTasksOnCurrentThread()) { | 139 static void DeleteHostController( |
| 123 // This can be invoked from the host controller internal thread. | 140 const base::WeakPtr<HostControllersManager>& manager_ptr, |
| 124 thread_->message_loop_proxy()->PostTask( | 141 scoped_ptr<HostController> host_controller) { |
| 125 FROM_HERE, | 142 HostController* const controller = host_controller.release(); |
| 126 base::Bind( | 143 HostControllersManager* const manager = manager_ptr.get(); |
| 127 &HostControllersManager::DeleteHostControllerOnInternalThread, | 144 if (!manager) { |
| 128 base::Unretained(this), host_controller)); | 145 // Note that |controller| is not leaked in this case since the host |
| 146 // controllers manager owns the controllers. If the manager was deleted | |
| 147 // then all the controllers (including |controller|) were also deleted. | |
| 129 return; | 148 return; |
| 130 } | 149 } |
| 131 DeleteHostControllerOnInternalThread(host_controller); | 150 DCHECK(manager->thread_->message_loop_proxy()->RunsTasksOnCurrentThread()); |
| 132 } | 151 // Note that this will delete |controller| which is owned by the map. |
| 133 | 152 manager->controllers_->erase( |
| 134 void DeleteHostControllerOnInternalThread(HostController* host_controller) { | 153 MakeHostControllerMapKey(controller->adb_port(), |
| 135 // Note that this will delete |host_controller| which is owned by the map. | 154 controller->device_port())); |
| 136 controllers_.erase( | |
| 137 MakeHostControllerMapKey(host_controller->adb_port(), | |
| 138 host_controller->device_port())); | |
| 139 } | 155 } |
| 140 | 156 |
| 141 void HandleRequestOnInternalThread(const std::string& device_serial, | 157 void HandleRequestOnInternalThread(const std::string& device_serial, |
| 142 int device_port, | 158 int device_port, |
| 143 int host_port, | 159 int host_port, |
| 144 scoped_ptr<Socket> client_socket) { | 160 scoped_ptr<Socket> client_socket) { |
| 145 const int adb_port = GetAdbPortForDevice(device_serial); | 161 const int adb_port = GetAdbPortForDevice(device_serial); |
| 146 if (adb_port < 0) { | 162 if (adb_port < 0) { |
| 147 SendMessage( | 163 SendMessage( |
| 148 "ERROR: could not get adb port for device. You might need to add " | 164 "ERROR: could not get adb port for device. You might need to add " |
| 149 "'adb' to your PATH or provide the device serial id.", | 165 "'adb' to your PATH or provide the device serial id.", |
| 150 client_socket.get()); | 166 client_socket.get()); |
| 151 return; | 167 return; |
| 152 } | 168 } |
| 153 if (device_port < 0) { | 169 if (device_port < 0) { |
| 154 // Remove the previously created host controller. | 170 // Remove the previously created host controller. |
| 155 const std::string controller_key = MakeHostControllerMapKey( | 171 const std::string controller_key = MakeHostControllerMapKey( |
| 156 adb_port, -device_port); | 172 adb_port, -device_port); |
| 157 const HostControllerMap::size_type removed_elements = controllers_.erase( | 173 const HostControllerMap::size_type removed_elements = controllers_->erase( |
| 158 controller_key); | 174 controller_key); |
| 159 SendMessage( | 175 SendMessage( |
| 160 !removed_elements ? "ERROR: could not unmap port" : "OK", | 176 !removed_elements ? "ERROR: could not unmap port" : "OK", |
| 161 client_socket.get()); | 177 client_socket.get()); |
| 162 return; | 178 return; |
| 163 } | 179 } |
| 164 if (host_port < 0) { | 180 if (host_port < 0) { |
| 165 SendMessage("ERROR: missing host port", client_socket.get()); | 181 SendMessage("ERROR: missing host port", client_socket.get()); |
| 166 return; | 182 return; |
| 167 } | 183 } |
| 168 const bool use_dynamic_port_allocation = device_port == 0; | 184 const bool use_dynamic_port_allocation = device_port == 0; |
| 169 if (!use_dynamic_port_allocation) { | 185 if (!use_dynamic_port_allocation) { |
| 170 const std::string controller_key = MakeHostControllerMapKey( | 186 const std::string controller_key = MakeHostControllerMapKey( |
| 171 adb_port, device_port); | 187 adb_port, device_port); |
| 172 if (controllers_.find(controller_key) != controllers_.end()) { | 188 if (controllers_->find(controller_key) != controllers_->end()) { |
| 173 LOG(INFO) << "Already forwarding device port " << device_port | 189 LOG(INFO) << "Already forwarding device port " << device_port |
| 174 << " to host port " << host_port; | 190 << " to host port " << host_port; |
| 175 SendMessage(base::StringPrintf("%d:%d", device_port, host_port), | 191 SendMessage(base::StringPrintf("%d:%d", device_port, host_port), |
| 176 client_socket.get()); | 192 client_socket.get()); |
| 177 return; | 193 return; |
| 178 } | 194 } |
| 179 } | 195 } |
| 180 // Create a new host controller. | 196 // Create a new host controller. |
| 181 scoped_ptr<HostController> host_controller( | 197 scoped_ptr<HostController> host_controller( |
| 182 new HostController( | 198 HostController::Create( |
| 183 device_port, "127.0.0.1", host_port, adb_port, GetExitNotifierFD(), | 199 device_port, host_port, adb_port, GetExitNotifierFD(), |
| 184 base::Bind(&HostControllersManager::DeleteHostController, | 200 base::Bind(&HostControllersManager::DeleteHostController, |
| 185 base::Unretained(this)))); | 201 weak_ptr_factory_.GetWeakPtr()))); |
| 186 if (!host_controller->Connect()) { | 202 if (!host_controller.get()) { |
| 187 has_failed_ = true; | 203 has_failed_ = true; |
| 188 SendMessage("ERROR: Connection to device failed.", client_socket.get()); | 204 SendMessage("ERROR: Connection to device failed.", client_socket.get()); |
| 189 return; | 205 return; |
| 190 } | 206 } |
| 191 // Get the current allocated port. | 207 // Get the current allocated port. |
| 192 device_port = host_controller->device_port(); | 208 device_port = host_controller->device_port(); |
| 193 LOG(INFO) << "Forwarding device port " << device_port << " to host port " | 209 LOG(INFO) << "Forwarding device port " << device_port << " to host port " |
| 194 << host_port; | 210 << host_port; |
| 195 const std::string msg = base::StringPrintf("%d:%d", device_port, host_port); | 211 const std::string msg = base::StringPrintf("%d:%d", device_port, host_port); |
| 196 if (!SendMessage(msg, client_socket.get())) | 212 if (!SendMessage(msg, client_socket.get())) |
| 197 return; | 213 return; |
| 198 host_controller->Start(); | 214 host_controller->Start(); |
| 199 controllers_.insert( | 215 controllers_->insert( |
| 200 std::make_pair(MakeHostControllerMapKey(adb_port, device_port), | 216 std::make_pair(MakeHostControllerMapKey(adb_port, device_port), |
| 201 linked_ptr<HostController>(host_controller.release()))); | 217 linked_ptr<HostController>(host_controller.release()))); |
| 202 } | 218 } |
| 203 | 219 |
| 204 int GetAdbPortForDevice(const std::string& device_serial) { | 220 int GetAdbPortForDevice(const std::string& device_serial) { |
| 205 base::hash_map<std::string, int>::const_iterator it = | 221 base::hash_map<std::string, int>::const_iterator it = |
| 206 device_serial_to_adb_port_map_.find(device_serial); | 222 device_serial_to_adb_port_map_.find(device_serial); |
| 207 if (it != device_serial_to_adb_port_map_.end()) | 223 if (it != device_serial_to_adb_port_map_.end()) |
| 208 return it->second; | 224 return it->second; |
| 209 Socket bind_socket; | 225 Socket bind_socket; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 225 } | 241 } |
| 226 | 242 |
| 227 bool SendMessage(const std::string& msg, Socket* client_socket) { | 243 bool SendMessage(const std::string& msg, Socket* client_socket) { |
| 228 bool result = client_socket->WriteString(msg); | 244 bool result = client_socket->WriteString(msg); |
| 229 DCHECK(result); | 245 DCHECK(result); |
| 230 if (!result) | 246 if (!result) |
| 231 has_failed_ = true; | 247 has_failed_ = true; |
| 232 return result; | 248 return result; |
| 233 } | 249 } |
| 234 | 250 |
| 251 base::WeakPtrFactory<HostControllersManager> weak_ptr_factory_; | |
| 235 base::hash_map<std::string, int> device_serial_to_adb_port_map_; | 252 base::hash_map<std::string, int> device_serial_to_adb_port_map_; |
| 236 HostControllerMap controllers_; | 253 scoped_ptr<HostControllerMap> controllers_; |
| 237 bool has_failed_; | 254 bool has_failed_; |
| 238 scoped_ptr<base::AtExitManager> at_exit_manager_; // Needed by base::Thread. | 255 scoped_ptr<base::AtExitManager> at_exit_manager_; // Needed by base::Thread. |
| 239 scoped_ptr<base::Thread> thread_; | 256 scoped_ptr<base::Thread> thread_; |
| 240 }; | 257 }; |
| 241 | 258 |
| 242 class ServerDelegate : public Daemon::ServerDelegate { | 259 class ServerDelegate : public Daemon::ServerDelegate { |
| 243 public: | 260 public: |
| 244 ServerDelegate() : has_failed_(false) {} | 261 ServerDelegate() : has_failed_(false) {} |
| 245 | 262 |
| 246 bool has_failed() const { | 263 bool has_failed() const { |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 388 | 405 |
| 389 return client_delegate.has_failed() || daemon_delegate.has_failed(); | 406 return client_delegate.has_failed() || daemon_delegate.has_failed(); |
| 390 } | 407 } |
| 391 | 408 |
| 392 } // namespace | 409 } // namespace |
| 393 } // namespace forwarder2 | 410 } // namespace forwarder2 |
| 394 | 411 |
| 395 int main(int argc, char** argv) { | 412 int main(int argc, char** argv) { |
| 396 return forwarder2::RunHostForwarder(argc, argv); | 413 return forwarder2::RunHostForwarder(argc, argv); |
| 397 } | 414 } |
| OLD | NEW |