Home | History | Annotate | Download | only in forwarder2
      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