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 read_buffer_
= buffer
;
195 if (read_result
!= net::ERR_IO_PENDING
)
196 OnSocketReadComplete(success_callback
, error_callback
, read_result
);
199 void BluetoothSocketNet::OnSocketReadComplete(
200 const ReceiveCompletionCallback
& success_callback
,
201 const ReceiveErrorCompletionCallback
& error_callback
,
203 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
204 base::ThreadRestrictions::AssertIOAllowed();
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
));
216 error_callback
.Run(BluetoothSocket::kSystemError
,
217 net::ErrorToString(read_result
));
221 void BluetoothSocketNet::DoSend(
222 scoped_refptr
<net::IOBuffer
> buffer
,
224 const SendCompletionCallback
& success_callback
,
225 const ErrorCompletionCallback
& error_callback
) {
226 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
227 base::ThreadRestrictions::AssertIOAllowed();
230 error_callback
.Run(kSocketNotConnected
);
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
;
240 write_queue_
.push(request
);
241 if (write_queue_
.size() == 1) {
242 SendFrontWriteRequest();
246 void BluetoothSocketNet::SendFrontWriteRequest() {
247 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
248 base::ThreadRestrictions::AssertIOAllowed();
253 if (write_queue_
.size() == 0)
256 linked_ptr
<WriteRequest
> request
= write_queue_
.front();
257 net::CompletionCallback callback
=
258 base::Bind(&BluetoothSocketNet::OnSocketWriteComplete
,
260 request
->success_callback
,
261 request
->error_callback
);
263 tcp_socket_
->Write(request
->buffer
, request
->buffer_size
, callback
);
264 if (send_result
!= net::ERR_IO_PENDING
) {
265 callback
.Run(send_result
);
269 void BluetoothSocketNet::OnSocketWriteComplete(
270 const SendCompletionCallback
& success_callback
,
271 const ErrorCompletionCallback
& error_callback
,
273 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
274 base::ThreadRestrictions::AssertIOAllowed();
278 if (send_result
>= net::OK
) {
279 success_callback
.Run(send_result
);
281 error_callback
.Run(net::ErrorToString(send_result
));
284 // Don't call directly to avoid potentail large recursion.
285 socket_thread_
->task_runner()->PostNonNestableTask(
287 base::Bind(&BluetoothSocketNet::SendFrontWriteRequest
, this));
290 void BluetoothSocketNet::PostReceiveCompletion(
291 const ReceiveCompletionCallback
& callback
,
293 scoped_refptr
<net::IOBuffer
> io_buffer
) {
294 ui_task_runner_
->PostTask(FROM_HERE
,
295 base::Bind(callback
, io_buffer_size
, io_buffer
));
298 void BluetoothSocketNet::PostReceiveErrorCompletion(
299 const ReceiveErrorCompletionCallback
& callback
,
301 const std::string
& error_message
) {
302 ui_task_runner_
->PostTask(FROM_HERE
,
303 base::Bind(callback
, reason
, error_message
));
306 void BluetoothSocketNet::PostSendCompletion(
307 const SendCompletionCallback
& callback
,
309 ui_task_runner_
->PostTask(FROM_HERE
, base::Bind(callback
, bytes_written
));
312 } // namespace device