1 // Copyright (c) 2013 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/adb/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 is_closed_(false) {
38 }
39
~AndroidUsbSocket()40 AndroidUsbSocket::~AndroidUsbSocket() {
41 DCHECK(CalledOnValidThread());
42 if (is_connected_)
43 Disconnect();
44 delete_callback_.Run(local_id_);
45 }
46
HandleIncoming(scoped_refptr<AdbMessage> message)47 void AndroidUsbSocket::HandleIncoming(scoped_refptr<AdbMessage> message) {
48 CHECK_EQ(message->arg1, local_id_);
49 switch (message->command) {
50 case AdbMessage::kCommandOKAY:
51 if (!is_connected_) {
52 remote_id_ = message->arg0;
53 is_connected_ = true;
54 net::CompletionCallback callback = connect_callback_;
55 connect_callback_.Reset();
56 callback.Run(net::OK);
57 // "this" can be NULL.
58 } else {
59 RespondToWriters();
60 // "this" can be NULL.
61 }
62 break;
63 case AdbMessage::kCommandWRTE:
64 device_->Send(AdbMessage::kCommandOKAY, local_id_, message->arg0, "");
65 read_buffer_ += message->body;
66 // Allow WRTE over new connection even though OKAY ack was not received.
67 if (!is_connected_) {
68 remote_id_ = message->arg0;
69 is_connected_ = true;
70 net::CompletionCallback callback = connect_callback_;
71 connect_callback_.Reset();
72 callback.Run(net::OK);
73 // "this" can be NULL.
74 } else {
75 RespondToReaders(false);
76 // "this" can be NULL.
77 }
78 break;
79 case AdbMessage::kCommandCLSE:
80 if (is_connected_)
81 device_->Send(AdbMessage::kCommandCLSE, local_id_, 0, "");
82 is_connected_ = false;
83 is_closed_ = true;
84 RespondToReaders(true);
85 // "this" can be NULL.
86 break;
87 default:
88 break;
89 }
90 }
91
Terminated()92 void AndroidUsbSocket::Terminated() {
93 is_connected_ = false;
94 is_closed_ = true;
95 if (!connect_callback_.is_null()) {
96 net::CompletionCallback callback = connect_callback_;
97 connect_callback_.Reset();
98 callback.Run(net::ERR_FAILED);
99 // "this" can be NULL.
100 return;
101 }
102 RespondToReaders(true);
103 }
104
Read(net::IOBuffer * buffer,int length,const net::CompletionCallback & callback)105 int AndroidUsbSocket::Read(net::IOBuffer* buffer,
106 int length,
107 const net::CompletionCallback& callback) {
108 if (!is_connected_)
109 return is_closed_ ? 0 : net::ERR_SOCKET_NOT_CONNECTED;
110
111 if (read_buffer_.empty()) {
112 read_requests_.push_back(IORequest(buffer, length, callback));
113 return net::ERR_IO_PENDING;
114 }
115
116 size_t bytes_to_copy = static_cast<size_t>(length) > read_buffer_.length() ?
117 read_buffer_.length() : static_cast<size_t>(length);
118 memcpy(buffer->data(), read_buffer_.data(), bytes_to_copy);
119 if (read_buffer_.length() > bytes_to_copy)
120 read_buffer_ = read_buffer_.substr(bytes_to_copy);
121 else
122 read_buffer_ = "";
123 return bytes_to_copy;
124 }
125
Write(net::IOBuffer * buffer,int length,const net::CompletionCallback & callback)126 int AndroidUsbSocket::Write(net::IOBuffer* buffer,
127 int length,
128 const net::CompletionCallback& callback) {
129 if (!is_connected_)
130 return net::ERR_SOCKET_NOT_CONNECTED;
131
132 if (length > kMaxPayload)
133 length = kMaxPayload;
134 write_requests_.push_back(IORequest(NULL, length, callback));
135 device_->Send(AdbMessage::kCommandWRTE, local_id_, remote_id_,
136 std::string(buffer->data(), length));
137 return net::ERR_IO_PENDING;
138 }
139
SetReceiveBufferSize(int32 size)140 bool AndroidUsbSocket::SetReceiveBufferSize(int32 size) {
141 NOTIMPLEMENTED();
142 return false;
143 }
144
SetSendBufferSize(int32 size)145 bool AndroidUsbSocket::SetSendBufferSize(int32 size) {
146 NOTIMPLEMENTED();
147 return false;
148 }
149
Connect(const net::CompletionCallback & callback)150 int AndroidUsbSocket::Connect(const net::CompletionCallback& callback) {
151 DCHECK(CalledOnValidThread());
152 if (device_->terminated())
153 return net::ERR_FAILED;
154 connect_callback_ = callback;
155 device_->Send(AdbMessage::kCommandOPEN, local_id_, 0, command_);
156 return net::ERR_IO_PENDING;
157 }
158
Disconnect()159 void AndroidUsbSocket::Disconnect() {
160 is_connected_ = false;
161 device_->Send(AdbMessage::kCommandCLSE, local_id_, remote_id_, "");
162 RespondToReaders(true);
163 }
164
IsConnected() const165 bool AndroidUsbSocket::IsConnected() const {
166 DCHECK(CalledOnValidThread());
167 return is_connected_;
168 }
169
IsConnectedAndIdle() const170 bool AndroidUsbSocket::IsConnectedAndIdle() const {
171 NOTIMPLEMENTED();
172 return false;
173 }
174
GetPeerAddress(net::IPEndPoint * address) const175 int AndroidUsbSocket::GetPeerAddress(net::IPEndPoint* address) const {
176 net::IPAddressNumber ip(net::kIPv4AddressSize);
177 *address = net::IPEndPoint(ip, 0);
178 return net::OK;
179 }
180
GetLocalAddress(net::IPEndPoint * address) const181 int AndroidUsbSocket::GetLocalAddress(net::IPEndPoint* address) const {
182 NOTIMPLEMENTED();
183 return net::ERR_FAILED;
184 }
185
NetLog() const186 const net::BoundNetLog& AndroidUsbSocket::NetLog() const {
187 return net_log_;
188 }
189
SetSubresourceSpeculation()190 void AndroidUsbSocket::SetSubresourceSpeculation() {
191 NOTIMPLEMENTED();
192 }
193
SetOmniboxSpeculation()194 void AndroidUsbSocket::SetOmniboxSpeculation() {
195 NOTIMPLEMENTED();
196 }
197
WasEverUsed() const198 bool AndroidUsbSocket::WasEverUsed() const {
199 NOTIMPLEMENTED();
200 return true;
201 }
202
UsingTCPFastOpen() const203 bool AndroidUsbSocket::UsingTCPFastOpen() const {
204 NOTIMPLEMENTED();
205 return true;
206 }
207
WasNpnNegotiated() const208 bool AndroidUsbSocket::WasNpnNegotiated() const {
209 NOTIMPLEMENTED();
210 return true;
211 }
212
GetNegotiatedProtocol() const213 net::NextProto AndroidUsbSocket::GetNegotiatedProtocol() const {
214 NOTIMPLEMENTED();
215 return net::kProtoUnknown;
216 }
217
GetSSLInfo(net::SSLInfo * ssl_info)218 bool AndroidUsbSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
219 return false;
220 }
221
RespondToReaders(bool disconnect)222 void AndroidUsbSocket::RespondToReaders(bool disconnect) {
223 std::deque<IORequest> read_requests;
224 read_requests.swap(read_requests_);
225 while (!read_requests.empty() && (!read_buffer_.empty() || disconnect)) {
226 IORequest read_request = read_requests.front();
227 read_requests.pop_front();
228 size_t bytes_to_copy =
229 static_cast<size_t>(read_request.length) > read_buffer_.length() ?
230 read_buffer_.length() : static_cast<size_t>(read_request.length);
231 memcpy(read_request.buffer->data(), read_buffer_.data(), bytes_to_copy);
232 if (read_buffer_.length() > bytes_to_copy)
233 read_buffer_ = read_buffer_.substr(bytes_to_copy);
234 else
235 read_buffer_ = "";
236 read_request.callback.Run(bytes_to_copy);
237 }
238 }
239
RespondToWriters()240 void AndroidUsbSocket::RespondToWriters() {
241 if (!write_requests_.empty()) {
242 IORequest write_request = write_requests_.front();
243 write_requests_.pop_front();
244 write_request.callback.Run(write_request.length);
245 }
246 }
247