Home | History | Annotate | Download | only in bluetooth
      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/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"
     22 
     23 namespace {
     24 
     25 const char kSocketNotConnected[] = "Socket is not connected.";
     26 
     27 static void DeactivateSocket(
     28     const scoped_refptr<device::BluetoothSocketThread>& socket_thread) {
     29   socket_thread->OnSocketDeactivate();
     30 }
     31 
     32 }  // namespace
     33 
     34 namespace device {
     35 
     36 BluetoothSocketNet::WriteRequest::WriteRequest()
     37     : buffer_size(0) {}
     38 
     39 BluetoothSocketNet::WriteRequest::~WriteRequest() {}
     40 
     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();
     48 }
     49 
     50 BluetoothSocketNet::~BluetoothSocketNet() {
     51   DCHECK(tcp_socket_.get() == NULL);
     52   ui_task_runner_->PostTask(FROM_HERE,
     53                             base::Bind(&DeactivateSocket, socket_thread_));
     54 }
     55 
     56 void BluetoothSocketNet::Close() {
     57   DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
     58   socket_thread_->task_runner()->PostTask(
     59       FROM_HERE, base::Bind(&BluetoothSocketNet::DoClose, this));
     60 }
     61 
     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)));
     73 }
     74 
     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)));
     92 }
     93 
     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)));
    113 }
    114 
    115 void BluetoothSocketNet::ResetData() {
    116 }
    117 
    118 void BluetoothSocketNet::ResetTCPSocket() {
    119   tcp_socket_.reset(new net::TCPSocket(NULL, net::NetLog::Source()));
    120 }
    121 
    122 void BluetoothSocketNet::SetTCPSocket(scoped_ptr<net::TCPSocket> tcp_socket) {
    123   tcp_socket_ = tcp_socket.Pass();
    124 }
    125 
    126 void BluetoothSocketNet::PostSuccess(const base::Closure& callback) {
    127   ui_task_runner_->PostTask(FROM_HERE, callback);
    128 }
    129 
    130 void BluetoothSocketNet::PostErrorCompletion(
    131     const ErrorCompletionCallback& callback,
    132     const std::string& error) {
    133   ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, error));
    134 }
    135 
    136 void BluetoothSocketNet::DoClose() {
    137   DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
    138   base::ThreadRestrictions::AssertIOAllowed();
    139 
    140   if (tcp_socket_) {
    141     tcp_socket_->Close();
    142     tcp_socket_.reset(NULL);
    143   }
    144 
    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);
    151 
    152   ResetData();
    153 }
    154 
    155 void BluetoothSocketNet::DoDisconnect(const base::Closure& callback) {
    156   DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
    157   base::ThreadRestrictions::AssertIOAllowed();
    158 
    159   DoClose();
    160   callback.Run();
    161 }
    162 
    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();
    169 
    170   if (!tcp_socket_) {
    171     error_callback.Run(BluetoothSocket::kDisconnected, kSocketNotConnected);
    172     return;
    173   }
    174 
    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;
    180   }
    181 
    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));
    191 
    192   read_buffer_ = buffer;
    193   if (read_result != net::ERR_IO_PENDING)
    194     OnSocketReadComplete(success_callback, error_callback, read_result);
    195 }
    196 
    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();
    203 
    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));
    216   }
    217 }
    218 
    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();
    226 
    227   if (!tcp_socket_) {
    228     error_callback.Run(kSocketNotConnected);
    229     return;
    230   }
    231 
    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;
    237 
    238   write_queue_.push(request);
    239   if (write_queue_.size() == 1) {
    240     SendFrontWriteRequest();
    241   }
    242 }
    243 
    244 void BluetoothSocketNet::SendFrontWriteRequest() {
    245   DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread());
    246   base::ThreadRestrictions::AssertIOAllowed();
    247 
    248   if (!tcp_socket_)
    249     return;
    250 
    251   if (write_queue_.size() == 0)
    252     return;
    253 
    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);
    264   }
    265 }
    266 
    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();
    273 
    274   write_queue_.pop();
    275 
    276   if (send_result >= net::OK) {
    277     success_callback.Run(send_result);
    278   } else {
    279     error_callback.Run(net::ErrorToString(send_result));
    280   }
    281 
    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));
    286 }
    287 
    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));
    294 }
    295 
    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));
    302 }
    303 
    304 void BluetoothSocketNet::PostSendCompletion(
    305     const SendCompletionCallback& callback,
    306     int bytes_written) {
    307   ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, bytes_written));
    308 }
    309 
    310 }  // namespace device
    311