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

#include "device/bluetooth/bluez/bluetooth_socket_bluez.h"

#include <stdint.h>

#include <memory>
#include <queue>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/callback.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/task_runner_util.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/thread_task_runner_handle.h"
#include "dbus/bus.h"
#include "dbus/object_path.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_socket.h"
#include "device/bluetooth/bluetooth_socket_net.h"
#include "device/bluetooth/bluetooth_socket_thread.h"
#include "device/bluetooth/bluez/bluetooth_adapter_bluez.h"
#include "device/bluetooth/bluez/bluetooth_adapter_profile_bluez.h"
#include "device/bluetooth/bluez/bluetooth_device_bluez.h"
#include "device/bluetooth/dbus/bluetooth_device_client.h"
#include "device/bluetooth/dbus/bluetooth_profile_manager_client.h"
#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

using device::BluetoothAdapter;
using device::BluetoothDevice;
using device::BluetoothSocketThread;
using device::BluetoothUUID;

namespace {

const char kAcceptFailed[] = "Failed to accept connection.";
const char kInvalidUUID[] = "Invalid UUID";
const char kSocketNotListening[] = "Socket is not listening.";

}  // namespace

namespace bluez {

// static
scoped_refptr<BluetoothSocketBlueZ> BluetoothSocketBlueZ::CreateBluetoothSocket(
    scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
    scoped_refptr<BluetoothSocketThread> socket_thread) {
  DCHECK(ui_task_runner->RunsTasksInCurrentSequence());

  return base::WrapRefCounted(
      new BluetoothSocketBlueZ(ui_task_runner, socket_thread));
}

BluetoothSocketBlueZ::AcceptRequest::AcceptRequest() = default;

BluetoothSocketBlueZ::AcceptRequest::~AcceptRequest() = default;

BluetoothSocketBlueZ::ConnectionRequest::ConnectionRequest()
    : accepting(false), cancelled(false) {}

BluetoothSocketBlueZ::ConnectionRequest::~ConnectionRequest() = default;

BluetoothSocketBlueZ::BluetoothSocketBlueZ(
    scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
    scoped_refptr<BluetoothSocketThread> socket_thread)
    : BluetoothSocketNet(ui_task_runner, socket_thread), profile_(nullptr) {}

BluetoothSocketBlueZ::~BluetoothSocketBlueZ() {
  DCHECK(!profile_);

  if (adapter_.get()) {
    adapter_->RemoveObserver(this);
    adapter_ = nullptr;
  }
}

void BluetoothSocketBlueZ::Connect(
    const BluetoothDeviceBlueZ* device,
    const BluetoothUUID& uuid,
    SecurityLevel security_level,
    const base::Closure& success_callback,
    const ErrorCompletionCallback& error_callback) {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());
  DCHECK(!profile_);

  if (!uuid.IsValid()) {
    error_callback.Run(kInvalidUUID);
    return;
  }

  device_address_ = device->GetAddress();
  device_path_ = device->object_path();
  uuid_ = uuid;
  options_.reset(new bluez::BluetoothProfileManagerClient::Options());
  if (security_level == SECURITY_LEVEL_LOW)
    options_->require_authentication.reset(new bool(false));

  adapter_ = device->adapter();

  RegisterProfile(device->adapter(), success_callback, error_callback);
}

void BluetoothSocketBlueZ::Listen(
    scoped_refptr<BluetoothAdapter> adapter,
    SocketType socket_type,
    const BluetoothUUID& uuid,
    const BluetoothAdapter::ServiceOptions& service_options,
    const base::Closure& success_callback,
    const ErrorCompletionCallback& error_callback) {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());
  DCHECK(!profile_);

  if (!uuid.IsValid()) {
    error_callback.Run(kInvalidUUID);
    return;
  }

  adapter_ = adapter;
  adapter_->AddObserver(this);

  uuid_ = uuid;
  options_.reset(new bluez::BluetoothProfileManagerClient::Options());
  if (service_options.name)
    options_->name.reset(new std::string(*service_options.name));

  switch (socket_type) {
    case kRfcomm:
      options_->channel.reset(
          new uint16_t(service_options.channel ? *service_options.channel : 0));
      break;
    case kL2cap:
      options_->psm.reset(
          new uint16_t(service_options.psm ? *service_options.psm : 0));
      break;
    default:
      NOTREACHED();
  }

  RegisterProfile(static_cast<BluetoothAdapterBlueZ*>(adapter.get()),
                  success_callback, error_callback);
}

