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