Home | History | Annotate | Download | only in devtools
      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