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 "device/bluetooth/bluetooth_socket_net.h" 6 7 #include <queue> 8 #include <string> 9 10 #include "base/logging.h" 11 #include "base/memory/linked_ptr.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/sequenced_task_runner.h" 15 #include "base/threading/thread_restrictions.h" 16 #include "device/bluetooth/bluetooth_socket.h" 17 #include "device/bluetooth/bluetooth_socket_thread.h" 18 #include "net/base/io_buffer.h" 19 #include "net/base/net_errors.h" 20 21 namespace { 22 23 const char kSocketNotConnected[] = "Socket is not connected."; 24 25 static void DeactivateSocket( 26 const scoped_refptr<device::BluetoothSocketThread>& socket_thread) { 27 socket_thread->OnSocketDeactivate(); 28 } 29 30 } // namespace 31 32 namespace device { 33 34 BluetoothSocketNet::WriteRequest::WriteRequest() 35 : buffer_size(0) {} 36 37 BluetoothSocketNet::WriteRequest::~WriteRequest() {} 38 39 BluetoothSocketNet::BluetoothSocketNet( 40 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, 41 scoped_refptr<BluetoothSocketThread> socket_thread, 42 net::NetLog* net_log, 43 const net::NetLog::Source& source) 44 : ui_task_runner_(ui_task_runner), 45 socket_thread_(socket_thread), 46 net_log_(net_log), 47 source_(source) { 48 DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); 49 socket_thread_->OnSocketActivate(); 50 } 51 52 BluetoothSocketNet::~BluetoothSocketNet() { 53 DCHECK(tcp_socket_.get() == NULL); 54 ui_task_runner_->PostTask(FROM_HERE, 55 base::Bind(&DeactivateSocket, socket_thread_)); 56 } 57 58 void BluetoothSocketNet::Close() { 59 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); 60 socket_thread_->task_runner()->PostTask( 61 FROM_HERE, base::Bind(&BluetoothSocketNet::DoClose, this)); 62 } 63 64 void BluetoothSocketNet::Disconnect( 65 const base::Closure& success_callback) { 66 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); 67 socket_thread_->task_runner()->PostTask( 68 FROM_HERE, 69 base::Bind( 70 &BluetoothSocketNet::DoDisconnect, 71 this, 72 base::Bind(&BluetoothSocketNet::PostSuccess, 73 this, 74 success_callback))); 75 } 76 77 void BluetoothSocketNet::Receive( 78 int buffer_size, 79 const ReceiveCompletionCallback& success_callback, 80 const ReceiveErrorCompletionCallback& error_callback) { 81 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); 82 socket_thread_->task_runner()->PostTask( 83 FROM_HERE, 84 base::Bind( 85 &BluetoothSocketNet::DoReceive, 86 this, 87 buffer_size, 88 base::Bind(&BluetoothSocketNet::PostReceiveCompletion, 89 this, 90 success_callback), 91 base::Bind(&BluetoothSocketNet::PostReceiveErrorCompletion, 92 this, 93 error_callback))); 94 } 95 96 void BluetoothSocketNet::Send( 97 scoped_refptr<net::IOBuffer> buffer, 98 int buffer_size, 99 const SendCompletionCallback& success_callback, 100 const ErrorCompletionCallback& error_callback) { 101 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); 102 socket_thread_->task_runner()->PostTask( 103 FROM_HERE, 104 base::Bind( 105 &BluetoothSocketNet::DoSend, 106 this, 107 buffer, 108 buffer_size, 109 base::Bind(&BluetoothSocketNet::PostSendCompletion, 110 this, 111 success_callback), 112 base::Bind(&BluetoothSocketNet::PostErrorCompletion, 113 this, 114 error_callback))); 115 } 116 117 void BluetoothSocketNet::ResetData() { 118 } 119 120 void BluetoothSocketNet::ResetTCPSocket() { 121 tcp_socket_.reset(new net::TCPSocket(net_log_, source_)); 122 } 123 124 void BluetoothSocketNet::SetTCPSocket(scoped_ptr<net::TCPSocket> tcp_socket) { 125 tcp_socket_ = tcp_socket.Pass(); 126 } 127 128 void BluetoothSocketNet::PostSuccess(const base::Closure& callback) { 129 ui_task_runner_->PostTask(FROM_HERE, callback); 130 } 131 132 void BluetoothSocketNet::PostErrorCompletion( 133 const ErrorCompletionCallback& callback, 134 const std::string& error) { 135 ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, error)); 136 } 137 138 void BluetoothSocketNet::DoClose() { 139 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); 140 base::ThreadRestrictions::AssertIOAllowed(); 141 142 if (tcp_socket_) { 143 tcp_socket_->Close(); 144 tcp_socket_.reset(NULL); 145 } 146 147 // Note: Closing |tcp_socket_| above released all potential pending 148 // Send/Receive operations, so we can no safely release the state associated 149 // to those pending operations. 150 read_buffer_ = NULL; 151 std::queue<linked_ptr<WriteRequest> > empty; 152 std::swap(write_queue_, empty); 153 154 ResetData(); 155 } 156 157 void BluetoothSocketNet::DoDisconnect(const base::Closure& callback) { 158 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); 159 base::ThreadRestrictions::AssertIOAllowed(); 160 161 DoClose(); 162 callback.Run(); 163 } 164 165 void BluetoothSocketNet::DoReceive( 166 int buffer_size, 167 const ReceiveCompletionCallback& success_callback, 168 const ReceiveErrorCompletionCallback& error_callback) { 169 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); 170 base::ThreadRestrictions::AssertIOAllowed(); 171 172 if (!tcp_socket_) { 173 error_callback.Run(BluetoothSocket::kDisconnected, kSocketNotConnected); 174 return; 175 } 176 177 // Only one pending read at a time 178 if (read_buffer_.get()) { 179 error_callback.Run(BluetoothSocket::kIOPending, 180 net::ErrorToString(net::ERR_IO_PENDING)); 181 return; 182 } 183 184 scoped_refptr<net::IOBufferWithSize> buffer( 185 new net::IOBufferWithSize(buffer_size)); 186 int read_result = 187 tcp_socket_->Read(buffer.get(), 188 buffer->size(), 189 base::Bind(&BluetoothSocketNet::OnSocketReadComplete, 190 this, 191 success_callback, 192 error_callback)); 193 194 read_buffer_ = buffer; 195 if (read_result != net::ERR_IO_PENDING) 196 OnSocketReadComplete(success_callback, error_callback, read_result); 197 } 198 199 void BluetoothSocketNet::OnSocketReadComplete( 200 const ReceiveCompletionCallback& success_callback, 201 const ReceiveErrorCompletionCallback& error_callback, 202 int read_result) { 203 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); 204 base::ThreadRestrictions::AssertIOAllowed(); 205 206 scoped_refptr<net::IOBufferWithSize> buffer; 207 buffer.swap(read_buffer_); 208 if (read_result > 0) { 209 success_callback.Run(read_result, buffer); 210 } else if (read_result == net::OK || 211 read_result == net::ERR_CONNECTION_CLOSED || 212 read_result == net::ERR_CONNECTION_RESET) { 213 error_callback.Run(BluetoothSocket::kDisconnected, 214 net::ErrorToString(read_result)); 215 } else { 216 error_callback.Run(BluetoothSocket::kSystemError, 217 net::ErrorToString(read_result)); 218 } 219 } 220 221 void BluetoothSocketNet::DoSend( 222 scoped_refptr<net::IOBuffer> buffer, 223 int buffer_size, 224 const SendCompletionCallback& success_callback, 225 const ErrorCompletionCallback& error_callback) { 226 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); 227 base::ThreadRestrictions::AssertIOAllowed(); 228 229 if (!tcp_socket_) { 230 error_callback.Run(kSocketNotConnected); 231 return; 232 } 233 234 linked_ptr<WriteRequest> request(new WriteRequest()); 235 request->buffer = buffer; 236 request->buffer_size = buffer_size; 237 request->success_callback = success_callback; 238 request->error_callback = error_callback; 239 240 write_queue_.push(request); 241 if (write_queue_.size() == 1) { 242 SendFrontWriteRequest(); 243 } 244 } 245 246 void BluetoothSocketNet::SendFrontWriteRequest() { 247 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); 248 base::ThreadRestrictions::AssertIOAllowed(); 249 250 if (!tcp_socket_) 251 return; 252 253 if (write_queue_.size() == 0) 254 return; 255 256 linked_ptr<WriteRequest> request = write_queue_.front(); 257 net::CompletionCallback callback = 258 base::Bind(&BluetoothSocketNet::OnSocketWriteComplete, 259 this, 260 request->success_callback, 261 request->error_callback); 262 int send_result = 263 tcp_socket_->Write(request->buffer, request->buffer_size, callback); 264 if (send_result != net::ERR_IO_PENDING) { 265 callback.Run(send_result); 266 } 267 } 268 269 void BluetoothSocketNet::OnSocketWriteComplete( 270 const SendCompletionCallback& success_callback, 271 const ErrorCompletionCallback& error_callback, 272 int send_result) { 273 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); 274 base::ThreadRestrictions::AssertIOAllowed(); 275 276 write_queue_.pop(); 277 278 if (send_result >= net::OK) { 279 success_callback.Run(send_result); 280 } else { 281 error_callback.Run(net::ErrorToString(send_result)); 282 } 283 284 // Don't call directly to avoid potentail large recursion. 285 socket_thread_->task_runner()->PostNonNestableTask( 286 FROM_HERE, 287 base::Bind(&BluetoothSocketNet::SendFrontWriteRequest, this)); 288 } 289 290 void BluetoothSocketNet::PostReceiveCompletion( 291 const ReceiveCompletionCallback& callback, 292 int io_buffer_size, 293 scoped_refptr<net::IOBuffer> io_buffer) { 294 ui_task_runner_->PostTask(FROM_HERE, 295 base::Bind(callback, io_buffer_size, io_buffer)); 296 } 297 298 void BluetoothSocketNet::PostReceiveErrorCompletion( 299 const ReceiveErrorCompletionCallback& callback, 300 ErrorReason reason, 301 const std::string& error_message) { 302 ui_task_runner_->PostTask(FROM_HERE, 303 base::Bind(callback, reason, error_message)); 304 } 305 306 void BluetoothSocketNet::PostSendCompletion( 307 const SendCompletionCallback& callback, 308 int bytes_written) { 309 ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, bytes_written)); 310 } 311 312 } // namespace device 313