Roll breakpad a513e85:7caf028 (svn 1384:1385)
[chromium-blink-merge.git] / device / bluetooth / bluetooth_socket_net.cc
blobeb3776ca77aab0f4876fa95d9c217d580ebc2f53
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/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"
23 namespace {
25 const char kSocketNotConnected[] = "Socket is not connected.";
27 static void DeactivateSocket(
28 const scoped_refptr<device::BluetoothSocketThread>& socket_thread) {
29 socket_thread->OnSocketDeactivate();
32 } // namespace
34 namespace device {
36 BluetoothSocketNet::WriteRequest::WriteRequest()
37 : buffer_size(0) {}
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(
66 FROM_HERE,
67 base::Bind(
68 &BluetoothSocketNet::DoDisconnect,
69 this,
70 base::Bind(&BluetoothSocketNet::PostSuccess,
71 this,
72 success_callback)));
75 void BluetoothSocketNet::Receive(
76 int buffer_size,
77 const ReceiveCompletionCallback& success_callback,
78 const ReceiveErrorCompletionCallback& error_callback) {
79 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
80 socket_thread_->task_runner()->PostTask(
81 FROM_HERE,
82 base::Bind(
83 &BluetoothSocketNet::DoReceive,
84 this,
85 buffer_size,
86 base::Bind(&BluetoothSocketNet::PostReceiveCompletion,
87 this,
88 success_callback),
89 base::Bind(&BluetoothSocketNet::PostReceiveErrorCompletion,
90 this,
91 error_callback)));
94 void BluetoothSocketNet::Send(
95 scoped_refptr<net::IOBuffer> buffer,
96 int buffer_size,
97 const SendCompletionCallback& success_callback,
98 const ErrorCompletionCallback& error_callback) {
99 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
100 socket_thread_->task_runner()->PostTask(
101 FROM_HERE,
102 base::Bind(
103 &BluetoothSocketNet::DoSend,
104 this,
105 buffer,
106 buffer_size,
107 base::Bind(&BluetoothSocketNet::PostSendCompletion,
108 this,
109 success_callback),
110 base::Bind(&BluetoothSocketNet::PostErrorCompletion,
111 this,
112 error_callback)));
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();
140 if (tcp_socket_) {
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.
148 read_buffer_ = NULL;
149 std::queue<linked_ptr<WriteRequest> > empty;
150 std::swap(write_queue_, empty);
152 ResetData();
155 void BluetoothSocketNet::DoDisconnect(const base::Closure& callback) {
156 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
157 base::ThreadRestrictions::AssertIOAllowed();
159 DoClose();
160 callback.Run();
163 void BluetoothSocketNet::DoReceive(
164 int buffer_size,
165 const ReceiveCompletionCallback& success_callback,
166 const ReceiveErrorCompletionCallback& error_callback) {
167 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
168 base::ThreadRestrictions::AssertIOAllowed();
170 if (!tcp_socket_) {
171 error_callback.Run(BluetoothSocket::kDisconnected, kSocketNotConnected);
172 return;
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));
179 return;
182 scoped_refptr<net::IOBufferWithSize> buffer(
183 new net::IOBufferWithSize(buffer_size));
184 int read_result =
185 tcp_socket_->Read(buffer.get(),
186 buffer->size(),
187 base::Bind(&BluetoothSocketNet::OnSocketReadComplete,
188 this,
189 success_callback,
190 error_callback));
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,
200 int read_result) {
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));
213 } else {
214 error_callback.Run(BluetoothSocket::kSystemError,
215 net::ErrorToString(read_result));
219 void BluetoothSocketNet::DoSend(
220 scoped_refptr<net::IOBuffer> buffer,
221 int buffer_size,
222 const SendCompletionCallback& success_callback,
223 const ErrorCompletionCallback& error_callback) {
224 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
225 base::ThreadRestrictions::AssertIOAllowed();
227 if (!tcp_socket_) {
228 error_callback.Run(kSocketNotConnected);
229 return;
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();
248 if (!tcp_socket_)
249 return;
251 if (write_queue_.size() == 0)
252 return;
254 linked_ptr<WriteRequest> request = write_queue_.front();
255 net::CompletionCallback callback =
256 base::Bind(&BluetoothSocketNet::OnSocketWriteComplete,
257 this,
258 request->success_callback,
259 request->error_callback);
260 int send_result =
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,
270 int send_result) {
271 DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
272 base::ThreadRestrictions::AssertIOAllowed();
274 write_queue_.pop();
276 if (send_result >= net::OK) {
277 success_callback.Run(send_result);
278 } else {
279 error_callback.Run(net::ErrorToString(send_result));
282 // Don't call directly to avoid potentail large recursion.
283 socket_thread_->task_runner()->PostNonNestableTask(
284 FROM_HERE,
285 base::Bind(&BluetoothSocketNet::SendFrontWriteRequest, this));
288 void BluetoothSocketNet::PostReceiveCompletion(
289 const ReceiveCompletionCallback& callback,
290 int io_buffer_size,
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,
298 ErrorReason reason,
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,
306 int bytes_written) {
307 ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, bytes_written));
310 } // namespace device