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