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