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