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. 4 5 #include "chrome/browser/devtools/adb_client_socket.h" 6 7 #include "base/bind.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" 17 18 namespace { 19 20 const int kBufferSize = 16 * 1024; 21 const char kOkayResponse[] = "OKAY"; 22 const char kHostTransportCommand[] = "host:transport:%s"; 23 const char kLocalhost[] = "127.0.0.1"; 24 25 typedef base::Callback<void(int, const std::string&)> CommandCallback; 26 typedef base::Callback<void(int, net::StreamSocket*)> SocketCallback; 27 28 std::string EncodeMessage(const std::string& message) { 29 static const char kHexChars[] = "0123456789ABCDEF"; 30 31 size_t length = message.length(); 32 std::string result(4, '\0'); 33 char b = reinterpret_cast<const char*>(&length)[1]; 34 result[0] = kHexChars[(b >> 4) & 0xf]; 35 result[1] = kHexChars[b & 0xf]; 36 b = reinterpret_cast<const char*>(&length)[0]; 37 result[2] = kHexChars[(b >> 4) & 0xf]; 38 result[3] = kHexChars[b & 0xf]; 39 return result + message; 40 } 41 42 class AdbTransportSocket : public AdbClientSocket { 43 public: 44 AdbTransportSocket(int port, 45 const std::string& serial, 46 const std::string& socket_name, 47 const SocketCallback& callback) 48 : AdbClientSocket(port), 49 serial_(serial), 50 socket_name_(socket_name), 51 callback_(callback) { 52 Connect(base::Bind(&AdbTransportSocket::OnConnected, 53 base::Unretained(this))); 54 } 55 56 private: 57 ~AdbTransportSocket() {} 58 59 void OnConnected(int result) { 60 if (!CheckNetResultOrDie(result)) 61 return; 62 SendCommand(base::StringPrintf(kHostTransportCommand, serial_.c_str()), 63 true, base::Bind(&AdbTransportSocket::SendLocalAbstract, 64 base::Unretained(this))); 65 } 66 67 void SendLocalAbstract(int result, const std::string& response) { 68 if (!CheckNetResultOrDie(result)) 69 return; 70 SendCommand(socket_name_, true, 71 base::Bind(&AdbTransportSocket::OnSocketAvailable, 72 base::Unretained(this))); 73 } 74 75 void OnSocketAvailable(int result, const std::string& response) { 76 if (!CheckNetResultOrDie(result)) 77 return; 78 callback_.Run(net::OK, socket_.release()); 79 delete this; 80 } 81 82 bool CheckNetResultOrDie(int result) { 83 if (result >= 0) 84 return true; 85 callback_.Run(result, NULL); 86 delete this; 87 return false; 88 } 89 90 std::string serial_; 91 std::string socket_name_; 92 SocketCallback callback_; 93 }; 94 95 class HttpOverAdbSocket { 96 public: 97 HttpOverAdbSocket(net::StreamSocket* socket, 98 const std::string& request, 99 const CommandCallback& callback) 100 : socket_(socket), 101 command_callback_(callback), 102 body_pos_(0) { 103 SendRequest(request); 104 } 105 106 HttpOverAdbSocket(net::StreamSocket* socket, 107 const std::string& request, 108 const SocketCallback& callback) 109 : socket_(socket), 110 socket_callback_(callback), 111 body_pos_(0) { 112 SendRequest(request); 113 } 114 115 private: 116 ~HttpOverAdbSocket() { 117 } 118 119 void SendRequest(const std::string& request) { 120 scoped_refptr<net::StringIOBuffer> request_buffer = 121 new net::StringIOBuffer(request); 122 123 int result = socket_->Write( 124 request_buffer.get(), 125 request_buffer->size(), 126 base::Bind(&HttpOverAdbSocket::ReadResponse, base::Unretained(this))); 127 if (result != net::ERR_IO_PENDING) 128 ReadResponse(result); 129 } 130 131 void ReadResponse(int result) { 132 if (!CheckNetResultOrDie(result)) 133 return; 134 scoped_refptr<net::IOBuffer> response_buffer = 135 new net::IOBuffer(kBufferSize); 136 137 result = socket_->Read(response_buffer.get(), 138 kBufferSize, 139 base::Bind(&HttpOverAdbSocket::OnResponseData, 140 base::Unretained(this), 141 response_buffer, 142 -1)); 143 if (result != net::ERR_IO_PENDING) 144 OnResponseData(response_buffer, -1, result); 145 } 146 147 void OnResponseData(scoped_refptr<net::IOBuffer> response_buffer, 148 int bytes_total, 149 int result) { 150 if (!CheckNetResultOrDie(result)) 151 return; 152 if (result == 0) { 153 CheckNetResultOrDie(net::ERR_CONNECTION_CLOSED); 154 return; 155 } 156 157 response_ += std::string(response_buffer->data(), result); 158 int expected_length = 0; 159 if (bytes_total < 0) { 160 // TODO(kaznacheev): Use net::HttpResponseHeader to parse the header. 161 size_t content_pos = response_.find("Content-Length:"); 162 if (content_pos != std::string::npos) { 163 size_t endline_pos = response_.find("\n", content_pos); 164 if (endline_pos != std::string::npos) { 165 std::string len = response_.substr(content_pos + 15, 166 endline_pos - content_pos - 15); 167 TrimWhitespace(len, TRIM_ALL, &len); 168 if (!base::StringToInt(len, &expected_length)) { 169 CheckNetResultOrDie(net::ERR_FAILED); 170 return; 171 } 172 } 173 } 174 175 body_pos_ = response_.find("\r\n\r\n"); 176 if (body_pos_ != std::string::npos) { 177 body_pos_ += 4; 178 bytes_total = body_pos_ + expected_length; 179 } 180 } 181 182 if (bytes_total == static_cast<int>(response_.length())) { 183 if (!command_callback_.is_null()) 184 command_callback_.Run(net::OK, response_.substr(body_pos_)); 185 else 186 socket_callback_.Run(net::OK, socket_.release()); 187 delete this; 188 return; 189 } 190 191 result = socket_->Read(response_buffer.get(), 192 kBufferSize, 193 base::Bind(&HttpOverAdbSocket::OnResponseData, 194 base::Unretained(this), 195 response_buffer, 196 bytes_total)); 197 if (result != net::ERR_IO_PENDING) 198 OnResponseData(response_buffer, bytes_total, result); 199 } 200 201 bool CheckNetResultOrDie(int result) { 202 if (result >= 0) 203 return true; 204 if (!command_callback_.is_null()) 205 command_callback_.Run(result, std::string()); 206 else 207 socket_callback_.Run(result, NULL); 208 delete this; 209 return false; 210 } 211 212 scoped_ptr<net::StreamSocket> socket_; 213 std::string response_; 214 CommandCallback command_callback_; 215 SocketCallback socket_callback_; 216 size_t body_pos_; 217 }; 218 219 class AdbQuerySocket : AdbClientSocket { 220 public: 221 AdbQuerySocket(int port, 222 const std::string& query, 223 const CommandCallback& callback) 224 : AdbClientSocket(port), 225 current_query_(0), 226 callback_(callback) { 227 if (Tokenize(query, "|", &queries_) == 0) { 228 CheckNetResultOrDie(net::ERR_INVALID_ARGUMENT); 229 return; 230 } 231 Connect(base::Bind(&AdbQuerySocket::SendNextQuery, 232 base::Unretained(this))); 233 } 234 235 private: 236 ~AdbQuerySocket() { 237 } 238 239 void SendNextQuery(int result) { 240 if (!CheckNetResultOrDie(result)) 241 return; 242 std::string query = queries_[current_query_]; 243 if (query.length() > 0xFFFF) { 244 CheckNetResultOrDie(net::ERR_MSG_TOO_BIG); 245 return; 246 } 247 bool is_void = current_query_ < queries_.size() - 1; 248 SendCommand(query, is_void, 249 base::Bind(&AdbQuerySocket::OnResponse, base::Unretained(this))); 250 } 251 252 void OnResponse(int result, const std::string& response) { 253 if (++current_query_ < queries_.size()) { 254 SendNextQuery(net::OK); 255 } else { 256 callback_.Run(result, response); 257 delete this; 258 } 259 } 260 261 bool CheckNetResultOrDie(int result) { 262 if (result >= 0) 263 return true; 264 callback_.Run(result, std::string()); 265 delete this; 266 return false; 267 } 268 269 std::vector<std::string> queries_; 270 size_t current_query_; 271 CommandCallback callback_; 272 }; 273 274 } // namespace 275 276 // static 277 void AdbClientSocket::AdbQuery(int port, 278 const std::string& query, 279 const CommandCallback& callback) { 280 new AdbQuerySocket(port, query, callback); 281 } 282 283 #if defined(DEBUG_DEVTOOLS) 284 static void UseTransportQueryForDesktop(const SocketCallback& callback, 285 net::StreamSocket* socket, 286 int result) { 287 callback.Run(result, socket); 288 } 289 #endif // defined(DEBUG_DEVTOOLS) 290 291 // static 292 void AdbClientSocket::TransportQuery(int port, 293 const std::string& serial, 294 const std::string& socket_name, 295 const SocketCallback& callback) { 296 #if defined(DEBUG_DEVTOOLS) 297 if (serial.empty()) { 298 // Use plain socket for remote debugging on Desktop (debugging purposes). 299 net::IPAddressNumber ip_number; 300 net::ParseIPLiteralToNumber(kLocalhost, &ip_number); 301 302 int tcp_port = 0; 303 if (!base::StringToInt(socket_name, &tcp_port)) 304 tcp_port = 9222; 305 306 net::AddressList address_list = 307 net::AddressList::CreateFromIPAddress(ip_number, tcp_port); 308 net::TCPClientSocket* socket = new net::TCPClientSocket( 309 address_list, NULL, net::NetLog::Source()); 310 socket->Connect(base::Bind(&UseTransportQueryForDesktop, callback, socket)); 311 return; 312 } 313 #endif // defined(DEBUG_DEVTOOLS) 314 new AdbTransportSocket(port, serial, socket_name, callback); 315 } 316 317 // static 318 void AdbClientSocket::HttpQuery(net::StreamSocket* socket, 319 const std::string& request_path, 320 const CommandCallback& callback) { 321 new HttpOverAdbSocket(socket, request_path, callback); 322 } 323 324 // static 325 void AdbClientSocket::HttpQuery(net::StreamSocket* socket, 326 const std::string& request_path, 327 const SocketCallback& callback) { 328 new HttpOverAdbSocket(socket, request_path, callback); 329 } 330 331 AdbClientSocket::AdbClientSocket(int port) 332 : host_(kLocalhost), port_(port) { 333 } 334 335 AdbClientSocket::~AdbClientSocket() { 336 } 337 338 void AdbClientSocket::Connect(const net::CompletionCallback& callback) { 339 net::IPAddressNumber ip_number; 340 if (!net::ParseIPLiteralToNumber(host_, &ip_number)) { 341 callback.Run(net::ERR_FAILED); 342 return; 343 } 344 345 net::AddressList address_list = 346 net::AddressList::CreateFromIPAddress(ip_number, port_); 347 socket_.reset(new net::TCPClientSocket(address_list, NULL, 348 net::NetLog::Source())); 349 int result = socket_->Connect(callback); 350 if (result != net::ERR_IO_PENDING) 351 callback.Run(result); 352 } 353 354 void AdbClientSocket::SendCommand(const std::string& command, 355 bool is_void, 356 const CommandCallback& callback) { 357 scoped_refptr<net::StringIOBuffer> request_buffer = 358 new net::StringIOBuffer(EncodeMessage(command)); 359 int result = socket_->Write(request_buffer.get(), 360 request_buffer->size(), 361 base::Bind(&AdbClientSocket::ReadResponse, 362 base::Unretained(this), 363 callback, 364 is_void)); 365 if (result != net::ERR_IO_PENDING) 366 ReadResponse(callback, is_void, result); 367 } 368 369 void AdbClientSocket::ReadResponse(const CommandCallback& callback, 370 bool is_void, 371 int result) { 372 if (result < 0) { 373 callback.Run(result, "IO error"); 374 return; 375 } 376 scoped_refptr<net::IOBuffer> response_buffer = 377 new net::IOBuffer(kBufferSize); 378 result = socket_->Read(response_buffer.get(), 379 kBufferSize, 380 base::Bind(&AdbClientSocket::OnResponseHeader, 381 base::Unretained(this), 382 callback, 383 is_void, 384 response_buffer)); 385 if (result != net::ERR_IO_PENDING) 386 OnResponseHeader(callback, is_void, response_buffer, result); 387 } 388 389 void AdbClientSocket::OnResponseHeader( 390 const CommandCallback& callback, 391 bool is_void, 392 scoped_refptr<net::IOBuffer> response_buffer, 393 int result) { 394 if (result <= 0) { 395 callback.Run(result == 0 ? net::ERR_CONNECTION_CLOSED : result, 396 "IO error"); 397 return; 398 } 399 400 std::string data = std::string(response_buffer->data(), result); 401 if (result < 4) { 402 callback.Run(net::ERR_FAILED, "Response is too short: " + data); 403 return; 404 } 405 406 std::string status = data.substr(0, 4); 407 if (status != kOkayResponse) { 408 callback.Run(net::ERR_FAILED, data); 409 return; 410 } 411 412 data = data.substr(4); 413 414 if (!is_void) { 415 int payload_length = 0; 416 int bytes_left = -1; 417 if (data.length() >= 4 && 418 base::HexStringToInt(data.substr(0, 4), &payload_length)) { 419 data = data.substr(4); 420 bytes_left = payload_length - result + 8; 421 } else { 422 bytes_left = -1; 423 } 424 OnResponseData(callback, data, response_buffer, bytes_left, 0); 425 } else { 426 callback.Run(net::OK, data); 427 } 428 } 429 430 void AdbClientSocket::OnResponseData( 431 const CommandCallback& callback, 432 const std::string& response, 433 scoped_refptr<net::IOBuffer> response_buffer, 434 int bytes_left, 435 int result) { 436 if (result < 0) { 437 callback.Run(result, "IO error"); 438 return; 439 } 440 441 bytes_left -= result; 442 std::string new_response = 443 response + std::string(response_buffer->data(), result); 444 if (bytes_left == 0) { 445 callback.Run(net::OK, new_response); 446 return; 447 } 448 449 // Read tail 450 result = socket_->Read(response_buffer.get(), 451 kBufferSize, 452 base::Bind(&AdbClientSocket::OnResponseData, 453 base::Unretained(this), 454 callback, 455 new_response, 456 response_buffer, 457 bytes_left)); 458 if (result > 0) 459 OnResponseData(callback, new_response, response_buffer, bytes_left, result); 460 else if (result != net::ERR_IO_PENDING) 461 callback.Run(net::OK, new_response); 462 } 463