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.
5 #include "tools/android/forwarder2/host_controller.h"
9 #include "base/basictypes.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "tools/android/forwarder2/command.h"
15 #include "tools/android/forwarder2/forwarder.h"
16 #include "tools/android/forwarder2/socket.h"
18 namespace forwarder2
{
21 scoped_ptr
<HostController
> HostController::Create(
26 const ErrorCallback
& error_callback
) {
27 scoped_ptr
<HostController
> host_controller
;
28 scoped_ptr
<PipeNotifier
> delete_controller_notifier(new PipeNotifier());
29 scoped_ptr
<Socket
> adb_control_socket(new Socket());
30 adb_control_socket
->AddEventFd(exit_notifier_fd
);
31 adb_control_socket
->AddEventFd(delete_controller_notifier
->receiver_fd());
32 if (!adb_control_socket
->ConnectTcp(std::string(), adb_port
)) {
33 LOG(ERROR
) << "Could not connect HostController socket on port: "
35 return host_controller
.Pass();
37 // Send the command to the device start listening to the "device_forward_port"
38 bool send_command_success
= SendCommand(
39 command::LISTEN
, device_port
, adb_control_socket
.get());
40 CHECK(send_command_success
);
41 int device_port_allocated
;
42 command::Type command
;
44 adb_control_socket
.get(), &device_port_allocated
, &command
) ||
45 command
!= command::BIND_SUCCESS
) {
46 LOG(ERROR
) << "Device binding error using port " << device_port
;
47 return host_controller
.Pass();
49 host_controller
.reset(
51 device_port_allocated
, host_port
, adb_port
, exit_notifier_fd
,
52 error_callback
, adb_control_socket
.Pass(),
53 delete_controller_notifier
.Pass()));
54 return host_controller
.Pass();
57 HostController::~HostController() {
58 DCHECK(deletion_task_runner_
->RunsTasksOnCurrentThread());
59 delete_controller_notifier_
->Notify();
62 void HostController::Start() {
64 ReadNextCommandSoon();
67 HostController::HostController(
72 const ErrorCallback
& error_callback
,
73 scoped_ptr
<Socket
> adb_control_socket
,
74 scoped_ptr
<PipeNotifier
> delete_controller_notifier
)
75 : self_deleter_helper_(this, error_callback
),
76 device_port_(device_port
),
77 host_port_(host_port
),
79 global_exit_notifier_fd_(exit_notifier_fd
),
80 adb_control_socket_(adb_control_socket
.Pass()),
81 delete_controller_notifier_(delete_controller_notifier
.Pass()),
82 deletion_task_runner_(base::MessageLoopProxy::current()),
83 thread_("HostControllerThread") {
86 void HostController::ReadNextCommandSoon() {
87 thread_
.message_loop_proxy()->PostTask(
89 base::Bind(&HostController::ReadCommandOnInternalThread
,
90 base::Unretained(this)));
93 void HostController::ReadCommandOnInternalThread() {
94 if (!ReceivedCommand(command::ACCEPT_SUCCESS
, adb_control_socket_
.get())) {
95 LOG(ERROR
) << "Did not receive ACCEPT_SUCCESS for port: "
97 OnInternalThreadError();
100 // Try to connect to host server.
101 scoped_ptr
<Socket
> host_server_data_socket(new Socket());
102 if (!host_server_data_socket
->ConnectTcp(std::string(), host_port_
)) {
103 LOG(ERROR
) << "Could not Connect HostServerData socket on port: "
106 command::HOST_SERVER_ERROR
, device_port_
, adb_control_socket_
.get());
107 if (ReceivedCommand(command::ACK
, adb_control_socket_
.get())) {
108 // It can continue if the host forwarder could not connect to the host
109 // server but the device acknowledged that, so that the device could
111 ReadNextCommandSoon();
114 OnInternalThreadError();
117 LOG(INFO
) << "Will send HOST_SERVER_SUCCESS: " << host_port_
;
119 command::HOST_SERVER_SUCCESS
, device_port_
, adb_control_socket_
.get());
120 StartForwarder(host_server_data_socket
.Pass());
121 ReadNextCommandSoon();
124 void HostController::StartForwarder(
125 scoped_ptr
<Socket
> host_server_data_socket
) {
126 scoped_ptr
<Socket
> adb_data_socket(new Socket());
127 if (!adb_data_socket
->ConnectTcp("", adb_port_
)) {
128 LOG(ERROR
) << "Could not connect AdbDataSocket on port: " << adb_port_
;
129 OnInternalThreadError();
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());
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 OnInternalThreadError();
145 forwarders_manager_
.CreateAndStartNewForwarder(
146 host_server_data_socket
.Pass(), adb_data_socket
.Pass());
149 void HostController::OnInternalThreadError() {
151 self_deleter_helper_
.MaybeSelfDeleteSoon();
154 void HostController::UnmapPortOnDevice() {
156 if (!socket
.ConnectTcp("", adb_port_
)) {
157 LOG(ERROR
) << "Could not connect to device on port " << adb_port_
;
160 if (!SendCommand(command::UNLISTEN
, device_port_
, &socket
)) {
161 LOG(ERROR
) << "Could not send unmap command for port " << device_port_
;
164 if (!ReceivedCommand(command::UNLISTEN_SUCCESS
, &socket
)) {
165 LOG(ERROR
) << "Unamp command failed for port " << device_port_
;
170 } // namespace forwarder2