// Copyright 2019 The Fuchsia 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 "connection.h"

#include <endian.h>

#include "command_channel.h"
#include "defaults.h"
#include "lib/async/default.h"
#include "src/connectivity/bluetooth/core/bt-host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/hci.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/status.h"
#include "src/lib/fxl/strings/string_printf.h"
#include "transport.h"

namespace bt {
namespace hci {

// Production implementation of the Connection class against a HCI transport.
class ConnectionImpl final : public Connection {
 public:
  ConnectionImpl(ConnectionHandle handle, LinkType ll_type, Role role,
                 const DeviceAddress& local_address, const DeviceAddress& peer_address,
                 fxl::RefPtr<Transport> hci);
  ~ConnectionImpl() override;

  // Connection overrides:
  fxl::WeakPtr<Connection> WeakPtr() override;
  bool StartEncryption() override;
  State state() const { return conn_state_; }

  // Sends HCI Disconnect command with |reason|. Takes over handling of HCI
  // Disconnection Complete event with a lambda so that connection instance can be safely destroyed
  // immediately.
  void Disconnect(StatusCode reason) override;

  void set_state(State state) { conn_state_ = state; };

 private:
  // Start the BR/EDR link layer encryption. |ltk_| and |ltk_type_| must have already been set and
  // may be used for bonding and detecting the security properties following the encryption enable.
  bool BrEdrStartEncryption();

  // Start the LE link layer authentication procedure using the given |ltk|.
  bool LEStartEncryption(const LinkKey& ltk);

  // Called when encryption is enabled or disabled as a result of the link layer
  // encryption "start" or "pause" procedure. If |status| indicates failure,
  // then this method will disconnect the link before notifying the encryption
  // change handler.
  void HandleEncryptionStatus(Status status, bool enabled);

  // Request the current encryption key size and call |key_size_validity_cb|
  // when the controller responds. |key_size_validity_cb| will be called with a
  // success only if the link is encrypted with a key of size at least
  // |hci::kMinEncryptionKeySize|. Only valid for ACL-U connections.
  void ValidateAclEncryptionKeySize(hci::StatusCallback key_size_validity_cb);

  // HCI event handlers.
  CommandChannel::EventCallbackResult OnEncryptionChangeEvent(const EventPacket& event);
  CommandChannel::EventCallbackResult OnEncryptionKeyRefreshCompleteEvent(const EventPacket& event);
  CommandChannel::EventCallbackResult OnLELongTermKeyRequestEvent(const EventPacket& event);
  CommandChannel::EventCallbackResult OnDisconnectionCompleteEvent(const EventPacket& event);

  // Checks |event|, unregisters link, and clears pending packets count.
  // If the disconnection was initiated by the peer, call |peer_disconnect_callback|.
  // Returns true if event was valid and for this connection.
  // This method is static so that it can be called in an event handler
  // after this object has been destroyed.
  static CommandChannel::EventCallbackResult OnDisconnectionComplete(
      fxl::WeakPtr<ConnectionImpl> self, ConnectionHandle handle, fxl::RefPtr<Transport> hci,
      const EventPacket& event);

  fxl::ThreadChecker thread_checker_;

  // IDs for encryption related HCI event handlers.
  CommandChannel::EventHandlerId enc_change_id_;
  CommandChannel::EventHandlerId enc_key_refresh_cmpl_id_;
  CommandChannel::EventHandlerId le_ltk_request_id_;

  // The underlying HCI transport.
  fxl::RefPtr<Transport> hci_;

  State conn_state_;

