15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/forwarder2/host_controller.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/bind.h"
10ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/bind_helpers.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/forwarder2/command.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/forwarder2/forwarder.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/forwarder2/socket.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace forwarder2 {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// static
20d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochscoped_ptr<HostController> HostController::Create(
21d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    int device_port,
22d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    int host_port,
23d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    int adb_port,
24d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    int exit_notifier_fd,
25d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    const DeletionCallback& deletion_callback) {
26d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  scoped_ptr<HostController> host_controller;
27d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  scoped_ptr<PipeNotifier> delete_controller_notifier(new PipeNotifier());
28d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  scoped_ptr<Socket> adb_control_socket(new Socket());
29d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  adb_control_socket->AddEventFd(exit_notifier_fd);
30d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  adb_control_socket->AddEventFd(delete_controller_notifier->receiver_fd());
31d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!adb_control_socket->ConnectTcp(std::string(), adb_port)) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Could not connect HostController socket on port: "
33d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch               << adb_port;
34d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return host_controller.Pass();
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send the command to the device start listening to the "device_forward_port"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool send_command_success = SendCommand(
38d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      command::LISTEN, device_port, adb_control_socket.get());
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(send_command_success);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int device_port_allocated;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  command::Type command;
42d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!ReadCommand(
43d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          adb_control_socket.get(), &device_port_allocated, &command) ||
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command != command::BIND_SUCCESS) {
45d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    LOG(ERROR) << "Device binding error using port " << device_port;
46d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return host_controller.Pass();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
48d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  host_controller.reset(
49d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      new HostController(
50d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          device_port_allocated, host_port, adb_port, exit_notifier_fd,
51d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          deletion_callback, adb_control_socket.Pass(),
52d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          delete_controller_notifier.Pass()));
53d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return host_controller.Pass();
54d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
55d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
56d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochHostController::~HostController() {
57d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  DCHECK(deletion_task_runner_->RunsTasksOnCurrentThread());
58d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  delete_controller_notifier_->Notify();
59d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Note that the Forwarder instance (that also received a delete notification)
60d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // might still be running on its own thread at this point. This is not a
61d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // problem since it will self-delete once the socket that it is operating on
62d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // is closed.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HostController::Start() {
667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  thread_.Start();
67d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  ReadNextCommandSoon();
68d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
69d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
70d3868032626d59662ff73b372b5d584c1d144c53Ben MurdochHostController::HostController(
71d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    int device_port,
72d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    int host_port,
73d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    int adb_port,
74d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    int exit_notifier_fd,
75d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    const DeletionCallback& deletion_callback,
76d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    scoped_ptr<Socket> adb_control_socket,
77d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    scoped_ptr<PipeNotifier> delete_controller_notifier)
78d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    : device_port_(device_port),
79d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      host_port_(host_port),
80d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      adb_port_(adb_port),
81d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      global_exit_notifier_fd_(exit_notifier_fd),
82d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      deletion_callback_(deletion_callback),
83d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      adb_control_socket_(adb_control_socket.Pass()),
84d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      delete_controller_notifier_(delete_controller_notifier.Pass()),
85d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      deletion_task_runner_(base::MessageLoopProxy::current()),
86d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      thread_("HostControllerThread") {
87d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
88d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
89d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid HostController::ReadNextCommandSoon() {
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  thread_.message_loop_proxy()->PostTask(
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      FROM_HERE,
92d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      base::Bind(&HostController::ReadCommandOnInternalThread,
93d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                 base::Unretained(this)));
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
96d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid HostController::ReadCommandOnInternalThread() {
97d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!ReceivedCommand(command::ACCEPT_SUCCESS, adb_control_socket_.get())) {
98d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    SelfDelete();
99d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return;
100d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
101d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Try to connect to host server.
102d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  scoped_ptr<Socket> host_server_data_socket(CreateSocket());
103d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!host_server_data_socket->ConnectTcp(std::string(), host_port_)) {
104d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    LOG(ERROR) << "Could not Connect HostServerData socket on port: "
105d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch               << host_port_;
106d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    SendCommand(
107d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch        command::HOST_SERVER_ERROR, device_port_, adb_control_socket_.get());
108d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (ReceivedCommand(command::ACK, adb_control_socket_.get())) {
109d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // It can continue if the host forwarder could not connect to the host
110d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // server but the device acknowledged that, so that the device could
111d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      // re-try later.
112d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      ReadNextCommandSoon();
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
115d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    SelfDelete();
116d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    return;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
118d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  SendCommand(
119d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      command::HOST_SERVER_SUCCESS, device_port_, adb_control_socket_.get());
120d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  StartForwarder(host_server_data_socket.Pass());
121d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  ReadNextCommandSoon();
1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid HostController::StartForwarder(
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scoped_ptr<Socket> host_server_data_socket) {
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<Socket> adb_data_socket(CreateSocket());
1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!adb_data_socket->ConnectTcp("", adb_port_)) {
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    LOG(ERROR) << "Could not connect AdbDataSocket on port: " << adb_port_;
129ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    SelfDelete();
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Open the Adb data connection, and send a command with the
1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // |device_forward_port| as a way for the device to identify the connection.
134d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  SendCommand(command::DATA_CONNECTION, device_port_, adb_data_socket.get());
1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Check that the device received the new Adb Data Connection. Note that this
1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // check is done through the |adb_control_socket_| that is handled in the
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // DeviceListener thread just after the call to WaitForAdbDataSocket().
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!ReceivedCommand(command::ADB_DATA_SOCKET_SUCCESS,
140d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                       adb_control_socket_.get())) {
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    LOG(ERROR) << "Device could not handle the new Adb Data Connection.";
142ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    SelfDelete();
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
145d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  forwarder2::StartForwarder(
146d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      host_server_data_socket.Pass(), adb_data_socket.Pass());
1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochscoped_ptr<Socket> HostController::CreateSocket() {
1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<Socket> socket(new Socket());
1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  socket->AddEventFd(global_exit_notifier_fd_);
152d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  socket->AddEventFd(delete_controller_notifier_->receiver_fd());
1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return socket.Pass();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
156ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid HostController::SelfDelete() {
157d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  scoped_ptr<HostController> self_deleter(this);
158d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  deletion_task_runner_->PostTask(
159d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      FROM_HERE,
160d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      base::Bind(&HostController::SelfDeleteOnDeletionTaskRunner,
161d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch                 deletion_callback_, base::Passed(&self_deleter)));
162ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Tell the device to delete its corresponding controller instance before we
163ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // self-delete.
164ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  Socket socket;
165ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!socket.ConnectTcp("", adb_port_)) {
166ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    LOG(ERROR) << "Could not connect to device on port " << adb_port_;
167ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
168ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
169d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!SendCommand(command::UNLISTEN, device_port_, &socket)) {
170ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    LOG(ERROR) << "Could not send unmap command for port " << device_port_;
171ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
172ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
173d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!ReceivedCommand(command::UNLISTEN_SUCCESS, &socket)) {
174ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    LOG(ERROR) << "Unamp command failed for port " << device_port_;
175ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
176ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
177ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
178ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
179d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch// static
180d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid HostController::SelfDeleteOnDeletionTaskRunner(
181d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    const DeletionCallback& deletion_callback,
182d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    scoped_ptr<HostController> controller) {
183d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  deletion_callback.Run(controller.Pass());
184d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
185d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace forwarder2
187