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