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 <stddef.h>
8 
9 #include "base/callback_helpers.h"
10 #include "base/check_op.h"
11 #include "base/notreached.h"
12 #include "net/base/io_buffer.h"
13 #include "net/base/ip_address.h"
14 #include "net/base/net_errors.h"
15 #include "net/traffic_annotation/network_traffic_annotation.h"
16 
17 namespace {
18 
19 const int kMaxPayload = 4096;
20 
21 }  // namespace
22 
AndroidUsbSocket(scoped_refptr<AndroidUsbDevice> device,uint32_t socket_id,const std::string & command,base::Closure delete_callback)23 AndroidUsbSocket::AndroidUsbSocket(scoped_refptr<AndroidUsbDevice> device,
24                                    uint32_t socket_id,
25                                    const std::string& command,
26                                    base::Closure delete_callback)
27     : device_(device),
28       command_(command),
29       local_id_(socket_id),
30       remote_id_(0),
31       is_connected_(false),
32       delete_callback_(delete_callback) {}
33 
~AndroidUsbSocket()34 AndroidUsbSocket::~AndroidUsbSocket() {
35   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
36   if (is_connected_)
37     Disconnect();
38   if (!delete_callback_.is_null())
39     delete_callback_.Run();
40 }
41 
HandleIncoming(std::unique_ptr<AdbMessage> message)42 void AndroidUsbSocket::HandleIncoming(std::unique_ptr<AdbMessage> message) {
43   if (!device_.get())
44     return;
45 
46   CHECK_EQ(message->arg1, local_id_);
47   switch (message->command) {
48     case AdbMessage::kCommandOKAY:
49       if (!is_connected_) {
50         remote_id_ = message->arg0;
51         is_connected_ = true;
52         if (!connect_callback_.is_null())
53           std::move(connect_callback_).Run(net::OK);
54         // "this" can be deleted.
55       } else {
56         RespondToWriter(write_length_);
57         // "this" can be deleted.
58       }
59       break;
60     case AdbMessage::kCommandWRTE:
61       device_->Send(AdbMessage::kCommandOKAY, local_id_, message->arg0, "");
62       read_buffer_ += message->body;
63       // Allow WRTE over new connection even though OKAY ack was not received.
64       if (!is_connected_) {
65         remote_id_ = message->arg0;
66         is_connected_ = true;
67         if (!connect_callback_.is_null())
68           std::move(connect_callback_).Run(net::OK);
69         // "this" can be deleted.
70       } else {
71         RespondToReader(false);
72         // "this" can be deleted.
73       }
74       break;
75     case AdbMessage::kCommandCLSE:
76       if (is_connected_)
77         device_->Send(AdbMessage::kCommandCLSE, local_id_, 0, "");
78       Terminated(true);
79       // "this" can be deleted.
80       break;
81     default:
82       break;
83   }
84 }
85 
Terminated(bool closed_by_device)86 void AndroidUsbSocket::Terminated(bool closed_by_device) {
87   is_connected_ = false;
88 
89   // Break the socket -> device connection, release the device.
90   device_ = nullptr;
91   std::move(delete_callback_).Run();
92 
93   if (!closed_by_device)
94     return;
95 
96   // Respond to pending callbacks.
97   if (!connect_callback_.is_null()) {
98     std::move(connect_callback_).Run(net::ERR_FAILED);
99     // "this" can be deleted.
100     return;
101   }
102   base::WeakPtr<AndroidUsbSocket> weak_this = weak_factory_.GetWeakPtr();
103   RespondToReader(true);
104   // "this" can be deleted.
105   if (weak_this) {
106     RespondToWriter(net::ERR_FAILED);
107     // "this" can be deleted.
108   }
109 }
110 
Read(net::IOBuffer * buffer,int length,net::CompletionOnceCallback callback)111 int AndroidUsbSocket::Read(net::IOBuffer* buffer,
112                            int length,
113                            net::CompletionOnceCallback callback) {
114   DCHECK(!callback.is_null());
115   if (!is_connected_)
116     return device_.get() ? net::ERR_SOCKET_NOT_CONNECTED : 0;
117 
118   DCHECK(read_callback_.is_null());
119   if (read_buffer_.empty()) {
120     read_callback_ = std::move(callback);
121     read_io_buffer_ = buffer;
122     read_length_ = length;
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_ = std::string();
133   return bytes_to_copy;
134 }
135 
Write(net::IOBuffer * buffer,int length,net::CompletionOnceCallback callback,const net::NetworkTrafficAnnotationTag &)136 int AndroidUsbSocket::Write(
137     net::IOBuffer* buffer,
138     int length,
139     net::CompletionOnceCallback callback,
140     const net::NetworkTrafficAnnotationTag& /*traffic_annotation*/) {
141   DCHECK(!callback.is_null());
142   if (!is_connected_)
143     return net::ERR_SOCKET_NOT_CONNECTED;
144 
145   if (length > kMaxPayload)
146     length = kMaxPayload;
147 
148   DCHECK(write_callback_.is_null());
149   write_callback_ = std::move(callback);
150   write_length_ = length;
151   device_->Send(AdbMessage::kCommandWRTE, local_id_, remote_id_,
152                 std::string(buffer->data(), length));
153   return net::ERR_IO_PENDING;
154 }
155 
SetReceiveBufferSize(int32_t size)156 int AndroidUsbSocket::SetReceiveBufferSize(int32_t size) {
157   NOTIMPLEMENTED();
158   return net::ERR_NOT_IMPLEMENTED;
159 }
160 
SetSendBufferSize(int32_t size)161 int AndroidUsbSocket::SetSendBufferSize(int32_t size) {
162   NOTIMPLEMENTED();
163   return net::ERR_NOT_IMPLEMENTED;
164 }
165 
Connect(net::CompletionOnceCallback callback)166 int AndroidUsbSocket::Connect(net::CompletionOnceCallback callback) {
167   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
168   DCHECK(!callback.is_null());
169   if (!device_.get())
170     return net::ERR_FAILED;
171 
172   DCHECK(!is_connected_);
173   DCHECK(connect_callback_.is_null());
174   connect_callback_ = std::move(callback);
175   device_->Send(AdbMessage::kCommandOPEN, local_id_, 0, command_);
176   return net::ERR_IO_PENDING;
177 }
178 
Disconnect()179 void AndroidUsbSocket::Disconnect() {
180   if (!device_.get())
181     return;
182   device_->Send(AdbMessage::kCommandCLSE, local_id_, remote_id_, "");
183   Terminated(false);
184 }
185 
IsConnected() const186 bool AndroidUsbSocket::IsConnected() const {
187   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
188   return is_connected_;
189 }
190 
IsConnectedAndIdle() const191 bool AndroidUsbSocket::IsConnectedAndIdle() const {
192   NOTIMPLEMENTED();
193   return false;
194 }
195 
GetPeerAddress(net::IPEndPoint * address) const196 int AndroidUsbSocket::GetPeerAddress(net::IPEndPoint* address) const {
197   *address = net::IPEndPoint(net::IPAddress(0, 0, 0, 0), 0);
198   return net::OK;
199 }
200 
GetLocalAddress(net::IPEndPoint * address) const201 int AndroidUsbSocket::GetLocalAddress(net::IPEndPoint* address) const {
202   NOTIMPLEMENTED();
203   return net::ERR_NOT_IMPLEMENTED;
204 }
205 
NetLog() const206 const net::NetLogWithSource& AndroidUsbSocket::NetLog() const {
207   return net_log_;
208 }
209 
WasEverUsed() const210 bool AndroidUsbSocket::WasEverUsed() const {
211   NOTIMPLEMENTED();
212   return true;
213 }
214 
WasAlpnNegotiated() const215 bool AndroidUsbSocket::WasAlpnNegotiated() const {
216   NOTIMPLEMENTED();
217   return true;
218 }
219 
GetNegotiatedProtocol() const220 net::NextProto AndroidUsbSocket::GetNegotiatedProtocol() const {
221   NOTIMPLEMENTED();
222   return net::kProtoUnknown;
223 }
224 
GetSSLInfo(net::SSLInfo * ssl_info)225 bool AndroidUsbSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
226   return false;
227 }
228 
GetConnectionAttempts(net::ConnectionAttempts * out) const229 void AndroidUsbSocket::GetConnectionAttempts(
230     net::ConnectionAttempts* out) const {
231   out->clear();
232 }
233 
GetTotalReceivedBytes() const234 int64_t AndroidUsbSocket::GetTotalReceivedBytes() const {
235   NOTIMPLEMENTED();
236   return 0;
237 }
238 
ApplySocketTag(const net::SocketTag & tag)239 void AndroidUsbSocket::ApplySocketTag(const net::SocketTag& tag) {
240   NOTIMPLEMENTED();
241 }
242 
RespondToReader(bool disconnect)243 void AndroidUsbSocket::RespondToReader(bool disconnect) {
244   if (read_callback_.is_null() || (read_buffer_.empty() && !disconnect))
245     return;
246   size_t bytes_to_copy =
247       static_cast<size_t>(read_length_) > read_buffer_.length() ?
248           read_buffer_.length() : static_cast<size_t>(read_length_);
249   memcpy(read_io_buffer_->data(), read_buffer_.data(), bytes_to_copy);
250   if (read_buffer_.length() > bytes_to_copy)
251     read_buffer_ = read_buffer_.substr(bytes_to_copy);
252   else
253     read_buffer_ = std::string();
254   std::move(read_callback_).Run(bytes_to_copy);
255 }
256 
RespondToWriter(int result)257 void AndroidUsbSocket::RespondToWriter(int result) {
258   if (!write_callback_.is_null())
259     std::move(write_callback_).Run(result);
260 }
261