Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / tools / android / forwarder2 / host_forwarder_main.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 <errno.h>
6 #include <signal.h>
7 #include <sys/types.h>
8 #include <sys/wait.h>
9 #include <unistd.h>
10
11 #include <cstdio>
12 #include <iostream>
13 #include <limits>
14 #include <string>
15 #include <utility>
16 #include <vector>
17
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/scoped_vector.h"
29 #include "base/memory/weak_ptr.h"
30 #include "base/pickle.h"
31 #include "base/safe_strerror_posix.h"
32 #include "base/strings/string_number_conversions.h"
33 #include "base/strings/string_piece.h"
34 #include "base/strings/string_split.h"
35 #include "base/strings/string_util.h"
36 #include "base/strings/stringprintf.h"
37 #include "base/task_runner.h"
38 #include "base/threading/thread.h"
39 #include "tools/android/forwarder2/common.h"
40 #include "tools/android/forwarder2/daemon.h"
41 #include "tools/android/forwarder2/host_controller.h"
42 #include "tools/android/forwarder2/pipe_notifier.h"
43 #include "tools/android/forwarder2/socket.h"
44 #include "tools/android/forwarder2/util.h"
45
46 namespace forwarder2 {
47 namespace {
48
49 const char kLogFilePath[] = "/tmp/host_forwarder_log";
50 const char kDaemonIdentifier[] = "chrome_host_forwarder_daemon";
51
52 const int kBufSize = 256;
53
54 // Needs to be global to be able to be accessed from the signal handler.
55 PipeNotifier* g_notifier = NULL;
56
57 // Lets the daemon fetch the exit notifier file descriptor.
58 int GetExitNotifierFD() {
59   DCHECK(g_notifier);
60   return g_notifier->receiver_fd();
61 }
62
63 void KillHandler(int signal_number) {
64   char buf[kBufSize];
65   if (signal_number != SIGTERM && signal_number != SIGINT) {
66     snprintf(buf, sizeof(buf), "Ignoring unexpected signal %d.", signal_number);
67     SIGNAL_SAFE_LOG(WARNING, buf);
68     return;
69   }
70   snprintf(buf, sizeof(buf), "Received signal %d.", signal_number);
71   SIGNAL_SAFE_LOG(WARNING, buf);
72   static int s_kill_handler_count = 0;
73   CHECK(g_notifier);
74   // If for some reason the forwarder get stuck in any socket waiting forever,
75   // we can send a SIGKILL or SIGINT three times to force it die
76   // (non-nicely). This is useful when debugging.
77   ++s_kill_handler_count;
78   if (!g_notifier->Notify() || s_kill_handler_count > 2)
79     exit(1);
80 }
81
82 // Manages HostController instances. There is one HostController instance for
83 // each connection being forwarded. Note that forwarding can happen with many
84 // devices (identified with a serial id).
85 class HostControllersManager {
86  public:
87   HostControllersManager()
88       : weak_ptr_factory_(this),
89         controllers_(new HostControllerMap()),
90         has_failed_(false) {
91   }
92
93   ~HostControllersManager() {
94     if (!thread_.get())
95       return;
96     // Delete the controllers on the thread they were created on.
97     thread_->message_loop_proxy()->DeleteSoon(
98         FROM_HERE, controllers_.release());
99   }
100
101   void HandleRequest(const std::string& device_serial,
102                      int device_port,
103                      int host_port,
104                      scoped_ptr<Socket> client_socket) {
105     // Lazy initialize so that the CLI process doesn't get this thread created.
106     InitOnce();
107     thread_->message_loop_proxy()->PostTask(
108         FROM_HERE,
109         base::Bind(
110             &HostControllersManager::HandleRequestOnInternalThread,
111             base::Unretained(this), device_serial, device_port, host_port,
112             base::Passed(&client_socket)));
113   }
114
115   bool has_failed() const { return has_failed_; }
116
117  private:
118   typedef base::hash_map<
119       std::string, linked_ptr<HostController> > HostControllerMap;
120
121   static std::string MakeHostControllerMapKey(int adb_port, int device_port) {
122     return base::StringPrintf("%d:%d", adb_port, device_port);
123   }
124
125   void InitOnce() {
126     if (thread_.get())
127       return;
128     at_exit_manager_.reset(new base::AtExitManager());
129     thread_.reset(new base::Thread("HostControllersManagerThread"));
130     thread_->Start();
131   }
132
133   // Invoked when a HostController instance reports an error (e.g. due to a
134   // device connectivity issue). Note that this could be called after the
135   // controller manager was destroyed which is why a weak pointer is used.
136   static void DeleteHostController(
137       const base::WeakPtr<HostControllersManager>& manager_ptr,
138       scoped_ptr<HostController> host_controller) {
139     HostController* const controller = host_controller.release();
140     HostControllersManager* const manager = manager_ptr.get();
141     if (!manager) {
142       // Note that |controller| is not leaked in this case since the host
143       // controllers manager owns the controllers. If the manager was deleted
144       // then all the controllers (including |controller|) were also deleted.
145       return;
146     }
147     DCHECK(manager->thread_->message_loop_proxy()->RunsTasksOnCurrentThread());
148     // Note that this will delete |controller| which is owned by the map.
149     DeleteRefCountedValueInMap(
150         MakeHostControllerMapKey(
151             controller->adb_port(), controller->device_port()),
152         manager->controllers_.get());
153   }
154
155   void HandleRequestOnInternalThread(const std::string& device_serial,
156                                      int device_port,
157                                      int host_port,
158                                      scoped_ptr<Socket> client_socket) {
159     const int adb_port = GetAdbPortForDevice(device_serial);
160     if (adb_port < 0) {
161       SendMessage(
162           "ERROR: could not get adb port for device. You might need to add "
163           "'adb' to your PATH or provide the device serial id.",
164           client_socket.get());
165       return;
166     }
167     if (device_port < 0) {
168       // Remove the previously created host controller.
169       const std::string controller_key = MakeHostControllerMapKey(
170           adb_port, -device_port);
171       const bool controller_did_exist = DeleteRefCountedValueInMap(
172           controller_key, controllers_.get());
173       SendMessage(
174           !controller_did_exist ? "ERROR: could not unmap port" : "OK",
175           client_socket.get());
176
177       RemoveAdbPortForDeviceIfNeeded(device_serial);
178       return;
179     }
180     if (host_port < 0) {
181       SendMessage("ERROR: missing host port", client_socket.get());
182       return;
183     }
184     const bool use_dynamic_port_allocation = device_port == 0;
185     if (!use_dynamic_port_allocation) {
186       const std::string controller_key = MakeHostControllerMapKey(
187           adb_port, device_port);
188       if (controllers_->find(controller_key) != controllers_->end()) {
189         LOG(INFO) << "Already forwarding device port " << device_port
190                   << " to host port " << host_port;
191         SendMessage(base::StringPrintf("%d:%d", device_port, host_port),
192                     client_socket.get());
193         return;
194       }
195     }
196     // Create a new host controller.
197     scoped_ptr<HostController> host_controller(
198         HostController::Create(
199             device_port, host_port, adb_port, GetExitNotifierFD(),
200             base::Bind(&HostControllersManager::DeleteHostController,
201                        weak_ptr_factory_.GetWeakPtr())));
202     if (!host_controller.get()) {
203       has_failed_ = true;
204       SendMessage("ERROR: Connection to device failed.", client_socket.get());
205       return;
206     }
207     // Get the current allocated port.
208     device_port = host_controller->device_port();
209     LOG(INFO) << "Forwarding device port " << device_port << " to host port "
210               << host_port;
211     const std::string msg = base::StringPrintf("%d:%d", device_port, host_port);
212     if (!SendMessage(msg, client_socket.get()))
213       return;
214     host_controller->Start();
215     controllers_->insert(
216         std::make_pair(MakeHostControllerMapKey(adb_port, device_port),
217                        linked_ptr<HostController>(host_controller.release())));
218   }
219
220   void RemoveAdbPortForDeviceIfNeeded(const std::string& device_serial) {
221     base::hash_map<std::string, int>::const_iterator it =
222         device_serial_to_adb_port_map_.find(device_serial);
223     if (it == device_serial_to_adb_port_map_.end())
224       return;
225
226     int port = it->second;
227     const std::string prefix = base::StringPrintf("%d:", port);
228     for (HostControllerMap::const_iterator others = controllers_->begin();
229          others != controllers_->end(); ++others) {
230       if (others->first.find(prefix) == 0U)
231         return;
232     }
233     // No other port is being forwarded to this device:
234     // - Remove it from our internal serial -> adb port map.
235     // - Remove from "adb forward" command.
236     LOG(INFO) << "Device " << device_serial << " has no more ports.";
237     device_serial_to_adb_port_map_.erase(device_serial);
238     const std::string serial_part = device_serial.empty() ?
239         std::string() : std::string("-s ") + device_serial;
240     const std::string command = base::StringPrintf(
241         "adb %s forward --remove tcp:%d",
242         serial_part.c_str(),
243         port);
244     const int ret = system(command.c_str());
245     LOG(INFO) << command << " ret: " << ret;
246     // Wait for the socket to be fully unmapped.
247     const std::string port_mapped_cmd = base::StringPrintf(
248         "lsof -nPi:%d",
249         port);
250     const int poll_interval_us = 500 * 1000;
251     int retries = 3;
252     while (retries) {
253       const int port_unmapped = system(port_mapped_cmd.c_str());
254       LOG(INFO) << "Device " << device_serial << " port " << port << " unmap "
255                 << port_unmapped;
256       if (port_unmapped)
257         break;
258       --retries;
259       usleep(poll_interval_us);
260     }
261   }
262
263   int GetAdbPortForDevice(const std::string& device_serial) {
264     base::hash_map<std::string, int>::const_iterator it =
265         device_serial_to_adb_port_map_.find(device_serial);
266     if (it != device_serial_to_adb_port_map_.end())
267       return it->second;
268     Socket bind_socket;
269     CHECK(bind_socket.BindTcp("127.0.0.1", 0));
270     const int port = bind_socket.GetPort();
271     bind_socket.Close();
272     const std::string serial_part = device_serial.empty() ?
273         std::string() : std::string("-s ") + device_serial;
274     const std::string command = base::StringPrintf(
275         "adb %s forward tcp:%d localabstract:chrome_device_forwarder",
276         serial_part.c_str(),
277         port);
278     LOG(INFO) << command;
279     const int ret = system(command.c_str());
280     if (ret < 0 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0)
281       return -1;
282     device_serial_to_adb_port_map_[device_serial] = port;
283     return port;
284   }
285
286   bool SendMessage(const std::string& msg, Socket* client_socket) {
287     bool result = client_socket->WriteString(msg);
288     DCHECK(result);
289     if (!result)
290       has_failed_ = true;
291     return result;
292   }
293
294   base::WeakPtrFactory<HostControllersManager> weak_ptr_factory_;
295   base::hash_map<std::string, int> device_serial_to_adb_port_map_;
296   scoped_ptr<HostControllerMap> controllers_;
297   bool has_failed_;
298   scoped_ptr<base::AtExitManager> at_exit_manager_;  // Needed by base::Thread.
299   scoped_ptr<base::Thread> thread_;
300 };
301
302 class ServerDelegate : public Daemon::ServerDelegate {
303  public:
304   ServerDelegate() : has_failed_(false) {}
305
306   bool has_failed() const {
307     return has_failed_ || controllers_manager_.has_failed();
308   }
309
310   // Daemon::ServerDelegate:
311   virtual void Init() override {
312     LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")";
313     DCHECK(!g_notifier);
314     g_notifier = new PipeNotifier();
315     signal(SIGTERM, KillHandler);
316     signal(SIGINT, KillHandler);
317   }
318
319   virtual void OnClientConnected(scoped_ptr<Socket> client_socket) override {
320     char buf[kBufSize];
321     const int bytes_read = client_socket->Read(buf, sizeof(buf));
322     if (bytes_read <= 0) {
323       if (client_socket->DidReceiveEvent())
324         return;
325       PError("Read()");
326       has_failed_ = true;
327       return;
328     }
329     const Pickle command_pickle(buf, bytes_read);
330     PickleIterator pickle_it(command_pickle);
331     std::string device_serial;
332     CHECK(pickle_it.ReadString(&device_serial));
333     int device_port;
334     if (!pickle_it.ReadInt(&device_port)) {
335       client_socket->WriteString("ERROR: missing device port");
336       return;
337     }
338     int host_port;
339     if (!pickle_it.ReadInt(&host_port))
340       host_port = -1;
341     controllers_manager_.HandleRequest(
342         device_serial, device_port, host_port, client_socket.Pass());
343   }
344
345  private:
346   bool has_failed_;
347   HostControllersManager controllers_manager_;
348
349   DISALLOW_COPY_AND_ASSIGN(ServerDelegate);
350 };
351
352 class ClientDelegate : public Daemon::ClientDelegate {
353  public:
354   ClientDelegate(const Pickle& command_pickle)
355       : command_pickle_(command_pickle),
356         has_failed_(false) {
357   }
358
359   bool has_failed() const { return has_failed_; }
360
361   // Daemon::ClientDelegate:
362   virtual void OnDaemonReady(Socket* daemon_socket) override {
363     // Send the forward command to the daemon.
364     CHECK_EQ(static_cast<long>(command_pickle_.size()),
365              daemon_socket->WriteNumBytes(command_pickle_.data(),
366                                           command_pickle_.size()));
367     char buf[kBufSize];
368     const int bytes_read = daemon_socket->Read(
369         buf, sizeof(buf) - 1 /* leave space for null terminator */);
370     CHECK_GT(bytes_read, 0);
371     DCHECK(static_cast<size_t>(bytes_read) < sizeof(buf));
372     buf[bytes_read] = 0;
373     base::StringPiece msg(buf, bytes_read);
374     if (msg.starts_with("ERROR")) {
375       LOG(ERROR) << msg;
376       has_failed_ = true;
377       return;
378     }
379     printf("%s\n", buf);
380   }
381
382  private:
383   const Pickle command_pickle_;
384   bool has_failed_;
385 };
386
387 void ExitWithUsage() {
388   std::cerr << "Usage: host_forwarder [options]\n\n"
389                "Options:\n"
390                "  --serial-id=[0-9A-Z]{16}]\n"
391                "  --map DEVICE_PORT HOST_PORT\n"
392                "  --unmap DEVICE_PORT\n"
393                "  --kill-server\n";
394   exit(1);
395 }
396
397 int PortToInt(const std::string& s) {
398   int value;
399   // Note that 0 is a valid port (used for dynamic port allocation).
400   if (!base::StringToInt(s, &value) || value < 0 ||
401       value > std::numeric_limits<uint16>::max()) {
402     LOG(ERROR) << "Could not convert string " << s << " to port";
403     ExitWithUsage();
404   }
405   return value;
406 }
407
408 int RunHostForwarder(int argc, char** argv) {
409   CommandLine::Init(argc, argv);
410   const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
411   bool kill_server = false;
412
413   Pickle pickle;
414   pickle.WriteString(
415       cmd_line.HasSwitch("serial-id") ?
416           cmd_line.GetSwitchValueASCII("serial-id") : std::string());
417
418   const std::vector<std::string> args = cmd_line.GetArgs();
419   if (cmd_line.HasSwitch("kill-server")) {
420     kill_server = true;
421   } else if (cmd_line.HasSwitch("unmap")) {
422     if (args.size() != 1)
423       ExitWithUsage();
424     // Note the minus sign below.
425     pickle.WriteInt(-PortToInt(args[0]));
426   } else if (cmd_line.HasSwitch("map")) {
427     if (args.size() != 2)
428       ExitWithUsage();
429     pickle.WriteInt(PortToInt(args[0]));
430     pickle.WriteInt(PortToInt(args[1]));
431   } else {
432     ExitWithUsage();
433   }
434
435   if (kill_server && args.size() > 0)
436     ExitWithUsage();
437
438   ClientDelegate client_delegate(pickle);
439   ServerDelegate daemon_delegate;
440   Daemon daemon(
441       kLogFilePath, kDaemonIdentifier, &client_delegate, &daemon_delegate,
442       &GetExitNotifierFD);
443
444   if (kill_server)
445     return !daemon.Kill();
446   if (!daemon.SpawnIfNeeded())
447     return 1;
448
449   return client_delegate.has_failed() || daemon_delegate.has_failed();
450 }
451
452 }  // namespace
453 }  // namespace forwarder2
454
455 int main(int argc, char** argv) {
456   return forwarder2::RunHostForwarder(argc, argv);
457 }