  // Keep this as the last member to make sure that all weak pointers are
  // invalidated before other members get destroyed.
  fxl::WeakPtrFactory<ConnectionImpl> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ConnectionImpl);
};

namespace {

std::string LinkTypeToString(Connection::LinkType type) {
  switch (type) {
    case Connection::LinkType::kACL:
      return "ACL";
    case Connection::LinkType::kSCO:
      return "SCO";
    case Connection::LinkType::kESCO:
      return "ESCO";
    case Connection::LinkType::kLE:
      return "LE";
  }

  ZX_PANIC("invalid link type: %u", static_cast<unsigned int>(type));
  return "(invalid)";
}

template <
    CommandChannel::EventCallbackResult (ConnectionImpl::*EventHandlerMethod)(const EventPacket&)>
CommandChannel::EventCallback BindEventHandler(fxl::WeakPtr<ConnectionImpl> conn) {
  return [conn](const auto& event) {
    if (conn) {
      return ((conn.get())->*EventHandlerMethod)(event);
    }
    return CommandChannel::EventCallbackResult::kRemove;
  };
}

}  // namespace

// ====== Connection member methods  =====

// static
std::unique_ptr<Connection> Connection::CreateLE(ConnectionHandle handle, Role role,
                                                 const DeviceAddress& local_address,
                                                 const DeviceAddress& peer_address,
                                                 const LEConnectionParameters& params,
                                                 fxl::RefPtr<Transport> hci) {
  ZX_DEBUG_ASSERT(local_address.type() != DeviceAddress::Type::kBREDR);
  ZX_DEBUG_ASSERT(peer_address.type() != DeviceAddress::Type::kBREDR);
  auto conn = std::make_unique<ConnectionImpl>(handle, LinkType::kLE, role, local_address,
                                               peer_address, hci);
  conn->set_low_energy_parameters(params);
  return conn;
}

// static
std::unique_ptr<Connection> Connection::CreateACL(ConnectionHandle handle, Role role,
                                                  const DeviceAddress& local_address,
                                                  const DeviceAddress& peer_address,
                                                  fxl::RefPtr<Transport> hci) {
  ZX_DEBUG_ASSERT(local_address.type() == DeviceAddress::Type::kBREDR);
  ZX_DEBUG_ASSERT(peer_address.type() == DeviceAddress::Type::kBREDR);
  auto conn = std::make_unique<ConnectionImpl>(handle, LinkType::kACL, role, local_address,
                                               peer_address, hci);
  return conn;
}

Connection::Connection(ConnectionHandle handle, LinkType ll_type, Role role,
                       const DeviceAddress& local_address, const DeviceAddress& peer_address)
    : ll_type_(ll_type),
      handle_(handle),
      role_(role),
      local_address_(local_address),
      peer_address_(peer_address) {
  ZX_DEBUG_ASSERT(handle_);
}

std::string Connection::ToString() const {
  std::string params = "";
  if (ll_type() == LinkType::kLE) {
    params = ", " + le_params_.ToString();
  }
  return fxl::StringPrintf("(%s link - handle: %#.4x, role: %s, address: %s%s)",
                           LinkTypeToString(ll_type_).c_str(), handle_,
                           role_ == Role::kMaster ? "master" : "slave",
                           peer_address_.ToString().c_str(), params.c_str());
}

// ====== ConnectionImpl member methods ======

ConnectionImpl::ConnectionImpl(ConnectionHandle handle, LinkType ll_type, Role role,
                               const DeviceAddress& local_address,
                               const DeviceAddress& peer_address, fxl::RefPtr<Transport> hci)
    : Connection(handle, ll_type, role, local_address, peer_address),
      hci_(hci),
      conn_state_(State::kConnected),
      weak_ptr_factory_(this) {
  ZX_DEBUG_ASSERT(hci_);

  auto self = weak_ptr_factory_.GetWeakPtr();

  enc_change_id_ = hci_->command_channel()->AddEventHandler(
      kEncryptionChangeEventCode, BindEventHandler<&ConnectionImpl::OnEncryptionChangeEvent>(self),
      async_get_default_dispatcher());

  enc_key_refresh_cmpl_id_ = hci_->command_channel()->AddEventHandler(
      kEncryptionKeyRefreshCompleteEventCode,
      BindEventHandler<&ConnectionImpl::OnEncryptionKeyRefreshCompleteEvent>(self),
      async_get_default_dispatcher());

  le_ltk_request_id_ = hci_->command_channel()->AddLEMetaEventHandler(
      kLELongTermKeyRequestSubeventCode,
      BindEventHandler<&ConnectionImpl::OnLELongTermKeyRequestEvent>(self),
      async_get_default_dispatcher());

  auto disconn_complete_handler = [self, handle, hci](auto& event) {
    return ConnectionImpl::OnDisconnectionComplete(self, handle, hci, event);
  };

  hci_->command_channel()->AddEventHandler(
      kDisconnectionCompleteEventCode, disconn_complete_handler, async_get_default_dispatcher());

  // Allow packets to be sent on this link immediately.
  hci->acl_data_channel()->RegisterLink(handle, ll_type);
}

ConnectionImpl::~ConnectionImpl() {
  if (conn_state_ == Connection::State::kConnected) {
    Disconnect(StatusCode::kRemoteUserTerminatedConnection);
  }

  // Unregister HCI event handlers.
  hci_->command_channel()->RemoveEventHandler(enc_change_id_);
  hci_->command_channel()->RemoveEventHandler(enc_key_refresh_cmpl_id_);
  hci_->command_channel()->RemoveEventHandler(le_ltk_request_id_);
}

fxl::WeakPtr<Connection> ConnectionImpl::WeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }

