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