- add sources.
[platform/framework/web/crosswalk.git] / src / tools / android / forwarder2 / host_controller.cc
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/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "tools/android/forwarder2/command.h"
14 #include "tools/android/forwarder2/forwarder.h"
15 #include "tools/android/forwarder2/socket.h"
16
17 namespace forwarder2 {
18
19 // static
20 scoped_ptr<HostController> HostController::Create(
21     int device_port,
22     int host_port,
23     int adb_port,
24     int exit_notifier_fd,
25     const DeletionCallback& deletion_callback) {
26   scoped_ptr<HostController> host_controller;
27   scoped_ptr<PipeNotifier> delete_controller_notifier(new PipeNotifier());
28   scoped_ptr<Socket> adb_control_socket(new Socket());
29   adb_control_socket->AddEventFd(exit_notifier_fd);
30   adb_control_socket->AddEventFd(delete_controller_notifier->receiver_fd());
31   if (!adb_control_socket->ConnectTcp(std::string(), adb_port)) {
32     LOG(ERROR) << "Could not connect HostController socket on port: "
33                << adb_port;
34     return host_controller.Pass();
35   }
36   // Send the command to the device start listening to the "device_forward_port"
37   bool send_command_success = SendCommand(
38       command::LISTEN, device_port, adb_control_socket.get());
39   CHECK(send_command_success);
40   int device_port_allocated;
41   command::Type command;
42   if (!ReadCommand(
43           adb_control_socket.get(), &device_port_allocated, &command) ||
44       command != command::BIND_SUCCESS) {
45     LOG(ERROR) << "Device binding error using port " << device_port;
46     return host_controller.Pass();
47   }
48   host_controller.reset(
49       new HostController(
50           device_port_allocated, host_port, adb_port, exit_notifier_fd,
51           deletion_callback, adb_control_socket.Pass(),
52           delete_controller_notifier.Pass()));
53   return host_controller.Pass();
54 }
55
56 HostController::~HostController() {
57   DCHECK(deletion_task_runner_->RunsTasksOnCurrentThread());
58   delete_controller_notifier_->Notify();
59   // Note that the Forwarder instance (that also received a delete notification)
60   // might still be running on its own thread at this point. This is not a
61   // problem since it will self-delete once the socket that it is operating on
62   // is closed.
63 }
64
65 void HostController::Start() {
66   thread_.Start();
67   ReadNextCommandSoon();
68 }
69
70 HostController::HostController(
71     int device_port,
72     int host_port,
73     int adb_port,
74     int exit_notifier_fd,
75     const DeletionCallback& deletion_callback,
76     scoped_ptr<Socket> adb_control_socket,
77     scoped_ptr<PipeNotifier> delete_controller_notifier)
78     : device_port_(device_port),
79       host_port_(host_port),
80       adb_port_(adb_port),
81       global_exit_notifier_fd_(exit_notifier_fd),
82       deletion_callback_(deletion_callback),
83       adb_control_socket_(adb_control_socket.Pass()),
84       delete_controller_notifier_(delete_controller_notifier.Pass()),
85       deletion_task_runner_(base::MessageLoopProxy::current()),
86       thread_("HostControllerThread") {
87 }
88
89 void HostController::ReadNextCommandSoon() {
90   thread_.message_loop_proxy()->PostTask(
91       FROM_HERE,
92       base::Bind(&HostController::ReadCommandOnInternalThread,
93                  base::Unretained(this)));
94 }
95
96 void HostController::ReadCommandOnInternalThread() {
97   if (!ReceivedCommand(command::ACCEPT_SUCCESS, adb_control_socket_.get())) {
98     SelfDelete();
99     return;
100   }
101   // Try to connect to host server.
102   scoped_ptr<Socket> host_server_data_socket(CreateSocket());
103   if (!host_server_data_socket->ConnectTcp(std::string(), host_port_)) {
104     LOG(ERROR) << "Could not Connect HostServerData socket on port: "
105                << host_port_;
106     SendCommand(
107         command::HOST_SERVER_ERROR, device_port_, adb_control_socket_.get());
108     if (ReceivedCommand(command::ACK, adb_control_socket_.get())) {
109       // It can continue if the host forwarder could not connect to the host
110       // server but the device acknowledged that, so that the device could
111       // re-try later.
112       ReadNextCommandSoon();
113       return;
114     }
115     SelfDelete();
116     return;
117   }
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(CreateSocket());
127   if (!adb_data_socket->ConnectTcp("", adb_port_)) {
128     LOG(ERROR) << "Could not connect AdbDataSocket on port: " << adb_port_;
129     SelfDelete();
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     SelfDelete();
143     return;
144   }
145   forwarder2::StartForwarder(
146       host_server_data_socket.Pass(), adb_data_socket.Pass());
147 }
148
149 scoped_ptr<Socket> HostController::CreateSocket() {
150   scoped_ptr<Socket> socket(new Socket());
151   socket->AddEventFd(global_exit_notifier_fd_);
152   socket->AddEventFd(delete_controller_notifier_->receiver_fd());
153   return socket.Pass();
154 }
155
156 void HostController::SelfDelete() {
157   scoped_ptr<HostController> self_deleter(this);
158   deletion_task_runner_->PostTask(
159       FROM_HERE,
160       base::Bind(&HostController::SelfDeleteOnDeletionTaskRunner,
161                  deletion_callback_, base::Passed(&self_deleter)));
162   // Tell the device to delete its corresponding controller instance before we
163   // self-delete.
164   Socket socket;
165   if (!socket.ConnectTcp("", adb_port_)) {
166     LOG(ERROR) << "Could not connect to device on port " << adb_port_;
167     return;
168   }
169   if (!SendCommand(command::UNLISTEN, device_port_, &socket)) {
170     LOG(ERROR) << "Could not send unmap command for port " << device_port_;
171     return;
172   }
173   if (!ReceivedCommand(command::UNLISTEN_SUCCESS, &socket)) {
174     LOG(ERROR) << "Unamp command failed for port " << device_port_;
175     return;
176   }
177 }
178
179 // static
180 void HostController::SelfDeleteOnDeletionTaskRunner(
181     const DeletionCallback& deletion_callback,
182     scoped_ptr<HostController> controller) {
183   deletion_callback.Run(controller.Pass());
184 }
185
186 }  // namespace forwarder2