Home | History | Annotate | Download | only in adb
      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/android_usb_socket.h"
      6 
      7 #include "base/message_loop/message_loop.h"
      8 
      9 namespace {
     10 
     11 const int kMaxPayload = 4096;
     12 
     13 }  // namespace
     14 
     15 AndroidUsbSocket::IORequest::IORequest(
     16     net::IOBuffer* buffer,
     17     int length,
     18     const net::CompletionCallback& callback)
     19     : buffer(buffer),
     20       length(length),
     21       callback(callback) {
     22 }
     23 
     24 AndroidUsbSocket::IORequest::~IORequest() {
     25 }
     26 
     27 AndroidUsbSocket::AndroidUsbSocket(scoped_refptr<AndroidUsbDevice> device,
     28                                    uint32 socket_id,
     29                                    const std::string& command,
     30                                    base::Callback<void(uint32)> delete_callback)
     31     : device_(device),
     32       command_(command),
     33       delete_callback_(delete_callback),
     34       local_id_(socket_id),
     35       remote_id_(0),
     36       is_connected_(false),
     37       is_closed_(false) {
     38 }
     39 
     40 AndroidUsbSocket::~AndroidUsbSocket() {
     41   DCHECK(CalledOnValidThread());
     42   if (is_connected_)
     43     Disconnect();
     44   delete_callback_.Run(local_id_);
     45 }
     46 
     47 void AndroidUsbSocket::HandleIncoming(scoped_refptr<AdbMessage> message) {
     48   CHECK_EQ(message->arg1, local_id_);
     49   switch (message->command) {
     50     case AdbMessage::kCommandOKAY:
     51       if (!is_connected_) {
     52         remote_id_ = message->arg0;
     53         is_connected_ = true;
     54         net::CompletionCallback callback = connect_callback_;
     55         connect_callback_.Reset();
     56         callback.Run(net::OK);
     57         // "this" can be NULL.
     58       } else {
     59         RespondToWriters();
     60         // "this" can be NULL.
     61       }
     62       break;
     63     case AdbMessage::kCommandWRTE:
     64       device_->Send(AdbMessage::kCommandOKAY, local_id_, message->arg0, "");
     65       read_buffer_ += message->body;
     66       // Allow WRTE over new connection even though OKAY ack was not received.
     67       if (!is_connected_) {
     68         remote_id_ = message->arg0;
     69         is_connected_ = true;
     70         net::CompletionCallback callback = connect_callback_;
     71         connect_callback_.Reset();
     72         callback.Run(net::OK);
     73         // "this" can be NULL.
     74       } else {
     75         RespondToReaders(false);
     76         // "this" can be NULL.
     77       }
     78       break;
     79     case AdbMessage::kCommandCLSE:
     80       if (is_connected_)
     81         device_->Send(AdbMessage::kCommandCLSE, local_id_, 0, "");
     82       is_connected_ = false;
     83       is_closed_ = true;
     84       RespondToReaders(true);
     85       // "this" can be NULL.
     86       break;
     87     default:
     88       break;
     89   }
     90 }
     91 
     92 void AndroidUsbSocket::Terminated() {
     93   is_connected_ = false;
     94   is_closed_ = true;
     95   if (!connect_callback_.is_null()) {
     96     net::CompletionCallback callback = connect_callback_;
     97     connect_callback_.Reset();
     98     callback.Run(net::ERR_FAILED);
     99     // "this" can be NULL.
    100     return;
    101   }
    102   RespondToReaders(true);
    103 }
    104 
    105 int AndroidUsbSocket::Read(net::IOBuffer* buffer,
    106                            int length,
    107                            const net::CompletionCallback& callback) {
    108   if (!is_connected_)
    109     return is_closed_ ? 0 : net::ERR_SOCKET_NOT_CONNECTED;
    110 
    111   if (read_buffer_.empty()) {
    112     read_requests_.push_back(IORequest(buffer, length, callback));
    113     return net::ERR_IO_PENDING;
    114   }
    115 
    116   size_t bytes_to_copy = static_cast<size_t>(length) > read_buffer_.length() ?
    117       read_buffer_.length() : static_cast<size_t>(length);
    118   memcpy(buffer->data(), read_buffer_.data(), bytes_to_copy);
    119   if (read_buffer_.length() > bytes_to_copy)
    120     read_buffer_ = read_buffer_.substr(bytes_to_copy);
    121   else
    122     read_buffer_ = "";
    123   return net::OK;
    124 }
    125 
    126 int AndroidUsbSocket::Write(net::IOBuffer* buffer,
    127                             int length,
    128                             const net::CompletionCallback& callback) {
    129   if (!is_connected_)
    130     return net::ERR_SOCKET_NOT_CONNECTED;
    131 
    132   if (length > kMaxPayload)
    133     length = kMaxPayload;
    134   write_requests_.push_back(IORequest(NULL, length, callback));
    135   device_->Send(AdbMessage::kCommandWRTE, local_id_, remote_id_,
    136                  std::string(buffer->data(), length));
    137   return net::ERR_IO_PENDING;
    138 }
    139 
    140 bool AndroidUsbSocket::SetReceiveBufferSize(int32 size) {
    141   NOTIMPLEMENTED();
    142   return false;
    143 }
    144 
    145 bool AndroidUsbSocket::SetSendBufferSize(int32 size) {
    146   NOTIMPLEMENTED();
    147   return false;
    148 }
    149 
    150 int AndroidUsbSocket::Connect(const net::CompletionCallback& callback) {
    151   DCHECK(CalledOnValidThread());
    152   if (device_->terminated())
    153     return net::ERR_FAILED;
    154   connect_callback_ = callback;
    155   device_->Send(AdbMessage::kCommandOPEN, local_id_, 0, command_);
    156   return net::ERR_IO_PENDING;
    157 }
    158 
    159 void AndroidUsbSocket::Disconnect() {
    160   is_connected_ = false;
    161   device_->Send(AdbMessage::kCommandCLSE, local_id_, remote_id_, "");
    162   RespondToReaders(true);
    163 }
    164 
    165 bool AndroidUsbSocket::IsConnected() const {
    166   DCHECK(CalledOnValidThread());
    167   return is_connected_;
    168 }
    169 
    170 bool AndroidUsbSocket::IsConnectedAndIdle() const {
    171   NOTIMPLEMENTED();
    172   return false;
    173 }
    174 
    175 int AndroidUsbSocket::GetPeerAddress(net::IPEndPoint* address) const {
    176   net::IPAddressNumber ip(net::kIPv4AddressSize);
    177   *address = net::IPEndPoint(ip, 0);
    178   return net::OK;
    179 }
    180 
    181 int AndroidUsbSocket::GetLocalAddress(net::IPEndPoint* address) const {
    182   NOTIMPLEMENTED();
    183   return net::ERR_FAILED;
    184 }
    185 
    186 const net::BoundNetLog& AndroidUsbSocket::NetLog() const {
    187   return net_log_;
    188 }
    189 
    190 void AndroidUsbSocket::SetSubresourceSpeculation() {
    191   NOTIMPLEMENTED();
    192 }
    193 
    194 void AndroidUsbSocket::SetOmniboxSpeculation() {
    195   NOTIMPLEMENTED();
    196 }
    197 
    198 bool AndroidUsbSocket::WasEverUsed() const {
    199   NOTIMPLEMENTED();
    200   return true;
    201 }
    202 
    203 bool AndroidUsbSocket::UsingTCPFastOpen() const {
    204   NOTIMPLEMENTED();
    205   return true;
    206 }
    207 
    208 bool AndroidUsbSocket::WasNpnNegotiated() const {
    209   NOTIMPLEMENTED();
    210   return true;
    211 }
    212 
    213 net::NextProto AndroidUsbSocket::GetNegotiatedProtocol() const {
    214   NOTIMPLEMENTED();
    215   return net::kProtoUnknown;
    216 }
    217 
    218 bool AndroidUsbSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
    219   return false;
    220 }
    221 
    222 void AndroidUsbSocket::RespondToReaders(bool disconnect) {
    223   std::deque<IORequest> read_requests;
    224   read_requests.swap(read_requests_);
    225   while (!read_requests.empty() && (!read_buffer_.empty() || disconnect)) {
    226     IORequest read_request = read_requests.front();
    227     read_requests.pop_front();
    228     size_t bytes_to_copy =
    229         static_cast<size_t>(read_request.length) > read_buffer_.length() ?
    230             read_buffer_.length() : static_cast<size_t>(read_request.length);
    231     memcpy(read_request.buffer->data(), read_buffer_.data(), bytes_to_copy);
    232     if (read_buffer_.length() > bytes_to_copy)
    233       read_buffer_ = read_buffer_.substr(bytes_to_copy);
    234     else
    235       read_buffer_ = "";
    236     read_request.callback.Run(bytes_to_copy);
    237   }
    238 }
    239 
    240 void AndroidUsbSocket::RespondToWriters() {
    241   if (!write_requests_.empty()) {
    242     IORequest write_request = write_requests_.front();
    243     write_requests_.pop_front();
    244     write_request.callback.Run(write_request.length);
    245   }
    246 }
    247