CommandChannel::EventCallbackResult ConnectionImpl::OnDisconnectionComplete(
    fxl::WeakPtr<ConnectionImpl> self, ConnectionHandle handle, fxl::RefPtr<Transport> hci,
    const EventPacket& event) {
  ZX_DEBUG_ASSERT(event.event_code() == kDisconnectionCompleteEventCode);

  if (event.view().payload_size() != sizeof(DisconnectionCompleteEventParams)) {
    bt_log(WARN, "hci", "malformed disconnection complete event");
    return CommandChannel::EventCallbackResult::kContinue;
  }

  const auto& params = event.params<DisconnectionCompleteEventParams>();
  const auto event_handle = le16toh(params.connection_handle);

  // Silently ignore this event as it isn't meant for this connection.
  if (event_handle != handle) {
    return CommandChannel::EventCallbackResult::kContinue;
  }

  bt_log(INFO, "hci", "disconnection complete - %s, handle: %#.4x, reason: %#.2x",
         bt_str(event.ToStatus()), handle, params.reason);

  // Stop data flow and revoke queued packets for this connection.
  hci->acl_data_channel()->UnregisterLink(handle);

  // Notify ACL data channel that packets have been flushed from controller buffer.
  hci->acl_data_channel()->ClearControllerPacketCount(handle);

  if (!self) {
    return CommandChannel::EventCallbackResult::kRemove;
  }

  self->set_state(State::kDisconnected);

  // Peer disconnect. Callback may destroy connection.
  if (self->peer_disconnect_callback()) {
    self->peer_disconnect_callback()(self.get());
  }

  return CommandChannel::EventCallbackResult::kRemove;
}

void ConnectionImpl::Disconnect(StatusCode reason) {
  ZX_ASSERT(conn_state_ == Connection::State::kConnected);

  conn_state_ = Connection::State::kWaitingForDisconnectionComplete;

  // Here we send a HCI_Disconnect command without waiting for it to complete.
  auto status_cb = [](auto id, const EventPacket& event) {
    ZX_DEBUG_ASSERT(event.event_code() == kCommandStatusEventCode);
    hci_is_error(event, TRACE, "hci", "ignoring disconnection failure");
  };

  auto disconn = CommandPacket::New(kDisconnect, sizeof(DisconnectCommandParams));
  auto params = disconn->mutable_payload<DisconnectCommandParams>();
  params->connection_handle = htole16(handle());
  params->reason = reason;

  bt_log(TRACE, "hci", "disconnecting connection (handle: %#.4x, reason: %#.2x)", handle(), reason);

  // Send HCI Disconnect.
  hci_->command_channel()->SendCommand(std::move(disconn), async_get_default_dispatcher(),
                                       std::move(status_cb), kCommandStatusEventCode);
}

