10529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
50529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "chrome/browser/devtools/device/adb/adb_client_socket.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_errors.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/base/net_util.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/socket/tcp_client_socket.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kBufferSize = 16 * 1024;
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kOkayResponse[] = "OKAY";
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kHostTransportCommand[] = "host:transport:%s";
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kLocalhost[] = "127.0.0.1";
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef base::Callback<void(int, const std::string&)> CommandCallback;
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)typedef base::Callback<void(int, net::StreamSocket*)> SocketCallback;
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string EncodeMessage(const std::string& message) {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const char kHexChars[] = "0123456789ABCDEF";
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t length = message.length();
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string result(4, '\0');
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  char b = reinterpret_cast<const char*>(&length)[1];
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result[0] = kHexChars[(b >> 4) & 0xf];
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result[1] = kHexChars[b & 0xf];
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  b = reinterpret_cast<const char*>(&length)[0];
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result[2] = kHexChars[(b >> 4) & 0xf];
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  result[3] = kHexChars[b & 0xf];
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return result + message;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class AdbTransportSocket : public AdbClientSocket {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AdbTransportSocket(int port,
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     const std::string& serial,
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     const std::string& socket_name,
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                     const SocketCallback& callback)
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : AdbClientSocket(port),
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      serial_(serial),
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      socket_name_(socket_name),
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      callback_(callback) {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Connect(base::Bind(&AdbTransportSocket::OnConnected,
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       base::Unretained(this)));
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~AdbTransportSocket() {}
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnConnected(int result) {
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!CheckNetResultOrDie(result))
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SendCommand(base::StringPrintf(kHostTransportCommand, serial_.c_str()),
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        true, base::Bind(&AdbTransportSocket::SendLocalAbstract,
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         base::Unretained(this)));
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SendLocalAbstract(int result, const std::string& response) {
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!CheckNetResultOrDie(result))
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SendCommand(socket_name_, true,
697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                base::Bind(&AdbTransportSocket::OnSocketAvailable,
707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                           base::Unretained(this)));
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnSocketAvailable(int result, const std::string& response) {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!CheckNetResultOrDie(result))
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback_.Run(net::OK, socket_.release());
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete this;
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool CheckNetResultOrDie(int result) {
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (result >= 0)
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback_.Run(result, NULL);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete this;
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string serial_;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string socket_name_;
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SocketCallback callback_;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class AdbQuerySocket : AdbClientSocket {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AdbQuerySocket(int port,
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 const std::string& query,
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 const CommandCallback& callback)
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : AdbClientSocket(port),
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        current_query_(0),
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        callback_(callback) {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (Tokenize(query, "|", &queries_) == 0) {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CheckNetResultOrDie(net::ERR_INVALID_ARGUMENT);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Connect(base::Bind(&AdbQuerySocket::SendNextQuery,
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       base::Unretained(this)));
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~AdbQuerySocket() {
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SendNextQuery(int result) {
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!CheckNetResultOrDie(result))
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string query = queries_[current_query_];
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (query.length() > 0xFFFF) {
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CheckNetResultOrDie(net::ERR_MSG_TOO_BIG);
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool is_void = current_query_ < queries_.size() - 1;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SendCommand(query, is_void,
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&AdbQuerySocket::OnResponse, base::Unretained(this)));
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnResponse(int result, const std::string& response) {
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (++current_query_ < queries_.size()) {
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SendNextQuery(net::OK);
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      callback_.Run(result, response);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      delete this;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool CheckNetResultOrDie(int result) {
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (result >= 0)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback_.Run(result, std::string());
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete this;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<std::string> queries_;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t current_query_;
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CommandCallback callback_;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AdbClientSocket::AdbQuery(int port,
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               const std::string& query,
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               const CommandCallback& callback) {
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  new AdbQuerySocket(port, query, callback);
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AdbClientSocket::TransportQuery(int port,
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     const std::string& serial,
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     const std::string& socket_name,
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                     const SocketCallback& callback) {
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  new AdbTransportSocket(port, serial, socket_name, callback);
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)AdbClientSocket::AdbClientSocket(int port)
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : host_(kLocalhost), port_(port) {
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AdbClientSocket::~AdbClientSocket() {
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AdbClientSocket::Connect(const net::CompletionCallback& callback) {
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::IPAddressNumber ip_number;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!net::ParseIPLiteralToNumber(host_, &ip_number)) {
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(net::ERR_FAILED);
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  net::AddressList address_list =
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::AddressList::CreateFromIPAddress(ip_number, port_);
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  socket_.reset(new net::TCPClientSocket(address_list, NULL,
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                         net::NetLog::Source()));
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int result = socket_->Connect(callback);
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (result != net::ERR_IO_PENDING)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(result);
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AdbClientSocket::SendCommand(const std::string& command,
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  bool is_void,
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  const CommandCallback& callback) {
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::StringIOBuffer> request_buffer =
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new net::StringIOBuffer(EncodeMessage(command));
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int result = socket_->Write(request_buffer.get(),
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              request_buffer->size(),
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              base::Bind(&AdbClientSocket::ReadResponse,
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         base::Unretained(this),
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         callback,
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                         is_void));
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (result != net::ERR_IO_PENDING)
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ReadResponse(callback, is_void, result);
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AdbClientSocket::ReadResponse(const CommandCallback& callback,
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   bool is_void,
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   int result) {
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (result < 0) {
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(result, "IO error");
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<net::IOBuffer> response_buffer =
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new net::IOBuffer(kBufferSize);
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  result = socket_->Read(response_buffer.get(),
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         kBufferSize,
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         base::Bind(&AdbClientSocket::OnResponseHeader,
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    base::Unretained(this),
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    callback,
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    is_void,
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    response_buffer));
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (result != net::ERR_IO_PENDING)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OnResponseHeader(callback, is_void, response_buffer, result);
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AdbClientSocket::OnResponseHeader(
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const CommandCallback& callback,
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool is_void,
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<net::IOBuffer> response_buffer,
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int result) {
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (result <= 0) {
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(result == 0 ? net::ERR_CONNECTION_CLOSED : result,
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 "IO error");
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string data = std::string(response_buffer->data(), result);
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (result < 4) {
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(net::ERR_FAILED, "Response is too short: " + data);
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string status = data.substr(0, 4);
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (status != kOkayResponse) {
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(net::ERR_FAILED, data);
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data = data.substr(4);
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!is_void) {
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int payload_length = 0;
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int bytes_left = -1;
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (data.length() >= 4 &&
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::HexStringToInt(data.substr(0, 4), &payload_length)) {
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      data = data.substr(4);
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bytes_left = payload_length - result + 8;
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bytes_left = -1;
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OnResponseData(callback, data, response_buffer, bytes_left, 0);
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(net::OK, data);
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AdbClientSocket::OnResponseData(
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const CommandCallback& callback,
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& response,
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<net::IOBuffer> response_buffer,
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int bytes_left,
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int result) {
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (result < 0) {
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(result, "IO error");
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bytes_left -= result;
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string new_response =
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      response + std::string(response_buffer->data(), result);
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (bytes_left == 0) {
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(net::OK, new_response);
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Read tail
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  result = socket_->Read(response_buffer.get(),
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         kBufferSize,
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         base::Bind(&AdbClientSocket::OnResponseData,
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    base::Unretained(this),
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    callback,
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    new_response,
290868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    response_buffer,
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                    bytes_left));
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (result > 0)
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OnResponseData(callback, new_response, response_buffer, bytes_left, result);
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else if (result != net::ERR_IO_PENDING)
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback.Run(net::OK, new_response);
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
297