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/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 BluetoothSocketNet::WriteRequest::WriteRequest()
     35     : buffer_size(0) {}
     36 
     37 BluetoothSocketNet::WriteRequest::~WriteRequest() {}
     38 
     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 
     52 BluetoothSocketNet::~BluetoothSocketNet() {
     53   DCHECK(tcp_socket_.get() == NULL);
     54   ui_task_runner_->PostTask(FROM_HERE,
     55                             base::Bind(&DeactivateSocket, socket_thread_));
     56 }
     57 
     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 
     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 
     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 
     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 
    117 void BluetoothSocketNet::ResetData() {
    118 }
    119 
    120 void BluetoothSocketNet::ResetTCPSocket() {
    121   tcp_socket_.reset(new net::TCPSocket(net_log_, source_));
    122 }
    123 
    124 void BluetoothSocketNet::SetTCPSocket(scoped_ptr<net::TCPSocket> tcp_socket) {
    125   tcp_socket_ = tcp_socket.Pass();
    126 }
    127 
    128 void BluetoothSocketNet::PostSuccess(const base::Closure& callback) {
    129   ui_task_runner_->PostTask(FROM_HERE, callback);
    130 }
    131 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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