bool ConnectionImpl::StartEncryption() {
  ZX_DEBUG_ASSERT(thread_checker_.IsCreationThreadCurrent());
  if (conn_state_ != Connection::State::kConnected) {
    bt_log(TRACE, "hci", "connection closed; cannot start encryption");
    return false;
  }

  if (ll_type() != LinkType::kLE) {
    return BrEdrStartEncryption();
  }

  if (role() != Role::kMaster) {
    bt_log(TRACE, "hci", "only the master can start encryption");
    return false;
  }

  if (!ltk()) {
    bt_log(TRACE, "hci", "connection has no LTK; cannot start encryption");
    return false;
  }

  return LEStartEncryption(*ltk());
}

bool ConnectionImpl::BrEdrStartEncryption() {
  ZX_DEBUG_ASSERT(thread_checker_.IsCreationThreadCurrent());

  ZX_ASSERT(ltk().has_value() == ltk_type().has_value());
  if (!ltk().has_value()) {
    bt_log(TRACE, "hci", "connection link key type has not been set; not starting encryption");
    return false;
  }

  auto cmd =
      CommandPacket::New(kSetConnectionEncryption, sizeof(SetConnectionEncryptionCommandParams));
  auto* params = cmd->mutable_payload<SetConnectionEncryptionCommandParams>();
  params->connection_handle = htole16(handle());
  params->encryption_enable = GenericEnableParam::kEnable;

  auto self = weak_ptr_factory_.GetWeakPtr();
  auto status_cb = [self, handle = handle()](auto id, const EventPacket& event) {
    if (!self) {
      return;
    }

    const Status status = event.ToStatus();
    if (!bt_is_error(status, ERROR, "hci-bredr", "could not set encryption on link %#.04x",
                     handle)) {
      bt_log(TRACE, "hci-bredr", "requested encryption start on %#.04x", handle);
      return;
    }

    if (self->encryption_change_callback()) {
      self->encryption_change_callback()(status, false);
    }
  };

  return hci_->command_channel()->SendCommand(std::move(cmd), async_get_default_dispatcher(),
                                              std::move(status_cb), kCommandStatusEventCode) != 0u;
}

bool ConnectionImpl::LEStartEncryption(const LinkKey& ltk) {
  ZX_DEBUG_ASSERT(thread_checker_.IsCreationThreadCurrent());
  ZX_ASSERT(!ltk_type().has_value());

  // TODO(BT-208): Tell the data channel to stop data flow.

  auto cmd = CommandPacket::New(kLEStartEncryption, sizeof(LEStartEncryptionCommandParams));
  auto* params = cmd->mutable_payload<LEStartEncryptionCommandParams>();
  params->connection_handle = htole16(handle());
  params->random_number = htole64(ltk.rand());
  params->encrypted_diversifier = htole16(ltk.ediv());
  params->long_term_key = ltk.value();

  auto self = weak_ptr_factory_.GetWeakPtr();
  auto status_cb = [self, handle = handle()](auto id, const EventPacket& event) {
    if (!self) {
      return;
    }

    const Status status = event.ToStatus();
    if (!bt_is_error(status, ERROR, "hci-le", "could not set encryption on link %#.04x", handle)) {
      bt_log(TRACE, "hci-le", "requested encryption start on %#.04x", handle);
      return;
    }

    if (self->encryption_change_callback()) {
      self->encryption_change_callback()(status, false);
    }
  };

  return hci_->command_channel()->SendCommand(std::move(cmd), async_get_default_dispatcher(),
                                              std::move(status_cb), kCommandStatusEventCode) != 0u;
}

