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