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 <signal.h>
6 #include <stdlib.h>
7 
8 #include <iostream>
9 #include <string>
10 
11 #include "base/at_exit.h"
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/compiler_specific.h"
15 #include "base/logging.h"
16 #include "base/single_thread_task_runner.h"
17 #include "base/strings/string_piece.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/threading/thread.h"
21 #include "tools/android/forwarder2/common.h"
22 #include "tools/android/forwarder2/daemon.h"
23 #include "tools/android/forwarder2/device_controller.h"
24 #include "tools/android/forwarder2/pipe_notifier.h"
25 
26 namespace forwarder2 {
27 namespace {
28 
29 // Leaky global instance, accessed from the signal handler.
30 forwarder2::PipeNotifier* g_notifier = NULL;
31 
32 const int kBufSize = 256;
33 
34 const char kUnixDomainSocketPath[] = "chrome_device_forwarder";
35 const char kDaemonIdentifier[] = "chrome_device_forwarder_daemon";
36 
KillHandler(int)37 void KillHandler(int /* unused */) {
38   CHECK(g_notifier);
39   if (!g_notifier->Notify())
40     exit(1);
41 }
42 
43 // Lets the daemon fetch the exit notifier file descriptor.
GetExitNotifierFD()44 int GetExitNotifierFD() {
45   DCHECK(g_notifier);
46   return g_notifier->receiver_fd();
47 }
48 
49 class ServerDelegate : public Daemon::ServerDelegate {
50  public:
ServerDelegate()51   ServerDelegate() : initialized_(false) {}
52 
~ServerDelegate()53   ~ServerDelegate() override {
54     if (!controller_thread_.get())
55       return;
56     // The DeviceController instance, if any, is constructed on the controller
57     // thread. Make sure that it gets deleted on that same thread.
58     controller_thread_->task_runner()->DeleteSoon(
59         FROM_HERE, controller_.release());
60   }
61 
62   // Daemon::ServerDelegate:
Init()63   void Init() override {
64     DCHECK(!g_notifier);
65     g_notifier = new forwarder2::PipeNotifier();
66     signal(SIGTERM, KillHandler);
67     signal(SIGINT, KillHandler);
68     controller_thread_.reset(new base::Thread("controller_thread"));
69     controller_thread_->Start();
70   }
71 
OnClientConnected(std::unique_ptr<Socket> client_socket)72   void OnClientConnected(std::unique_ptr<Socket> client_socket) override {
73     if (initialized_) {
74       client_socket->WriteString("OK");
75       return;
76     }
77     controller_thread_->task_runner()->PostTask(
78         FROM_HERE,
79         base::BindOnce(&ServerDelegate::StartController, base::Unretained(this),
80                        GetExitNotifierFD(), std::move(client_socket)));
81     initialized_ = true;
82   }
83 
84  private:
StartController(int exit_notifier_fd,std::unique_ptr<Socket> client_socket)85   void StartController(int exit_notifier_fd,
86                        std::unique_ptr<Socket> client_socket) {
87     DCHECK(!controller_.get());
88     std::unique_ptr<DeviceController> controller(
89         DeviceController::Create(kUnixDomainSocketPath, exit_notifier_fd));
90     if (!controller.get()) {
91       client_socket->WriteString(
92           base::StringPrintf("ERROR: Could not initialize device controller "
93                              "with ADB socket path: %s",
94                              kUnixDomainSocketPath));
95       return;
96     }
97     controller_.swap(controller);
98     controller_->Start();
99     client_socket->WriteString("OK");
100     client_socket->Close();
101   }
102 
103   std::unique_ptr<DeviceController> controller_;
104   std::unique_ptr<base::Thread> controller_thread_;
105   bool initialized_;
106 };
107 
108 class ClientDelegate : public Daemon::ClientDelegate {
109  public:
ClientDelegate()110   ClientDelegate() : has_failed_(false) {}
111 
has_failed() const112   bool has_failed() const { return has_failed_; }
113 
114   // Daemon::ClientDelegate:
OnDaemonReady(Socket * daemon_socket)115   void OnDaemonReady(Socket* daemon_socket) override {
116     char buf[kBufSize];
117     const int bytes_read = daemon_socket->Read(
118         buf, sizeof(buf) - 1 /* leave space for null terminator */);
119     CHECK_GT(bytes_read, 0);
120     DCHECK(static_cast<unsigned int>(bytes_read) < sizeof(buf));
121     buf[bytes_read] = 0;
122     base::StringPiece msg(buf, bytes_read);
123     if (base::StartsWith(msg, "ERROR")) {
124       LOG(ERROR) << msg;
125       has_failed_ = true;
126       return;
127     }
128   }
129 
130  private:
131   bool has_failed_;
132 };
133 
RunDeviceForwarder(int argc,char ** argv)134 int RunDeviceForwarder(int argc, char** argv) {
135   base::CommandLine::Init(argc, argv);  // Needed by logging.
136   const bool kill_server =
137       base::CommandLine::ForCurrentProcess()->HasSwitch("kill-server");
138   if ((kill_server && argc != 2) || (!kill_server && argc != 1)) {
139     std::cerr << "Usage: device_forwarder [--kill-server]" << std::endl;
140     return 1;
141   }
142   base::AtExitManager at_exit_manager;  // Used by base::Thread.
143   ClientDelegate client_delegate;
144   ServerDelegate daemon_delegate;
145   const char kLogFilePath[] = "";  // Log to logcat.
146   Daemon daemon(kLogFilePath, kDaemonIdentifier, &client_delegate,
147                 &daemon_delegate, &GetExitNotifierFD);
148 
149   if (kill_server)
150     return !daemon.Kill();
151 
152   if (!daemon.SpawnIfNeeded())
153     return 1;
154   return client_delegate.has_failed();
155 }
156 
157 }  // namespace
158 }  // namespace forwarder2
159 
main(int argc,char ** argv)160 int main(int argc, char** argv) {
161   return forwarder2::RunDeviceForwarder(argc, argv);
162 }
163