host_controllers_manager.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. // Copyright 2017 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. #include "tools/android/forwarder2/host_controllers_manager.h"
  5. #include <memory>
  6. #include "base/bind.h"
  7. #include "base/logging.h"
  8. #include "base/process/launch.h"
  9. #include "base/strings/string_split.h"
  10. #include "base/strings/string_util.h"
  11. #include "base/strings/stringprintf.h"
  12. #include "tools/android/forwarder2/util.h"
  13. namespace forwarder2 {
  14. HostControllersManager::HostControllersManager(
  15. base::RepeatingCallback<int()> exit_notifier_fd_callback)
  16. : controllers_(new HostControllerMap()),
  17. exit_notifier_fd_callback_(exit_notifier_fd_callback),
  18. has_failed_(false),
  19. weak_ptr_factory_(this) {}
  20. HostControllersManager::~HostControllersManager() {
  21. if (!thread_.get())
  22. return;
  23. // Delete the controllers on the thread they were created on.
  24. thread_->task_runner()->DeleteSoon(FROM_HERE, controllers_.release());
  25. }
  26. void HostControllersManager::HandleRequest(
  27. const std::string& adb_path,
  28. const std::string& device_serial,
  29. int command,
  30. int device_port,
  31. int host_port,
  32. std::unique_ptr<Socket> client_socket) {
  33. // Lazy initialize so that the CLI process doesn't get this thread created.
  34. InitOnce();
  35. thread_->task_runner()->PostTask(
  36. FROM_HERE,
  37. base::BindOnce(&HostControllersManager::HandleRequestOnInternalThread,
  38. base::Unretained(this), adb_path, device_serial, command,
  39. device_port, host_port, std::move(client_socket)));
  40. }
  41. // static
  42. std::string HostControllersManager::MakeHostControllerMapKey(int adb_port,
  43. int device_port) {
  44. return base::StringPrintf("%d:%d", adb_port, device_port);
  45. }
  46. void HostControllersManager::InitOnce() {
  47. if (thread_.get())
  48. return;
  49. at_exit_manager_ = std::make_unique<base::AtExitManager>();
  50. thread_ = std::make_unique<base::Thread>("HostControllersManagerThread");
  51. thread_->Start();
  52. }
  53. // static
  54. void HostControllersManager::DeleteHostController(
  55. const base::WeakPtr<HostControllersManager>& manager_ptr,
  56. std::unique_ptr<HostController> host_controller) {
  57. HostController* const controller = host_controller.release();
  58. HostControllersManager* const manager = manager_ptr.get();
  59. if (!manager) {
  60. // Note that |controller| is not leaked in this case since the host
  61. // controllers manager owns the controllers. If the manager was deleted
  62. // then all the controllers (including |controller|) were also deleted.
  63. return;
  64. }
  65. DCHECK(manager->thread_->task_runner()->RunsTasksInCurrentSequence());
  66. // Note that this will delete |controller| which is owned by the map.
  67. DeleteRefCountedValueInMap(
  68. MakeHostControllerMapKey(controller->adb_port(),
  69. controller->device_port()),
  70. manager->controllers_.get());
  71. }
  72. void HostControllersManager::Map(const std::string& adb_path,
  73. const std::string& device_serial,
  74. int adb_port,
  75. int device_port,
  76. int host_port,
  77. Socket* client_socket) {
  78. if (host_port < 0) {
  79. SendMessage("ERROR: missing host port\n", client_socket);
  80. return;
  81. }
  82. const bool use_dynamic_port_allocation = device_port == 0;
  83. if (!use_dynamic_port_allocation) {
  84. const std::string controller_key =
  85. MakeHostControllerMapKey(adb_port, device_port);
  86. if (controllers_->find(controller_key) != controllers_->end()) {
  87. LOG(INFO) << "Already forwarding device port " << device_port
  88. << " to host port " << host_port;
  89. SendMessage(base::StringPrintf("%d:%d", device_port, host_port),
  90. client_socket);
  91. return;
  92. }
  93. }
  94. // Create a new host controller.
  95. std::unique_ptr<HostController> host_controller(HostController::Create(
  96. device_serial, device_port, host_port, adb_port,
  97. exit_notifier_fd_callback_.Run(),
  98. base::BindOnce(&HostControllersManager::DeleteHostController,
  99. weak_ptr_factory_.GetWeakPtr())));
  100. if (!host_controller.get()) {
  101. has_failed_ = true;
  102. SendMessage("ERROR: Connection to device failed.\n", client_socket);
  103. LogExistingControllers(client_socket);
  104. return;
  105. }
  106. // Get the current allocated port.
  107. device_port = host_controller->device_port();
  108. LOG(INFO) << "Forwarding device port " << device_port << " to host port "
  109. << host_port;
  110. const std::string msg = base::StringPrintf("%d:%d", device_port, host_port);
  111. if (!SendMessage(msg, client_socket))
  112. return;
  113. host_controller->Start();
  114. controllers_->emplace(MakeHostControllerMapKey(adb_port, device_port),
  115. std::move(host_controller));
  116. }
  117. void HostControllersManager::Unmap(const std::string& adb_path,
  118. const std::string& device_serial,
  119. int adb_port,
  120. int device_port,
  121. Socket* client_socket) {
  122. // Remove the previously created host controller.
  123. const std::string controller_key =
  124. MakeHostControllerMapKey(adb_port, device_port);
  125. const bool controller_did_exist =
  126. DeleteRefCountedValueInMap(controller_key, controllers_.get());
  127. if (!controller_did_exist) {
  128. SendMessage("ERROR: could not unmap port.\n", client_socket);
  129. LogExistingControllers(client_socket);
  130. } else {
  131. SendMessage("OK", client_socket);
  132. }
  133. RemoveAdbPortForDeviceIfNeeded(adb_path, device_serial);
  134. }
  135. void HostControllersManager::UnmapAll(const std::string& adb_path,
  136. const std::string& device_serial,
  137. int adb_port,
  138. Socket* client_socket) {
  139. const std::string adb_port_str = base::StringPrintf("%d", adb_port);
  140. for (auto controller_key = controllers_->begin();
  141. controller_key != controllers_->end(); ++controller_key) {
  142. std::vector<std::string> pieces =
  143. base::SplitString(controller_key->first, ":", base::KEEP_WHITESPACE,
  144. base::SPLIT_WANT_ALL);
  145. if (pieces.size() == 2) {
  146. if (pieces[0] == adb_port_str) {
  147. DeleteRefCountedValueInMapFromIterator(controller_key,
  148. controllers_.get());
  149. }
  150. } else {
  151. LOG(ERROR) << "Unexpected controller key: " << controller_key->first;
  152. }
  153. }
  154. RemoveAdbPortForDeviceIfNeeded(adb_path, device_serial);
  155. SendMessage("OK", client_socket);
  156. }
  157. void HostControllersManager::HandleRequestOnInternalThread(
  158. const std::string& adb_path,
  159. const std::string& device_serial,
  160. int command,
  161. int device_port,
  162. int host_port,
  163. std::unique_ptr<Socket> client_socket) {
  164. const int adb_port = GetAdbPortForDevice(adb_path, device_serial);
  165. if (adb_port < 0) {
  166. SendMessage(
  167. "ERROR: could not get adb port for device. You might need to add "
  168. "'adb' to your PATH or provide the device serial id.\n",
  169. client_socket.get());
  170. return;
  171. }
  172. switch (command) {
  173. case MAP:
  174. Map(adb_path, device_serial, adb_port, device_port, host_port,
  175. client_socket.get());
  176. break;
  177. case UNMAP:
  178. Unmap(adb_path, device_serial, adb_port, device_port,
  179. client_socket.get());
  180. break;
  181. case UNMAP_ALL:
  182. UnmapAll(adb_path, device_serial, adb_port, client_socket.get());
  183. break;
  184. default:
  185. SendMessage(
  186. base::StringPrintf("ERROR: unrecognized command %d\n", command),
  187. client_socket.get());
  188. break;
  189. }
  190. }
  191. void HostControllersManager::LogExistingControllers(Socket* client_socket) {
  192. SendMessage("ERROR: Existing controllers:\n", client_socket);
  193. for (const auto& controller : *controllers_) {
  194. SendMessage(base::StringPrintf("ERROR: %s\n", controller.first.c_str()),
  195. client_socket);
  196. }
  197. }
  198. bool HostControllersManager::Adb(const std::string& adb_path,
  199. const std::string& device_serial,
  200. const std::string& command,
  201. std::string* output_and_error) {
  202. // We use the vector version of GetAppOutputAndError rather than the
  203. // more standard base::CommandLine version because base::CommandLine
  204. // reorders the command s.t. switches precede arguments and doing so
  205. // here creates an invalid adb command.
  206. std::vector<std::string> adb_command{adb_path};
  207. if (!device_serial.empty()) {
  208. adb_command.push_back("-s");
  209. adb_command.push_back(device_serial);
  210. }
  211. const std::vector<std::string> split_command = base::SplitString(
  212. command, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  213. adb_command.insert(adb_command.end(), split_command.begin(),
  214. split_command.end());
  215. return GetAppOutputAndError(adb_command, output_and_error);
  216. }
  217. void HostControllersManager::RemoveAdbPortForDeviceIfNeeded(
  218. const std::string& adb_path,
  219. const std::string& device_serial) {
  220. std::unordered_map<std::string, int>::const_iterator it =
  221. device_serial_to_adb_port_map_.find(device_serial);
  222. if (it == device_serial_to_adb_port_map_.end())
  223. return;
  224. int port = it->second;
  225. const std::string prefix = base::StringPrintf("%d:", port);
  226. for (auto others = controllers_->begin(); others != controllers_->end();
  227. ++others) {
  228. if (base::StartsWith(others->first, prefix, base::CompareCase::SENSITIVE))
  229. return;
  230. }
  231. // No other port is being forwarded to this device:
  232. // - Remove it from our internal serial -> adb port map.
  233. // - Remove from "adb forward" command.
  234. LOG(INFO) << "Device " << device_serial << " has no more ports.";
  235. device_serial_to_adb_port_map_.erase(device_serial);
  236. const std::string command =
  237. base::StringPrintf("forward --remove tcp:%d", port);
  238. std::string output;
  239. if (!Adb(adb_path, device_serial, command, &output)) {
  240. LOG(ERROR) << command << " failed. output: \"" << output << "\"";
  241. } else {
  242. LOG(INFO) << command << " (output: \"" << output << "\")";
  243. }
  244. // Wait for the socket to be fully unmapped.
  245. const std::string port_mapped_cmd = base::StringPrintf("lsof -nPi:%d", port);
  246. const std::vector<std::string> port_mapped_split_cmd = base::SplitString(
  247. port_mapped_cmd, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  248. const int poll_interval_us = 500 * 1000;
  249. int retries = 3;
  250. while (retries) {
  251. // lsof failure means the port was successfully unmapped.
  252. bool port_unmapped = !GetAppOutputAndError(port_mapped_split_cmd, &output);
  253. LOG(INFO) << "Device " << device_serial << " port " << port
  254. << (port_unmapped ? "" : " not") << " unmapped";
  255. if (port_unmapped)
  256. break;
  257. --retries;
  258. usleep(poll_interval_us);
  259. }
  260. }
  261. int HostControllersManager::GetAdbPortForDevice(
  262. const std::string adb_path,
  263. const std::string& device_serial) {
  264. std::unordered_map<std::string, int>::const_iterator it =
  265. device_serial_to_adb_port_map_.find(device_serial);
  266. if (it != device_serial_to_adb_port_map_.end())
  267. return it->second;
  268. Socket bind_socket;
  269. CHECK(bind_socket.BindTcp("127.0.0.1", 0));
  270. const int port = bind_socket.GetPort();
  271. bind_socket.Close();
  272. const std::string command = base::StringPrintf(
  273. "forward tcp:%d localabstract:chrome_device_forwarder", port);
  274. std::string output;
  275. if (!Adb(adb_path, device_serial, command, &output)) {
  276. LOG(ERROR) << command << " failed. output: " << output;
  277. return -1;
  278. }
  279. LOG(INFO) << command;
  280. device_serial_to_adb_port_map_[device_serial] = port;
  281. return port;
  282. }
  283. bool HostControllersManager::SendMessage(const std::string& msg,
  284. Socket* client_socket) {
  285. bool result = client_socket->WriteString(msg);
  286. DCHECK(result);
  287. if (!result)
  288. has_failed_ = true;
  289. return result;
  290. }
  291. bool HostControllersManager::GetAppOutputAndError(
  292. const std::vector<std::string>& argv,
  293. std::string* output) {
  294. return base::GetAppOutputAndError(argv, output);
  295. }
  296. } // namespace forwarder2