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 <stdlib.h> | 7 #include <stdlib.h> |
7 | 8 |
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"; | |
33 const char kDaemonIdentifier[] = "chrome_device_forwarder_daemon"; | 32 const char kDaemonIdentifier[] = "chrome_device_forwarder_daemon"; |
34 | 33 |
| 34 const char kKillServerCommand[] = "kill-server"; |
| 35 const char kStartCommand[] = "start"; |
| 36 |
35 void KillHandler(int /* unused */) { | 37 void KillHandler(int /* unused */) { |
36 CHECK(g_notifier); | 38 CHECK(g_notifier); |
37 if (!g_notifier->Notify()) | 39 if (!g_notifier->Notify()) |
38 exit(1); | 40 exit(1); |
39 } | 41 } |
40 | 42 |
41 // Lets the daemon fetch the exit notifier file descriptor. | 43 // Lets the daemon fetch the exit notifier file descriptor. |
42 int GetExitNotifierFD() { | 44 int GetExitNotifierFD() { |
43 DCHECK(g_notifier); | 45 DCHECK(g_notifier); |
44 return g_notifier->receiver_fd(); | 46 return g_notifier->receiver_fd(); |
45 } | 47 } |
46 | 48 |
47 class ServerDelegate : public Daemon::ServerDelegate { | 49 class ServerDelegate : public Daemon::ServerDelegate { |
48 public: | 50 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 if (initialized_) { | 62 char buf[kBufSize]; |
| 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_) { |
63 client_socket->WriteString("OK"); | 72 client_socket->WriteString("OK"); |
64 return; | 73 return; |
65 } | 74 } |
| 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; |
66 controller_thread_->message_loop()->PostTask( | 83 controller_thread_->message_loop()->PostTask( |
67 FROM_HERE, | 84 FROM_HERE, |
68 base::Bind(&ServerDelegate::StartController, GetExitNotifierFD(), | 85 base::Bind(&ServerDelegate::StartController, adb_socket_path, |
69 base::Passed(&client_socket))); | 86 GetExitNotifierFD(), base::Passed(&client_socket))); |
70 initialized_ = true; | |
71 } | 87 } |
72 | 88 |
73 virtual void OnServerExited() OVERRIDE {} | 89 virtual void OnServerExited() OVERRIDE {} |
74 | 90 |
75 private: | 91 private: |
76 static void StartController(int exit_notifier_fd, | 92 static void StartController(const std::string& adb_socket_path, |
| 93 int exit_notifier_fd, |
77 scoped_ptr<Socket> client_socket) { | 94 scoped_ptr<Socket> client_socket) { |
78 forwarder2::DeviceController controller(exit_notifier_fd); | 95 forwarder2::DeviceController controller(exit_notifier_fd); |
79 if (!controller.Init(kUnixDomainSocketPath)) { | 96 if (!controller.Init(adb_socket_path)) { |
80 client_socket->WriteString( | 97 client_socket->WriteString( |
81 base::StringPrintf("ERROR: Could not initialize device controller " | 98 base::StringPrintf("ERROR: Could not initialize device controller " |
82 "with ADB socket path: %s", | 99 "with ADB socket path: %s", |
83 kUnixDomainSocketPath)); | 100 adb_socket_path.c_str())); |
84 return; | 101 return; |
85 } | 102 } |
86 client_socket->WriteString("OK"); | 103 client_socket->WriteString("OK"); |
87 client_socket->Close(); | 104 client_socket->Close(); |
88 // Note that the following call is blocking which explains why the device | 105 // Note that the following call is blocking which explains why the device |
89 // controller has to live on a separate thread (so that the daemon command | 106 // controller has to live on a separate thread (so that the daemon command |
90 // server is not blocked). | 107 // server is not blocked). |
91 controller.Start(); | 108 controller.Start(); |
92 } | 109 } |
93 | 110 |
94 base::AtExitManager at_exit_manager_; // Used by base::Thread. | 111 base::AtExitManager at_exit_manager_; // Used by base::Thread. |
95 scoped_ptr<base::Thread> controller_thread_; | 112 scoped_ptr<base::Thread> controller_thread_; |
96 bool initialized_; | 113 std::string adb_socket_path_; |
97 }; | 114 }; |
98 | 115 |
99 class ClientDelegate : public Daemon::ClientDelegate { | 116 class ClientDelegate : public Daemon::ClientDelegate { |
100 public: | 117 public: |
101 ClientDelegate() : has_failed_(false) {} | 118 ClientDelegate(const std::string& adb_socket) |
| 119 : adb_socket_(adb_socket), |
| 120 has_failed_(false) { |
| 121 } |
102 | 122 |
103 bool has_failed() const { return has_failed_; } | 123 bool has_failed() const { return has_failed_; } |
104 | 124 |
105 // Daemon::ClientDelegate: | 125 // Daemon::ClientDelegate: |
106 virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE { | 126 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())); |
107 char buf[kBufSize]; | 130 char buf[kBufSize]; |
108 const int bytes_read = daemon_socket->Read( | 131 const int bytes_read = daemon_socket->Read( |
109 buf, sizeof(buf) - 1 /* leave space for null terminator */); | 132 buf, sizeof(buf) - 1 /* leave space for null terminator */); |
110 CHECK_GT(bytes_read, 0); | 133 CHECK_GT(bytes_read, 0); |
111 DCHECK(bytes_read < sizeof(buf)); | 134 DCHECK(bytes_read < sizeof(buf)); |
112 buf[bytes_read] = 0; | 135 buf[bytes_read] = 0; |
113 base::StringPiece msg(buf, bytes_read); | 136 base::StringPiece msg(buf, bytes_read); |
114 if (msg.starts_with("ERROR")) { | 137 if (msg.starts_with("ERROR")) { |
115 LOG(ERROR) << msg; | 138 LOG(ERROR) << msg; |
116 has_failed_ = true; | 139 has_failed_ = true; |
117 return; | 140 return; |
118 } | 141 } |
119 } | 142 } |
120 | 143 |
121 private: | 144 private: |
| 145 const std::string adb_socket_; |
122 bool has_failed_; | 146 bool has_failed_; |
123 }; | 147 }; |
124 | 148 |
125 int RunDeviceForwarder(int argc, char** argv) { | 149 int RunDeviceForwarder(int argc, char** argv) { |
126 CommandLine::Init(argc, argv); // Needed by logging. | 150 if (argc != 2) { |
127 const bool kill_server = CommandLine::ForCurrentProcess()->HasSwitch( | 151 fprintf(stderr, |
128 "kill-server"); | 152 "Usage: %s kill-server|<adb_socket>\n" |
129 if ((kill_server && argc != 2) || (!kill_server && argc != 1)) { | 153 " <adb_socket> is the abstract Unix Domain Socket path " |
130 std::cerr << "Usage: device_forwarder [--kill-server]" << std::endl; | 154 "where Adb is configured to forward from.\n", argv[0]); |
131 return 1; | 155 return 1; |
132 } | 156 } |
133 ClientDelegate client_delegate; | 157 CommandLine::Init(argc, argv); // Needed by logging. |
| 158 const char* const command = |
| 159 !strcmp(argv[1], kKillServerCommand) ? kKillServerCommand : kStartCommand; |
| 160 ClientDelegate client_delegate(argv[1]); |
134 ServerDelegate daemon_delegate; | 161 ServerDelegate daemon_delegate; |
135 const char kLogFilePath[] = ""; // Log to logcat. | 162 const char kLogFilePath[] = ""; // Log to logcat. |
136 Daemon daemon(kLogFilePath, kDaemonIdentifier, &client_delegate, | 163 Daemon daemon(kLogFilePath, kDaemonIdentifier, &client_delegate, |
137 &daemon_delegate, &GetExitNotifierFD); | 164 &daemon_delegate, &GetExitNotifierFD); |
138 | 165 |
139 if (kill_server) | 166 if (command == kKillServerCommand) |
140 return !daemon.Kill(); | 167 return !daemon.Kill(); |
141 | 168 |
| 169 DCHECK(command == kStartCommand); |
142 if (!daemon.SpawnIfNeeded()) | 170 if (!daemon.SpawnIfNeeded()) |
143 return 1; | 171 return 1; |
144 return client_delegate.has_failed(); | 172 return client_delegate.has_failed(); |
145 } | 173 } |
146 | 174 |
147 } // namespace | 175 } // namespace |
148 } // namespace forwarder2 | 176 } // namespace forwarder2 |
149 | 177 |
150 int main(int argc, char** argv) { | 178 int main(int argc, char** argv) { |
151 return forwarder2::RunDeviceForwarder(argc, argv); | 179 return forwarder2::RunDeviceForwarder(argc, argv); |
152 } | 180 } |
OLD | NEW |