Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(761)

Side by Side Diff: tools/android/forwarder2/host_forwarder_main.cc

Issue 11360248: Use the new forwarder2's Daemon implementation in device_forwarder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address David's comments Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/android/forwarder2/forwarder.gyp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <errno.h> 5 #include <errno.h>
6 #include <signal.h> 6 #include <signal.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h> 7 #include <unistd.h>
10 8
9 #include <cstdio>
10 #include <cstring>
11 #include <string>
11 #include <vector> 12 #include <vector>
12 #include <string>
13 13
14 #include "base/command_line.h" 14 #include "base/command_line.h"
15 #include "base/compiler_specific.h"
15 #include "base/file_path.h" 16 #include "base/file_path.h"
16 #include "base/file_util.h" 17 #include "base/file_util.h"
17 #include "base/logging.h" 18 #include "base/logging.h"
18 #include "base/memory/scoped_vector.h" 19 #include "base/memory/scoped_vector.h"
19 #include "base/posix/eintr_wrapper.h" 20 #include "base/posix/eintr_wrapper.h"
20 #include "base/safe_strerror_posix.h" 21 #include "base/safe_strerror_posix.h"
21 #include "base/string_number_conversions.h" 22 #include "base/string_number_conversions.h"
22 #include "base/string_piece.h" 23 #include "base/string_piece.h"
23 #include "base/string_split.h" 24 #include "base/string_split.h"
24 #include "base/string_util.h" 25 #include "base/string_util.h"
25 #include "base/stringprintf.h" 26 #include "base/stringprintf.h"
26 #include "tools/android/forwarder2/common.h" 27 #include "tools/android/forwarder2/common.h"
27 #include "tools/android/forwarder2/daemon.h" 28 #include "tools/android/forwarder2/daemon.h"
28 #include "tools/android/forwarder2/host_controller.h" 29 #include "tools/android/forwarder2/host_controller.h"
29 #include "tools/android/forwarder2/pipe_notifier.h" 30 #include "tools/android/forwarder2/pipe_notifier.h"
30 #include "tools/android/forwarder2/socket.h" 31 #include "tools/android/forwarder2/socket.h"
31 32
32 using base::StringToInt;
33
34 namespace forwarder2 { 33 namespace forwarder2 {
35 namespace { 34 namespace {
36 35
36 const char kLogFilePath[] = "/tmp/host_forwarder_log";
37 const char kPIDFilePath[] = "/tmp/host_forwarder_pid"; 37 const char kPIDFilePath[] = "/tmp/host_forwarder_pid";
38 const char kCommandSocketPath[] = "host_forwarder_command_socket"; 38 const char kDaemonIdentifier[] = "chrome_host_forwarder_daemon";
39 const char kWelcomeMessage[] = "forwarder2"; 39
40 const char kKillServerCommand[] = "kill-server";
41 const char kForwardCommand[] = "forward";
42
40 const int kBufSize = 256; 43 const int kBufSize = 256;
41 44
42 // Need to be global to be able to accessed from the signal handler. 45 // Needs to be global to be able to be accessed from the signal handler.
43 PipeNotifier* g_notifier; 46 PipeNotifier* g_notifier = NULL;
47
48 // Lets the daemon fetch the exit notifier file descriptor.
49 int GetExitNotifierFD() {
50 DCHECK(g_notifier);
51 return g_notifier->receiver_fd();
52 }
44 53
45 void KillHandler(int signal_number) { 54 void KillHandler(int signal_number) {
55 char buf[kBufSize];
46 if (signal_number != SIGTERM && signal_number != SIGINT) { 56 if (signal_number != SIGTERM && signal_number != SIGINT) {
47 char buf[kBufSize];
48 snprintf(buf, sizeof(buf), "Ignoring unexpected signal %d.", signal_number); 57 snprintf(buf, sizeof(buf), "Ignoring unexpected signal %d.", signal_number);
49 SIGNAL_SAFE_LOG(WARNING, buf); 58 SIGNAL_SAFE_LOG(WARNING, buf);
50 return; 59 return;
51 } 60 }
61 snprintf(buf, sizeof(buf), "Received signal %d.", signal_number);
62 SIGNAL_SAFE_LOG(WARNING, buf);
52 static int s_kill_handler_count = 0; 63 static int s_kill_handler_count = 0;
53 CHECK(g_notifier); 64 CHECK(g_notifier);
54 // If for some reason the forwarder get stuck in any socket waiting forever, 65 // If for some reason the forwarder get stuck in any socket waiting forever,
55 // we can send a SIGKILL or SIGINT three times to force it die 66 // we can send a SIGKILL or SIGINT three times to force it die
56 // (non-nicely). This is useful when debugging. 67 // (non-nicely). This is useful when debugging.
57 ++s_kill_handler_count; 68 ++s_kill_handler_count;
58 if (!g_notifier->Notify() || s_kill_handler_count > 2) 69 if (!g_notifier->Notify() || s_kill_handler_count > 2)
59 exit(1); 70 exit(1);
60 } 71 }
61 72
62 enum {
63 kConnectSingleTry = 1,
64 kConnectNoIdleTime = 0,
65 };
66
67 scoped_ptr<Socket> ConnectToDaemon(int tries_count, int idle_time_msec) {
68 for (int i = 0; i < tries_count; ++i) {
69 scoped_ptr<Socket> socket(new Socket());
70 if (!socket->ConnectUnix(kCommandSocketPath, true)) {
71 if (idle_time_msec)
72 usleep(idle_time_msec * 1000);
73 continue;
74 }
75 char buf[sizeof(kWelcomeMessage)];
76 memset(buf, 0, sizeof(buf));
77 if (socket->Read(buf, sizeof(buf)) < 0) {
78 perror("read");
79 continue;
80 }
81 if (strcmp(buf, kWelcomeMessage)) {
82 LOG(ERROR) << "Unexpected message read from daemon: " << buf;
83 break;
84 }
85 return socket.Pass();
86 }
87 return scoped_ptr<Socket>(NULL);
88 }
89
90 // Format of |command|: 73 // Format of |command|:
91 // <ADB port>:<Device port>[:<Forward to port>:<Forward to address>]. 74 // <ADB port>:<Device port>[:<Forward to port>:<Forward to address>].
92 bool ParseForwardCommand(const std::string& command, 75 bool ParseForwardCommand(const std::string& command,
93 int* adb_port, 76 int* adb_port,
94 int* device_port, 77 int* device_port,
95 std::string* forward_to_host, 78 std::string* forward_to_host,
96 int* forward_to_port) { 79 int* forward_to_port) {
97 std::vector<std::string> command_pieces; 80 std::vector<std::string> command_pieces;
98 base::SplitString(command, ':', &command_pieces); 81 base::SplitString(command, ':', &command_pieces);
99 82
100 if (command_pieces.size() < 2 || 83 if (command_pieces.size() < 2 ||
101 !StringToInt(command_pieces[0], adb_port) || 84 !base::StringToInt(command_pieces[0], adb_port) ||
102 !StringToInt(command_pieces[1], device_port)) 85 !base::StringToInt(command_pieces[1], device_port))
103 return false; 86 return false;
104 87
105 if (command_pieces.size() > 2) { 88 if (command_pieces.size() > 2) {
106 if (!StringToInt(command_pieces[2], forward_to_port)) 89 if (!base::StringToInt(command_pieces[2], forward_to_port))
107 return false; 90 return false;
108 if (command_pieces.size() > 3) 91 if (command_pieces.size() > 3)
109 *forward_to_host = command_pieces[3]; 92 *forward_to_host = command_pieces[3];
110 } else { 93 } else {
111 *forward_to_port = *device_port; 94 *forward_to_port = *device_port;
112 } 95 }
113 return true; 96 return true;
114 } 97 }
115 98
116 bool IsForwardCommandValid(const std::string& command) { 99 bool IsForwardCommandValid(const std::string& command) {
117 int adb_port, device_port, forward_to_port; 100 int adb_port, device_port, forward_to_port;
118 std::string forward_to_host; 101 std::string forward_to_host;
119 std::vector<std::string> command_pieces; 102 std::vector<std::string> command_pieces;
120 return ParseForwardCommand( 103 return ParseForwardCommand(
121 command, &adb_port, &device_port, &forward_to_host, &forward_to_port); 104 command, &adb_port, &device_port, &forward_to_host, &forward_to_port);
122 } 105 }
123 106
124 bool DaemonHandler() { 107 class ServerDelegate : public Daemon::ServerDelegate {
125 LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")"; 108 public:
126 DCHECK(!g_notifier); 109 ServerDelegate() : has_failed_(false) {}
127 g_notifier = new PipeNotifier();
128 110
129 const int notifier_fd = g_notifier->receiver_fd(); 111 bool has_failed() const { return has_failed_; }
130 Socket command_socket; 112
131 if (!command_socket.BindUnix(kCommandSocketPath, true)) { 113 // Daemon::ServerDelegate:
132 LOG(ERROR) << "Could not bind Unix Domain Socket"; 114 virtual void Init() OVERRIDE {
133 return false; 115 LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")";
116 DCHECK(!g_notifier);
117 g_notifier = new PipeNotifier();
118 signal(SIGTERM, KillHandler);
119 signal(SIGINT, KillHandler);
134 } 120 }
135 command_socket.set_exit_notifier_fd(notifier_fd);
136 121
137 signal(SIGTERM, KillHandler); 122 virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE {
138 signal(SIGINT, KillHandler);
139
140 ScopedVector<HostController> controllers;
141 int failed_count = 0;
142
143 for (;;) {
144 Socket client_socket;
145 if (!command_socket.Accept(&client_socket)) {
146 if (command_socket.exited())
147 return true;
148 PError("Accept()");
149 return false;
150 }
151 if (!client_socket.Write(kWelcomeMessage, sizeof(kWelcomeMessage))) {
152 PError("Write()");
153 continue;
154 }
155 char buf[kBufSize]; 123 char buf[kBufSize];
156 const int bytes_read = client_socket.Read(buf, sizeof(buf)); 124 const int bytes_read = client_socket->Read(buf, sizeof(buf));
157 if (bytes_read <= 0) { 125 if (bytes_read <= 0) {
158 if (client_socket.exited()) 126 if (client_socket->exited())
159 break; 127 return;
160 PError("Read()"); 128 PError("Read()");
161 ++failed_count; 129 has_failed_ = true;
130 return;
162 } 131 }
163 const std::string command(buf, bytes_read); 132 const std::string command(buf, bytes_read);
164 int adb_port = 0; 133 int adb_port = 0;
165 int device_port = 0; 134 int device_port = 0;
166 std::string forward_to_host; 135 std::string forward_to_host;
167 int forward_to_port = 0; 136 int forward_to_port = 0;
168 const bool succeeded = ParseForwardCommand( 137 const bool succeeded = ParseForwardCommand(
169 command, &adb_port, &device_port, &forward_to_host, &forward_to_port); 138 command, &adb_port, &device_port, &forward_to_host, &forward_to_port);
170 if (!succeeded) { 139 if (!succeeded) {
171 ++failed_count; 140 has_failed_ = true;
172 client_socket.WriteString( 141 client_socket->WriteString(
173 base::StringPrintf("ERROR: Could not parse forward command '%s'", 142 base::StringPrintf("ERROR: Could not parse forward command '%s'",
174 command.c_str())); 143 command.c_str()));
175 continue; 144 return;
176 } 145 }
177 scoped_ptr<HostController> host_controller( 146 scoped_ptr<HostController> host_controller(
178 new HostController(device_port, forward_to_host, forward_to_port, 147 new HostController(device_port, forward_to_host, forward_to_port,
179 adb_port, notifier_fd)); 148 adb_port, GetExitNotifierFD()));
180 if (!host_controller->Connect()) { 149 if (!host_controller->Connect()) {
181 ++failed_count; 150 has_failed_ = true;
182 client_socket.WriteString("ERROR: Connection to device failed."); 151 client_socket->WriteString("ERROR: Connection to device failed.");
183 continue; 152 return;
184 } 153 }
185 // Get the current allocated port. 154 // Get the current allocated port.
186 device_port = host_controller->device_port(); 155 device_port = host_controller->device_port();
187 LOG(INFO) << "Forwarding device port " << device_port << " to host " 156 LOG(INFO) << "Forwarding device port " << device_port << " to host "
188 << forward_to_host << ":" << forward_to_port; 157 << forward_to_host << ":" << forward_to_port;
189 if (!client_socket.WriteString( 158 if (!client_socket->WriteString(
190 base::StringPrintf("%d:%d", device_port, forward_to_port))) { 159 base::StringPrintf("%d:%d", device_port, forward_to_port))) {
191 ++failed_count; 160 has_failed_ = true;
192 continue; 161 return;
193 } 162 }
194 host_controller->Start(); 163 host_controller->Start();
195 controllers.push_back(host_controller.release()); 164 controllers_.push_back(host_controller.release());
196 } 165 }
197 for (int i = 0; i < controllers.size(); ++i)
198 controllers[i]->Join();
199 166
200 if (controllers.size() == 0) { 167 virtual void OnServerExited() OVERRIDE {
201 LOG(ERROR) << "No forwarder servers could be started. Exiting."; 168 for (int i = 0; i < controllers_.size(); ++i)
202 return false; 169 controllers_[i]->Join();
170 if (controllers_.size() == 0) {
171 LOG(ERROR) << "No forwarder servers could be started. Exiting.";
172 has_failed_ = true;
173 }
203 } 174 }
204 return true; 175
205 } 176 private:
177 ScopedVector<HostController> controllers_;
178 bool has_failed_;
179
180 DISALLOW_COPY_AND_ASSIGN(ServerDelegate);
181 };
182
183 class ClientDelegate : public Daemon::ClientDelegate {
184 public:
185 ClientDelegate(const std::string& forward_command)
186 : forward_command_(forward_command),
187 has_failed_(false) {
188 }
189
190 bool has_failed() const { return has_failed_; }
191
192 // Daemon::ClientDelegate:
193 virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE {
194 // Send the forward command to the daemon.
195 CHECK(daemon_socket->WriteString(forward_command_));
196 char buf[kBufSize];
197 const int bytes_read = daemon_socket->Read(
198 buf, sizeof(buf) - 1 /* leave space for null terminator */);
199 CHECK_GT(bytes_read, 0);
200 DCHECK(bytes_read < sizeof(buf));
201 buf[bytes_read] = 0;
202 base::StringPiece msg(buf, bytes_read);
203 if (msg.starts_with("ERROR")) {
204 LOG(ERROR) << msg;
205 has_failed_ = true;
206 return;
207 }
208 printf("%s\n", buf);
209 }
210
211 private:
212 const std::string forward_command_;
213 bool has_failed_;
214 };
206 215
207 void PrintUsage(const char* program_name) { 216 void PrintUsage(const char* program_name) {
208 LOG(ERROR) << program_name << " adb_port:from_port:to_port:to_host\n" 217 LOG(ERROR) << program_name << " adb_port:from_port:to_port:to_host\n"
209 "<adb port> is the TCP port Adb is configured to forward to."; 218 "<adb port> is the TCP port Adb is configured to forward to.";
210 } 219 }
211 220
212 int RunHostForwarder(int argc, char** argv) { 221 int RunHostForwarder(int argc, char** argv) {
213 if (!CommandLine::Init(argc, argv)) { 222 if (!CommandLine::Init(argc, argv)) {
214 LOG(ERROR) << "Could not initialize command line"; 223 LOG(ERROR) << "Could not initialize command line";
215 return 1; 224 return 1;
216 } 225 }
217 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 226 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
218 std::string command; 227 const char* command = NULL;
219 int adb_port = 0; 228 int adb_port = 0;
220 if (argc != 2) { 229 if (argc != 2) {
221 PrintUsage(argv[0]); 230 PrintUsage(argv[0]);
222 return 1; 231 return 1;
223 } 232 }
224 if (!strcmp(argv[1], "kill-server")) { 233 if (!strcmp(argv[1], kKillServerCommand)) {
225 command = "kill-server"; 234 command = kKillServerCommand;
226 } else { 235 } else {
227 command = "forward"; 236 command = kForwardCommand;
228 if (!IsForwardCommandValid(argv[1])) { 237 if (!IsForwardCommandValid(argv[1])) {
229 PrintUsage(argv[0]); 238 PrintUsage(argv[0]);
230 return 1; 239 return 1;
231 } 240 }
232 } 241 }
233 242
234 Daemon daemon(kPIDFilePath); 243 ClientDelegate client_delegate(argv[1]);
244 ServerDelegate daemon_delegate;
245 Daemon daemon(
246 kLogFilePath, kPIDFilePath, kDaemonIdentifier, &client_delegate,
247 &daemon_delegate, &GetExitNotifierFD);
235 248
236 if (command == "kill-server") 249 if (command == kKillServerCommand)
237 return !daemon.Kill(); 250 return !daemon.Kill();
238 251
239 bool is_daemon = false; 252 DCHECK(command == kForwardCommand);
240 scoped_ptr<Socket> daemon_socket = ConnectToDaemon( 253 if (!daemon.SpawnIfNeeded())
241 kConnectSingleTry, kConnectNoIdleTime); 254 return 1;
242 if (!daemon_socket) {
243 if (!daemon.Spawn(&is_daemon))
244 return 1;
245 }
246 255
247 if (is_daemon) 256 return client_delegate.has_failed() || daemon_delegate.has_failed();
248 return !DaemonHandler();
249
250 if (!daemon_socket) {
251 const int kTries = 10;
252 const int kIdleTimeMsec = 10;
253 daemon_socket = ConnectToDaemon(kTries, kIdleTimeMsec);
254 if (!daemon_socket) {
255 LOG(ERROR) << "Could not connect to daemon.";
256 return 1;
257 }
258 }
259
260 // Send the forward command to the daemon.
261 CHECK(daemon_socket->Write(argv[1], strlen(argv[1])));
262 char buf[kBufSize];
263 const int bytes_read = daemon_socket->Read(
264 buf, sizeof(buf) - 1 /* leave space for null terminator */);
265 CHECK_GT(bytes_read, 0);
266 DCHECK(bytes_read < sizeof(buf));
267 buf[bytes_read] = 0;
268 base::StringPiece msg(buf, bytes_read);
269 if (msg.starts_with("ERROR")) {
270 LOG(ERROR) << msg;
271 return 1;
272 }
273 printf("%s\n", buf);
274 return 0;
275 } 257 }
276 258
277 } // namespace 259 } // namespace
278 } // namespace forwarder2 260 } // namespace forwarder2
279 261
280 int main(int argc, char** argv) { 262 int main(int argc, char** argv) {
281 return forwarder2::RunHostForwarder(argc, argv); 263 return forwarder2::RunHostForwarder(argc, argv);
282 } 264 }
OLDNEW
« no previous file with comments | « tools/android/forwarder2/forwarder.gyp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698