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 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