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/location.h"
11 #include "base/logging.h"
12 #include "base/memory/linked_ptr.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/sequenced_task_runner.h"
16 #include "base/threading/thread_restrictions.h"
17 #include "device/bluetooth/bluetooth_socket.h"
18 #include "device/bluetooth/bluetooth_socket_thread.h"
19 #include "net/base/io_buffer.h"
20 #include "net/base/net_errors.h"
21 #include "net/base/net_log.h"
25 const char kSocketNotConnected
[] = "Socket is not connected.";
27 static void DeactivateSocket(
28 const scoped_refptr
<device::BluetoothSocketThread
>& socket_thread
) {
29 socket_thread
->OnSocketDeactivate();
36 BluetoothSocketNet::WriteRequest::WriteRequest()
39 BluetoothSocketNet::WriteRequest::~WriteRequest() {}
41 BluetoothSocketNet::BluetoothSocketNet(
42 scoped_refptr
<base::SequencedTaskRunner
> ui_task_runner
,
43 scoped_refptr
<BluetoothSocketThread
> socket_thread
)
44 : ui_task_runner_(ui_task_runner
),
45 socket_thread_(socket_thread
) {
46 DCHECK(ui_task_runner
->RunsTasksOnCurrentThread());
47 socket_thread_
->OnSocketActivate();
50 BluetoothSocketNet::~BluetoothSocketNet() {
51 DCHECK(tcp_socket_
.get() == NULL
);
52 ui_task_runner_
->PostTask(FROM_HERE
,
53 base::Bind(&DeactivateSocket
, socket_thread_
));
56 void BluetoothSocketNet::Close() {
57 DCHECK(ui_task_runner_
->RunsTasksOnCurrentThread());
58 socket_thread_
->task_runner()->PostTask(
59 FROM_HERE
, base::Bind(&BluetoothSocketNet::DoClose
, this));
62 void BluetoothSocketNet::Disconnect(
63 const base::Closure
& success_callback
) {
64 DCHECK(ui_task_runner_
->RunsTasksOnCurrentThread());
65 socket_thread_
->task_runner()->PostTask(
68 &BluetoothSocketNet::DoDisconnect
,
70 base::Bind(&BluetoothSocketNet::PostSuccess
,
75 void BluetoothSocketNet::Receive(
77 const ReceiveCompletionCallback
& success_callback
,
78 const ReceiveErrorCompletionCallback
& error_callback
) {
79 DCHECK(ui_task_runner_
->RunsTasksOnCurrentThread());
80 socket_thread_
->task_runner()->PostTask(
83 &BluetoothSocketNet::DoReceive
,
86 base::Bind(&BluetoothSocketNet::PostReceiveCompletion
,
89 base::Bind(&BluetoothSocketNet::PostReceiveErrorCompletion
,
94 void BluetoothSocketNet::Send(
95 scoped_refptr
<net::IOBuffer
> buffer
,
97 const SendCompletionCallback
& success_callback
,
98 const ErrorCompletionCallback
& error_callback
) {
99 DCHECK(ui_task_runner_
->RunsTasksOnCurrentThread());
100 socket_thread_
->task_runner()->PostTask(
103 &BluetoothSocketNet::DoSend
,
107 base::Bind(&BluetoothSocketNet::PostSendCompletion
,
110 base::Bind(&BluetoothSocketNet::PostErrorCompletion
,
115 void BluetoothSocketNet::ResetData() {
118 void BluetoothSocketNet::ResetTCPSocket() {
119 tcp_socket_
.reset(new net::TCPSocket(NULL
, net::NetLog::Source()));
122 void BluetoothSocketNet::SetTCPSocket(scoped_ptr
<net::TCPSocket
> tcp_socket
) {
123 tcp_socket_
= tcp_socket
.Pass();
126 void BluetoothSocketNet::PostSuccess(const base::Closure
& callback
) {
127 ui_task_runner_
->PostTask(FROM_HERE
, callback
);
130 void BluetoothSocketNet::PostErrorCompletion(
131 const ErrorCompletionCallback
& callback
,
132 const std::string
& error
) {
133 ui_task_runner_
->PostTask(FROM_HERE
, base::Bind(callback
, error
));
136 void BluetoothSocketNet::DoClose() {
137 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
138 base::ThreadRestrictions::AssertIOAllowed();
141 tcp_socket_
->Close();
142 tcp_socket_
.reset(NULL
);
145 // Note: Closing |tcp_socket_| above released all potential pending
146 // Send/Receive operations, so we can no safely release the state associated
147 // to those pending operations.
149 std::queue
<linked_ptr
<WriteRequest
> > empty
;
150 std::swap(write_queue_
, empty
);
155 void BluetoothSocketNet::DoDisconnect(const base::Closure
& callback
) {
156 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
157 base::ThreadRestrictions::AssertIOAllowed();
163 void BluetoothSocketNet::DoReceive(
165 const ReceiveCompletionCallback
& success_callback
,
166 const ReceiveErrorCompletionCallback
& error_callback
) {
167 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
168 base::ThreadRestrictions::AssertIOAllowed();
171 error_callback
.Run(BluetoothSocket::kDisconnected
, kSocketNotConnected
);
175 // Only one pending read at a time
176 if (read_buffer_
.get()) {
177 error_callback
.Run(BluetoothSocket::kIOPending
,
178 net::ErrorToString(net::ERR_IO_PENDING
));
182 scoped_refptr
<net::IOBufferWithSize
> buffer(
183 new net::IOBufferWithSize(buffer_size
));
185 tcp_socket_
->Read(buffer
.get(),
187 base::Bind(&BluetoothSocketNet::OnSocketReadComplete
,
192 read_buffer_
= buffer
;
193 if (read_result
!= net::ERR_IO_PENDING
)
194 OnSocketReadComplete(success_callback
, error_callback
, read_result
);
197 void BluetoothSocketNet::OnSocketReadComplete(
198 const ReceiveCompletionCallback
& success_callback
,
199 const ReceiveErrorCompletionCallback
& error_callback
,
201 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
202 base::ThreadRestrictions::AssertIOAllowed();
204 scoped_refptr
<net::IOBufferWithSize
> buffer
;
205 buffer
.swap(read_buffer_
);
206 if (read_result
> 0) {
207 success_callback
.Run(read_result
, buffer
);
208 } else if (read_result
== net::OK
||
209 read_result
== net::ERR_CONNECTION_CLOSED
||
210 read_result
== net::ERR_CONNECTION_RESET
) {
211 error_callback
.Run(BluetoothSocket::kDisconnected
,
212 net::ErrorToString(read_result
));
214 error_callback
.Run(BluetoothSocket::kSystemError
,
215 net::ErrorToString(read_result
));
219 void BluetoothSocketNet::DoSend(
220 scoped_refptr
<net::IOBuffer
> buffer
,
222 const SendCompletionCallback
& success_callback
,
223 const ErrorCompletionCallback
& error_callback
) {
224 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
225 base::ThreadRestrictions::AssertIOAllowed();
228 error_callback
.Run(kSocketNotConnected
);
232 linked_ptr
<WriteRequest
> request(new WriteRequest());
233 request
->buffer
= buffer
;
234 request
->buffer_size
= buffer_size
;
235 request
->success_callback
= success_callback
;
236 request
->error_callback
= error_callback
;
238 write_queue_
.push(request
);
239 if (write_queue_
.size() == 1) {
240 SendFrontWriteRequest();
244 void BluetoothSocketNet::SendFrontWriteRequest() {
245 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
246 base::ThreadRestrictions::AssertIOAllowed();
251 if (write_queue_
.size() == 0)
254 linked_ptr
<WriteRequest
> request
= write_queue_
.front();
255 net::CompletionCallback callback
=
256 base::Bind(&BluetoothSocketNet::OnSocketWriteComplete
,
258 request
->success_callback
,
259 request
->error_callback
);
261 tcp_socket_
->Write(request
->buffer
.get(), request
->buffer_size
, callback
);
262 if (send_result
!= net::ERR_IO_PENDING
) {
263 callback
.Run(send_result
);
267 void BluetoothSocketNet::OnSocketWriteComplete(
268 const SendCompletionCallback
& success_callback
,
269 const ErrorCompletionCallback
& error_callback
,
271 DCHECK(socket_thread_
->task_runner()->RunsTasksOnCurrentThread());
272 base::ThreadRestrictions::AssertIOAllowed();
276 if (send_result
>= net::OK
) {
277 success_callback
.Run(send_result
);
279 error_callback
.Run(net::ErrorToString(send_result
));
282 // Don't call directly to avoid potentail large recursion.
283 socket_thread_
->task_runner()->PostNonNestableTask(
285 base::Bind(&BluetoothSocketNet::SendFrontWriteRequest
, this));
288 void BluetoothSocketNet::PostReceiveCompletion(
289 const ReceiveCompletionCallback
& callback
,
291 scoped_refptr
<net::IOBuffer
> io_buffer
) {
292 ui_task_runner_
->PostTask(FROM_HERE
,
293 base::Bind(callback
, io_buffer_size
, io_buffer
));
296 void BluetoothSocketNet::PostReceiveErrorCompletion(
297 const ReceiveErrorCompletionCallback
& callback
,
299 const std::string
& error_message
) {
300 ui_task_runner_
->PostTask(FROM_HERE
,
301 base::Bind(callback
, reason
, error_message
));
304 void BluetoothSocketNet::PostSendCompletion(
305 const SendCompletionCallback
& callback
,
307 ui_task_runner_
->PostTask(FROM_HERE
, base::Bind(callback
, bytes_written
));
310 } // namespace device