• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
DeactivateSocket(const scoped_refptr<device::BluetoothSocketThread> & socket_thread)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 
WriteRequest()34 BluetoothSocketNet::WriteRequest::WriteRequest()
35     : buffer_size(0) {}
36 
~WriteRequest()37 BluetoothSocketNet::WriteRequest::~WriteRequest() {}
38 
BluetoothSocketNet(scoped_refptr<base::SequencedTaskRunner> ui_task_runner,scoped_refptr<BluetoothSocketThread> socket_thread,net::NetLog * net_log,const net::NetLog::Source & source)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();
50 }
51 
~BluetoothSocketNet()52 BluetoothSocketNet::~BluetoothSocketNet() {
53   DCHECK(tcp_socket_.get() == NULL);
54   ui_task_runner_->PostTask(FROM_HERE,
55                             base::Bind(&DeactivateSocket, socket_thread_));
56 }
57 
Close()58 void BluetoothSocketNet::Close() {
59   DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
60   socket_thread_->task_runner()->PostTask(
61       FROM_HERE, base::Bind(&BluetoothSocketNet::DoClose, this));
62 }
63 
Disconnect(const base::Closure & success_callback)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)));
75 }
76 
Receive(int buffer_size,const ReceiveCompletionCallback & success_callback,const ReceiveErrorCompletionCallback & error_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)));
94 }
95 
Send(scoped_refptr<net::IOBuffer> buffer,int buffer_size,const SendCompletionCallback & success_callback,const ErrorCompletionCallback & 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)));
115 }
116 
ResetData()117 void BluetoothSocketNet::ResetData() {
118 }
119 
ResetTCPSocket()120 void BluetoothSocketNet::ResetTCPSocket() {
121   tcp_socket_.reset(new net::TCPSocket(net_log_, source_));
122 }
123 
SetTCPSocket(scoped_ptr<net::TCPSocket> tcp_socket)124 void BluetoothSocketNet::SetTCPSocket(scoped_ptr<net::TCPSocket> tcp_socket) {
125   tcp_socket_ = tcp_socket.Pass();
126 }
127 
PostSuccess(const base::Closure & callback)128 void BluetoothSocketNet::PostSuccess(const base::Closure& callback) {
129   ui_task_runner_->PostTask(FROM_HERE, callback);
130 }
131 
PostErrorCompletion(const ErrorCompletionCallback & callback,const std::string & error)132 void BluetoothSocketNet::PostErrorCompletion(
133     const ErrorCompletionCallback& callback,
134     const std::string& error) {
135   ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, error));
136 }
137 
DoClose()138 void BluetoothSocketNet::DoClose() {
139   DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
140   base::ThreadRestrictions::AssertIOAllowed();
141 
142   if (tcp_socket_) {
143     tcp_socket_->Close();
144     tcp_socket_.reset(NULL);
145   }
146 
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);
153 
154   ResetData();
155 }
156 
DoDisconnect(const base::Closure & callback)157 void BluetoothSocketNet::DoDisconnect(const base::Closure& callback) {
158   DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
159   base::ThreadRestrictions::AssertIOAllowed();
160 
161   DoClose();
162   callback.Run();
163 }
164 
DoReceive(int buffer_size,const ReceiveCompletionCallback & success_callback,const ReceiveErrorCompletionCallback & error_callback)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();
171 
172   if (!tcp_socket_) {
173     error_callback.Run(BluetoothSocket::kDisconnected, kSocketNotConnected);
174     return;
175   }
176 
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;
182   }
183 
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));
193 
194   read_buffer_ = buffer;
195   if (read_result != net::ERR_IO_PENDING)
196     OnSocketReadComplete(success_callback, error_callback, read_result);
197 }
198 
OnSocketReadComplete(const ReceiveCompletionCallback & success_callback,const ReceiveErrorCompletionCallback & error_callback,int read_result)199 void BluetoothSocketNet::OnSocketReadComplete(
200     const ReceiveCompletionCallback& success_callback,
201     const ReceiveErrorCompletionCallback& error_callback,
202     int read_result) {
203   DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
204   base::ThreadRestrictions::AssertIOAllowed();
205 
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));
215   } else {
216     error_callback.Run(BluetoothSocket::kSystemError,
217                        net::ErrorToString(read_result));
218   }
219 }
220 
DoSend(scoped_refptr<net::IOBuffer> buffer,int buffer_size,const SendCompletionCallback & success_callback,const ErrorCompletionCallback & error_callback)221 void BluetoothSocketNet::DoSend(
222     scoped_refptr<net::IOBuffer> buffer,
223     int buffer_size,
224     const SendCompletionCallback& success_callback,
225     const ErrorCompletionCallback& error_callback) {
226   DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
227   base::ThreadRestrictions::AssertIOAllowed();
228 
229   if (!tcp_socket_) {
230     error_callback.Run(kSocketNotConnected);
231     return;
232   }
233 
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;
239 
240   write_queue_.push(request);
241   if (write_queue_.size() == 1) {
242     SendFrontWriteRequest();
243   }
244 }
245 
SendFrontWriteRequest()246 void BluetoothSocketNet::SendFrontWriteRequest() {
247   DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
248   base::ThreadRestrictions::AssertIOAllowed();
249 
250   if (!tcp_socket_)
251     return;
252 
253   if (write_queue_.size() == 0)
254     return;
255 
256   linked_ptr<WriteRequest> request = write_queue_.front();
257   net::CompletionCallback callback =
258       base::Bind(&BluetoothSocketNet::OnSocketWriteComplete,
259                  this,
260                  request->success_callback,
261                  request->error_callback);
262   int send_result =
263       tcp_socket_->Write(request->buffer, request->buffer_size, callback);
264   if (send_result != net::ERR_IO_PENDING) {
265     callback.Run(send_result);
266   }
267 }
268 
OnSocketWriteComplete(const SendCompletionCallback & success_callback,const ErrorCompletionCallback & error_callback,int send_result)269 void BluetoothSocketNet::OnSocketWriteComplete(
270     const SendCompletionCallback& success_callback,
271     const ErrorCompletionCallback& error_callback,
272     int send_result) {
273   DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
274   base::ThreadRestrictions::AssertIOAllowed();
275 
276   write_queue_.pop();
277 
278   if (send_result >= net::OK) {
279     success_callback.Run(send_result);
280   } else {
281     error_callback.Run(net::ErrorToString(send_result));
282   }
283 
284   // Don't call directly to avoid potentail large recursion.
285   socket_thread_->task_runner()->PostNonNestableTask(
286       FROM_HERE,
287       base::Bind(&BluetoothSocketNet::SendFrontWriteRequest, this));
288 }
289 
PostReceiveCompletion(const ReceiveCompletionCallback & callback,int io_buffer_size,scoped_refptr<net::IOBuffer> io_buffer)290 void BluetoothSocketNet::PostReceiveCompletion(
291     const ReceiveCompletionCallback& callback,
292     int io_buffer_size,
293     scoped_refptr<net::IOBuffer> io_buffer) {
294   ui_task_runner_->PostTask(FROM_HERE,
295                             base::Bind(callback, io_buffer_size, io_buffer));
296 }
297 
PostReceiveErrorCompletion(const ReceiveErrorCompletionCallback & callback,ErrorReason reason,const std::string & error_message)298 void BluetoothSocketNet::PostReceiveErrorCompletion(
299     const ReceiveErrorCompletionCallback& callback,
300     ErrorReason reason,
301     const std::string& error_message) {
302   ui_task_runner_->PostTask(FROM_HERE,
303                             base::Bind(callback, reason, error_message));
304 }
305 
PostSendCompletion(const SendCompletionCallback & callback,int bytes_written)306 void BluetoothSocketNet::PostSendCompletion(
307     const SendCompletionCallback& callback,
308     int bytes_written) {
309   ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, bytes_written));
310 }
311 
312 }  // namespace device
313