• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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"
17 
18 namespace forwarder2 {
19 
20 // static
Create(int device_port,int host_port,int adb_port,int exit_notifier_fd,const ErrorCallback & error_callback)21 scoped_ptr<HostController> HostController::Create(
22     int device_port,
23     int host_port,
24     int adb_port,
25     int exit_notifier_fd,
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: "
34                << adb_port;
35     return host_controller.Pass();
36   }
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;
43   if (!ReadCommand(
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();
48   }
49   host_controller.reset(
50       new HostController(
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();
55 }
56 
~HostController()57 HostController::~HostController() {
58   DCHECK(deletion_task_runner_->RunsTasksOnCurrentThread());
59   delete_controller_notifier_->Notify();
60 }
61 
Start()62 void HostController::Start() {
63   thread_.Start();
64   ReadNextCommandSoon();
65 }
66 
HostController(int device_port,int host_port,int adb_port,int exit_notifier_fd,const ErrorCallback & error_callback,scoped_ptr<Socket> adb_control_socket,scoped_ptr<PipeNotifier> delete_controller_notifier)67 HostController::HostController(
68     int device_port,
69     int host_port,
70     int adb_port,
71     int exit_notifier_fd,
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),
78       adb_port_(adb_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") {
84 }
85 
ReadNextCommandSoon()86 void HostController::ReadNextCommandSoon() {
87   thread_.message_loop_proxy()->PostTask(
88       FROM_HERE,
89       base::Bind(&HostController::ReadCommandOnInternalThread,
90                  base::Unretained(this)));
91 }
92 
ReadCommandOnInternalThread()93 void HostController::ReadCommandOnInternalThread() {
94   if (!ReceivedCommand(command::ACCEPT_SUCCESS, adb_control_socket_.get())) {
95     LOG(ERROR) << "Did not receive ACCEPT_SUCCESS for port: "
96                << host_port_;
97     OnInternalThreadError();
98     return;
99   }
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: "
104                << host_port_;
105     SendCommand(
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
110       // re-try later.
111       ReadNextCommandSoon();
112       return;
113     }
114     OnInternalThreadError();
115     return;
116   }
117   LOG(INFO) << "Will send HOST_SERVER_SUCCESS: " << host_port_;
118   SendCommand(
119       command::HOST_SERVER_SUCCESS, device_port_, adb_control_socket_.get());
120   StartForwarder(host_server_data_socket.Pass());
121   ReadNextCommandSoon();
122 }
123 
StartForwarder(scoped_ptr<Socket> host_server_data_socket)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();
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     OnInternalThreadError();
143     return;
144   }
145   forwarders_manager_.CreateAndStartNewForwarder(
146       host_server_data_socket.Pass(), adb_data_socket.Pass());
147 }
148 
OnInternalThreadError()149 void HostController::OnInternalThreadError() {
150   UnmapPortOnDevice();
151   self_deleter_helper_.MaybeSelfDeleteSoon();
152 }
153 
UnmapPortOnDevice()154 void HostController::UnmapPortOnDevice() {
155   Socket socket;
156   if (!socket.ConnectTcp("", adb_port_)) {
157     LOG(ERROR) << "Could not connect to device on port " << adb_port_;
158     return;
159   }
160   if (!SendCommand(command::UNLISTEN, device_port_, &socket)) {
161     LOG(ERROR) << "Could not send unmap command for port " << device_port_;
162     return;
163   }
164   if (!ReceivedCommand(command::UNLISTEN_SUCCESS, &socket)) {
165     LOG(ERROR) << "Unamp command failed for port " << device_port_;
166     return;
167   }
168 }
169 
170 }  // namespace forwarder2
171