summaryrefslogtreecommitdiffstats
path: root/tools/android/forwarder2/host_controller.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tools/android/forwarder2/host_controller.cc')
-rw-r--r--tools/android/forwarder2/host_controller.cc186
1 files changed, 102 insertions, 84 deletions
diff --git a/tools/android/forwarder2/host_controller.cc b/tools/android/forwarder2/host_controller.cc
index d98a4ad2..1588e72 100644
--- a/tools/android/forwarder2/host_controller.cc
+++ b/tools/android/forwarder2/host_controller.cc
@@ -16,95 +16,109 @@
namespace forwarder2 {
-HostController::HostController(int device_port,
- const std::string& forward_to_host,
- int forward_to_host_port,
- int adb_port,
- int exit_notifier_fd,
- const DeleteCallback& delete_callback)
- : device_port_(device_port),
- forward_to_host_(forward_to_host),
- forward_to_host_port_(forward_to_host_port),
- adb_port_(adb_port),
- global_exit_notifier_fd_(exit_notifier_fd),
- delete_callback_(delete_callback),
- ready_(false),
- thread_("HostControllerThread") {
- adb_control_socket_.AddEventFd(global_exit_notifier_fd_);
- adb_control_socket_.AddEventFd(delete_controller_notifier_.receiver_fd());
-}
-
-HostController::~HostController() {
- delete_controller_notifier_.Notify();
- // Note that the Forwarder instance (that also received a delete notification)
- // might still be running on its own thread at this point. This is not a
- // problem since it will self-delete once the socket that it is operating on
- // is closed.
-}
-
-bool HostController::Connect() {
- if (!adb_control_socket_.ConnectTcp("", adb_port_)) {
+// static
+scoped_ptr<HostController> HostController::Create(
+ int device_port,
+ int host_port,
+ int adb_port,
+ int exit_notifier_fd,
+ const DeletionCallback& deletion_callback) {
+ scoped_ptr<HostController> host_controller;
+ scoped_ptr<PipeNotifier> delete_controller_notifier(new PipeNotifier());
+ scoped_ptr<Socket> adb_control_socket(new Socket());
+ adb_control_socket->AddEventFd(exit_notifier_fd);
+ adb_control_socket->AddEventFd(delete_controller_notifier->receiver_fd());
+ if (!adb_control_socket->ConnectTcp(std::string(), adb_port)) {
LOG(ERROR) << "Could not connect HostController socket on port: "
- << adb_port_;
- SelfDelete();
- return false;
+ << adb_port;
+ return host_controller.Pass();
}
// Send the command to the device start listening to the "device_forward_port"
bool send_command_success = SendCommand(
- command::LISTEN, device_port_, &adb_control_socket_);
+ command::LISTEN, device_port, adb_control_socket.get());
CHECK(send_command_success);
int device_port_allocated;
command::Type command;
- if (!ReadCommand(&adb_control_socket_, &device_port_allocated, &command) ||
+ if (!ReadCommand(
+ adb_control_socket.get(), &device_port_allocated, &command) ||
command != command::BIND_SUCCESS) {
- LOG(ERROR) << "Device binding error using port " << device_port_;
- SelfDelete();
- return false;
+ LOG(ERROR) << "Device binding error using port " << device_port;
+ return host_controller.Pass();
}
- // When doing dynamically allocation of port, we get the port from the
- // BIND_SUCCESS command we received above.
- device_port_ = device_port_allocated;
- ready_ = true;
- return true;
+ host_controller.reset(
+ new HostController(
+ device_port_allocated, host_port, adb_port, exit_notifier_fd,
+ deletion_callback, adb_control_socket.Pass(),
+ delete_controller_notifier.Pass()));
+ return host_controller.Pass();
+}
+
+HostController::~HostController() {
+ DCHECK(deletion_task_runner_->RunsTasksOnCurrentThread());
+ delete_controller_notifier_->Notify();
+ // Note that the Forwarder instance (that also received a delete notification)
+ // might still be running on its own thread at this point. This is not a
+ // problem since it will self-delete once the socket that it is operating on
+ // is closed.
}
void HostController::Start() {
thread_.Start();
+ ReadNextCommandSoon();
+}
+
+HostController::HostController(
+ int device_port,
+ int host_port,
+ int adb_port,
+ int exit_notifier_fd,
+ const DeletionCallback& deletion_callback,
+ scoped_ptr<Socket> adb_control_socket,
+ scoped_ptr<PipeNotifier> delete_controller_notifier)
+ : device_port_(device_port),
+ host_port_(host_port),
+ adb_port_(adb_port),
+ global_exit_notifier_fd_(exit_notifier_fd),
+ deletion_callback_(deletion_callback),
+ adb_control_socket_(adb_control_socket.Pass()),
+ delete_controller_notifier_(delete_controller_notifier.Pass()),
+ deletion_task_runner_(base::MessageLoopProxy::current()),
+ thread_("HostControllerThread") {
+}
+
+void HostController::ReadNextCommandSoon() {
thread_.message_loop_proxy()->PostTask(
FROM_HERE,
- base::Bind(&HostController::ThreadHandler, base::Unretained(this)));
+ base::Bind(&HostController::ReadCommandOnInternalThread,
+ base::Unretained(this)));
}
-void HostController::ThreadHandler() {
- CHECK(ready_) << "HostController not ready. Must call Connect() first.";
- while (true) {
- if (!ReceivedCommand(command::ACCEPT_SUCCESS, &adb_control_socket_)) {
- SelfDelete();
- return;
- }
- // Try to connect to host server.
- scoped_ptr<Socket> host_server_data_socket(CreateSocket());
- if (!host_server_data_socket->ConnectTcp(
- forward_to_host_, forward_to_host_port_)) {
- LOG(ERROR) << "Could not Connect HostServerData socket on port: "
- << forward_to_host_port_;
- SendCommand(command::HOST_SERVER_ERROR,
- device_port_,
- &adb_control_socket_);
- if (ReceivedCommand(command::ACK, &adb_control_socket_)) {
- // It can continue if the host forwarder could not connect to the host
- // server but the device acknowledged that, so that the device could
- // re-try later.
- continue;
- }
- SelfDelete();
+void HostController::ReadCommandOnInternalThread() {
+ if (!ReceivedCommand(command::ACCEPT_SUCCESS, adb_control_socket_.get())) {
+ SelfDelete();
+ return;
+ }
+ // Try to connect to host server.
+ scoped_ptr<Socket> host_server_data_socket(CreateSocket());
+ if (!host_server_data_socket->ConnectTcp(std::string(), host_port_)) {
+ LOG(ERROR) << "Could not Connect HostServerData socket on port: "
+ << host_port_;
+ SendCommand(
+ command::HOST_SERVER_ERROR, device_port_, adb_control_socket_.get());
+ if (ReceivedCommand(command::ACK, adb_control_socket_.get())) {
+ // It can continue if the host forwarder could not connect to the host
+ // server but the device acknowledged that, so that the device could
+ // re-try later.
+ ReadNextCommandSoon();
return;
}
- SendCommand(command::HOST_SERVER_SUCCESS,
- device_port_,
- &adb_control_socket_);
- StartForwarder(host_server_data_socket.Pass());
+ SelfDelete();
+ return;
}
+ SendCommand(
+ command::HOST_SERVER_SUCCESS, device_port_, adb_control_socket_.get());
+ StartForwarder(host_server_data_socket.Pass());
+ ReadNextCommandSoon();
}
void HostController::StartForwarder(
@@ -117,37 +131,34 @@ void HostController::StartForwarder(
}
// Open the Adb data connection, and send a command with the
// |device_forward_port| as a way for the device to identify the connection.
- SendCommand(command::DATA_CONNECTION,
- device_port_,
- adb_data_socket.get());
+ SendCommand(command::DATA_CONNECTION, device_port_, adb_data_socket.get());
// Check that the device received the new Adb Data Connection. Note that this
// check is done through the |adb_control_socket_| that is handled in the
// DeviceListener thread just after the call to WaitForAdbDataSocket().
if (!ReceivedCommand(command::ADB_DATA_SOCKET_SUCCESS,
- &adb_control_socket_)) {
+ adb_control_socket_.get())) {
LOG(ERROR) << "Device could not handle the new Adb Data Connection.";
SelfDelete();
return;
}
- Forwarder* forwarder = new Forwarder(host_server_data_socket.Pass(),
- adb_data_socket.Pass());
- // Forwarder object will self delete after returning.
- forwarder->Start();
+ forwarder2::StartForwarder(
+ host_server_data_socket.Pass(), adb_data_socket.Pass());
}
scoped_ptr<Socket> HostController::CreateSocket() {
scoped_ptr<Socket> socket(new Socket());
socket->AddEventFd(global_exit_notifier_fd_);
- socket->AddEventFd(delete_controller_notifier_.receiver_fd());
+ socket->AddEventFd(delete_controller_notifier_->receiver_fd());
return socket.Pass();
}
void HostController::SelfDelete() {
- base::ScopedClosureRunner delete_runner(
- base::Bind(
- &DeleteCallback::Run, base::Unretained(&delete_callback_),
- base::Unretained(this)));
+ scoped_ptr<HostController> self_deleter(this);
+ deletion_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&HostController::SelfDeleteOnDeletionTaskRunner,
+ deletion_callback_, base::Passed(&self_deleter)));
// Tell the device to delete its corresponding controller instance before we
// self-delete.
Socket socket;
@@ -155,14 +166,21 @@ void HostController::SelfDelete() {
LOG(ERROR) << "Could not connect to device on port " << adb_port_;
return;
}
- if (!SendCommand(command::UNMAP_PORT, device_port_, &socket)) {
+ if (!SendCommand(command::UNLISTEN, device_port_, &socket)) {
LOG(ERROR) << "Could not send unmap command for port " << device_port_;
return;
}
- if (!ReceivedCommand(command::UNMAP_PORT_SUCCESS, &socket)) {
+ if (!ReceivedCommand(command::UNLISTEN_SUCCESS, &socket)) {
LOG(ERROR) << "Unamp command failed for port " << device_port_;
return;
}
}
+// static
+void HostController::SelfDeleteOnDeletionTaskRunner(
+ const DeletionCallback& deletion_callback,
+ scoped_ptr<HostController> controller) {
+ deletion_callback.Run(controller.Pass());
+}
+
} // namespace forwarder2