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.
5 #include "device/bluetooth/bluetooth_socket_net.h"
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"
23 const char kSocketNotConnected
[] = "Socket is not connected.";
25 static void DeactivateSocket(
26 const scoped_refptr
<device::BluetoothSocketThread
>& socket_thread
) {
27 socket_thread
->OnSocketDeactivate();
34 BluetoothSocketNet::WriteRequest::WriteRequest()
37 BluetoothSocketNet::WriteRequest::~WriteRequest() {}
39 BluetoothSocketNet::BluetoothSocketNet(
40 scoped_refptr
<base::SequencedTaskRunner
> ui_task_runner
,
41 scoped_refptr
<BluetoothSocketThread
> socket_thread
,
43 const net::NetLog::Source
& source
)
44 : ui_task_runner_(ui_task_runner
),
45 socket_thread_(socket_thread
),
48 DCHECK(ui_task_runner
->RunsTasksOnCurrentThread());
49 socket_thread_
->OnSocketActivate();
52 BluetoothSocketNet::~BluetoothSocketNet() {
53 DCHECK(tcp_socket_
.get() == NULL
);
54 ui_task_runner_
->PostTask(FROM_HERE
,
55 base::Bind(&DeactivateSocket
, socket_thread_
));
58 void BluetoothSocketNet::Close() {
59 DCHECK(ui_task_runner_
->RunsTasksOnCurrentThread());
60 socket_thread_
->task_runner()->PostTask(
61 FROM_HERE
, base::Bind(&BluetoothSocketNet::DoClose
, this));
64 void BluetoothSocketNet::Disconnect(
65 const base::Closure
& success_callback
) {
66 DCHECK(ui_task_runner_
->RunsTasksOnCurrentThread());
67 socket_thread_
->task_runner()->PostTask(
70 &BluetoothSocketNet::DoDisconnect
,
72 base::Bind(&BluetoothSocketNet::PostSuccess
,
77 void BluetoothSocketNet::Receive(
79 const ReceiveCompletionCallback
& success_callback
,
80 const ReceiveErrorCompletionCallback
& error_callback
) {
81 DCHECK(ui_task_runner_
->RunsTasksOnCurrentThread());
82 socket_thread_
->task_runner()->PostTask(
85 &BluetoothSocketNet::DoReceive
,
88 base::Bind(&BluetoothSocketNet::PostReceiveCompletion
,
91 base::Bind(&BluetoothSocketNet::PostReceiveErrorCompletion
,
96 void BluetoothSocketNet::Send(
97 scoped_refptr
<net::IOBuffer
> buffer
,
99 const SendCompletionCallback
& success_callback
,
100 const ErrorCompletionCallback
& error_callback
) {
101 DCHECK(ui_task_runner_
->RunsTasksOnCurrentThread());
102 socket_thread_
->task_runner()->PostTask(
105 &BluetoothSocketNet::DoSend
,
109 base::Bind(&BluetoothSocketNet::PostSendCompletion
,
112 base::Bind(&BluetoothSocketNet::PostErrorCompletion
,
117 void BluetoothSocketNet::ResetData() {
120 void BluetoothSocketNet::ResetTCPSocket() {
121 tcp_socket_
.reset(new net::TCPSocket(net_log_
, source_
));
124 void BluetoothSocketNet::SetTCPSocket(scoped_ptr
<net::TCPSocket
> tcp_socket
) {
125 tcp_socket_
= tcp_socket
.Pass();
128 void BluetoothSocketNet::PostSuccess(const base::Closure
& callback
) {
129 ui_task_runner_
->PostTask(FROM_HERE
, callback
);
132 void BluetoothSocketNet::PostErrorCompletion(
133 const ErrorCompletionCallback
& callback
,
134 const std::string
& error
) {
135 ui_task_runner_
->PostTask(FROM_HERE
, base::Bind(callback
, error
));
138 void BluetoothSocketNet::DoClose() {
139 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
140 base::ThreadRestrictions::AssertIOAllowed();
143 tcp_socket_
->Close();
144 tcp_socket_
.reset(NULL
);
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.
151 std::queue
<linked_ptr
<WriteRequest
> > empty
;
152 std::swap(write_queue_
, empty
);
157 void BluetoothSocketNet::DoDisconnect(const base::Closure
& callback
) {
158 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
159 base::ThreadRestrictions::AssertIOAllowed();
165 void BluetoothSocketNet::DoReceive(
167 const ReceiveCompletionCallback
& success_callback
,
168 const ReceiveErrorCompletionCallback
& error_callback
) {
169 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
170 base::ThreadRestrictions::AssertIOAllowed();
173 error_callback
.Run(BluetoothSocket::kDisconnected
, kSocketNotConnected
);
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
));
184 scoped_refptr
<net::IOBufferWithSize
> buffer(
185 new net::IOBufferWithSize(buffer_size
));
187 tcp_socket_
->Read(buffer
.get(),
189 base::Bind(&BluetoothSocketNet::OnSocketReadComplete
,
194 if (read_result
> 0) {
195 success_callback
.Run(read_result
, buffer
);
196 } else if (read_result
== net::OK
||
197 read_result
== net::ERR_CONNECTION_CLOSED
) {
198 error_callback
.Run(BluetoothSocket::kDisconnected
,
199 net::ErrorToString(net::ERR_CONNECTION_CLOSED
));
200 } else if (read_result
== net::ERR_IO_PENDING
) {
201 read_buffer_
= buffer
;
203 error_callback
.Run(BluetoothSocket::kSystemError
,
204 net::ErrorToString(read_result
));
208 void BluetoothSocketNet::OnSocketReadComplete(
209 const ReceiveCompletionCallback
& success_callback
,
210 const ReceiveErrorCompletionCallback
& error_callback
,
212 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
213 base::ThreadRestrictions::AssertIOAllowed();
215 scoped_refptr
<net::IOBufferWithSize
> buffer
;
216 buffer
.swap(read_buffer_
);
217 if (read_result
> 0) {
218 success_callback
.Run(read_result
, buffer
);
219 } else if (read_result
== net::OK
||
220 read_result
== net::ERR_CONNECTION_CLOSED
) {
221 error_callback
.Run(BluetoothSocket::kDisconnected
,
222 net::ErrorToString(net::ERR_CONNECTION_CLOSED
));
224 error_callback
.Run(BluetoothSocket::kSystemError
,
225 net::ErrorToString(read_result
));
229 void BluetoothSocketNet::DoSend(
230 scoped_refptr
<net::IOBuffer
> buffer
,
232 const SendCompletionCallback
& success_callback
,
233 const ErrorCompletionCallback
& error_callback
) {
234 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
235 base::ThreadRestrictions::AssertIOAllowed();
238 error_callback
.Run(kSocketNotConnected
);
242 linked_ptr
<WriteRequest
> request(new WriteRequest());
243 request
->buffer
= buffer
;
244 request
->buffer_size
= buffer_size
;
245 request
->success_callback
= success_callback
;
246 request
->error_callback
= error_callback
;
248 write_queue_
.push(request
);
249 if (write_queue_
.size() == 1) {
250 SendFrontWriteRequest();
254 void BluetoothSocketNet::SendFrontWriteRequest() {
255 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
256 base::ThreadRestrictions::AssertIOAllowed();
261 if (write_queue_
.size() == 0)
264 linked_ptr
<WriteRequest
> request
= write_queue_
.front();
265 net::CompletionCallback callback
=
266 base::Bind(&BluetoothSocketNet::OnSocketWriteComplete
,
268 request
->success_callback
,
269 request
->error_callback
);
271 tcp_socket_
->Write(request
->buffer
, request
->buffer_size
, callback
);
272 if (send_result
!= net::ERR_IO_PENDING
) {
273 callback
.Run(send_result
);
277 void BluetoothSocketNet::OnSocketWriteComplete(
278 const SendCompletionCallback
& success_callback
,
279 const ErrorCompletionCallback
& error_callback
,
281 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
282 base::ThreadRestrictions::AssertIOAllowed();
286 if (send_result
>= net::OK
) {
287 success_callback
.Run(send_result
);
289 error_callback
.Run(net::ErrorToString(send_result
));
292 // Don't call directly to avoid potentail large recursion.
293 socket_thread_
->task_runner()->PostNonNestableTask(
295 base::Bind(&BluetoothSocketNet::SendFrontWriteRequest
, this));
298 void BluetoothSocketNet::PostReceiveCompletion(
299 const ReceiveCompletionCallback
& callback
,
301 scoped_refptr
<net::IOBuffer
> io_buffer
) {
302 ui_task_runner_
->PostTask(FROM_HERE
,
303 base::Bind(callback
, io_buffer_size
, io_buffer
));
306 void BluetoothSocketNet::PostReceiveErrorCompletion(
307 const ReceiveErrorCompletionCallback
& callback
,
309 const std::string
& error_message
) {
310 ui_task_runner_
->PostTask(FROM_HERE
,
311 base::Bind(callback
, reason
, error_message
));
314 void BluetoothSocketNet::PostSendCompletion(
315 const SendCompletionCallback
& callback
,
317 ui_task_runner_
->PostTask(FROM_HERE
, base::Bind(callback
, bytes_written
));
320 } // namespace device