OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <signal.h> | 5 #include <signal.h> |
6 #include <stdio.h> | |
7 #include <stdlib.h> | 6 #include <stdlib.h> |
8 | 7 |
| 8 #include <iostream> |
9 #include <string> | 9 #include <string> |
10 | 10 |
11 #include "base/at_exit.h" | 11 #include "base/at_exit.h" |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
14 #include "base/compiler_specific.h" | 14 #include "base/compiler_specific.h" |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "base/strings/string_piece.h" | 16 #include "base/strings/string_piece.h" |
17 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
18 #include "base/threading/thread.h" | 18 #include "base/threading/thread.h" |
19 #include "tools/android/forwarder2/common.h" | 19 #include "tools/android/forwarder2/common.h" |
20 #include "tools/android/forwarder2/daemon.h" | 20 #include "tools/android/forwarder2/daemon.h" |
21 #include "tools/android/forwarder2/device_controller.h" | 21 #include "tools/android/forwarder2/device_controller.h" |
22 #include "tools/android/forwarder2/pipe_notifier.h" | 22 #include "tools/android/forwarder2/pipe_notifier.h" |
23 | 23 |
24 namespace forwarder2 { | 24 namespace forwarder2 { |
25 namespace { | 25 namespace { |
26 | 26 |
27 // Leaky global instance, accessed from the signal handler. | 27 // Leaky global instance, accessed from the signal handler. |
28 forwarder2::PipeNotifier* g_notifier = NULL; | 28 forwarder2::PipeNotifier* g_notifier = NULL; |
29 | 29 |
30 const int kBufSize = 256; | 30 const int kBufSize = 256; |
31 | 31 |
| 32 const char kUnixDomainSocketPath[] = "chrome_device_forwarder"; |
32 const char kDaemonIdentifier[] = "chrome_device_forwarder_daemon"; | 33 const char kDaemonIdentifier[] = "chrome_device_forwarder_daemon"; |
33 | 34 |
34 const char kKillServerCommand[] = "kill-server"; | |
35 const char kStartCommand[] = "start"; | |
36 | |
37 void KillHandler(int /* unused */) { | 35 void KillHandler(int /* unused */) { |
38 CHECK(g_notifier); | 36 CHECK(g_notifier); |
39 if (!g_notifier->Notify()) | 37 if (!g_notifier->Notify()) |
40 exit(1); | 38 exit(1); |
41 } | 39 } |
42 | 40 |
43 // Lets the daemon fetch the exit notifier file descriptor. | 41 // Lets the daemon fetch the exit notifier file descriptor. |
44 int GetExitNotifierFD() { | 42 int GetExitNotifierFD() { |
45 DCHECK(g_notifier); | 43 DCHECK(g_notifier); |
46 return g_notifier->receiver_fd(); | 44 return g_notifier->receiver_fd(); |
47 } | 45 } |
48 | 46 |
49 class ServerDelegate : public Daemon::ServerDelegate { | 47 class ServerDelegate : public Daemon::ServerDelegate { |
50 public: | 48 public: |
| 49 ServerDelegate() : initialized_(false) {} |
| 50 |
51 // Daemon::ServerDelegate: | 51 // Daemon::ServerDelegate: |
52 virtual void Init() OVERRIDE { | 52 virtual void Init() OVERRIDE { |
53 DCHECK(!g_notifier); | 53 DCHECK(!g_notifier); |
54 g_notifier = new forwarder2::PipeNotifier(); | 54 g_notifier = new forwarder2::PipeNotifier(); |
55 signal(SIGTERM, KillHandler); | 55 signal(SIGTERM, KillHandler); |
56 signal(SIGINT, KillHandler); | 56 signal(SIGINT, KillHandler); |
57 controller_thread_.reset(new base::Thread("controller_thread")); | 57 controller_thread_.reset(new base::Thread("controller_thread")); |
58 controller_thread_->Start(); | 58 controller_thread_->Start(); |
59 } | 59 } |
60 | 60 |
61 virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE { | 61 virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE { |
62 char buf[kBufSize]; | 62 if (initialized_) { |
63 const int bytes_read = client_socket->Read(buf, sizeof(buf)); | |
64 if (bytes_read <= 0) { | |
65 if (client_socket->DidReceiveEvent()) | |
66 return; | |
67 PError("Read()"); | |
68 return; | |
69 } | |
70 const std::string adb_socket_path(buf, bytes_read); | |
71 if (adb_socket_path == adb_socket_path_) { | |
72 client_socket->WriteString("OK"); | 63 client_socket->WriteString("OK"); |
73 return; | 64 return; |
74 } | 65 } |
75 if (!adb_socket_path_.empty()) { | |
76 client_socket->WriteString( | |
77 base::StringPrintf( | |
78 "ERROR: Device controller already running (adb_socket_path=%s)", | |
79 adb_socket_path_.c_str())); | |
80 return; | |
81 } | |
82 adb_socket_path_ = adb_socket_path; | |
83 controller_thread_->message_loop()->PostTask( | 66 controller_thread_->message_loop()->PostTask( |
84 FROM_HERE, | 67 FROM_HERE, |
85 base::Bind(&ServerDelegate::StartController, adb_socket_path, | 68 base::Bind(&ServerDelegate::StartController, GetExitNotifierFD(), |
86 GetExitNotifierFD(), base::Passed(&client_socket))); | 69 base::Passed(&client_socket))); |
| 70 initialized_ = true; |
87 } | 71 } |
88 | 72 |
89 virtual void OnServerExited() OVERRIDE {} | 73 virtual void OnServerExited() OVERRIDE {} |
90 | 74 |
91 private: | 75 private: |
92 static void StartController(const std::string& adb_socket_path, | 76 static void StartController(int exit_notifier_fd, |
93 int exit_notifier_fd, | |
94 scoped_ptr<Socket> client_socket) { | 77 scoped_ptr<Socket> client_socket) { |
95 forwarder2::DeviceController controller(exit_notifier_fd); | 78 forwarder2::DeviceController controller(exit_notifier_fd); |
96 if (!controller.Init(adb_socket_path)) { | 79 if (!controller.Init(kUnixDomainSocketPath)) { |
97 client_socket->WriteString( | 80 client_socket->WriteString( |
98 base::StringPrintf("ERROR: Could not initialize device controller " | 81 base::StringPrintf("ERROR: Could not initialize device controller " |
99 "with ADB socket path: %s", | 82 "with ADB socket path: %s", |
100 adb_socket_path.c_str())); | 83 kUnixDomainSocketPath)); |
101 return; | 84 return; |
102 } | 85 } |
103 client_socket->WriteString("OK"); | 86 client_socket->WriteString("OK"); |
104 client_socket->Close(); | 87 client_socket->Close(); |
105 // Note that the following call is blocking which explains why the device | 88 // Note that the following call is blocking which explains why the device |
106 // controller has to live on a separate thread (so that the daemon command | 89 // controller has to live on a separate thread (so that the daemon command |
107 // server is not blocked). | 90 // server is not blocked). |
108 controller.Start(); | 91 controller.Start(); |
109 } | 92 } |
110 | 93 |
111 base::AtExitManager at_exit_manager_; // Used by base::Thread. | 94 base::AtExitManager at_exit_manager_; // Used by base::Thread. |
112 scoped_ptr<base::Thread> controller_thread_; | 95 scoped_ptr<base::Thread> controller_thread_; |
113 std::string adb_socket_path_; | 96 bool initialized_; |
114 }; | 97 }; |
115 | 98 |
116 class ClientDelegate : public Daemon::ClientDelegate { | 99 class ClientDelegate : public Daemon::ClientDelegate { |
117 public: | 100 public: |
118 ClientDelegate(const std::string& adb_socket) | 101 ClientDelegate() : has_failed_(false) {} |
119 : adb_socket_(adb_socket), | |
120 has_failed_(false) { | |
121 } | |
122 | 102 |
123 bool has_failed() const { return has_failed_; } | 103 bool has_failed() const { return has_failed_; } |
124 | 104 |
125 // Daemon::ClientDelegate: | 105 // Daemon::ClientDelegate: |
126 virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE { | 106 virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE { |
127 // Send the adb socket path to the daemon. | |
128 CHECK(daemon_socket->Write(adb_socket_.c_str(), | |
129 adb_socket_.length())); | |
130 char buf[kBufSize]; | 107 char buf[kBufSize]; |
131 const int bytes_read = daemon_socket->Read( | 108 const int bytes_read = daemon_socket->Read( |
132 buf, sizeof(buf) - 1 /* leave space for null terminator */); | 109 buf, sizeof(buf) - 1 /* leave space for null terminator */); |
133 CHECK_GT(bytes_read, 0); | 110 CHECK_GT(bytes_read, 0); |
134 DCHECK(bytes_read < sizeof(buf)); | 111 DCHECK(bytes_read < sizeof(buf)); |
135 buf[bytes_read] = 0; | 112 buf[bytes_read] = 0; |
136 base::StringPiece msg(buf, bytes_read); | 113 base::StringPiece msg(buf, bytes_read); |
137 if (msg.starts_with("ERROR")) { | 114 if (msg.starts_with("ERROR")) { |
138 LOG(ERROR) << msg; | 115 LOG(ERROR) << msg; |
139 has_failed_ = true; | 116 has_failed_ = true; |
140 return; | 117 return; |
141 } | 118 } |
142 } | 119 } |
143 | 120 |
144 private: | 121 private: |
145 const std::string adb_socket_; | |
146 bool has_failed_; | 122 bool has_failed_; |
147 }; | 123 }; |
148 | 124 |
149 int RunDeviceForwarder(int argc, char** argv) { | 125 int RunDeviceForwarder(int argc, char** argv) { |
150 if (argc != 2) { | 126 CommandLine::Init(argc, argv); // Needed by logging. |
151 fprintf(stderr, | 127 const bool kill_server = CommandLine::ForCurrentProcess()->HasSwitch( |
152 "Usage: %s kill-server|<adb_socket>\n" | 128 "kill-server"); |
153 " <adb_socket> is the abstract Unix Domain Socket path " | 129 if ((kill_server && argc != 2) || (!kill_server && argc != 1)) { |
154 "where Adb is configured to forward from.\n", argv[0]); | 130 std::cerr << "Usage: device_forwarder [--kill-server]" << std::endl; |
155 return 1; | 131 return 1; |
156 } | 132 } |
157 CommandLine::Init(argc, argv); // Needed by logging. | 133 ClientDelegate client_delegate; |
158 const char* const command = | |
159 !strcmp(argv[1], kKillServerCommand) ? kKillServerCommand : kStartCommand; | |
160 ClientDelegate client_delegate(argv[1]); | |
161 ServerDelegate daemon_delegate; | 134 ServerDelegate daemon_delegate; |
162 const char kLogFilePath[] = ""; // Log to logcat. | 135 const char kLogFilePath[] = ""; // Log to logcat. |
163 Daemon daemon(kLogFilePath, kDaemonIdentifier, &client_delegate, | 136 Daemon daemon(kLogFilePath, kDaemonIdentifier, &client_delegate, |
164 &daemon_delegate, &GetExitNotifierFD); | 137 &daemon_delegate, &GetExitNotifierFD); |
165 | 138 |
166 if (command == kKillServerCommand) | 139 if (kill_server) |
167 return !daemon.Kill(); | 140 return !daemon.Kill(); |
168 | 141 |
169 DCHECK(command == kStartCommand); | |
170 if (!daemon.SpawnIfNeeded()) | 142 if (!daemon.SpawnIfNeeded()) |
171 return 1; | 143 return 1; |
172 return client_delegate.has_failed(); | 144 return client_delegate.has_failed(); |
173 } | 145 } |
174 | 146 |
175 } // namespace | 147 } // namespace |
176 } // namespace forwarder2 | 148 } // namespace forwarder2 |
177 | 149 |
178 int main(int argc, char** argv) { | 150 int main(int argc, char** argv) { |
179 return forwarder2::RunDeviceForwarder(argc, argv); | 151 return forwarder2::RunDeviceForwarder(argc, argv); |
180 } | 152 } |
OLD | NEW |