void ConnectionImpl::HandleEncryptionStatus(Status status, bool enabled) {
  // "On an authentication failure, the connection shall be automatically
  // disconnected by the Link Layer." (HCI_LE_Start_Encryption, Vol 2, Part E,
  // 7.8.24). We make sure of this by telling the controller to disconnect.
  //
  // For ACL-U, Vol 3, Part C, 5.2.2.1.1 and 5.2.2.2.1 mention disconnecting the
  // link after pairing failures (supported by TS GAP/SEC/SEM/BV-10-C), but do
  // not specify actions to take after encryption failures. We'll choose to
  // disconnect ACL links after encryption failure.
  if (!status) {
    Disconnect(StatusCode::kAuthenticationFailure);
  } else {
    // TODO(BT-208): Tell the data channel to resume data flow.
  }

  if (!encryption_change_callback()) {
    bt_log(TRACE, "hci", "%#.4x: no encryption status callback assigned", handle());
    return;
  }

  encryption_change_callback()(status, enabled);
}

void ConnectionImpl::ValidateAclEncryptionKeySize(hci::StatusCallback key_size_validity_cb) {
  ZX_ASSERT(ll_type() == LinkType::kACL);
  ZX_ASSERT(conn_state_ == Connection::State::kConnected);

  auto cmd = CommandPacket::New(kReadEncryptionKeySize, sizeof(ReadEncryptionKeySizeParams));
  auto* params = cmd->mutable_payload<ReadEncryptionKeySizeParams>();
  params->connection_handle = htole16(handle());

  auto status_cb = [self = weak_ptr_factory_.GetWeakPtr(),
                    valid_cb = std::move(key_size_validity_cb)](auto, const EventPacket& event) {
    if (!self) {
      return;
    }

    Status status = event.ToStatus();
    if (!bt_is_error(status, ERROR, "hci", "Could not read ACL encryption key size on %#.4x",
                     self->handle())) {
      const auto& return_params = *event.return_params<ReadEncryptionKeySizeReturnParams>();
      const auto key_size = return_params.key_size;
      bt_log(SPEW, "hci", "%#.4x: encryption key size %hhu", self->handle(), key_size);

      if (key_size < hci::kMinEncryptionKeySize) {
        bt_log(WARN, "hci", "%#.4x: encryption key size %hhu insufficient", self->handle(),
               key_size);
        status = Status(HostError::kInsufficientSecurity);
      }
    }
    valid_cb(status);
  };

  hci_->command_channel()->SendCommand(std::move(cmd), async_get_default_dispatcher(),
                                       std::move(status_cb));
}

CommandChannel::EventCallbackResult ConnectionImpl::OnEncryptionChangeEvent(
    const EventPacket& event) {
  ZX_DEBUG_ASSERT(event.event_code() == kEncryptionChangeEventCode);
  ZX_DEBUG_ASSERT(thread_checker_.IsCreationThreadCurrent());

  if (event.view().payload_size() != sizeof(EncryptionChangeEventParams)) {
    bt_log(WARN, "hci", "malformed encryption change event");
    return CommandChannel::EventCallbackResult::kContinue;
  }

  const auto& params = event.params<EncryptionChangeEventParams>();
  hci::ConnectionHandle handle = le16toh(params.connection_handle);

  // Silently ignore the event as it isn't meant for this connection.
  if (handle != this->handle()) {
    return CommandChannel::EventCallbackResult::kContinue;
  }

  if (conn_state_ != Connection::State::kConnected) {
    bt_log(TRACE, "hci", "encryption change ignored: connection closed");
    return CommandChannel::EventCallbackResult::kContinue;
  }

  Status status(params.status);
  bool enabled = params.encryption_enabled != EncryptionStatus::kOff;

  bt_log(TRACE, "hci", "encryption change (%s) %s", enabled ? "enabled" : "disabled",
         status.ToString().c_str());

  if (ll_type() == LinkType::kACL && status && enabled) {
    ValidateAclEncryptionKeySize([this](const Status& key_valid_status) {
      HandleEncryptionStatus(key_valid_status, true /* enabled */);
    });
    return CommandChannel::EventCallbackResult::kContinue;
  }

  HandleEncryptionStatus(status, enabled);

  return CommandChannel::EventCallbackResult::kContinue;
}

