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