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 ServerDelegate : public Daemon::ServerDelegate { |
| 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(&ServerDelegate::StartController, adb_socket_path, |
| 87 GetExitNotifierFD(), 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 ServerDelegate 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 |