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/device_listener.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/bind_helpers.h"
      9 #include "base/callback.h"
     10 #include "base/logging.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/message_loop/message_loop_proxy.h"
     13 #include "base/single_thread_task_runner.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<DeviceListener> DeviceListener::Create(
     22     scoped_ptr<Socket> host_socket,
     23     int listener_port,
     24     const ErrorCallback& error_callback) {
     25   scoped_ptr<Socket> listener_socket(new Socket());
     26   scoped_ptr<DeviceListener> device_listener;
     27   if (!listener_socket->BindTcp("", listener_port)) {
     28     LOG(ERROR) << "Device could not bind and listen to local port "
     29                << listener_port;
     30     SendCommand(command::BIND_ERROR, listener_port, host_socket.get());
     31     return device_listener.Pass();
     32   }
     33   // In case the |listener_port_| was zero, GetPort() will return the
     34   // currently (non-zero) allocated port for this socket.
     35   listener_port = listener_socket->GetPort();
     36   SendCommand(command::BIND_SUCCESS, listener_port, host_socket.get());
     37   device_listener.reset(
     38       new DeviceListener(listener_socket.Pass(), host_socket.Pass(),
     39                          listener_port, error_callback));
     40   return device_listener.Pass();
     41 }
     42 
     43 DeviceListener::~DeviceListener() {
     44   DCHECK(deletion_task_runner_->RunsTasksOnCurrentThread());
     45   deletion_notifier_.Notify();
     46 }
     47 
     48 void DeviceListener::Start() {
     49   thread_.Start();
     50   AcceptNextClientSoon();
     51 }
     52 
     53 void DeviceListener::SetAdbDataSocket(scoped_ptr<Socket> adb_data_socket) {
     54   thread_.message_loop_proxy()->PostTask(
     55       FROM_HERE,
     56       base::Bind(&DeviceListener::OnAdbDataSocketReceivedOnInternalThread,
     57                  base::Unretained(this), base::Passed(&adb_data_socket)));
     58 }
     59 
     60 DeviceListener::DeviceListener(scoped_ptr<Socket> listener_socket,
     61                                scoped_ptr<Socket> host_socket,
     62                                int port,
     63                                const ErrorCallback& error_callback)
     64     : self_deleter_helper_(this, error_callback),
     65       listener_socket_(listener_socket.Pass()),
     66       host_socket_(host_socket.Pass()),
     67       listener_port_(port),
     68       deletion_task_runner_(base::MessageLoopProxy::current()),
     69       thread_("DeviceListener") {
     70   CHECK(host_socket_.get());
     71   DCHECK(deletion_task_runner_.get());
     72   host_socket_->AddEventFd(deletion_notifier_.receiver_fd());
     73   listener_socket_->AddEventFd(deletion_notifier_.receiver_fd());
     74 }
     75 
     76 void DeviceListener::AcceptNextClientSoon() {
     77   thread_.message_loop_proxy()->PostTask(
     78       FROM_HERE,
     79       base::Bind(&DeviceListener::AcceptClientOnInternalThread,
     80                  base::Unretained(this)));
     81 }
     82 
     83 void DeviceListener::AcceptClientOnInternalThread() {
     84   device_data_socket_.reset(new Socket());
     85   if (!listener_socket_->Accept(device_data_socket_.get())) {
     86     if (listener_socket_->DidReceiveEvent()) {
     87       LOG(INFO) << "Received exit notification, stopped accepting clients.";
     88       OnInternalThreadError();
     89       return;
     90     }
     91     LOG(WARNING) << "Could not Accept in ListenerSocket.";
     92     SendCommand(command::ACCEPT_ERROR, listener_port_, host_socket_.get());
     93     OnInternalThreadError();
     94     return;
     95   }
     96   SendCommand(command::ACCEPT_SUCCESS, listener_port_, host_socket_.get());
     97   if (!ReceivedCommand(command::HOST_SERVER_SUCCESS,
     98                        host_socket_.get())) {
     99     SendCommand(command::ACK, listener_port_, host_socket_.get());
    100     LOG(ERROR) << "Host could not connect to server.";
    101     device_data_socket_->Close();
    102     if (host_socket_->has_error()) {
    103       LOG(ERROR) << "Adb Control connection lost. "
    104                  << "Listener port: " << listener_port_;
    105       OnInternalThreadError();
    106       return;
    107     }
    108     // It can continue if the host forwarder could not connect to the host
    109     // server but the control connection is still alive (no errors). The device
    110     // acknowledged that (above), and it can re-try later.
    111     AcceptNextClientSoon();
    112     return;
    113   }
    114 }
    115 
    116 void DeviceListener::OnAdbDataSocketReceivedOnInternalThread(
    117     scoped_ptr<Socket> adb_data_socket) {
    118   DCHECK(adb_data_socket);
    119   SendCommand(command::ADB_DATA_SOCKET_SUCCESS, listener_port_,
    120               host_socket_.get());
    121   forwarders_manager_.CreateAndStartNewForwarder(
    122       device_data_socket_.Pass(), adb_data_socket.Pass());
    123   AcceptNextClientSoon();
    124 }
    125 
    126 void DeviceListener::OnInternalThreadError() {
    127   self_deleter_helper_.MaybeSelfDeleteSoon();
    128 }
    129 
    130 }  // namespace forwarder
    131