Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / device / bluetooth / bluetooth_socket_net.cc
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.
4
5 #include "device/bluetooth/bluetooth_socket_net.h"
6
7 #include <queue>
8 #include <string>
9
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"
20
21 namespace {
22
23 const char kSocketNotConnected[] = "Socket is not connected.";
24
25 static void DeactivateSocket(
26     const scoped_refptr<device::BluetoothSocketThread>& socket_thread) {
27   socket_thread->OnSocketDeactivate();
28 }
29
30 }  // namespace
31
32 namespace device {
33
34 // static
35 scoped_refptr<BluetoothSocketNet>
36 BluetoothSocketNet::CreateBluetoothSocket(
37     scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
38     scoped_refptr<BluetoothSocketThread> socket_thread,
39     net::NetLog* net_log,
40     const net::NetLog::Source& source) {
41   DCHECK(ui_task_runner->RunsTasksOnCurrentThread());
42
43   return make_scoped_refptr(
44       new BluetoothSocketNet(ui_task_runner, socket_thread, net_log, source));
45 }
46
47 BluetoothSocketNet::WriteRequest::WriteRequest()
48     : buffer_size(0) {}
49
50 BluetoothSocketNet::WriteRequest::~WriteRequest() {}
51
52 BluetoothSocketNet::BluetoothSocketNet(
53     scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
54     scoped_refptr<BluetoothSocketThread> socket_thread,
55     net::NetLog* net_log,
56     const net::NetLog::Source& source)
57     : ui_task_runner_(ui_task_runner),
58       socket_thread_(socket_thread),
59       net_log_(net_log),
60       source_(source) {
61   DCHECK(ui_task_runner->RunsTasksOnCurrentThread());
62   socket_thread_->OnSocketActivate();
63 }
64
65 BluetoothSocketNet::~BluetoothSocketNet() {
66   DCHECK(tcp_socket_.get() == NULL);
67   ui_task_runner_->PostTask(FROM_HERE,
68                             base::Bind(&DeactivateSocket, socket_thread_));
69 }
70
71 void BluetoothSocketNet::Close() {
72   DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
73   socket_thread_->task_runner()->PostTask(
74       FROM_HERE, base::Bind(&BluetoothSocketNet::DoClose, this));
75 }
76
77 void BluetoothSocketNet::Disconnect(
78     const base::Closure& success_callback) {
79   DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
80   socket_thread_->task_runner()->PostTask(
81       FROM_HERE,
82       base::Bind(
83           &BluetoothSocketNet::DoDisconnect,
84           this,
85           base::Bind(&BluetoothSocketNet::PostSuccess,
86                      this,
87                      success_callback)));
88 }
89
90 void BluetoothSocketNet::Receive(
91     int buffer_size,
92     const ReceiveCompletionCallback& success_callback,
93     const ReceiveErrorCompletionCallback& error_callback) {
94   DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
95   socket_thread_->task_runner()->PostTask(
96       FROM_HERE,
97       base::Bind(
98           &BluetoothSocketNet::DoReceive,
99           this,
100           buffer_size,
101           base::Bind(&BluetoothSocketNet::PostReceiveCompletion,
102                      this,
103                      success_callback),
104           base::Bind(&BluetoothSocketNet::PostReceiveErrorCompletion,
105                      this,
106                      error_callback)));
107 }
108
109 void BluetoothSocketNet::Send(
110     scoped_refptr<net::IOBuffer> buffer,
111     int buffer_size,
112     const SendCompletionCallback& success_callback,
113     const ErrorCompletionCallback& error_callback) {
114   DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
115   socket_thread_->task_runner()->PostTask(
116       FROM_HERE,
117       base::Bind(
118           &BluetoothSocketNet::DoSend,
119           this,
120           buffer,
121           buffer_size,
122           base::Bind(&BluetoothSocketNet::PostSendCompletion,
123                      this,
124                      success_callback),
125           base::Bind(&BluetoothSocketNet::PostErrorCompletion,
126                      this,
127                      error_callback)));
128 }
129
130 void BluetoothSocketNet::ResetData() {
131 }
132
133 void BluetoothSocketNet::ResetTCPSocket() {
134   tcp_socket_.reset(new net::TCPSocket(net_log_, source_));
135 }
136
137 void BluetoothSocketNet::SetTCPSocket(scoped_ptr<net::TCPSocket> tcp_socket) {
138   tcp_socket_ = tcp_socket.Pass();
139 }
140
141 void BluetoothSocketNet::PostSuccess(const base::Closure& callback) {
142   ui_task_runner_->PostTask(FROM_HERE, callback);
143 }
144
145 void BluetoothSocketNet::PostErrorCompletion(
146     const ErrorCompletionCallback& callback,
147     const std::string& error) {
148   ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, error));
149 }
150
151 void BluetoothSocketNet::DoClose() {
152   DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
153   base::ThreadRestrictions::AssertIOAllowed();
154
155   if (tcp_socket_) {
156     tcp_socket_->Close();
157     tcp_socket_.reset(NULL);
158   }
159
160   // Note: Closing |tcp_socket_| above released all potential pending
161   // Send/Receive operations, so we can no safely release the state associated
162   // to those pending operations.
163   read_buffer_ = NULL;
164   std::queue<linked_ptr<WriteRequest> > empty;
165   std::swap(write_queue_, empty);
166
167   ResetData();
168 }
169
170 void BluetoothSocketNet::DoDisconnect(const base::Closure& callback) {
171   DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
172   base::ThreadRestrictions::AssertIOAllowed();
173
174   DoClose();
175   callback.Run();
176 }
177
178 void BluetoothSocketNet::DoReceive(
179     int buffer_size,
180     const ReceiveCompletionCallback& success_callback,
181     const ReceiveErrorCompletionCallback& error_callback) {
182   DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
183   base::ThreadRestrictions::AssertIOAllowed();
184
185   if (!tcp_socket_) {
186     error_callback.Run(BluetoothSocket::kDisconnected, kSocketNotConnected);
187     return;
188   }
189
190   // Only one pending read at a time
191   if (read_buffer_.get()) {
192     error_callback.Run(BluetoothSocket::kIOPending,
193                        net::ErrorToString(net::ERR_IO_PENDING));
194     return;
195   }
196
197   scoped_refptr<net::IOBufferWithSize> buffer(
198       new net::IOBufferWithSize(buffer_size));
199   int read_result =
200       tcp_socket_->Read(buffer.get(),
201                         buffer->size(),
202                         base::Bind(&BluetoothSocketNet::OnSocketReadComplete,
203                                    this,
204                                    success_callback,
205                                    error_callback));
206
207   if (read_result > 0) {
208     success_callback.Run(read_result, buffer);
209   } else if (read_result == net::OK ||
210              read_result == net::ERR_CONNECTION_CLOSED) {
211     error_callback.Run(BluetoothSocket::kDisconnected,
212                        net::ErrorToString(net::ERR_CONNECTION_CLOSED));
213   } else if (read_result == net::ERR_IO_PENDING) {
214     read_buffer_ = buffer;
215   } else {
216     error_callback.Run(BluetoothSocket::kSystemError,
217                        net::ErrorToString(read_result));
218   }
219 }
220
221 void BluetoothSocketNet::OnSocketReadComplete(
222     const ReceiveCompletionCallback& success_callback,
223     const ReceiveErrorCompletionCallback& error_callback,
224     int read_result) {
225   DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
226   base::ThreadRestrictions::AssertIOAllowed();
227
228   scoped_refptr<net::IOBufferWithSize> buffer;
229   buffer.swap(read_buffer_);
230   if (read_result > 0) {
231     success_callback.Run(read_result, buffer);
232   } else if (read_result == net::OK ||
233              read_result == net::ERR_CONNECTION_CLOSED) {
234     error_callback.Run(BluetoothSocket::kDisconnected,
235                        net::ErrorToString(net::ERR_CONNECTION_CLOSED));
236   } else {
237     error_callback.Run(BluetoothSocket::kSystemError,
238                        net::ErrorToString(read_result));
239   }
240 }
241
242 void BluetoothSocketNet::DoSend(
243     scoped_refptr<net::IOBuffer> buffer,
244     int buffer_size,
245     const SendCompletionCallback& success_callback,
246     const ErrorCompletionCallback& error_callback) {
247   DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
248   base::ThreadRestrictions::AssertIOAllowed();
249
250   if (!tcp_socket_) {
251     error_callback.Run(kSocketNotConnected);
252     return;
253   }
254
255   linked_ptr<WriteRequest> request(new WriteRequest());
256   request->buffer = buffer;
257   request->buffer_size = buffer_size;
258   request->success_callback = success_callback;
259   request->error_callback = error_callback;
260
261   write_queue_.push(request);
262   if (write_queue_.size() == 1) {
263     SendFrontWriteRequest();
264   }
265 }
266
267 void BluetoothSocketNet::SendFrontWriteRequest() {
268   DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
269   base::ThreadRestrictions::AssertIOAllowed();
270
271   if (!tcp_socket_)
272     return;
273
274   if (write_queue_.size() == 0)
275     return;
276
277   linked_ptr<WriteRequest> request = write_queue_.front();
278   net::CompletionCallback callback =
279       base::Bind(&BluetoothSocketNet::OnSocketWriteComplete,
280                  this,
281                  request->success_callback,
282                  request->error_callback);
283   int send_result =
284       tcp_socket_->Write(request->buffer, request->buffer_size, callback);
285   if (send_result != net::ERR_IO_PENDING) {
286     callback.Run(send_result);
287   }
288 }
289
290 void BluetoothSocketNet::OnSocketWriteComplete(
291     const SendCompletionCallback& success_callback,
292     const ErrorCompletionCallback& error_callback,
293     int send_result) {
294   DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
295   base::ThreadRestrictions::AssertIOAllowed();
296
297   write_queue_.pop();
298
299   if (send_result >= net::OK) {
300     success_callback.Run(send_result);
301   } else {
302     error_callback.Run(net::ErrorToString(send_result));
303   }
304
305   // Don't call directly to avoid potentail large recursion.
306   socket_thread_->task_runner()->PostNonNestableTask(
307       FROM_HERE,
308       base::Bind(&BluetoothSocketNet::SendFrontWriteRequest, this));
309 }
310
311 void BluetoothSocketNet::PostReceiveCompletion(
312     const ReceiveCompletionCallback& callback,
313     int io_buffer_size,
314     scoped_refptr<net::IOBuffer> io_buffer) {
315   ui_task_runner_->PostTask(FROM_HERE,
316                             base::Bind(callback, io_buffer_size, io_buffer));
317 }
318
319 void BluetoothSocketNet::PostReceiveErrorCompletion(
320     const ReceiveErrorCompletionCallback& callback,
321     ErrorReason reason,
322     const std::string& error_message) {
323   ui_task_runner_->PostTask(FROM_HERE,
324                             base::Bind(callback, reason, error_message));
325 }
326
327 void BluetoothSocketNet::PostSendCompletion(
328     const SendCompletionCallback& callback,
329     int bytes_written) {
330   ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, bytes_written));
331 }
332
333 }  // namespace device