1 // Copyright 2014 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/browser/devtools/device/adb/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/net_errors.h"
13 #include "net/base/net_util.h"
14 #include "net/socket/tcp_client_socket.h"
18 const int kBufferSize
= 16 * 1024;
19 const char kOkayResponse
[] = "OKAY";
20 const char kHostTransportCommand
[] = "host:transport:%s";
21 const char kLocalhost
[] = "127.0.0.1";
23 std::string
EncodeMessage(const std::string
& message
) {
24 static const char kHexChars
[] = "0123456789ABCDEF";
26 size_t length
= message
.length();
27 std::string
result(4, '\0');
28 char b
= reinterpret_cast<const char*>(&length
)[1];
29 result
[0] = kHexChars
[(b
>> 4) & 0xf];
30 result
[1] = kHexChars
[b
& 0xf];
31 b
= reinterpret_cast<const char*>(&length
)[0];
32 result
[2] = kHexChars
[(b
>> 4) & 0xf];
33 result
[3] = kHexChars
[b
& 0xf];
34 return result
+ message
;
37 class AdbTransportSocket
: public AdbClientSocket
{
39 AdbTransportSocket(int port
,
40 const std::string
& serial
,
41 const std::string
& socket_name
,
42 const SocketCallback
& callback
)
43 : AdbClientSocket(port
),
45 socket_name_(socket_name
),
47 Connect(base::Bind(&AdbTransportSocket::OnConnected
,
48 base::Unretained(this)));
52 ~AdbTransportSocket() {}
54 void OnConnected(int result
) {
55 if (!CheckNetResultOrDie(result
))
57 SendCommand(base::StringPrintf(kHostTransportCommand
, serial_
.c_str()),
58 true, base::Bind(&AdbTransportSocket::SendLocalAbstract
,
59 base::Unretained(this)));
62 void SendLocalAbstract(int result
, const std::string
& response
) {
63 if (!CheckNetResultOrDie(result
))
65 SendCommand(socket_name_
, true,
66 base::Bind(&AdbTransportSocket::OnSocketAvailable
,
67 base::Unretained(this)));
70 void OnSocketAvailable(int result
, const std::string
& response
) {
71 if (!CheckNetResultOrDie(result
))
73 callback_
.Run(net::OK
, socket_
.Pass());
77 bool CheckNetResultOrDie(int result
) {
80 callback_
.Run(result
, make_scoped_ptr
<net::StreamSocket
>(NULL
));
86 std::string socket_name_
;
87 SocketCallback callback_
;
90 class AdbQuerySocket
: AdbClientSocket
{
92 AdbQuerySocket(int port
,
93 const std::string
& query
,
94 const CommandCallback
& callback
)
95 : AdbClientSocket(port
),
98 if (Tokenize(query
, "|", &queries_
) == 0) {
99 CheckNetResultOrDie(net::ERR_INVALID_ARGUMENT
);
102 Connect(base::Bind(&AdbQuerySocket::SendNextQuery
,
103 base::Unretained(this)));
110 void SendNextQuery(int result
) {
111 if (!CheckNetResultOrDie(result
))
113 std::string query
= queries_
[current_query_
];
114 if (query
.length() > 0xFFFF) {
115 CheckNetResultOrDie(net::ERR_MSG_TOO_BIG
);
118 bool is_void
= current_query_
< queries_
.size() - 1;
119 SendCommand(query
, is_void
,
120 base::Bind(&AdbQuerySocket::OnResponse
, base::Unretained(this)));
123 void OnResponse(int result
, const std::string
& response
) {
124 if (++current_query_
< queries_
.size()) {
125 SendNextQuery(net::OK
);
127 callback_
.Run(result
, response
);
132 bool CheckNetResultOrDie(int result
) {
135 callback_
.Run(result
, std::string());
140 std::vector
<std::string
> queries_
;
141 size_t current_query_
;
142 CommandCallback callback_
;
148 void AdbClientSocket::AdbQuery(int port
,
149 const std::string
& query
,
150 const CommandCallback
& callback
) {
151 new AdbQuerySocket(port
, query
, callback
);
155 void AdbClientSocket::TransportQuery(int port
,
156 const std::string
& serial
,
157 const std::string
& socket_name
,
158 const SocketCallback
& callback
) {
159 new AdbTransportSocket(port
, serial
, socket_name
, callback
);
162 AdbClientSocket::AdbClientSocket(int port
)
163 : host_(kLocalhost
), port_(port
) {
166 AdbClientSocket::~AdbClientSocket() {
169 void AdbClientSocket::Connect(const net::CompletionCallback
& callback
) {
170 net::IPAddressNumber ip_number
;
171 if (!net::ParseIPLiteralToNumber(host_
, &ip_number
)) {
172 callback
.Run(net::ERR_FAILED
);
176 net::AddressList address_list
=
177 net::AddressList::CreateFromIPAddress(ip_number
, port_
);
178 socket_
.reset(new net::TCPClientSocket(address_list
, NULL
,
179 net::NetLog::Source()));
180 int result
= socket_
->Connect(callback
);
181 if (result
!= net::ERR_IO_PENDING
)
182 callback
.Run(result
);
185 void AdbClientSocket::SendCommand(const std::string
& command
,
187 const CommandCallback
& callback
) {
188 scoped_refptr
<net::StringIOBuffer
> request_buffer
=
189 new net::StringIOBuffer(EncodeMessage(command
));
190 int result
= socket_
->Write(request_buffer
.get(),
191 request_buffer
->size(),
192 base::Bind(&AdbClientSocket::ReadResponse
,
193 base::Unretained(this),
196 if (result
!= net::ERR_IO_PENDING
)
197 ReadResponse(callback
, is_void
, result
);
200 void AdbClientSocket::ReadResponse(const CommandCallback
& callback
,
204 callback
.Run(result
, "IO error");
207 scoped_refptr
<net::IOBuffer
> response_buffer
=
208 new net::IOBuffer(kBufferSize
);
209 result
= socket_
->Read(response_buffer
.get(),
211 base::Bind(&AdbClientSocket::OnResponseHeader
,
212 base::Unretained(this),
216 if (result
!= net::ERR_IO_PENDING
)
217 OnResponseHeader(callback
, is_void
, response_buffer
, result
);
220 void AdbClientSocket::OnResponseHeader(
221 const CommandCallback
& callback
,
223 scoped_refptr
<net::IOBuffer
> response_buffer
,
226 callback
.Run(result
== 0 ? net::ERR_CONNECTION_CLOSED
: result
,
231 std::string data
= std::string(response_buffer
->data(), result
);
233 callback
.Run(net::ERR_FAILED
, "Response is too short: " + data
);
237 std::string status
= data
.substr(0, 4);
238 if (status
!= kOkayResponse
) {
239 callback
.Run(net::ERR_FAILED
, data
);
243 data
= data
.substr(4);
246 int payload_length
= 0;
248 if (data
.length() >= 4 &&
249 base::HexStringToInt(data
.substr(0, 4), &payload_length
)) {
250 data
= data
.substr(4);
251 bytes_left
= payload_length
- result
+ 8;
255 OnResponseData(callback
, data
, response_buffer
, bytes_left
, 0);
257 callback
.Run(net::OK
, data
);
261 void AdbClientSocket::OnResponseData(
262 const CommandCallback
& callback
,
263 const std::string
& response
,
264 scoped_refptr
<net::IOBuffer
> response_buffer
,
268 callback
.Run(result
, "IO error");
272 bytes_left
-= result
;
273 std::string new_response
=
274 response
+ std::string(response_buffer
->data(), result
);
275 if (bytes_left
== 0) {
276 callback
.Run(net::OK
, new_response
);
281 result
= socket_
->Read(response_buffer
.get(),
283 base::Bind(&AdbClientSocket::OnResponseData
,
284 base::Unretained(this),
290 OnResponseData(callback
, new_response
, response_buffer
, bytes_left
, result
);
291 else if (result
!= net::ERR_IO_PENDING
)
292 callback
.Run(net::OK
, new_response
);