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.
18 #include "base/at_exit.h"
19 #include "base/basictypes.h"
20 #include "base/bind.h"
21 #include "base/command_line.h"
22 #include "base/compiler_specific.h"
23 #include "base/containers/hash_tables.h"
24 #include "base/files/file_path.h"
25 #include "base/files/file_util.h"
26 #include "base/logging.h"
27 #include "base/memory/linked_ptr.h"
28 #include "base/memory/weak_ptr.h"
29 #include "base/pickle.h"
30 #include "base/strings/string_number_conversions.h"
31 #include "base/strings/string_piece.h"
32 #include "base/strings/string_split.h"
33 #include "base/strings/string_util.h"
34 #include "base/strings/stringprintf.h"
35 #include "base/task_runner.h"
36 #include "base/threading/thread.h"
37 #include "tools/android/forwarder2/common.h"
38 #include "tools/android/forwarder2/daemon.h"
39 #include "tools/android/forwarder2/host_controller.h"
40 #include "tools/android/forwarder2/pipe_notifier.h"
41 #include "tools/android/forwarder2/socket.h"
42 #include "tools/android/forwarder2/util.h"
44 namespace forwarder2
{
47 const char kLogFilePath
[] = "/tmp/host_forwarder_log";
48 const char kDaemonIdentifier
[] = "chrome_host_forwarder_daemon";
50 const int kBufSize
= 256;
52 // Needs to be global to be able to be accessed from the signal handler.
53 PipeNotifier
* g_notifier
= NULL
;
55 // Lets the daemon fetch the exit notifier file descriptor.
56 int GetExitNotifierFD() {
58 return g_notifier
->receiver_fd();
61 void KillHandler(int signal_number
) {
63 if (signal_number
!= SIGTERM
&& signal_number
!= SIGINT
) {
64 snprintf(buf
, sizeof(buf
), "Ignoring unexpected signal %d.", signal_number
);
65 SIGNAL_SAFE_LOG(WARNING
, buf
);
68 snprintf(buf
, sizeof(buf
), "Received signal %d.", signal_number
);
69 SIGNAL_SAFE_LOG(WARNING
, buf
);
70 static int s_kill_handler_count
= 0;
72 // If for some reason the forwarder get stuck in any socket waiting forever,
73 // we can send a SIGKILL or SIGINT three times to force it die
74 // (non-nicely). This is useful when debugging.
75 ++s_kill_handler_count
;
76 if (!g_notifier
->Notify() || s_kill_handler_count
> 2)
80 // Manages HostController instances. There is one HostController instance for
81 // each connection being forwarded. Note that forwarding can happen with many
82 // devices (identified with a serial id).
83 class HostControllersManager
{
85 HostControllersManager()
86 : controllers_(new HostControllerMap()),
88 weak_ptr_factory_(this) {
91 ~HostControllersManager() {
94 // Delete the controllers on the thread they were created on.
95 thread_
->task_runner()->DeleteSoon(
96 FROM_HERE
, controllers_
.release());
99 void HandleRequest(const std::string
& adb_path
,
100 const std::string
& device_serial
,
103 scoped_ptr
<Socket
> client_socket
) {
104 // Lazy initialize so that the CLI process doesn't get this thread created.
106 thread_
->task_runner()->PostTask(
108 base::Bind(&HostControllersManager::HandleRequestOnInternalThread
,
109 base::Unretained(this), adb_path
, device_serial
, device_port
,
110 host_port
, base::Passed(&client_socket
)));
113 bool has_failed() const { return has_failed_
; }
116 typedef base::hash_map
<
117 std::string
, linked_ptr
<HostController
> > HostControllerMap
;
119 static std::string
MakeHostControllerMapKey(int adb_port
, int device_port
) {
120 return base::StringPrintf("%d:%d", adb_port
, device_port
);
126 at_exit_manager_
.reset(new base::AtExitManager());
127 thread_
.reset(new base::Thread("HostControllersManagerThread"));
131 // Invoked when a HostController instance reports an error (e.g. due to a
132 // device connectivity issue). Note that this could be called after the
133 // controller manager was destroyed which is why a weak pointer is used.
134 static void DeleteHostController(
135 const base::WeakPtr
<HostControllersManager
>& manager_ptr
,
136 scoped_ptr
<HostController
> host_controller
) {
137 HostController
* const controller
= host_controller
.release();
138 HostControllersManager
* const manager
= manager_ptr
.get();
140 // Note that |controller| is not leaked in this case since the host
141 // controllers manager owns the controllers. If the manager was deleted
142 // then all the controllers (including |controller|) were also deleted.
145 DCHECK(manager
->thread_
->task_runner()->RunsTasksOnCurrentThread());
146 // Note that this will delete |controller| which is owned by the map.
147 DeleteRefCountedValueInMap(
148 MakeHostControllerMapKey(
149 controller
->adb_port(), controller
->device_port()),
150 manager
->controllers_
.get());
153 void HandleRequestOnInternalThread(const std::string
& adb_path
,
154 const std::string
& device_serial
,
157 scoped_ptr
<Socket
> client_socket
) {
158 const int adb_port
= GetAdbPortForDevice(adb_path
, device_serial
);
161 "ERROR: could not get adb port for device. You might need to add "
162 "'adb' to your PATH or provide the device serial id.",
163 client_socket
.get());
166 if (device_port
< 0) {
167 // Remove the previously created host controller.
168 const std::string controller_key
= MakeHostControllerMapKey(
169 adb_port
, -device_port
);
170 const bool controller_did_exist
= DeleteRefCountedValueInMap(
171 controller_key
, controllers_
.get());
172 if (!controller_did_exist
) {
173 SendMessage("ERROR: could not unmap port.", client_socket
.get());
174 LogExistingControllers(client_socket
);
176 SendMessage("OK", client_socket
.get());
179 RemoveAdbPortForDeviceIfNeeded(adb_path
, device_serial
);
183 SendMessage("ERROR: missing host port", client_socket
.get());
186 const bool use_dynamic_port_allocation
= device_port
== 0;
187 if (!use_dynamic_port_allocation
) {
188 const std::string controller_key
= MakeHostControllerMapKey(
189 adb_port
, device_port
);
190 if (controllers_
->find(controller_key
) != controllers_
->end()) {
191 LOG(INFO
) << "Already forwarding device port " << device_port
192 << " to host port " << host_port
;
193 SendMessage(base::StringPrintf("%d:%d", device_port
, host_port
),
194 client_socket
.get());
198 // Create a new host controller.
199 scoped_ptr
<HostController
> host_controller(
200 HostController::Create(
201 device_port
, host_port
, adb_port
, GetExitNotifierFD(),
202 base::Bind(&HostControllersManager::DeleteHostController
,
203 weak_ptr_factory_
.GetWeakPtr())));
204 if (!host_controller
.get()) {
206 SendMessage("ERROR: Connection to device failed.", client_socket
.get());
207 LogExistingControllers(client_socket
);
210 // Get the current allocated port.
211 device_port
= host_controller
->device_port();
212 LOG(INFO
) << "Forwarding device port " << device_port
<< " to host port "
214 const std::string msg
= base::StringPrintf("%d:%d", device_port
, host_port
);
215 if (!SendMessage(msg
, client_socket
.get()))
217 host_controller
->Start();
218 controllers_
->insert(
219 std::make_pair(MakeHostControllerMapKey(adb_port
, device_port
),
220 linked_ptr
<HostController
>(host_controller
.release())));
223 void LogExistingControllers(const scoped_ptr
<Socket
>& client_socket
) {
224 SendMessage("ERROR: Existing controllers:", client_socket
.get());
225 for (const auto& controller
: *controllers_
) {
226 SendMessage(base::StringPrintf("ERROR: %s", controller
.first
.c_str()),
227 client_socket
.get());
231 void RemoveAdbPortForDeviceIfNeeded(const std::string
& adb_path
,
232 const std::string
& device_serial
) {
233 base::hash_map
<std::string
, int>::const_iterator it
=
234 device_serial_to_adb_port_map_
.find(device_serial
);
235 if (it
== device_serial_to_adb_port_map_
.end())
238 int port
= it
->second
;
239 const std::string prefix
= base::StringPrintf("%d:", port
);
240 for (HostControllerMap::const_iterator others
= controllers_
->begin();
241 others
!= controllers_
->end(); ++others
) {
242 if (others
->first
.find(prefix
) == 0U)
245 // No other port is being forwarded to this device:
246 // - Remove it from our internal serial -> adb port map.
247 // - Remove from "adb forward" command.
248 LOG(INFO
) << "Device " << device_serial
<< " has no more ports.";
249 device_serial_to_adb_port_map_
.erase(device_serial
);
250 const std::string serial_part
= device_serial
.empty() ?
251 std::string() : std::string("-s ") + device_serial
;
252 const std::string command
= base::StringPrintf(
253 "%s %s forward --remove tcp:%d",
257 const int ret
= system(command
.c_str());
258 LOG(INFO
) << command
<< " ret: " << ret
;
259 // Wait for the socket to be fully unmapped.
260 const std::string port_mapped_cmd
= base::StringPrintf(
263 const int poll_interval_us
= 500 * 1000;
266 const int port_unmapped
= system(port_mapped_cmd
.c_str());
267 LOG(INFO
) << "Device " << device_serial
<< " port " << port
<< " unmap "
272 usleep(poll_interval_us
);
276 int GetAdbPortForDevice(const std::string adb_path
,
277 const std::string
& device_serial
) {
278 base::hash_map
<std::string
, int>::const_iterator it
=
279 device_serial_to_adb_port_map_
.find(device_serial
);
280 if (it
!= device_serial_to_adb_port_map_
.end())
283 CHECK(bind_socket
.BindTcp("127.0.0.1", 0));
284 const int port
= bind_socket
.GetPort();
286 const std::string serial_part
= device_serial
.empty() ?
287 std::string() : std::string("-s ") + device_serial
;
288 const std::string command
= base::StringPrintf(
289 "%s %s forward tcp:%d localabstract:chrome_device_forwarder",
293 LOG(INFO
) << command
;
294 const int ret
= system(command
.c_str());
295 if (ret
< 0 || !WIFEXITED(ret
) || WEXITSTATUS(ret
) != 0)
297 device_serial_to_adb_port_map_
[device_serial
] = port
;
301 bool SendMessage(const std::string
& msg
, Socket
* client_socket
) {
302 bool result
= client_socket
->WriteString(msg
);
309 base::hash_map
<std::string
, int> device_serial_to_adb_port_map_
;
310 scoped_ptr
<HostControllerMap
> controllers_
;
312 scoped_ptr
<base::AtExitManager
> at_exit_manager_
; // Needed by base::Thread.
313 scoped_ptr
<base::Thread
> thread_
;
314 base::WeakPtrFactory
<HostControllersManager
> weak_ptr_factory_
;
317 class ServerDelegate
: public Daemon::ServerDelegate
{
319 ServerDelegate(const std::string
& adb_path
)
320 : adb_path_(adb_path
), has_failed_(false) {}
322 bool has_failed() const {
323 return has_failed_
|| controllers_manager_
.has_failed();
326 // Daemon::ServerDelegate:
327 void Init() override
{
328 LOG(INFO
) << "Starting host process daemon (pid=" << getpid() << ")";
330 g_notifier
= new PipeNotifier();
331 signal(SIGTERM
, KillHandler
);
332 signal(SIGINT
, KillHandler
);
335 void OnClientConnected(scoped_ptr
<Socket
> client_socket
) override
{
337 const int bytes_read
= client_socket
->Read(buf
, sizeof(buf
));
338 if (bytes_read
<= 0) {
339 if (client_socket
->DidReceiveEvent())
345 const base::Pickle
command_pickle(buf
, bytes_read
);
346 base::PickleIterator
pickle_it(command_pickle
);
347 std::string device_serial
;
348 CHECK(pickle_it
.ReadString(&device_serial
));
350 if (!pickle_it
.ReadInt(&device_port
)) {
351 client_socket
->WriteString("ERROR: missing device port");
355 if (!pickle_it
.ReadInt(&host_port
))
357 controllers_manager_
.HandleRequest(adb_path_
, device_serial
, device_port
,
358 host_port
, client_socket
.Pass());
362 std::string adb_path_
;
364 HostControllersManager controllers_manager_
;
366 DISALLOW_COPY_AND_ASSIGN(ServerDelegate
);
369 class ClientDelegate
: public Daemon::ClientDelegate
{
371 ClientDelegate(const base::Pickle
& command_pickle
)
372 : command_pickle_(command_pickle
), has_failed_(false) {}
374 bool has_failed() const { return has_failed_
; }
376 // Daemon::ClientDelegate:
377 void OnDaemonReady(Socket
* daemon_socket
) override
{
378 // Send the forward command to the daemon.
379 CHECK_EQ(static_cast<long>(command_pickle_
.size()),
380 daemon_socket
->WriteNumBytes(command_pickle_
.data(),
381 command_pickle_
.size()));
383 const int bytes_read
= daemon_socket
->Read(
384 buf
, sizeof(buf
) - 1 /* leave space for null terminator */);
385 CHECK_GT(bytes_read
, 0);
386 DCHECK(static_cast<size_t>(bytes_read
) < sizeof(buf
));
388 base::StringPiece
msg(buf
, bytes_read
);
389 if (msg
.starts_with("ERROR")) {
398 const base::Pickle command_pickle_
;
402 void ExitWithUsage() {
403 std::cerr
<< "Usage: host_forwarder [options]\n\n"
405 " --serial-id=[0-9A-Z]{16}]\n"
406 " --map DEVICE_PORT HOST_PORT\n"
407 " --unmap DEVICE_PORT\n"
408 " --adb PATH_TO_ADB\n"
413 int PortToInt(const std::string
& s
) {
415 // Note that 0 is a valid port (used for dynamic port allocation).
416 if (!base::StringToInt(s
, &value
) || value
< 0 ||
417 value
> std::numeric_limits
<uint16
>::max()) {
418 LOG(ERROR
) << "Could not convert string " << s
<< " to port";
424 int RunHostForwarder(int argc
, char** argv
) {
425 base::CommandLine::Init(argc
, argv
);
426 const base::CommandLine
& cmd_line
= *base::CommandLine::ForCurrentProcess();
427 std::string adb_path
= "adb";
428 bool kill_server
= false;
432 cmd_line
.HasSwitch("serial-id") ?
433 cmd_line
.GetSwitchValueASCII("serial-id") : std::string());
435 const std::vector
<std::string
> args
= cmd_line
.GetArgs();
436 if (cmd_line
.HasSwitch("kill-server")) {
438 } else if (cmd_line
.HasSwitch("unmap")) {
439 if (args
.size() != 1)
441 // Note the minus sign below.
442 pickle
.WriteInt(-PortToInt(args
[0]));
443 } else if (cmd_line
.HasSwitch("map")) {
444 if (args
.size() != 2)
446 pickle
.WriteInt(PortToInt(args
[0]));
447 pickle
.WriteInt(PortToInt(args
[1]));
452 if (cmd_line
.HasSwitch("adb")) {
453 adb_path
= cmd_line
.GetSwitchValueASCII("adb");
456 if (kill_server
&& args
.size() > 0)
459 ClientDelegate
client_delegate(pickle
);
460 ServerDelegate
daemon_delegate(adb_path
);
462 kLogFilePath
, kDaemonIdentifier
, &client_delegate
, &daemon_delegate
,
466 return !daemon
.Kill();
467 if (!daemon
.SpawnIfNeeded())
470 return client_delegate
.has_failed() || daemon_delegate
.has_failed();
474 } // namespace forwarder2
476 int main(int argc
, char** argv
) {
477 return forwarder2::RunHostForwarder(argc
, argv
);