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/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
     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 
     57 HostController::~HostController() {
     58   DCHECK(deletion_task_runner_->RunsTasksOnCurrentThread());
     59   delete_controller_notifier_->Notify();
     60 }
     61 
     62 void HostController::Start() {
     63   thread_.Start();
     64   ReadNextCommandSoon();
     65 }
     66 
     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 
     86 void HostController::ReadNextCommandSoon() {
     87   thread_.message_loop_proxy()->PostTask(
     88       FROM_HERE,
     89       base::Bind(&HostController::ReadCommandOnInternalThread,
     90                  base::Unretained(this)));
     91 }
     92 
     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 
    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 
    149 void HostController::OnInternalThreadError() {
    150   UnmapPortOnDevice();
    151   self_deleter_helper_.MaybeSelfDeleteSoon();
    152 }
    153 
    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