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

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

Issue 18354005: Add --serial-id option to host_forwarder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase on issue 18522003 Created 7 years, 5 months 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
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 <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 <cstring>
11 #include <string> 13 #include <string>
12 #include <utility> 14 #include <utility>
13 #include <vector> 15 #include <vector>
14 16
15 #include "base/command_line.h" 17 #include "base/command_line.h"
16 #include "base/compiler_specific.h" 18 #include "base/compiler_specific.h"
17 #include "base/containers/hash_tables.h" 19 #include "base/containers/hash_tables.h"
18 #include "base/file_util.h" 20 #include "base/file_util.h"
19 #include "base/files/file_path.h" 21 #include "base/files/file_path.h"
20 #include "base/logging.h" 22 #include "base/logging.h"
21 #include "base/memory/linked_ptr.h" 23 #include "base/memory/linked_ptr.h"
22 #include "base/memory/scoped_vector.h" 24 #include "base/memory/scoped_vector.h"
25 #include "base/pickle.h"
23 #include "base/posix/eintr_wrapper.h" 26 #include "base/posix/eintr_wrapper.h"
24 #include "base/safe_strerror_posix.h" 27 #include "base/safe_strerror_posix.h"
25 #include "base/strings/string_number_conversions.h" 28 #include "base/strings/string_number_conversions.h"
26 #include "base/strings/string_piece.h" 29 #include "base/strings/string_piece.h"
27 #include "base/strings/string_split.h" 30 #include "base/strings/string_split.h"
28 #include "base/strings/string_util.h" 31 #include "base/strings/string_util.h"
29 #include "base/strings/stringprintf.h" 32 #include "base/strings/stringprintf.h"
30 #include "tools/android/forwarder2/common.h" 33 #include "tools/android/forwarder2/common.h"
31 #include "tools/android/forwarder2/daemon.h" 34 #include "tools/android/forwarder2/daemon.h"
32 #include "tools/android/forwarder2/host_controller.h" 35 #include "tools/android/forwarder2/host_controller.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 static int s_kill_handler_count = 0; 68 static int s_kill_handler_count = 0;
66 CHECK(g_notifier); 69 CHECK(g_notifier);
67 // If for some reason the forwarder get stuck in any socket waiting forever, 70 // 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 71 // we can send a SIGKILL or SIGINT three times to force it die
69 // (non-nicely). This is useful when debugging. 72 // (non-nicely). This is useful when debugging.
70 ++s_kill_handler_count; 73 ++s_kill_handler_count;
71 if (!g_notifier->Notify() || s_kill_handler_count > 2) 74 if (!g_notifier->Notify() || s_kill_handler_count > 2)
72 exit(1); 75 exit(1);
73 } 76 }
74 77
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 { 78 class ServerDelegate : public Daemon::ServerDelegate {
110 public: 79 public:
111 ServerDelegate() : has_failed_(false) {} 80 ServerDelegate() : has_failed_(false) {}
112 81
113 bool has_failed() const { return has_failed_; } 82 bool has_failed() const { return has_failed_; }
114 83
115 // Daemon::ServerDelegate: 84 // Daemon::ServerDelegate:
116 virtual void Init() OVERRIDE { 85 virtual void Init() OVERRIDE {
117 LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")"; 86 LOG(INFO) << "Starting host process daemon (pid=" << getpid() << ")";
118 DCHECK(!g_notifier); 87 DCHECK(!g_notifier);
119 g_notifier = new PipeNotifier(); 88 g_notifier = new PipeNotifier();
120 signal(SIGTERM, KillHandler); 89 signal(SIGTERM, KillHandler);
121 signal(SIGINT, KillHandler); 90 signal(SIGINT, KillHandler);
122 } 91 }
123 92
124 virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE { 93 virtual void OnClientConnected(scoped_ptr<Socket> client_socket) OVERRIDE {
125 char buf[kBufSize]; 94 char buf[kBufSize];
126 const int bytes_read = client_socket->Read(buf, sizeof(buf)); 95 const int bytes_read = client_socket->Read(buf, sizeof(buf));
127 if (bytes_read <= 0) { 96 if (bytes_read <= 0) {
128 if (client_socket->DidReceiveEvent()) 97 if (client_socket->DidReceiveEvent())
129 return; 98 return;
130 PError("Read()"); 99 PError("Read()");
131 has_failed_ = true; 100 has_failed_ = true;
132 return; 101 return;
133 } 102 }
134 const std::string command(buf, bytes_read); 103 const Pickle command_pickle(buf, bytes_read);
135 int adb_port = 0; 104 PickleIterator pickle_it(command_pickle);
136 int device_port = 0; 105 std::string device_serial;
137 std::string forward_to_host; 106 CHECK(pickle_it.ReadString(&device_serial));
138 int forward_to_port = 0; 107 int device_port, host_port = -1;
139 const bool succeeded = ParseForwardCommand( 108 if (!pickle_it.ReadInt(&device_port)) {
140 command, &adb_port, &device_port, &forward_to_host, &forward_to_port); 109 SendMessage("ERROR: missing device port", client_socket.get());
141 if (!succeeded) { 110 return;
142 has_failed_ = true; 111 }
143 const std::string msg = base::StringPrintf( 112 if (device_port >= 0) {
144 "ERROR: Could not parse forward command '%s'", command.c_str()); 113 if (!pickle_it.ReadInt(&host_port)) {
145 SendMessage(msg, client_socket.get()); 114 SendMessage("ERROR: missing host port", client_socket.get());
115 return;
116 }
117 }
118 const int adb_port = GetAdbPortForDevice(device_serial);
119 if (adb_port < 0) {
120 SendMessage(
121 "ERROR: could not get adb port for device. You might need to add "
122 "'adb' to your PATH or provide the device serial id.",
123 client_socket.get());
146 return; 124 return;
147 } 125 }
148 if (device_port < 0) { 126 if (device_port < 0) {
149 // Remove the previously created host controller. 127 // Remove the previously created host controller.
150 const std::string controller_key = MakeHostControllerMapKey( 128 const std::string controller_key = MakeHostControllerMapKey(
151 adb_port, -device_port); 129 adb_port, -device_port);
152 const HostControllerMap::size_type removed_elements = controllers_.erase( 130 const HostControllerMap::size_type removed_elements = controllers_.erase(
153 controller_key); 131 controller_key);
154 SendMessage( 132 SendMessage(
155 !removed_elements ? "ERROR: could not unmap port" : "OK", 133 !removed_elements ? "ERROR: could not unmap port" : "OK",
156 client_socket.get()); 134 client_socket.get());
157 return; 135 return;
158 } 136 }
159 // Create a new host controller. 137 // Create a new host controller.
160 scoped_ptr<HostController> host_controller( 138 scoped_ptr<HostController> host_controller(
161 new HostController(device_port, forward_to_host, forward_to_port, 139 new HostController(device_port, "127.0.0.1", host_port, adb_port,
162 adb_port, GetExitNotifierFD())); 140 GetExitNotifierFD()));
163 if (!host_controller->Connect()) { 141 if (!host_controller->Connect()) {
164 has_failed_ = true; 142 has_failed_ = true;
165 SendMessage("ERROR: Connection to device failed.", client_socket.get()); 143 SendMessage("ERROR: Connection to device failed.", client_socket.get());
166 return; 144 return;
167 } 145 }
168 // Get the current allocated port. 146 // Get the current allocated port.
169 device_port = host_controller->device_port(); 147 device_port = host_controller->device_port();
170 LOG(INFO) << "Forwarding device port " << device_port << " to host " 148 LOG(INFO) << "Forwarding device port " << device_port << " to host port "
171 << forward_to_host << ":" << forward_to_port; 149 << host_port;
172 const std::string msg = base::StringPrintf( 150 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())) 151 if (!SendMessage(msg, client_socket.get()))
175 return; 152 return;
176 host_controller->Start(); 153 host_controller->Start();
177 const std::string controller_key = MakeHostControllerMapKey( 154 const std::string controller_key = MakeHostControllerMapKey(
178 adb_port, device_port); 155 adb_port, device_port);
179 controllers_.insert( 156 controllers_.insert(
180 std::make_pair(controller_key, 157 std::make_pair(controller_key,
181 linked_ptr<HostController>(host_controller.release()))); 158 linked_ptr<HostController>(host_controller.release())));
182 } 159 }
183 160
(...skipping 10 matching lines...) Expand all
194 } 171 }
195 172
196 private: 173 private:
197 typedef base::hash_map< 174 typedef base::hash_map<
198 std::string, linked_ptr<HostController> > HostControllerMap; 175 std::string, linked_ptr<HostController> > HostControllerMap;
199 176
200 static std::string MakeHostControllerMapKey(int adb_port, int device_port) { 177 static std::string MakeHostControllerMapKey(int adb_port, int device_port) {
201 return base::StringPrintf("%d:%d", adb_port, device_port); 178 return base::StringPrintf("%d:%d", adb_port, device_port);
202 } 179 }
203 180
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() ?
digit1 2013/07/02 15:32:18 I assume you wanted to use serial_part.c_str() her
Philippe 2013/07/02 15:58:25 Oops :)
195 "" : (std::string("-s ") + device_serial).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(const char* program_name) {
252 LOG(ERROR) << program_name 256 LOG(ERROR) << program_name
253 << " adb_port:from_port:to_port:to_host\n" 257 << " [--serial-id=[0-9A-Z]{16}] device_port [host_port]\n"
254 "<adb port> is the TCP port Adb is configured to forward to.\n" 258 "Note that device_port can be negative for unmapping. In that "
255 "Note that <from_port> can be unmapped by making it negative."; 259 "case host_port should not be provided.";
260
261 exit(1);
256 } 262 }
257 263
258 int RunHostForwarder(int argc, char** argv) { 264 int RunHostForwarder(int argc, char** argv) {
259 if (!CommandLine::Init(argc, argv)) { 265 if (argc == 1)
260 LOG(ERROR) << "Could not initialize command line"; 266 ExitWithUsage(argv[0]);
261 return 1; 267 CommandLine::Init(argc, argv);
268 Pickle pickle;
269 bool kill_server = false;
270 for (int i = 1; i < argc; ++i) {
bulach 2013/07/02 12:42:49 only saw this now, sorry.. rather than iterating t
Philippe 2013/07/02 12:51:22 Yeah that was the initial code until I notice that
digit1 2013/07/02 15:32:18 I think the current code is largely enough, but pl
Philippe 2013/07/02 15:58:25 I moved to CommandLine since I changed the command
271 if (!strncmp(argv[i], "kill-server", 11)) {
digit1 2013/07/02 15:32:18 I'd recommend using: if (!strcmp(argv[i], "kill
Philippe 2013/07/02 15:58:25 Yes, good point (although I'm not using strncmp()
272 if (argc != 2)
273 ExitWithUsage(argv[0]);
274 kill_server = true;
275 break;
276 }
277 if (!strncmp(argv[i], "--serial-id=", 12)) {
278 pickle.WriteString(argv[i] + 12);
279 continue;
280 }
281 int port;
282 if (!base::StringToInt(argv[i], &port))
digit1 2013/07/02 15:32:18 Might add a comment here explaining that negative
Philippe 2013/07/02 15:58:25 Good point. I also changed this while addressing M
283 ExitWithUsage(argv[0]);
284 pickle.WriteInt(port);
262 } 285 }
263 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 286 ClientDelegate client_delegate(pickle);
264 const char* command = NULL;
265 int adb_port = 0;
266 if (argc != 2) {
267 PrintUsage(argv[0]);
268 return 1;
269 }
270 if (!strcmp(argv[1], kKillServerCommand)) {
271 command = kKillServerCommand;
272 } else {
273 command = kForwardCommand;
274 if (!IsForwardCommandValid(argv[1])) {
275 PrintUsage(argv[0]);
276 return 1;
277 }
278 }
279
280 ClientDelegate client_delegate(argv[1]);
281 ServerDelegate daemon_delegate; 287 ServerDelegate daemon_delegate;
282 Daemon daemon( 288 Daemon daemon(
283 kLogFilePath, kDaemonIdentifier, &client_delegate, &daemon_delegate, 289 kLogFilePath, kDaemonIdentifier, &client_delegate, &daemon_delegate,
284 &GetExitNotifierFD); 290 &GetExitNotifierFD);
285 291
286 if (command == kKillServerCommand) 292 if (kill_server)
287 return !daemon.Kill(); 293 return !daemon.Kill();
288
289 DCHECK(command == kForwardCommand);
290 if (!daemon.SpawnIfNeeded()) 294 if (!daemon.SpawnIfNeeded())
291 return 1; 295 return 1;
292 296
293 return client_delegate.has_failed() || daemon_delegate.has_failed(); 297 return client_delegate.has_failed() || daemon_delegate.has_failed();
294 } 298 }
295 299
296 } // namespace 300 } // namespace
297 } // namespace forwarder2 301 } // namespace forwarder2
298 302
299 int main(int argc, char** argv) { 303 int main(int argc, char** argv) {
300 return forwarder2::RunHostForwarder(argc, argv); 304 return forwarder2::RunHostForwarder(argc, argv);
301 } 305 }
OLDNEW
« build/android/pylib/forwarder.py ('K') | « build/android/pylib/forwarder.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698