void BluetoothSocketBlueZ::Close() {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());

  if (profile_)
    UnregisterProfile();

  // In the case below, where an asynchronous task gets posted on the socket
  // thread in BluetoothSocketNet::Close, a reference will be held to this
  // socket by the callback. This may cause the BluetoothAdapter to outlive
  // BluezDBusManager during shutdown if that callback executes too late.
  if (adapter_.get()) {
    adapter_->RemoveObserver(this);
    adapter_ = nullptr;
  }

  if (!device_path_.value().empty()) {
    BluetoothSocketNet::Close();
  } else {
    DoCloseListening();
  }
}

void BluetoothSocketBlueZ::Disconnect(const base::Closure& callback) {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());

  if (profile_)
    UnregisterProfile();

  if (!device_path_.value().empty()) {
    BluetoothSocketNet::Disconnect(callback);
  } else {
    DoCloseListening();
    callback.Run();
  }
}

void BluetoothSocketBlueZ::Accept(
    const AcceptCompletionCallback& success_callback,
    const ErrorCompletionCallback& error_callback) {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());

  if (!device_path_.value().empty()) {
    error_callback.Run(kSocketNotListening);
    return;
  }

  // Only one pending accept at a time
  if (accept_request_.get()) {
    error_callback.Run(net::ErrorToString(net::ERR_IO_PENDING));
    return;
  }

  accept_request_.reset(new AcceptRequest);
  accept_request_->success_callback = success_callback;
  accept_request_->error_callback = error_callback;

  if (connection_request_queue_.size() >= 1) {
    AcceptConnectionRequest();
  }
}

void BluetoothSocketBlueZ::RegisterProfile(
    BluetoothAdapterBlueZ* adapter,
    const base::Closure& success_callback,
    const ErrorCompletionCallback& error_callback) {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());
  DCHECK(!profile_);
  DCHECK(adapter);

  // If the adapter is not present, this is a listening socket and the
  // adapter isn't running yet.  Report success and carry on;
  // the profile will be registered when the daemon becomes available.
  if (!adapter->IsPresent()) {
    VLOG(1) << uuid_.canonical_value() << " on " << device_path_.value()
            << ": Delaying profile registration.";
    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, success_callback);
    return;
  }

  VLOG(1) << uuid_.canonical_value() << " on " << device_path_.value()
          << ": Acquiring profile.";

  adapter->UseProfile(uuid_, device_path_, *options_, this,
                      base::Bind(&BluetoothSocketBlueZ::OnRegisterProfile, this,
                                 success_callback, error_callback),
                      base::Bind(&BluetoothSocketBlueZ::OnRegisterProfileError,
                                 this, error_callback));
}

void BluetoothSocketBlueZ::OnRegisterProfile(
    const base::Closure& success_callback,
    const ErrorCompletionCallback& error_callback,
    BluetoothAdapterProfileBlueZ* profile) {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());
  DCHECK(!profile_);

  profile_ = profile;

  if (device_path_.value().empty()) {
    VLOG(1) << uuid_.canonical_value() << ": Profile registered.";
    success_callback.Run();
    return;
  }

  VLOG(1) << uuid_.canonical_value() << ": Got profile, connecting to "
          << device_path_.value();

  bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->ConnectProfile(
      device_path_, uuid_.canonical_value(),
      base::Bind(&BluetoothSocketBlueZ::OnConnectProfile, this,
                 success_callback),
      base::Bind(&BluetoothSocketBlueZ::OnConnectProfileError, this,
                 error_callback));
}

void BluetoothSocketBlueZ::OnRegisterProfileError(
    const ErrorCompletionCallback& error_callback,
    const std::string& error_message) {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());

  LOG(WARNING) << uuid_.canonical_value()
               << ": Failed to register profile: " << error_message;
  error_callback.Run(error_message);
}

