blob: 85962caf6f69a6f096f8ca0066cc870a12da37d4 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef TOOLS_ANDROID_FORWARDER2_DEVICE_LISTENER_H_
#define TOOLS_ANDROID_FORWARDER2_DEVICE_LISTENER_H_
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/thread.h"
#include "tools/android/forwarder2/pipe_notifier.h"
#include "tools/android/forwarder2/self_deleter_helper.h"
#include "tools/android/forwarder2/socket.h"
namespace base {
class SingleThreadTaskRunner;
} // namespace base
namespace forwarder2 {
class Forwarder;
// A DeviceListener instance is used in the device_forwarder program to bind to
// a specific device-side |port| and wait for client connections. When a
// connection happens, it informs the corresponding HostController instance
// running on the host, through |host_socket|. Then the class expects a call to
// its SetAdbDataSocket() method (performed by the device controller) once the
// host opened a new connection to the device. When this happens, a new internal
// Forwarder instance is started.
// Note that instances of this class are owned by the device controller which
// creates and destroys them on the same thread. In case an internal error
// happens on the DeviceListener's internal thread, the DeviceListener
// can also self-delete by executing the user-provided callback on the thread
// the DeviceListener was created on.
// Note that the DeviceListener's destructor joins its internal thread (i.e.
// waits for its completion) which means that the internal thread is guaranteed
// not to be running anymore once the object is deleted.
class DeviceListener {
public:
// Callback that is used for self-deletion on error to let the device
// controller perform some additional cleanup work (e.g. removing the device
// listener instance from its internal map before deleting it).
typedef base::Callback<void (scoped_ptr<DeviceListener>)> ErrorCallback;
static scoped_ptr<DeviceListener> Create(scoped_ptr<Socket> host_socket,
int port,
const ErrorCallback& error_callback);
~DeviceListener();
void Start();
void SetAdbDataSocket(scoped_ptr<Socket> adb_data_socket);
int listener_port() const { return listener_port_; }
private:
DeviceListener(scoped_ptr<PipeNotifier> pipe_notifier,
scoped_ptr<Socket> listener_socket,
scoped_ptr<Socket> host_socket,
int port,
const ErrorCallback& error_callback);
// Pushes an AcceptClientOnInternalThread() task to the internal thread's
// message queue in order to wait for a new client soon.
void AcceptNextClientSoon();
void AcceptClientOnInternalThread();
void OnAdbDataSocketReceivedOnInternalThread(
scoped_ptr<Socket> adb_data_socket);
void OnInternalThreadError();
SelfDeleterHelper<DeviceListener> self_deleter_helper_;
// Used for the listener thread to be notified on destruction. We have one
// notifier per Listener thread since each Listener thread may be requested to
// exit for different reasons independently from each other and independent
// from the main program, ex. when the host requests to forward/listen the
// same port again. Both the |host_socket_| and |listener_socket_|
// must share the same receiver file descriptor from |exit_notifier_| and it
// is set in the constructor.
const scoped_ptr<PipeNotifier> exit_notifier_;
// The local device listener socket for accepting connections from the local
// port (listener_port_).
const scoped_ptr<Socket> listener_socket_;
// The listener socket for sending control commands.
const scoped_ptr<Socket> host_socket_;
scoped_ptr<Socket> device_data_socket_;
// This is the adb connection to transport the actual data, used for creating
// the forwarder. Ownership transferred to the Forwarder.
scoped_ptr<Socket> adb_data_socket_;
const int listener_port_;
// Task runner used for deletion set at construction time (i.e. the object is
// deleted on the same thread it is created on).
scoped_refptr<base::SingleThreadTaskRunner> deletion_task_runner_;
base::Thread thread_;
DISALLOW_COPY_AND_ASSIGN(DeviceListener);
};
} // namespace forwarder
#endif // TOOLS_ANDROID_FORWARDER2_DEVICE_LISTENER_H_