chromium/chrome/services/sharing/nearby/platform/bluetooth_socket.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/services/sharing/nearby/platform/bluetooth_socket.h"

#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "chrome/services/sharing/nearby/platform/bidirectional_stream.h"

namespace nearby {
namespace chrome {

BluetoothSocket::BluetoothSocket(
    bluetooth::mojom::DeviceInfoPtr device,
    mojo::PendingRemote<bluetooth::mojom::Socket> socket,
    mojo::ScopedDataPipeConsumerHandle receive_stream,
    mojo::ScopedDataPipeProducerHandle send_stream)
    : remote_device_(std::move(device)),
      remote_device_ref_(*remote_device_),
      task_runner_(
          base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})),
      socket_(std::move(socket), task_runner_),
      bidirectional_stream_(connections::mojom::Medium::kBluetooth,
                            task_runner_,
                            std::move(receive_stream),
                            std::move(send_stream)) {}

BluetoothSocket::BluetoothSocket(
    api::BluetoothDevice& remote_device,
    mojo::PendingRemote<bluetooth::mojom::Socket> socket,
    mojo::ScopedDataPipeConsumerHandle receive_stream,
    mojo::ScopedDataPipeProducerHandle send_stream)
    : remote_device_ref_(remote_device),
      task_runner_(
          base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})),
      socket_(std::move(socket), task_runner_),
      bidirectional_stream_(connections::mojom::Medium::kBluetooth,
                            task_runner_,
                            std::move(receive_stream),
                            std::move(send_stream)) {}

BluetoothSocket::~BluetoothSocket() {
  Close();
}

InputStream& BluetoothSocket::GetInputStream() {
  DCHECK(bidirectional_stream_.GetInputStream());
  return *bidirectional_stream_.GetInputStream();
}

OutputStream& BluetoothSocket::GetOutputStream() {
  DCHECK(bidirectional_stream_.GetOutputStream());
  return *bidirectional_stream_.GetOutputStream();
}

Exception BluetoothSocket::Close() {
  CloseMojoSocketIfNecessary();

  return bidirectional_stream_.Close();
}

api::BluetoothDevice* BluetoothSocket::GetRemoteDevice() {
  return &*remote_device_ref_;
}

void BluetoothSocket::CloseMojoSocketIfNecessary() {
  base::AutoLock lock(lock_);

  if (!socket_)
    return;

  // TODO(crbug.com/40057928): Remove CHECKs when crash fix is verified.
  // If not for the lock--or if thread safety is violated in some unexpected
  // way--these CHECKs would be triggered when Close() is called simultaneously
  // from multiple threads.
  CHECK(socket_);
  socket_->Disconnect();
  CHECK(socket_);
  socket_.reset();
}

}  // namespace chrome
}  // namespace nearby