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