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 <sys/types.h> | |
8 #include <sys/wait.h> | |
9 #include <unistd.h> | 7 #include <unistd.h> |
10 | 8 |
11 #include <cstdio> | 9 #include <cstdio> |
12 #include <iostream> | 10 #include <cstring> |
13 #include <limits> | |
14 #include <string> | 11 #include <string> |
15 #include <utility> | 12 #include <utility> |
16 #include <vector> | 13 #include <vector> |
17 | 14 |
18 #include "base/command_line.h" | 15 #include "base/command_line.h" |
19 #include "base/compiler_specific.h" | 16 #include "base/compiler_specific.h" |
20 #include "base/containers/hash_tables.h" | 17 #include "base/containers/hash_tables.h" |
21 #include "base/file_util.h" | 18 #include "base/file_util.h" |
22 #include "base/files/file_path.h" | 19 #include "base/files/file_path.h" |
23 #include "base/logging.h" | 20 #include "base/logging.h" |
24 #include "base/memory/linked_ptr.h" | 21 #include "base/memory/linked_ptr.h" |
25 #include "base/memory/scoped_vector.h" | 22 #include "base/memory/scoped_vector.h" |
26 #include "base/pickle.h" | |
27 #include "base/posix/eintr_wrapper.h" | 23 #include "base/posix/eintr_wrapper.h" |
28 #include "base/safe_strerror_posix.h" | 24 #include "base/safe_strerror_posix.h" |
29 #include "base/strings/string_number_conversions.h" | 25 #include "base/strings/string_number_conversions.h" |
30 #include "base/strings/string_piece.h" | 26 #include "base/strings/string_piece.h" |
31 #include "base/strings/string_split.h" | 27 #include "base/strings/string_split.h" |
32 #include "base/strings/string_util.h" | 28 #include "base/strings/string_util.h" |
33 #include "base/strings/stringprintf.h" | 29 #include "base/strings/stringprintf.h" |
34 #include "tools/android/forwarder2/common.h" | 30 #include "tools/android/forwarder2/common.h" |
35 #include "tools/android/forwarder2/daemon.h" | 31 #include "tools/android/forwarder2/daemon.h" |
36 #include "tools/android/forwarder2/host_controller.h" | 32 #include "tools/android/forwarder2/host_controller.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 static int s_kill_handler_count = 0; | 65 static int s_kill_handler_count = 0; |
70 CHECK(g_notifier); | 66 CHECK(g_notifier); |
71 // If for some reason the forwarder get stuck in any socket waiting forever, | 67 // If for some reason the forwarder get stuck in any socket waiting forever, |
72 // we can send a SIGKILL or SIGINT three times to force it die | 68 // we can send a SIGKILL or SIGINT three times to force it die |
73 // (non-nicely). This is useful when debugging. | 69 // (non-nicely). This is useful when debugging. |
74 ++s_kill_handler_count; | 70 ++s_kill_handler_count; |
75 if (!g_notifier->Notify() || s_kill_handler_count > 2) | 71 if (!g_notifier->Notify() || s_kill_handler_count > 2) |
76 exit(1); | 72 exit(1); |
77 } | 73 } |
78 | 74 |
| 75 // Format of |command|: |
| 76 // <ADB port>:<Device port>[:<Forward to port>:<Forward to address>]. |
| 77 bool ParseForwardCommand(const std::string& command, |
| 78 int* adb_port, |
| 79 int* device_port, |
| 80 std::string* forward_to_host, |
| 81 int* forward_to_port) { |
| 82 std::vector<std::string> command_pieces; |
| 83 base::SplitString(command, ':', &command_pieces); |
| 84 |
| 85 if (command_pieces.size() < 2 || |
| 86 !base::StringToInt(command_pieces[0], adb_port) || |
| 87 !base::StringToInt(command_pieces[1], device_port)) |
| 88 return false; |
| 89 |
| 90 if (command_pieces.size() > 2) { |
| 91 if (!base::StringToInt(command_pieces[2], forward_to_port)) |
| 92 return false; |
| 93 if (command_pieces.size() > 3) |
| 94 *forward_to_host = command_pieces[3]; |
| 95 } else { |
| 96 *forward_to_port = *device_port; |
| 97 } |
| 98 return true; |
| 99 } |
| 100 |
| 101 bool IsForwardCommandValid(const std::string& command) { |
| 102 int adb_port, device_port, forward_to_port; |
| 103 std::string forward_to_host; |
| 104 std::vector<std::string> command_pieces; |
| 105 return ParseForwardCommand( |
| 106 command, &adb_port, &device_port, &forward_to_host, &forward_to_port); |
| 107 } |
| 108 |
79 class ServerDelegate : public Daemon::ServerDelegate { | 109 class ServerDelegate : public Daemon::ServerDelegate { |
80 public: | 110 public: |
81 ServerDelegate() : has_failed_(false) {} | 111 ServerDelegate() : has_failed_(false) {} |
82 | 112 |
83 bool has_failed() const { return has_failed_; } | 113 bool has_failed() const { return has_failed_; } |
84 | 114 |
85 // Daemon::ServerDelegate: | 115 // Daemon::ServerDelegate: |
86 virtual void Init() OVERRIDE { | 116 virtual void Init() OVERRIDE { |
87 LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")"; | 117 LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")"; |
88 DCHECK(!g_notifier); | 118 DCHECK(!g_notifier); |
89 g_notifier = new PipeNotifier(); | 119 g_notifier = new PipeNotifier(); |
90 signal(SIGTERM, KillHandler); | 120 signal(SIGTERM, KillHandler); |
91 signal(SIGINT, KillHandler); | 121 signal(SIGINT, KillHandler); |
92 } | 122 } |
93 | 123 |
94 virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE { | 124 virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE { |
95 char buf[kBufSize]; | 125 char buf[kBufSize]; |
96 const int bytes_read = client_socket->Read(buf, sizeof(buf)); | 126 const int bytes_read = client_socket->Read(buf, sizeof(buf)); |
97 if (bytes_read <= 0) { | 127 if (bytes_read <= 0) { |
98 if (client_socket->DidReceiveEvent()) | 128 if (client_socket->DidReceiveEvent()) |
99 return; | 129 return; |
100 PError("Read()"); | 130 PError("Read()"); |
101 has_failed_ = true; | 131 has_failed_ = true; |
102 return; | 132 return; |
103 } | 133 } |
104 const Pickle command_pickle(buf, bytes_read); | 134 const std::string command(buf, bytes_read); |
105 PickleIterator pickle_it(command_pickle); | 135 int adb_port = 0; |
106 std::string device_serial; | 136 int device_port = 0; |
107 CHECK(pickle_it.ReadString(&device_serial)); | 137 std::string forward_to_host; |
108 int device_port; | 138 int forward_to_port = 0; |
109 if (!pickle_it.ReadInt(&device_port)) { | 139 const bool succeeded = ParseForwardCommand( |
110 SendMessage("ERROR: missing device port", client_socket.get()); | 140 command, &adb_port, &device_port, &forward_to_host, &forward_to_port); |
111 return; | 141 if (!succeeded) { |
112 } | 142 has_failed_ = true; |
113 const int adb_port = GetAdbPortForDevice(device_serial); | 143 const std::string msg = base::StringPrintf( |
114 if (adb_port < 0) { | 144 "ERROR: Could not parse forward command '%s'", command.c_str()); |
115 SendMessage( | 145 SendMessage(msg, client_socket.get()); |
116 "ERROR: could not get adb port for device. You might need to add " | |
117 "'adb' to your PATH or provide the device serial id.", | |
118 client_socket.get()); | |
119 return; | 146 return; |
120 } | 147 } |
121 if (device_port < 0) { | 148 if (device_port < 0) { |
122 // Remove the previously created host controller. | 149 // Remove the previously created host controller. |
123 const std::string controller_key = MakeHostControllerMapKey( | 150 const std::string controller_key = MakeHostControllerMapKey( |
124 adb_port, -device_port); | 151 adb_port, -device_port); |
125 const HostControllerMap::size_type removed_elements = controllers_.erase( | 152 const HostControllerMap::size_type removed_elements = controllers_.erase( |
126 controller_key); | 153 controller_key); |
127 SendMessage( | 154 SendMessage( |
128 !removed_elements ? "ERROR: could not unmap port" : "OK", | 155 !removed_elements ? "ERROR: could not unmap port" : "OK", |
129 client_socket.get()); | 156 client_socket.get()); |
130 return; | 157 return; |
131 } | 158 } |
132 int host_port; | |
133 if (!pickle_it.ReadInt(&host_port)) { | |
134 SendMessage("ERROR: missing host port", client_socket.get()); | |
135 return; | |
136 } | |
137 // Create a new host controller. | 159 // Create a new host controller. |
138 scoped_ptr<HostController> host_controller( | 160 scoped_ptr<HostController> host_controller( |
139 new HostController(device_port, "127.0.0.1", host_port, adb_port, | 161 new HostController(device_port, forward_to_host, forward_to_port, |
140 GetExitNotifierFD())); | 162 adb_port, GetExitNotifierFD())); |
141 if (!host_controller->Connect()) { | 163 if (!host_controller->Connect()) { |
142 has_failed_ = true; | 164 has_failed_ = true; |
143 SendMessage("ERROR: Connection to device failed.", client_socket.get()); | 165 SendMessage("ERROR: Connection to device failed.", client_socket.get()); |
144 return; | 166 return; |
145 } | 167 } |
146 // Get the current allocated port. | 168 // Get the current allocated port. |
147 device_port = host_controller->device_port(); | 169 device_port = host_controller->device_port(); |
148 LOG(INFO) << "Forwarding device port " << device_port << " to host port " | 170 LOG(INFO) << "Forwarding device port " << device_port << " to host " |
149 << host_port; | 171 << forward_to_host << ":" << forward_to_port; |
150 const std::string msg = base::StringPrintf("%d:%d", device_port, host_port); | 172 const std::string msg = base::StringPrintf( |
| 173 "%d:%d", device_port, forward_to_port); |
151 if (!SendMessage(msg, client_socket.get())) | 174 if (!SendMessage(msg, client_socket.get())) |
152 return; | 175 return; |
153 host_controller->Start(); | 176 host_controller->Start(); |
154 const std::string controller_key = MakeHostControllerMapKey( | 177 const std::string controller_key = MakeHostControllerMapKey( |
155 adb_port, device_port); | 178 adb_port, device_port); |
156 controllers_.insert( | 179 controllers_.insert( |
157 std::make_pair(controller_key, | 180 std::make_pair(controller_key, |
158 linked_ptr<HostController>(host_controller.release()))); | 181 linked_ptr<HostController>(host_controller.release()))); |
159 } | 182 } |
160 | 183 |
(...skipping 10 matching lines...) Expand all Loading... |
171 } | 194 } |
172 | 195 |
173 private: | 196 private: |
174 typedef base::hash_map< | 197 typedef base::hash_map< |
175 std::string, linked_ptr<HostController> > HostControllerMap; | 198 std::string, linked_ptr<HostController> > HostControllerMap; |
176 | 199 |
177 static std::string MakeHostControllerMapKey(int adb_port, int device_port) { | 200 static std::string MakeHostControllerMapKey(int adb_port, int device_port) { |
178 return base::StringPrintf("%d:%d", adb_port, device_port); | 201 return base::StringPrintf("%d:%d", adb_port, device_port); |
179 } | 202 } |
180 | 203 |
181 int GetAdbPortForDevice(const std::string& device_serial) { | |
182 base::hash_map<std::string, int>::const_iterator it = | |
183 device_serial_to_adb_port_map_.find(device_serial); | |
184 if (it != device_serial_to_adb_port_map_.end()) | |
185 return it->second; | |
186 Socket bind_socket; | |
187 CHECK(bind_socket.BindTcp("127.0.0.1", 0)); | |
188 const int port = bind_socket.GetPort(); | |
189 bind_socket.Close(); | |
190 const std::string serial_part = device_serial.empty() ? | |
191 std::string() : std::string("-s ") + device_serial; | |
192 const std::string command = base::StringPrintf( | |
193 "adb %s forward tcp:%d localabstract:chrome_device_forwarder", | |
194 device_serial.empty() ? "" : serial_part.c_str(), | |
195 port); | |
196 LOG(INFO) << command; | |
197 const int ret = system(command.c_str()); | |
198 if (ret < 0 || !WIFEXITED(ret) || WEXITSTATUS(ret) != 0) | |
199 return -1; | |
200 device_serial_to_adb_port_map_[device_serial] = port; | |
201 return port; | |
202 } | |
203 | |
204 bool SendMessage(const std::string& msg, Socket* client_socket) { | 204 bool SendMessage(const std::string& msg, Socket* client_socket) { |
205 bool result = client_socket->WriteString(msg); | 205 bool result = client_socket->WriteString(msg); |
206 DCHECK(result); | 206 DCHECK(result); |
207 if (!result) | 207 if (!result) |
208 has_failed_ = true; | 208 has_failed_ = true; |
209 return result; | 209 return result; |
210 } | 210 } |
211 | 211 |
212 base::hash_map<std::string, int> device_serial_to_adb_port_map_; | |
213 HostControllerMap controllers_; | 212 HostControllerMap controllers_; |
214 bool has_failed_; | 213 bool has_failed_; |
215 | 214 |
216 DISALLOW_COPY_AND_ASSIGN(ServerDelegate); | 215 DISALLOW_COPY_AND_ASSIGN(ServerDelegate); |
217 }; | 216 }; |
218 | 217 |
219 class ClientDelegate : public Daemon::ClientDelegate { | 218 class ClientDelegate : public Daemon::ClientDelegate { |
220 public: | 219 public: |
221 ClientDelegate(const Pickle& command_pickle) | 220 ClientDelegate(const std::string& forward_command) |
222 : command_pickle_(command_pickle), | 221 : forward_command_(forward_command), |
223 has_failed_(false) { | 222 has_failed_(false) { |
224 } | 223 } |
225 | 224 |
226 bool has_failed() const { return has_failed_; } | 225 bool has_failed() const { return has_failed_; } |
227 | 226 |
228 // Daemon::ClientDelegate: | 227 // Daemon::ClientDelegate: |
229 virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE { | 228 virtual void OnDaemonReady(Socket* daemon_socket) OVERRIDE { |
230 // Send the forward command to the daemon. | 229 // Send the forward command to the daemon. |
231 CHECK_EQ(command_pickle_.size(), | 230 CHECK(daemon_socket->WriteString(forward_command_)); |
232 daemon_socket->WriteNumBytes(command_pickle_.data(), | |
233 command_pickle_.size())); | |
234 char buf[kBufSize]; | 231 char buf[kBufSize]; |
235 const int bytes_read = daemon_socket->Read( | 232 const int bytes_read = daemon_socket->Read( |
236 buf, sizeof(buf) - 1 /* leave space for null terminator */); | 233 buf, sizeof(buf) - 1 /* leave space for null terminator */); |
237 CHECK_GT(bytes_read, 0); | 234 CHECK_GT(bytes_read, 0); |
238 DCHECK(bytes_read < sizeof(buf)); | 235 DCHECK(bytes_read < sizeof(buf)); |
239 buf[bytes_read] = 0; | 236 buf[bytes_read] = 0; |
240 base::StringPiece msg(buf, bytes_read); | 237 base::StringPiece msg(buf, bytes_read); |
241 if (msg.starts_with("ERROR")) { | 238 if (msg.starts_with("ERROR")) { |
242 LOG(ERROR) << msg; | 239 LOG(ERROR) << msg; |
243 has_failed_ = true; | 240 has_failed_ = true; |
244 return; | 241 return; |
245 } | 242 } |
246 printf("%s\n", buf); | 243 printf("%s\n", buf); |
247 } | 244 } |
248 | 245 |
249 private: | 246 private: |
250 const Pickle command_pickle_; | 247 const std::string forward_command_; |
251 bool has_failed_; | 248 bool has_failed_; |
252 }; | 249 }; |
253 | 250 |
254 void ExitWithUsage() { | 251 void PrintUsage(const char* program_name) { |
255 std::cerr << "Usage: host_forwarder [options]\n\n" | 252 LOG(ERROR) << program_name |
256 "Options:\n" | 253 << " adb_port:from_port:to_port:to_host\n" |
257 " --serial-id=[0-9A-Z]{16}]\n" | 254 "<adb port> is the TCP port Adb is configured to forward to.\n" |
258 " --map DEVICE_PORT HOST_PORT\n" | 255 "Note that <from_port> can be unmapped by making it negative."; |
259 " --unmap DEVICE_PORT\n" | |
260 " --kill-server\n"; | |
261 exit(1); | |
262 } | |
263 | |
264 int PortToInt(const std::string& s) { | |
265 int value; | |
266 // Note that 0 is a valid port (used for dynamic port allocation). | |
267 if (!base::StringToInt(s, &value) || value < 0 || | |
268 value > std::numeric_limits<uint16>::max()) { | |
269 LOG(ERROR) << "Could not convert string " << s << " to port"; | |
270 ExitWithUsage(); | |
271 } | |
272 return value; | |
273 } | 256 } |
274 | 257 |
275 int RunHostForwarder(int argc, char** argv) { | 258 int RunHostForwarder(int argc, char** argv) { |
276 CommandLine::Init(argc, argv); | 259 if (!CommandLine::Init(argc, argv)) { |
277 const CommandLine& cmd_line = *CommandLine::ForCurrentProcess(); | 260 LOG(ERROR) << "Could not initialize command line"; |
278 bool kill_server = false; | 261 return 1; |
279 | 262 } |
280 Pickle pickle; | 263 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
281 pickle.WriteString( | 264 const char* command = NULL; |
282 cmd_line.HasSwitch("serial-id") ? | 265 int adb_port = 0; |
283 cmd_line.GetSwitchValueASCII("serial-id") : std::string()); | 266 if (argc != 2) { |
284 | 267 PrintUsage(argv[0]); |
285 const std::vector<std::string> args = cmd_line.GetArgs(); | 268 return 1; |
286 if (cmd_line.HasSwitch("kill-server")) { | 269 } |
287 kill_server = true; | 270 if (!strcmp(argv[1], kKillServerCommand)) { |
288 } else if (cmd_line.HasSwitch("unmap")) { | 271 command = kKillServerCommand; |
289 if (args.size() != 1) | |
290 ExitWithUsage(); | |
291 // Note the minus sign below. | |
292 pickle.WriteInt(-PortToInt(args[0])); | |
293 } else if (cmd_line.HasSwitch("map")) { | |
294 if (args.size() != 2) | |
295 ExitWithUsage(); | |
296 pickle.WriteInt(PortToInt(args[0])); | |
297 pickle.WriteInt(PortToInt(args[1])); | |
298 } else { | 272 } else { |
299 ExitWithUsage(); | 273 command = kForwardCommand; |
| 274 if (!IsForwardCommandValid(argv[1])) { |
| 275 PrintUsage(argv[0]); |
| 276 return 1; |
| 277 } |
300 } | 278 } |
301 | 279 |
302 if (kill_server && args.size() > 0) | 280 ClientDelegate client_delegate(argv[1]); |
303 ExitWithUsage(); | |
304 | |
305 ClientDelegate client_delegate(pickle); | |
306 ServerDelegate daemon_delegate; | 281 ServerDelegate daemon_delegate; |
307 Daemon daemon( | 282 Daemon daemon( |
308 kLogFilePath, kDaemonIdentifier, &client_delegate, &daemon_delegate, | 283 kLogFilePath, kDaemonIdentifier, &client_delegate, &daemon_delegate, |
309 &GetExitNotifierFD); | 284 &GetExitNotifierFD); |
310 | 285 |
311 if (kill_server) | 286 if (command == kKillServerCommand) |
312 return !daemon.Kill(); | 287 return !daemon.Kill(); |
| 288 |
| 289 DCHECK(command == kForwardCommand); |
313 if (!daemon.SpawnIfNeeded()) | 290 if (!daemon.SpawnIfNeeded()) |
314 return 1; | 291 return 1; |
315 | 292 |
316 return client_delegate.has_failed() || daemon_delegate.has_failed(); | 293 return client_delegate.has_failed() || daemon_delegate.has_failed(); |
317 } | 294 } |
318 | 295 |
319 } // namespace | 296 } // namespace |
320 } // namespace forwarder2 | 297 } // namespace forwarder2 |
321 | 298 |
322 int main(int argc, char** argv) { | 299 int main(int argc, char** argv) { |
323 return forwarder2::RunHostForwarder(argc, argv); | 300 return forwarder2::RunHostForwarder(argc, argv); |
324 } | 301 } |
OLD | NEW |