1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/test/chromedriver/net/adb_client_socket.h"
8 #include "base/compiler_specific.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "net/base/address_list.h"
13 #include "net/base/completion_callback.h"
14 #include "net/base/net_errors.h"
15 #include "net/base/net_util.h"
16 #include "net/socket/tcp_client_socket.h"
20 const int kBufferSize = 16 * 1024;
21 const char kOkayResponse[] = "OKAY";
22 const char kHostTransportCommand[] = "host:transport:%s";
23 const char kLocalAbstractCommand[] = "localabstract:%s";
24 const char kLocalhost[] = "127.0.0.1";
26 typedef base::Callback<void(int, const std::string&)> CommandCallback;
27 typedef base::Callback<void(int, net::StreamSocket*)> SocketCallback;
29 std::string EncodeMessage(const std::string& message) {
30 static const char kHexChars[] = "0123456789ABCDEF";
32 size_t length = message.length();
33 std::string result(4, '\0');
34 char b = reinterpret_cast<const char*>(&length)[1];
35 result[0] = kHexChars[(b >> 4) & 0xf];
36 result[1] = kHexChars[b & 0xf];
37 b = reinterpret_cast<const char*>(&length)[0];
38 result[2] = kHexChars[(b >> 4) & 0xf];
39 result[3] = kHexChars[b & 0xf];
40 return result + message;
43 class AdbTransportSocket : public AdbClientSocket {
45 AdbTransportSocket(int port,
46 const std::string& serial,
47 const std::string& socket_name,
48 const SocketCallback& callback)
49 : AdbClientSocket(port),
51 socket_name_(socket_name),
53 Connect(base::Bind(&AdbTransportSocket::OnConnected,
54 base::Unretained(this)));
58 ~AdbTransportSocket() {}
60 void OnConnected(int result) {
61 if (!CheckNetResultOrDie(result))
63 SendCommand(base::StringPrintf(kHostTransportCommand, serial_.c_str()),
64 true, base::Bind(&AdbTransportSocket::SendLocalAbstract,
65 base::Unretained(this)));
68 void SendLocalAbstract(int result, const std::string& response) {
69 if (!CheckNetResultOrDie(result))
71 SendCommand(base::StringPrintf(kLocalAbstractCommand, socket_name_.c_str()),
72 true, base::Bind(&AdbTransportSocket::OnSocketAvailable,
73 base::Unretained(this)));
76 void OnSocketAvailable(int result, const std::string& response) {
77 if (!CheckNetResultOrDie(result))
79 callback_.Run(net::OK, socket_.release());
83 bool CheckNetResultOrDie(int result) {
86 callback_.Run(result, NULL);
92 std::string socket_name_;
93 SocketCallback callback_;
96 class HttpOverAdbSocket {
98 HttpOverAdbSocket(int port,
99 const std::string& serial,
100 const std::string& socket_name,
101 const std::string& request,
102 const CommandCallback& callback)
104 command_callback_(callback),
106 Connect(port, serial, socket_name);
109 HttpOverAdbSocket(int port,
110 const std::string& serial,
111 const std::string& socket_name,
112 const std::string& request,
113 const SocketCallback& callback)
115 socket_callback_(callback),
117 Connect(port, serial, socket_name);
121 ~HttpOverAdbSocket() {
124 void Connect(int port,
125 const std::string& serial,
126 const std::string& socket_name) {
127 AdbClientSocket::TransportQuery(
128 port, serial, socket_name,
129 base::Bind(&HttpOverAdbSocket::OnSocketAvailable,
130 base::Unretained(this)));
133 void OnSocketAvailable(int result,
134 net::StreamSocket* socket) {
135 if (!CheckNetResultOrDie(result))
138 socket_.reset(socket);
140 scoped_refptr<net::StringIOBuffer> request_buffer =
141 new net::StringIOBuffer(request_);
143 result = socket_->Write(
144 request_buffer.get(),
145 request_buffer->size(),
146 base::Bind(&HttpOverAdbSocket::ReadResponse, base::Unretained(this)));
147 if (result != net::ERR_IO_PENDING)
148 ReadResponse(result);
151 void ReadResponse(int result) {
152 if (!CheckNetResultOrDie(result))
155 scoped_refptr<net::IOBuffer> response_buffer =
156 new net::IOBuffer(kBufferSize);
158 result = socket_->Read(response_buffer.get(),
160 base::Bind(&HttpOverAdbSocket::OnResponseData,
161 base::Unretained(this),
164 if (result != net::ERR_IO_PENDING)
165 OnResponseData(response_buffer, -1, result);
168 void OnResponseData(scoped_refptr<net::IOBuffer> response_buffer,
171 if (!CheckNetResultOrDie(result))
174 CheckNetResultOrDie(net::ERR_CONNECTION_CLOSED);
178 response_ += std::string(response_buffer->data(), result);
179 int expected_length = 0;
180 if (bytes_total < 0) {
181 size_t content_pos = response_.find("Content-Length:");
182 if (content_pos != std::string::npos) {
183 size_t endline_pos = response_.find("\n", content_pos);
184 if (endline_pos != std::string::npos) {
185 std::string len = response_.substr(content_pos + 15,
186 endline_pos - content_pos - 15);
187 TrimWhitespace(len, TRIM_ALL, &len);
188 if (!base::StringToInt(len, &expected_length)) {
189 CheckNetResultOrDie(net::ERR_FAILED);
195 body_pos_ = response_.find("\r\n\r\n");
196 if (body_pos_ != std::string::npos) {
198 bytes_total = body_pos_ + expected_length;
202 if (bytes_total == static_cast<int>(response_.length())) {
203 if (!command_callback_.is_null())
204 command_callback_.Run(body_pos_, response_);
206 socket_callback_.Run(net::OK, socket_.release());
211 result = socket_->Read(response_buffer.get(),
213 base::Bind(&HttpOverAdbSocket::OnResponseData,
214 base::Unretained(this),
217 if (result != net::ERR_IO_PENDING)
218 OnResponseData(response_buffer, bytes_total, result);
221 bool CheckNetResultOrDie(int result) {
224 if (!command_callback_.is_null())
225 command_callback_.Run(result, std::string());
227 socket_callback_.Run(result, NULL);
232 scoped_ptr<net::StreamSocket> socket_;
233 std::string request_;
234 std::string response_;
235 CommandCallback command_callback_;
236 SocketCallback socket_callback_;
240 class AdbQuerySocket : AdbClientSocket {
242 AdbQuerySocket(int port,
243 const std::string& query,
244 const CommandCallback& callback)
245 : AdbClientSocket(port),
247 callback_(callback) {
248 if (Tokenize(query, "|", &queries_) == 0) {
249 CheckNetResultOrDie(net::ERR_INVALID_ARGUMENT);
252 Connect(base::Bind(&AdbQuerySocket::SendNextQuery,
253 base::Unretained(this)));
260 void SendNextQuery(int result) {
261 if (!CheckNetResultOrDie(result))
263 std::string query = queries_[current_query_];
264 if (query.length() > 0xFFFF) {
265 CheckNetResultOrDie(net::ERR_MSG_TOO_BIG);
268 bool is_void = current_query_ < queries_.size() - 1;
269 SendCommand(query, is_void,
270 base::Bind(&AdbQuerySocket::OnResponse, base::Unretained(this)));
273 void OnResponse(int result, const std::string& response) {
274 if (++current_query_ < queries_.size()) {
275 SendNextQuery(net::OK);
277 callback_.Run(result, response);
282 bool CheckNetResultOrDie(int result) {
285 callback_.Run(result, std::string());
290 std::vector<std::string> queries_;
291 size_t current_query_;
292 CommandCallback callback_;
298 void AdbClientSocket::AdbQuery(int port,
299 const std::string& query,
300 const CommandCallback& callback) {
301 new AdbQuerySocket(port, query, callback);
304 #if defined(DEBUG_DEVTOOLS)
305 static void UseTransportQueryForDesktop(const SocketCallback& callback,
306 net::StreamSocket* socket,
308 callback.Run(result, socket);
310 #endif // defined(DEBUG_DEVTOOLS)
313 void AdbClientSocket::TransportQuery(int port,
314 const std::string& serial,
315 const std::string& socket_name,
316 const SocketCallback& callback) {
317 #if defined(DEBUG_DEVTOOLS)
318 if (serial.empty()) {
319 // Use plain socket for remote debugging on Desktop (debugging purposes).
320 net::IPAddressNumber ip_number;
321 net::ParseIPLiteralToNumber(kLocalhost, &ip_number);
324 if (!base::StringToInt(socket_name, &tcp_port))
327 net::AddressList address_list =
328 net::AddressList::CreateFromIPAddress(ip_number, tcp_port);
329 net::TCPClientSocket* socket = new net::TCPClientSocket(
330 address_list, NULL, net::NetLog::Source());
331 socket->Connect(base::Bind(&UseTransportQueryForDesktop, callback, socket));
334 #endif // defined(DEBUG_DEVTOOLS)
335 new AdbTransportSocket(port, serial, socket_name, callback);
339 void AdbClientSocket::HttpQuery(int port,
340 const std::string& serial,
341 const std::string& socket_name,
342 const std::string& request_path,
343 const CommandCallback& callback) {
344 new HttpOverAdbSocket(port, serial, socket_name, request_path,
349 void AdbClientSocket::HttpQuery(int port,
350 const std::string& serial,
351 const std::string& socket_name,
352 const std::string& request_path,
353 const SocketCallback& callback) {
354 new HttpOverAdbSocket(port, serial, socket_name, request_path,
358 AdbClientSocket::AdbClientSocket(int port)
359 : host_(kLocalhost), port_(port) {
362 AdbClientSocket::~AdbClientSocket() {
365 void AdbClientSocket::Connect(const net::CompletionCallback& callback) {
366 net::IPAddressNumber ip_number;
367 if (!net::ParseIPLiteralToNumber(host_, &ip_number)) {
368 callback.Run(net::ERR_FAILED);
372 net::AddressList address_list =
373 net::AddressList::CreateFromIPAddress(ip_number, port_);
374 socket_.reset(new net::TCPClientSocket(address_list, NULL,
375 net::NetLog::Source()));
376 int result = socket_->Connect(callback);
377 if (result != net::ERR_IO_PENDING)
378 callback.Run(result);
381 void AdbClientSocket::SendCommand(const std::string& command,
383 const CommandCallback& callback) {
384 scoped_refptr<net::StringIOBuffer> request_buffer =
385 new net::StringIOBuffer(EncodeMessage(command));
386 int result = socket_->Write(request_buffer.get(),
387 request_buffer->size(),
388 base::Bind(&AdbClientSocket::ReadResponse,
389 base::Unretained(this),
392 if (result != net::ERR_IO_PENDING)
393 ReadResponse(callback, is_void, result);
396 void AdbClientSocket::ReadResponse(const CommandCallback& callback,
400 callback.Run(result, "IO error");
403 scoped_refptr<net::IOBuffer> response_buffer =
404 new net::IOBuffer(kBufferSize);
405 result = socket_->Read(response_buffer.get(),
407 base::Bind(&AdbClientSocket::OnResponseHeader,
408 base::Unretained(this),
412 if (result != net::ERR_IO_PENDING)
413 OnResponseHeader(callback, is_void, response_buffer, result);
416 void AdbClientSocket::OnResponseHeader(
417 const CommandCallback& callback,
419 scoped_refptr<net::IOBuffer> response_buffer,
422 callback.Run(result == 0 ? net::ERR_CONNECTION_CLOSED : result,
427 std::string data = std::string(response_buffer->data(), result);
429 callback.Run(net::ERR_FAILED, "Response is too short: " + data);
433 std::string status = data.substr(0, 4);
434 if (status != kOkayResponse) {
435 callback.Run(net::ERR_FAILED, data);
439 data = data.substr(4);
442 int payload_length = 0;
444 if (data.length() >= 4 &&
445 base::HexStringToInt(data.substr(0, 4), &payload_length)) {
446 data = data.substr(4);
447 bytes_left = payload_length - result + 8;
451 OnResponseData(callback, data, response_buffer, bytes_left, 0);
453 callback.Run(net::OK, data);
457 void AdbClientSocket::OnResponseData(
458 const CommandCallback& callback,
459 const std::string& response,
460 scoped_refptr<net::IOBuffer> response_buffer,
464 callback.Run(result, "IO error");
468 bytes_left -= result;
469 std::string new_response =
470 response + std::string(response_buffer->data(), result);
471 if (bytes_left == 0) {
472 callback.Run(net::OK, new_response);
477 result = socket_->Read(response_buffer.get(),
479 base::Bind(&AdbClientSocket::OnResponseData,
480 base::Unretained(this),
486 OnResponseData(callback, new_response, response_buffer, bytes_left, result);
487 else if (result != net::ERR_IO_PENDING)
488 callback.Run(net::OK, new_response);