Revert 269361 "Fix WebURLLoaderImpl::Context leak if a pending r..."
[chromium-blink-merge.git] / device / bluetooth / bluetooth_socket_net.cc
blob8ee2900f04ce5952bea0a03ab2937e5c4bdb45e9
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"
7 #include <queue>
8 #include <string>
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"
21 namespace {
23 const char kSocketNotConnected[] = "Socket is not connected.";
25 static void DeactivateSocket(
26 const scoped_refptr<device::BluetoothSocketThread>& socket_thread) {
27 socket_thread->OnSocketDeactivate();
30 } // namespace
32 namespace device {
34 BluetoothSocketNet::WriteRequest::WriteRequest()
35 : buffer_size(0) {}
37 BluetoothSocketNet::WriteRequest::~WriteRequest() {}
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();
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(
68 FROM_HERE,
69 base::Bind(
70 &BluetoothSocketNet::DoDisconnect,
71 this,
72 base::Bind(&BluetoothSocketNet::PostSuccess,
73 this,
74 success_callback)));
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)));
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)));
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();
142 if (tcp_socket_) {
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.
150 read_buffer_ = NULL;
151 std::queue<linked_ptr<WriteRequest> > empty;
152 std::swap(write_queue_, empty);
154 ResetData();
157 void BluetoothSocketNet::DoDisconnect(const base::Closure& callback) {
158 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
159 base::ThreadRestrictions::AssertIOAllowed();
161 DoClose();
162 callback.Run();
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();
172 if (!tcp_socket_) {
173 error_callback.Run(BluetoothSocket::kDisconnected, kSocketNotConnected);
174 return;
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;
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));
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;
202 } else {
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,
211 int read_result) {
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));
223 } else {
224 error_callback.Run(BluetoothSocket::kSystemError,
225 net::ErrorToString(read_result));
229 void BluetoothSocketNet::DoSend(
230 scoped_refptr<net::IOBuffer> buffer,
231 int buffer_size,
232 const SendCompletionCallback& success_callback,
233 const ErrorCompletionCallback& error_callback) {
234 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
235 base::ThreadRestrictions::AssertIOAllowed();
237 if (!tcp_socket_) {
238 error_callback.Run(kSocketNotConnected);
239 return;
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();
258 if (!tcp_socket_)
259 return;
261 if (write_queue_.size() == 0)
262 return;
264 linked_ptr<WriteRequest> request = write_queue_.front();
265 net::CompletionCallback callback =
266 base::Bind(&BluetoothSocketNet::OnSocketWriteComplete,
267 this,
268 request->success_callback,
269 request->error_callback);
270 int send_result =
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,
280 int send_result) {
281 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
282 base::ThreadRestrictions::AssertIOAllowed();
284 write_queue_.pop();
286 if (send_result >= net::OK) {
287 success_callback.Run(send_result);
288 } else {
289 error_callback.Run(net::ErrorToString(send_result));
292 // Don't call directly to avoid potentail large recursion.
293 socket_thread_->task_runner()->PostNonNestableTask(
294 FROM_HERE,
295 base::Bind(&BluetoothSocketNet::SendFrontWriteRequest, this));
298 void BluetoothSocketNet::PostReceiveCompletion(
299 const ReceiveCompletionCallback& callback,
300 int io_buffer_size,
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,
308 ErrorReason reason,
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,
316 int bytes_written) {
317 ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, bytes_written));
320 } // namespace device