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 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 24 AndroidUsbSocket::IORequest::~IORequest() { 25 } 26 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 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 47 void AndroidUsbSocket::HandleIncoming(scoped_refptr<AdbMessage> message) { 48 if (!device_.get()) 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(true); 86 // "this" can be NULL. 87 break; 88 default: 89 break; 90 } 91 } 92 93 void AndroidUsbSocket::Terminated(bool closed_by_device) { 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 if (!closed_by_device) 102 return; 103 104 // Respond to pending callbacks. 105 if (!connect_callback_.is_null()) { 106 net::CompletionCallback callback = connect_callback_; 107 connect_callback_.Reset(); 108 callback.Run(net::ERR_FAILED); 109 // "this" can be NULL. 110 return; 111 } 112 RespondToReaders(true); 113 } 114 115 int AndroidUsbSocket::Read(net::IOBuffer* buffer, 116 int length, 117 const net::CompletionCallback& callback) { 118 if (!is_connected_) 119 return device_.get() ? net::ERR_SOCKET_NOT_CONNECTED : 0; 120 121 if (read_buffer_.empty()) { 122 read_requests_.push_back(IORequest(buffer, length, callback)); 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_ = ""; 133 return bytes_to_copy; 134 } 135 136 int AndroidUsbSocket::Write(net::IOBuffer* buffer, 137 int length, 138 const net::CompletionCallback& callback) { 139 if (!is_connected_) 140 return net::ERR_SOCKET_NOT_CONNECTED; 141 142 if (length > kMaxPayload) 143 length = kMaxPayload; 144 write_requests_.push_back(IORequest(NULL, length, callback)); 145 device_->Send(AdbMessage::kCommandWRTE, local_id_, remote_id_, 146 std::string(buffer->data(), length)); 147 return net::ERR_IO_PENDING; 148 } 149 150 int AndroidUsbSocket::SetReceiveBufferSize(int32 size) { 151 NOTIMPLEMENTED(); 152 return net::ERR_NOT_IMPLEMENTED; 153 } 154 155 int AndroidUsbSocket::SetSendBufferSize(int32 size) { 156 NOTIMPLEMENTED(); 157 return net::ERR_NOT_IMPLEMENTED; 158 } 159 160 int AndroidUsbSocket::Connect(const net::CompletionCallback& callback) { 161 DCHECK(CalledOnValidThread()); 162 if (!device_.get()) 163 return net::ERR_FAILED; 164 connect_callback_ = callback; 165 device_->Send(AdbMessage::kCommandOPEN, local_id_, 0, command_); 166 return net::ERR_IO_PENDING; 167 } 168 169 void AndroidUsbSocket::Disconnect() { 170 if (!device_.get()) 171 return; 172 device_->Send(AdbMessage::kCommandCLSE, local_id_, remote_id_, ""); 173 Terminated(false); 174 } 175 176 bool AndroidUsbSocket::IsConnected() const { 177 DCHECK(CalledOnValidThread()); 178 return is_connected_; 179 } 180 181 bool AndroidUsbSocket::IsConnectedAndIdle() const { 182 NOTIMPLEMENTED(); 183 return false; 184 } 185 186 int AndroidUsbSocket::GetPeerAddress(net::IPEndPoint* address) const { 187 net::IPAddressNumber ip(net::kIPv4AddressSize); 188 *address = net::IPEndPoint(ip, 0); 189 return net::OK; 190 } 191 192 int AndroidUsbSocket::GetLocalAddress(net::IPEndPoint* address) const { 193 NOTIMPLEMENTED(); 194 return net::ERR_NOT_IMPLEMENTED; 195 } 196 197 const net::BoundNetLog& AndroidUsbSocket::NetLog() const { 198 return net_log_; 199 } 200 201 void AndroidUsbSocket::SetSubresourceSpeculation() { 202 NOTIMPLEMENTED(); 203 } 204 205 void AndroidUsbSocket::SetOmniboxSpeculation() { 206 NOTIMPLEMENTED(); 207 } 208 209 bool AndroidUsbSocket::WasEverUsed() const { 210 NOTIMPLEMENTED(); 211 return true; 212 } 213 214 bool AndroidUsbSocket::UsingTCPFastOpen() const { 215 NOTIMPLEMENTED(); 216 return true; 217 } 218 219 bool AndroidUsbSocket::WasNpnNegotiated() const { 220 NOTIMPLEMENTED(); 221 return true; 222 } 223 224 net::NextProto AndroidUsbSocket::GetNegotiatedProtocol() const { 225 NOTIMPLEMENTED(); 226 return net::kProtoUnknown; 227 } 228 229 bool AndroidUsbSocket::GetSSLInfo(net::SSLInfo* ssl_info) { 230 return false; 231 } 232 233 void AndroidUsbSocket::RespondToReaders(bool disconnect) { 234 std::deque<IORequest> read_requests; 235 read_requests.swap(read_requests_); 236 while (!read_requests.empty() && (!read_buffer_.empty() || disconnect)) { 237 IORequest read_request = read_requests.front(); 238 read_requests.pop_front(); 239 size_t bytes_to_copy = 240 static_cast<size_t>(read_request.length) > read_buffer_.length() ? 241 read_buffer_.length() : static_cast<size_t>(read_request.length); 242 memcpy(read_request.buffer->data(), read_buffer_.data(), bytes_to_copy); 243 if (read_buffer_.length() > bytes_to_copy) 244 read_buffer_ = read_buffer_.substr(bytes_to_copy); 245 else 246 read_buffer_ = ""; 247 read_request.callback.Run(bytes_to_copy); 248 } 249 } 250 251 void AndroidUsbSocket::RespondToWriters() { 252 if (!write_requests_.empty()) { 253 IORequest write_request = write_requests_.front(); 254 write_requests_.pop_front(); 255 write_request.callback.Run(write_request.length); 256 } 257 } 258