void BluetoothSocketBlueZ::OnConnectProfile(
    const base::Closure& success_callback) {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());
  DCHECK(profile_);

  VLOG(1) << profile_->object_path().value() << ": Profile connected.";
  UnregisterProfile();
  success_callback.Run();
}

void BluetoothSocketBlueZ::OnConnectProfileError(
    const ErrorCompletionCallback& error_callback,
    const std::string& error_name,
    const std::string& error_message) {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());
  DCHECK(profile_);

  LOG(WARNING) << profile_->object_path().value()
               << ": Failed to connect profile: " << error_name << ": "
               << error_message;
  UnregisterProfile();
  error_callback.Run(error_message);
}

void BluetoothSocketBlueZ::AdapterPresentChanged(BluetoothAdapter* adapter,
                                                 bool present) {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());

  if (!present) {
    // Adapter removed, we can't use the profile anymore.
    UnregisterProfile();
    return;
  }

  DCHECK(!profile_);

  VLOG(1) << uuid_.canonical_value() << " on " << device_path_.value()
          << ": Acquiring profile.";

  static_cast<BluetoothAdapterBlueZ*>(adapter)->UseProfile(
      uuid_, device_path_, *options_, this,
      base::Bind(&BluetoothSocketBlueZ::OnInternalRegisterProfile, this),
      base::Bind(&BluetoothSocketBlueZ::OnInternalRegisterProfileError, this));
}

void BluetoothSocketBlueZ::OnInternalRegisterProfile(
    BluetoothAdapterProfileBlueZ* profile) {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());
  DCHECK(!profile_);

  profile_ = profile;

  VLOG(1) << uuid_.canonical_value() << ": Profile re-registered";
}

void BluetoothSocketBlueZ::OnInternalRegisterProfileError(
    const std::string& error_message) {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());

  LOG(WARNING) << "Failed to re-register profile: " << error_message;
}

void BluetoothSocketBlueZ::Released() {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());
  DCHECK(profile_);

  VLOG(1) << profile_->object_path().value() << ": Release";
}

void BluetoothSocketBlueZ::NewConnection(
    const dbus::ObjectPath& device_path,
    base::ScopedFD fd,
    const bluez::BluetoothProfileServiceProvider::Delegate::Options& options,
    const ConfirmationCallback& callback) {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());

  VLOG(1) << uuid_.canonical_value()
          << ": New connection from device: " << device_path.value();

  if (!device_path_.value().empty()) {
    DCHECK(device_path_ == device_path);

    socket_thread()->task_runner()->PostTask(
        FROM_HERE,
        base::BindOnce(&BluetoothSocketBlueZ::DoNewConnection, this,
                       device_path_, std::move(fd), options, callback));
  } else {
    auto request = std::make_unique<ConnectionRequest>();
    request->device_path = device_path;
    request->fd = std::move(fd);
    request->options = options;
    request->callback = callback;

    connection_request_queue_.push(std::move(request));
    VLOG(1) << uuid_.canonical_value() << ": Connection is now pending.";
    if (accept_request_) {
      AcceptConnectionRequest();
    }
  }
}

void BluetoothSocketBlueZ::RequestDisconnection(
    const dbus::ObjectPath& device_path,
    const ConfirmationCallback& callback) {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());
  DCHECK(profile_);

  VLOG(1) << profile_->object_path().value() << ": Request disconnection";
  callback.Run(SUCCESS);
}

void BluetoothSocketBlueZ::Cancel() {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());
  DCHECK(profile_);

  VLOG(1) << profile_->object_path().value() << ": Cancel";

  if (connection_request_queue_.empty())
    return;

  // If the front request is being accepted mark it as cancelled, otherwise
  // just pop it from the queue.
  ConnectionRequest* request = connection_request_queue_.front().get();
  if (!request->accepting) {
    request->cancelled = true;
  } else {
    connection_request_queue_.pop();
  }
}