CommandChannel::EventCallbackResult ConnectionImpl::OnEncryptionKeyRefreshCompleteEvent(
    const EventPacket& event) {
  ZX_DEBUG_ASSERT(thread_checker_.IsCreationThreadCurrent());
  ZX_DEBUG_ASSERT(event.event_code() == kEncryptionKeyRefreshCompleteEventCode);

  if (event.view().payload_size() != sizeof(EncryptionKeyRefreshCompleteEventParams)) {
    bt_log(WARN, "hci", "malformed encryption key refresh complete event");
    return CommandChannel::EventCallbackResult::kContinue;
  }

  const auto& params = event.params<EncryptionKeyRefreshCompleteEventParams>();
  hci::ConnectionHandle handle = le16toh(params.connection_handle);

  // Silently ignore this event as it isn't meant for this connection.
  if (handle != this->handle()) {
    return CommandChannel::EventCallbackResult::kContinue;
  }

  if (conn_state_ != Connection::State::kConnected) {
    bt_log(TRACE, "hci", "encryption key refresh ignored: connection closed");
    return CommandChannel::EventCallbackResult::kContinue;
  }

  Status status(params.status);

  bt_log(TRACE, "hci", "encryption key refresh %s", status.ToString().c_str());

  // Report that encryption got disabled on failure status. The accuracy of this
  // isn't that important since the link will be disconnected.
  HandleEncryptionStatus(status, static_cast<bool>(status));

  return CommandChannel::EventCallbackResult::kContinue;
}

CommandChannel::EventCallbackResult ConnectionImpl::OnLELongTermKeyRequestEvent(
    const EventPacket& event) {
  ZX_DEBUG_ASSERT(thread_checker_.IsCreationThreadCurrent());
  ZX_DEBUG_ASSERT(event.event_code() == kLEMetaEventCode);
  ZX_DEBUG_ASSERT(event.params<LEMetaEventParams>().subevent_code ==
                  kLELongTermKeyRequestSubeventCode);

  auto* params = event.le_event_params<LELongTermKeyRequestSubeventParams>();
  if (!params) {
    bt_log(WARN, "hci", "malformed LE LTK request event");
    return CommandChannel::EventCallbackResult::kContinue;
  }

  hci::ConnectionHandle handle = le16toh(params->connection_handle);

  // Silently ignore the event as it isn't meant for this connection.
  if (handle != this->handle()) {
    return CommandChannel::EventCallbackResult::kContinue;
  }

  // TODO(BT-767): Tell the data channel to stop data flow.

  std::unique_ptr<CommandPacket> cmd;

  uint64_t rand = le64toh(params->random_number);
  uint16_t ediv = le16toh(params->encrypted_diversifier);

  bt_log(TRACE, "hci", "LE LTK request - ediv: %#.4x, rand: %#.16lx", ediv, rand);
  if (ltk() && ltk()->rand() == rand && ltk()->ediv() == ediv) {
    cmd = CommandPacket::New(kLELongTermKeyRequestReply,
                             sizeof(LELongTermKeyRequestReplyCommandParams));
    auto* params = cmd->mutable_payload<LELongTermKeyRequestReplyCommandParams>();

    params->connection_handle = htole16(handle);
    params->long_term_key = ltk()->value();
  } else {
    bt_log(TRACE, "hci-le", "LTK request rejected");

    cmd = CommandPacket::New(kLELongTermKeyRequestNegativeReply,
                             sizeof(LELongTermKeyRequestNegativeReplyCommandParams));
    auto* params = cmd->mutable_payload<LELongTermKeyRequestNegativeReplyCommandParams>();
    params->connection_handle = htole16(handle);
  }

  auto status_cb = [](auto id, const EventPacket& event) {
    hci_is_error(event, TRACE, "hci-le", "failed to reply to LTK request");
  };
  hci_->command_channel()->SendCommand(std::move(cmd), async_get_default_dispatcher(),
                                       std::move(status_cb));
  return CommandChannel::EventCallbackResult::kContinue;
}

}  // namespace hci
}  // namespace bt
