Index: tools/android/forwarder2/host_controller.cc |
diff --git a/tools/android/forwarder2/host_controller.cc b/tools/android/forwarder2/host_controller.cc |
index d98a4ad2e7c7cdc0a8c8ffc0177f6a449f37f163..1588e7291b2a65772f42c3fe54008e43dd3889fe 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 |