void BluetoothSocketBlueZ::AcceptConnectionRequest() {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());
  DCHECK(accept_request_.get());
  DCHECK(connection_request_queue_.size() >= 1);
  DCHECK(profile_);

  VLOG(1) << profile_->object_path().value()
          << ": Accepting pending connection.";

  ConnectionRequest* request = connection_request_queue_.front().get();
  request->accepting = true;

  BluetoothDeviceBlueZ* device =
      static_cast<BluetoothAdapterBlueZ*>(adapter_.get())
          ->GetDeviceWithPath(request->device_path);
  DCHECK(device);

  scoped_refptr<BluetoothSocketBlueZ> client_socket =
      BluetoothSocketBlueZ::CreateBluetoothSocket(ui_task_runner(),
                                                  socket_thread());

  client_socket->device_address_ = device->GetAddress();
  client_socket->device_path_ = request->device_path;
  client_socket->uuid_ = uuid_;

  socket_thread()->task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(
          &BluetoothSocketBlueZ::DoNewConnection, client_socket,
          request->device_path, std::move(request->fd), request->options,
          base::BindRepeating(&BluetoothSocketBlueZ::OnNewConnection, this,
                              client_socket, request->callback)));
}

void BluetoothSocketBlueZ::DoNewConnection(
    const dbus::ObjectPath& device_path,
    base::ScopedFD fd,
    const bluez::BluetoothProfileServiceProvider::Delegate::Options& options,
    const ConfirmationCallback& callback) {
  DCHECK(socket_thread()->task_runner()->RunsTasksInCurrentSequence());
  base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::MAY_BLOCK);

  if (!fd.is_valid()) {
    LOG(WARNING) << uuid_.canonical_value() << " :" << fd.get()
                 << ": Invalid file descriptor received from Bluetooth Daemon.";
    ui_task_runner()->PostTask(FROM_HERE, base::BindOnce(callback, REJECTED));
    return;
  }

  if (tcp_socket()) {
    LOG(WARNING) << uuid_.canonical_value() << ": Already connected";
    ui_task_runner()->PostTask(FROM_HERE, base::BindOnce(callback, REJECTED));
    return;
  }

  ResetTCPSocket();

  // Note: We don't have a meaningful |IPEndPoint|, but that is ok since the
  // TCPSocket implementation does not actually require one.
  int net_result =
      tcp_socket()->AdoptConnectedSocket(fd.release(), net::IPEndPoint());
  if (net_result != net::OK) {
    LOG(WARNING) << uuid_.canonical_value() << ": Error adopting socket: "
                 << std::string(net::ErrorToString(net_result));
    ui_task_runner()->PostTask(FROM_HERE, base::BindOnce(callback, REJECTED));
    return;
  }
  ui_task_runner()->PostTask(FROM_HERE, base::BindOnce(callback, SUCCESS));
}

void BluetoothSocketBlueZ::OnNewConnection(
    scoped_refptr<BluetoothSocket> socket,
    const ConfirmationCallback& callback,
    Status status) {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());
  DCHECK(accept_request_.get());
  DCHECK(connection_request_queue_.size() >= 1);

  std::unique_ptr<ConnectionRequest> request =
      std::move(connection_request_queue_.front());
  if (status == SUCCESS && !request->cancelled) {
    BluetoothDeviceBlueZ* device =
        static_cast<BluetoothAdapterBlueZ*>(adapter_.get())
            ->GetDeviceWithPath(request->device_path);
    DCHECK(device);

    accept_request_->success_callback.Run(device, socket);
  } else {
    accept_request_->error_callback.Run(kAcceptFailed);
  }

  accept_request_.reset(nullptr);
  connection_request_queue_.pop();

  callback.Run(status);
}

void BluetoothSocketBlueZ::DoCloseListening() {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());

  if (accept_request_) {
    accept_request_->error_callback.Run(
        net::ErrorToString(net::ERR_CONNECTION_CLOSED));
    accept_request_.reset(nullptr);
  }

  while (connection_request_queue_.size() > 0) {
    connection_request_queue_.front()->callback.Run(REJECTED);
    connection_request_queue_.pop();
  }
}

void BluetoothSocketBlueZ::UnregisterProfile() {
  DCHECK(ui_task_runner()->RunsTasksInCurrentSequence());
  DCHECK(profile_);

  VLOG(1) << profile_->object_path().value() << ": Release profile";

  static_cast<BluetoothAdapterBlueZ*>(adapter_.get())
      ->ReleaseProfile(device_path_, profile_);
  profile_ = nullptr;
}

}  // namespace bluez
