• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
IORequest(net::IOBuffer * buffer,int length,const net::CompletionCallback & callback)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 
~IORequest()24 AndroidUsbSocket::IORequest::~IORequest() {
25 }
26 
AndroidUsbSocket(scoped_refptr<AndroidUsbDevice> device,uint32 socket_id,const std::string & command,base::Callback<void (uint32)> delete_callback)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 
~AndroidUsbSocket()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 
HandleIncoming(scoped_refptr<AdbMessage> message)47 void AndroidUsbSocket::HandleIncoming(scoped_refptr<AdbMessage> message) {
48   if (!device_)
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();
86       // "this" can be NULL.
87       break;
88     default:
89       break;
90   }
91 }
92 
Terminated()93 void AndroidUsbSocket::Terminated() {
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   // Respond to pending callbacks.
102   if (!connect_callback_.is_null()) {
103     net::CompletionCallback callback = connect_callback_;
104     connect_callback_.Reset();
105     callback.Run(net::ERR_FAILED);
106     // "this" can be NULL.
107     return;
108   }
109   RespondToReaders(true);
110 }
111 
Read(net::IOBuffer * buffer,int length,const net::CompletionCallback & callback)112 int AndroidUsbSocket::Read(net::IOBuffer* buffer,
113                            int length,
114                            const net::CompletionCallback& callback) {
115   if (!is_connected_)
116     return device_ ? net::ERR_SOCKET_NOT_CONNECTED : 0;
117 
118   if (read_buffer_.empty()) {
119     read_requests_.push_back(IORequest(buffer, length, callback));
120     return net::ERR_IO_PENDING;
121   }
122 
123   size_t bytes_to_copy = static_cast<size_t>(length) > read_buffer_.length() ?
124       read_buffer_.length() : static_cast<size_t>(length);
125   memcpy(buffer->data(), read_buffer_.data(), bytes_to_copy);
126   if (read_buffer_.length() > bytes_to_copy)
127     read_buffer_ = read_buffer_.substr(bytes_to_copy);
128   else
129     read_buffer_ = "";
130   return bytes_to_copy;
131 }
132 
Write(net::IOBuffer * buffer,int length,const net::CompletionCallback & callback)133 int AndroidUsbSocket::Write(net::IOBuffer* buffer,
134                             int length,
135                             const net::CompletionCallback& callback) {
136   if (!is_connected_)
137     return net::ERR_SOCKET_NOT_CONNECTED;
138 
139   if (length > kMaxPayload)
140     length = kMaxPayload;
141   write_requests_.push_back(IORequest(NULL, length, callback));
142   device_->Send(AdbMessage::kCommandWRTE, local_id_, remote_id_,
143                  std::string(buffer->data(), length));
144   return net::ERR_IO_PENDING;
145 }
146 
SetReceiveBufferSize(int32 size)147 int AndroidUsbSocket::SetReceiveBufferSize(int32 size) {
148   NOTIMPLEMENTED();
149   return net::ERR_NOT_IMPLEMENTED;
150 }
151 
SetSendBufferSize(int32 size)152 int AndroidUsbSocket::SetSendBufferSize(int32 size) {
153   NOTIMPLEMENTED();
154   return net::ERR_NOT_IMPLEMENTED;
155 }
156 
Connect(const net::CompletionCallback & callback)157 int AndroidUsbSocket::Connect(const net::CompletionCallback& callback) {
158   DCHECK(CalledOnValidThread());
159   if (!device_)
160     return net::ERR_FAILED;
161   connect_callback_ = callback;
162   device_->Send(AdbMessage::kCommandOPEN, local_id_, 0, command_);
163   return net::ERR_IO_PENDING;
164 }
165 
Disconnect()166 void AndroidUsbSocket::Disconnect() {
167   if (!device_)
168     return;
169   device_->Send(AdbMessage::kCommandCLSE, local_id_, remote_id_, "");
170   Terminated();
171 }
172 
IsConnected() const173 bool AndroidUsbSocket::IsConnected() const {
174   DCHECK(CalledOnValidThread());
175   return is_connected_;
176 }
177 
IsConnectedAndIdle() const178 bool AndroidUsbSocket::IsConnectedAndIdle() const {
179   NOTIMPLEMENTED();
180   return false;
181 }
182 
GetPeerAddress(net::IPEndPoint * address) const183 int AndroidUsbSocket::GetPeerAddress(net::IPEndPoint* address) const {
184   net::IPAddressNumber ip(net::kIPv4AddressSize);
185   *address = net::IPEndPoint(ip, 0);
186   return net::OK;
187 }
188 
GetLocalAddress(net::IPEndPoint * address) const189 int AndroidUsbSocket::GetLocalAddress(net::IPEndPoint* address) const {
190   NOTIMPLEMENTED();
191   return net::ERR_NOT_IMPLEMENTED;
192 }
193 
NetLog() const194 const net::BoundNetLog& AndroidUsbSocket::NetLog() const {
195   return net_log_;
196 }
197 
SetSubresourceSpeculation()198 void AndroidUsbSocket::SetSubresourceSpeculation() {
199   NOTIMPLEMENTED();
200 }
201 
SetOmniboxSpeculation()202 void AndroidUsbSocket::SetOmniboxSpeculation() {
203   NOTIMPLEMENTED();
204 }
205 
WasEverUsed() const206 bool AndroidUsbSocket::WasEverUsed() const {
207   NOTIMPLEMENTED();
208   return true;
209 }
210 
UsingTCPFastOpen() const211 bool AndroidUsbSocket::UsingTCPFastOpen() const {
212   NOTIMPLEMENTED();
213   return true;
214 }
215 
WasNpnNegotiated() const216 bool AndroidUsbSocket::WasNpnNegotiated() const {
217   NOTIMPLEMENTED();
218   return true;
219 }
220 
GetNegotiatedProtocol() const221 net::NextProto AndroidUsbSocket::GetNegotiatedProtocol() const {
222   NOTIMPLEMENTED();
223   return net::kProtoUnknown;
224 }
225 
GetSSLInfo(net::SSLInfo * ssl_info)226 bool AndroidUsbSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
227   return false;
228 }
229 
RespondToReaders(bool disconnect)230 void AndroidUsbSocket::RespondToReaders(bool disconnect) {
231   std::deque<IORequest> read_requests;
232   read_requests.swap(read_requests_);
233   while (!read_requests.empty() && (!read_buffer_.empty() || disconnect)) {
234     IORequest read_request = read_requests.front();
235     read_requests.pop_front();
236     size_t bytes_to_copy =
237         static_cast<size_t>(read_request.length) > read_buffer_.length() ?
238             read_buffer_.length() : static_cast<size_t>(read_request.length);
239     memcpy(read_request.buffer->data(), read_buffer_.data(), bytes_to_copy);
240     if (read_buffer_.length() > bytes_to_copy)
241       read_buffer_ = read_buffer_.substr(bytes_to_copy);
242     else
243       read_buffer_ = "";
244     read_request.callback.Run(bytes_to_copy);
245   }
246 }
247 
RespondToWriters()248 void AndroidUsbSocket::RespondToWriters() {
249   if (!write_requests_.empty()) {
250     IORequest write_request = write_requests_.front();
251     write_requests_.pop_front();
252     write_request.callback.Run(write_request.length);
253   }
254 }
255