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 <errno.h> | 5 #include <errno.h> |
6 #include <signal.h> | 6 #include <signal.h> |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 #include <stdlib.h> | 8 #include <stdlib.h> |
| 9 #include <unistd.h> |
9 | 10 |
10 #include <vector> | 11 #include <vector> |
11 #include <string> | 12 #include <string> |
12 | 13 |
13 #include "base/command_line.h" | 14 #include "base/command_line.h" |
| 15 #include "base/eintr_wrapper.h" |
| 16 #include "base/file_path.h" |
| 17 #include "base/file_util.h" |
14 #include "base/logging.h" | 18 #include "base/logging.h" |
15 #include "base/memory/scoped_vector.h" | 19 #include "base/memory/scoped_vector.h" |
| 20 #include "base/safe_strerror_posix.h" |
16 #include "base/string_number_conversions.h" | 21 #include "base/string_number_conversions.h" |
17 #include "base/string_piece.h" | 22 #include "base/string_piece.h" |
18 #include "base/string_split.h" | 23 #include "base/string_split.h" |
| 24 #include "base/string_util.h" |
19 #include "base/stringprintf.h" | 25 #include "base/stringprintf.h" |
20 #include "tools/android/common/daemon.h" | 26 #include "tools/android/forwarder2/common.h" |
| 27 #include "tools/android/forwarder2/daemon.h" |
21 #include "tools/android/forwarder2/host_controller.h" | 28 #include "tools/android/forwarder2/host_controller.h" |
22 #include "tools/android/forwarder2/pipe_notifier.h" | 29 #include "tools/android/forwarder2/pipe_notifier.h" |
| 30 #include "tools/android/forwarder2/socket.h" |
23 | 31 |
24 using base::StringToInt; | 32 using base::StringToInt; |
25 using forwarder2::HostController; | |
26 | 33 |
| 34 namespace forwarder2 { |
27 namespace { | 35 namespace { |
28 | 36 |
29 const int kDefaultAdbPort = 3000; | 37 const char kPIDFilePath[] = "/tmp/host_forwarder_pid"; |
| 38 const char kCommandSocketPath[] = "host_forwarder_command_socket"; |
| 39 const char kWelcomeMessage[] = "forwarder2"; |
| 40 const int kBufSize = 256; |
30 | 41 |
31 // Need to be global to be able to accessed from the signal handler. | 42 // Need to be global to be able to accessed from the signal handler. |
32 forwarder2::PipeNotifier* g_notifier; | 43 PipeNotifier* g_notifier; |
33 | 44 |
34 void KillHandler(int /* unused */) { | 45 void KillHandler(int signal_number) { |
| 46 if (signal_number != SIGTERM && signal_number != SIGINT) { |
| 47 char buf[kBufSize]; |
| 48 snprintf(buf, sizeof(buf), "Ignoring unexpected signal %d.", signal_number); |
| 49 SIGNAL_SAFE_LOG(WARNING, buf); |
| 50 return; |
| 51 } |
35 static int s_kill_handler_count = 0; | 52 static int s_kill_handler_count = 0; |
36 CHECK(g_notifier); | 53 CHECK(g_notifier); |
37 // If for some reason the forwarder get stuck in any socket waiting forever, | 54 // If for some reason the forwarder get stuck in any socket waiting forever, |
38 // we can send a SIGKILL or SIGINT three times to force it die | 55 // we can send a SIGKILL or SIGINT three times to force it die |
39 // (non-nicely). This is useful when debugging. | 56 // (non-nicely). This is useful when debugging. |
40 ++s_kill_handler_count; | 57 ++s_kill_handler_count; |
41 if (!g_notifier->Notify() || s_kill_handler_count > 2) | 58 if (!g_notifier->Notify() || s_kill_handler_count > 2) |
42 exit(1); | 59 exit(1); |
43 } | 60 } |
44 | 61 |
45 // Format of arg: <Device port>[:<Forward to port>:<Forward to address>] | 62 enum { |
46 bool ParseForwardArg(const std::string& arg, | 63 kConnectSingleTry = 1, |
47 int* device_port, | 64 kConnectNoIdleTime = 0, |
48 std::string* forward_to_host, | 65 }; |
49 int* forward_to_port) { | 66 |
50 std::vector<std::string> arg_pieces; | 67 scoped_ptr<Socket> ConnectToDaemon(int tries_count, int idle_time_msec) { |
51 base::SplitString(arg, ':', &arg_pieces); | 68 for (int i = 0; i < tries_count; ++i) { |
52 if (arg_pieces.size() == 0 || !StringToInt(arg_pieces[0], device_port)) | 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|: |
| 91 // <ADB port>:<Device port>[:<Forward to port>:<Forward to address>]. |
| 92 bool ParseForwardCommand(const std::string& command, |
| 93 int* adb_port, |
| 94 int* device_port, |
| 95 std::string* forward_to_host, |
| 96 int* forward_to_port) { |
| 97 std::vector<std::string> command_pieces; |
| 98 base::SplitString(command, ':', &command_pieces); |
| 99 |
| 100 if (command_pieces.size() < 2 || |
| 101 !StringToInt(command_pieces[0], adb_port) || |
| 102 !StringToInt(command_pieces[1], device_port)) |
53 return false; | 103 return false; |
54 | 104 |
55 if (arg_pieces.size() > 1) { | 105 if (command_pieces.size() > 2) { |
56 if (!StringToInt(arg_pieces[1], forward_to_port)) | 106 if (!StringToInt(command_pieces[2], forward_to_port)) |
57 return false; | 107 return false; |
58 if (arg_pieces.size() > 2) | 108 if (command_pieces.size() > 3) |
59 *forward_to_host = arg_pieces[2]; | 109 *forward_to_host = command_pieces[3]; |
60 } else { | 110 } else { |
61 *forward_to_port = *device_port; | 111 *forward_to_port = *device_port; |
62 } | 112 } |
63 return true; | 113 return true; |
64 } | 114 } |
65 | 115 |
66 } // namespace | 116 bool IsForwardCommandValid(const std::string& command) { |
67 | 117 int adb_port, device_port, forward_to_port; |
68 int main(int argc, char** argv) { | 118 std::string forward_to_host; |
69 printf("Host forwarder to handle incoming connections from Android.\n"); | 119 std::vector<std::string> command_pieces; |
70 printf("Like 'adb forward' but in the reverse direction\n"); | 120 return ParseForwardCommand( |
71 | 121 command, &adb_port, &device_port, &forward_to_host, &forward_to_port); |
72 CommandLine command_line(argc, argv); | 122 } |
73 bool show_help = tools::HasHelpSwitch(command_line); | 123 |
74 std::string adb_port_str = command_line.GetSwitchValueASCII("adb_port"); | 124 bool DaemonHandler() { |
75 int adb_port = kDefaultAdbPort; | 125 LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")"; |
76 if (!adb_port_str.empty() && !StringToInt(adb_port_str, &adb_port)) { | 126 DCHECK(!g_notifier); |
77 printf("Could not parse adb port number: %s\n", adb_port_str.c_str()); | 127 g_notifier = new PipeNotifier(); |
78 show_help = true; | 128 |
79 } | 129 const int notifier_fd = g_notifier->receiver_fd(); |
80 if (adb_port <= 0) { | 130 Socket command_socket; |
81 printf("Invalid adb port number: %s. Adb port must be a " | 131 if (!command_socket.BindUnix(kCommandSocketPath, true)) { |
82 "postivie integer.\n", adb_port_str.c_str()); | 132 LOG(ERROR) << "Could not bind Unix Domain Socket"; |
83 show_help = true; | 133 return false; |
84 } | 134 } |
85 CommandLine::StringVector forward_args = command_line.GetArgs(); | 135 command_socket.set_exit_notifier_fd(notifier_fd); |
86 if (show_help || forward_args.empty()) { | 136 |
87 tools::ShowHelp( | 137 signal(SIGTERM, KillHandler); |
88 argv[0], | 138 signal(SIGINT, KillHandler); |
89 "[--adb_port=<adb port>] " | 139 |
90 "<Device port>[:<Forward to port>:<Forward to address>] ...", | |
91 base::StringPrintf( | |
92 " <adb port> is the TCP port Adb is configured to forward to." | |
93 " Default is %d\n" | |
94 " <Forward to port> default is <Device port>\n" | |
95 " <Forward to address> default is 127.0.0.1.", | |
96 kDefaultAdbPort).c_str()); | |
97 return 1; | |
98 } | |
99 | |
100 g_notifier = new forwarder2::PipeNotifier(); | |
101 ScopedVector<HostController> controllers; | 140 ScopedVector<HostController> controllers; |
102 int failed_count = 0; | 141 int failed_count = 0; |
103 for (size_t i = 0; i < forward_args.size(); ++i) { | 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]; |
| 156 const int bytes_read = client_socket.Read(buf, sizeof(buf)); |
| 157 if (bytes_read <= 0) { |
| 158 if (client_socket.exited()) |
| 159 break; |
| 160 PError("Read()"); |
| 161 ++failed_count; |
| 162 } |
| 163 const std::string command(buf, bytes_read); |
| 164 int adb_port = 0; |
104 int device_port = 0; | 165 int device_port = 0; |
105 std::string forward_to_host; | 166 std::string forward_to_host; |
106 int forward_to_port = 0; | 167 int forward_to_port = 0; |
107 if (ParseForwardArg(forward_args[i], | 168 const bool succeeded = ParseForwardCommand( |
108 &device_port, | 169 command, &adb_port, &device_port, &forward_to_host, &forward_to_port); |
109 &forward_to_host, | 170 if (!succeeded) { |
110 &forward_to_port)) { | 171 ++failed_count; |
111 scoped_ptr<HostController> host_controller( | 172 client_socket.WriteString( |
112 new HostController(device_port, | 173 base::StringPrintf("ERROR: Could not parse forward command '%s'", |
113 forward_to_host, | 174 command.c_str())); |
114 forward_to_port, | 175 continue; |
115 adb_port, | 176 } |
116 g_notifier->receiver_fd())); | 177 scoped_ptr<HostController> host_controller( |
117 if (!host_controller->Connect()) | 178 new HostController(device_port, forward_to_host, forward_to_port, |
118 continue; | 179 adb_port, notifier_fd)); |
119 host_controller->Start(); | 180 if (!host_controller->Connect()) { |
120 // Get the current allocated port. | 181 ++failed_count; |
121 device_port = host_controller->device_port(); | 182 client_socket.WriteString("ERROR: Connection to device failed."); |
122 printf("Forwarding device port %d to host %d:%s\n", | 183 continue; |
123 device_port, forward_to_port, forward_to_host.c_str()); | 184 } |
124 | 185 // Get the current allocated port. |
125 controllers.push_back(host_controller.release()); | 186 device_port = host_controller->device_port(); |
126 } else { | 187 LOG(INFO) << "Forwarding device port " << device_port << " to host " |
127 printf("Couldn't start forwarder server for port spec: %s\n", | 188 << forward_to_host << ":" << forward_to_port; |
128 forward_args[i].c_str()); | 189 if (!client_socket.WriteString( |
129 ++failed_count; | 190 base::StringPrintf("%d:%d", device_port, forward_to_port))) { |
130 } | 191 ++failed_count; |
131 } | 192 continue; |
132 | 193 } |
133 // Signal handler must be installed after the for loop above where we start | 194 host_controller->Start(); |
134 // the host_controllers and push_back into the vector. Otherwise a race | 195 controllers.push_back(host_controller.release()); |
135 // condition may occur. | 196 } |
136 signal(SIGTERM, KillHandler); | |
137 signal(SIGINT, KillHandler); | |
138 | |
139 if (controllers.size() == 0) { | |
140 printf("No forwarder servers could be started. Exiting.\n"); | |
141 return failed_count; | |
142 } | |
143 | |
144 // TODO(felipeg): We should check if the controllers are really alive before | |
145 // printing Ready. | |
146 printf("Host Forwarder Ready.\n"); | |
147 for (int i = 0; i < controllers.size(); ++i) | 197 for (int i = 0; i < controllers.size(); ++i) |
148 controllers[i]->Join(); | 198 controllers[i]->Join(); |
149 | 199 |
| 200 if (controllers.size() == 0) { |
| 201 LOG(ERROR) << "No forwarder servers could be started. Exiting."; |
| 202 return false; |
| 203 } |
| 204 return true; |
| 205 } |
| 206 |
| 207 void PrintUsage(const char* program_name) { |
| 208 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."; |
| 210 } |
| 211 |
| 212 int RunHostForwarder(int argc, char** argv) { |
| 213 if (!CommandLine::Init(argc, argv)) { |
| 214 LOG(ERROR) << "Could not initialize command line"; |
| 215 return 1; |
| 216 } |
| 217 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
| 218 std::string command; |
| 219 int adb_port = 0; |
| 220 if (argc != 2) { |
| 221 PrintUsage(argv[0]); |
| 222 return 1; |
| 223 } |
| 224 if (!strcmp(argv[1], "kill-server")) { |
| 225 command = "kill-server"; |
| 226 } else { |
| 227 command = "forward"; |
| 228 if (!IsForwardCommandValid(argv[1])) { |
| 229 PrintUsage(argv[0]); |
| 230 return 1; |
| 231 } |
| 232 } |
| 233 |
| 234 Daemon daemon(kPIDFilePath); |
| 235 |
| 236 if (command == "kill-server") |
| 237 return !daemon.Kill(); |
| 238 |
| 239 bool is_daemon = false; |
| 240 scoped_ptr<Socket> daemon_socket = ConnectToDaemon( |
| 241 kConnectSingleTry, kConnectNoIdleTime); |
| 242 if (!daemon_socket) { |
| 243 if (!daemon.Spawn(&is_daemon)) |
| 244 return 1; |
| 245 } |
| 246 |
| 247 if (is_daemon) |
| 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); |
150 return 0; | 274 return 0; |
151 } | 275 } |
| 276 |
| 277 } // namespace |
| 278 } // namespace forwarder2 |
| 279 |
| 280 int main(int argc, char** argv) { |
| 281 return forwarder2::RunHostForwarder(argc, argv); |
| 282 } |
OLD | NEW |