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/host_controller.h" 6 7 #include <string> 8 9 #include "base/bind.h" 10 #include "base/bind_helpers.h" 11 #include "base/logging.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "tools/android/forwarder2/command.h" 14 #include "tools/android/forwarder2/forwarder.h" 15 #include "tools/android/forwarder2/socket.h" 16 17 namespace forwarder2 { 18 19 // static 20 scoped_ptr<HostController> HostController::Create( 21 int device_port, 22 int host_port, 23 int adb_port, 24 int exit_notifier_fd, 25 const DeletionCallback& deletion_callback) { 26 scoped_ptr<HostController> host_controller; 27 scoped_ptr<PipeNotifier> delete_controller_notifier(new PipeNotifier()); 28 scoped_ptr<Socket> adb_control_socket(new Socket()); 29 adb_control_socket->AddEventFd(exit_notifier_fd); 30 adb_control_socket->AddEventFd(delete_controller_notifier->receiver_fd()); 31 if (!adb_control_socket->ConnectTcp(std::string(), adb_port)) { 32 LOG(ERROR) << "Could not connect HostController socket on port: " 33 << adb_port; 34 return host_controller.Pass(); 35 } 36 // Send the command to the device start listening to the "device_forward_port" 37 bool send_command_success = SendCommand( 38 command::LISTEN, device_port, adb_control_socket.get()); 39 CHECK(send_command_success); 40 int device_port_allocated; 41 command::Type command; 42 if (!ReadCommand( 43 adb_control_socket.get(), &device_port_allocated, &command) || 44 command != command::BIND_SUCCESS) { 45 LOG(ERROR) << "Device binding error using port " << device_port; 46 return host_controller.Pass(); 47 } 48 host_controller.reset( 49 new HostController( 50 device_port_allocated, host_port, adb_port, exit_notifier_fd, 51 deletion_callback, adb_control_socket.Pass(), 52 delete_controller_notifier.Pass())); 53 return host_controller.Pass(); 54 } 55 56 HostController::~HostController() { 57 DCHECK(deletion_task_runner_->RunsTasksOnCurrentThread()); 58 delete_controller_notifier_->Notify(); 59 // Note that the Forwarder instance (that also received a delete notification) 60 // might still be running on its own thread at this point. This is not a 61 // problem since it will self-delete once the socket that it is operating on 62 // is closed. 63 } 64 65 void HostController::Start() { 66 thread_.Start(); 67 ReadNextCommandSoon(); 68 } 69 70 HostController::HostController( 71 int device_port, 72 int host_port, 73 int adb_port, 74 int exit_notifier_fd, 75 const DeletionCallback& deletion_callback, 76 scoped_ptr<Socket> adb_control_socket, 77 scoped_ptr<PipeNotifier> delete_controller_notifier) 78 : device_port_(device_port), 79 host_port_(host_port), 80 adb_port_(adb_port), 81 global_exit_notifier_fd_(exit_notifier_fd), 82 deletion_callback_(deletion_callback), 83 adb_control_socket_(adb_control_socket.Pass()), 84 delete_controller_notifier_(delete_controller_notifier.Pass()), 85 deletion_task_runner_(base::MessageLoopProxy::current()), 86 thread_("HostControllerThread") { 87 } 88 89 void HostController::ReadNextCommandSoon() { 90 thread_.message_loop_proxy()->PostTask( 91 FROM_HERE, 92 base::Bind(&HostController::ReadCommandOnInternalThread, 93 base::Unretained(this))); 94 } 95 96 void HostController::ReadCommandOnInternalThread() { 97 if (!ReceivedCommand(command::ACCEPT_SUCCESS, adb_control_socket_.get())) { 98 SelfDelete(); 99 return; 100 } 101 // Try to connect to host server. 102 scoped_ptr<Socket> host_server_data_socket(CreateSocket()); 103 if (!host_server_data_socket->ConnectTcp(std::string(), host_port_)) { 104 LOG(ERROR) << "Could not Connect HostServerData socket on port: " 105 << host_port_; 106 SendCommand( 107 command::HOST_SERVER_ERROR, device_port_, adb_control_socket_.get()); 108 if (ReceivedCommand(command::ACK, adb_control_socket_.get())) { 109 // It can continue if the host forwarder could not connect to the host 110 // server but the device acknowledged that, so that the device could 111 // re-try later. 112 ReadNextCommandSoon(); 113 return; 114 } 115 SelfDelete(); 116 return; 117 } 118 SendCommand( 119 command::HOST_SERVER_SUCCESS, device_port_, adb_control_socket_.get()); 120 StartForwarder(host_server_data_socket.Pass()); 121 ReadNextCommandSoon(); 122 } 123 124 void HostController::StartForwarder( 125 scoped_ptr<Socket> host_server_data_socket) { 126 scoped_ptr<Socket> adb_data_socket(CreateSocket()); 127 if (!adb_data_socket->ConnectTcp("", adb_port_)) { 128 LOG(ERROR) << "Could not connect AdbDataSocket on port: " << adb_port_; 129 SelfDelete(); 130 return; 131 } 132 // Open the Adb data connection, and send a command with the 133 // |device_forward_port| as a way for the device to identify the connection. 134 SendCommand(command::DATA_CONNECTION, device_port_, adb_data_socket.get()); 135 136 // Check that the device received the new Adb Data Connection. Note that this 137 // check is done through the |adb_control_socket_| that is handled in the 138 // DeviceListener thread just after the call to WaitForAdbDataSocket(). 139 if (!ReceivedCommand(command::ADB_DATA_SOCKET_SUCCESS, 140 adb_control_socket_.get())) { 141 LOG(ERROR) << "Device could not handle the new Adb Data Connection."; 142 SelfDelete(); 143 return; 144 } 145 forwarder2::StartForwarder( 146 host_server_data_socket.Pass(), adb_data_socket.Pass()); 147 } 148 149 scoped_ptr<Socket> HostController::CreateSocket() { 150 scoped_ptr<Socket> socket(new Socket()); 151 socket->AddEventFd(global_exit_notifier_fd_); 152 socket->AddEventFd(delete_controller_notifier_->receiver_fd()); 153 return socket.Pass(); 154 } 155 156 void HostController::SelfDelete() { 157 scoped_ptr<HostController> self_deleter(this); 158 deletion_task_runner_->PostTask( 159 FROM_HERE, 160 base::Bind(&HostController::SelfDeleteOnDeletionTaskRunner, 161 deletion_callback_, base::Passed(&self_deleter))); 162 // Tell the device to delete its corresponding controller instance before we 163 // self-delete. 164 Socket socket; 165 if (!socket.ConnectTcp("", adb_port_)) { 166 LOG(ERROR) << "Could not connect to device on port " << adb_port_; 167 return; 168 } 169 if (!SendCommand(command::UNLISTEN, device_port_, &socket)) { 170 LOG(ERROR) << "Could not send unmap command for port " << device_port_; 171 return; 172 } 173 if (!ReceivedCommand(command::UNLISTEN_SUCCESS, &socket)) { 174 LOG(ERROR) << "Unamp command failed for port " << device_port_; 175 return; 176 } 177 } 178 179 // static 180 void HostController::SelfDeleteOnDeletionTaskRunner( 181 const DeletionCallback& deletion_callback, 182 scoped_ptr<HostController> controller) { 183 deletion_callback.Run(controller.Pass()); 184 } 185 186 } // namespace forwarder2 187