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 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 is_closed_(false) { 38 } 39 40 AndroidUsbSocket::~AndroidUsbSocket() { 41 DCHECK(CalledOnValidThread()); 42 if (is_connected_) 43 Disconnect(); 44 delete_callback_.Run(local_id_); 45 } 46 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 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 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 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 140 bool AndroidUsbSocket::SetReceiveBufferSize(int32 size) { 141 NOTIMPLEMENTED(); 142 return false; 143 } 144 145 bool AndroidUsbSocket::SetSendBufferSize(int32 size) { 146 NOTIMPLEMENTED(); 147 return false; 148 } 149 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 159 void AndroidUsbSocket::Disconnect() { 160 is_connected_ = false; 161 device_->Send(AdbMessage::kCommandCLSE, local_id_, remote_id_, ""); 162 RespondToReaders(true); 163 } 164 165 bool AndroidUsbSocket::IsConnected() const { 166 DCHECK(CalledOnValidThread()); 167 return is_connected_; 168 } 169 170 bool AndroidUsbSocket::IsConnectedAndIdle() const { 171 NOTIMPLEMENTED(); 172 return false; 173 } 174 175 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 181 int AndroidUsbSocket::GetLocalAddress(net::IPEndPoint* address) const { 182 NOTIMPLEMENTED(); 183 return net::ERR_FAILED; 184 } 185 186 const net::BoundNetLog& AndroidUsbSocket::NetLog() const { 187 return net_log_; 188 } 189 190 void AndroidUsbSocket::SetSubresourceSpeculation() { 191 NOTIMPLEMENTED(); 192 } 193 194 void AndroidUsbSocket::SetOmniboxSpeculation() { 195 NOTIMPLEMENTED(); 196 } 197 198 bool AndroidUsbSocket::WasEverUsed() const { 199 NOTIMPLEMENTED(); 200 return true; 201 } 202 203 bool AndroidUsbSocket::UsingTCPFastOpen() const { 204 NOTIMPLEMENTED(); 205 return true; 206 } 207 208 bool AndroidUsbSocket::WasNpnNegotiated() const { 209 NOTIMPLEMENTED(); 210 return true; 211 } 212 213 net::NextProto AndroidUsbSocket::GetNegotiatedProtocol() const { 214 NOTIMPLEMENTED(); 215 return net::kProtoUnknown; 216 } 217 218 bool AndroidUsbSocket::GetSSLInfo(net::SSLInfo* ssl_info) { 219 return false; 220 } 221 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 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