// Copyright 2017 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 "src/connectivity/bluetooth/core/bt-host/common/log.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 common::DeviceAddress& local_address,
                 const common::DeviceAddress& peer_address,
                 fxl::RefPtr<Transport> hci);
  ~ConnectionImpl() override;

  // Connection overrides:
  fxl::WeakPtr<Connection> WeakPtr() override;
  void Close(StatusCode reason) override;
  bool StartEncryption() override;

 private:
  // Starts 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.
  void OnEncryptionChangeEvent(const EventPacket& event);
  void OnEncryptionKeyRefreshCompleteEvent(const EventPacket& event);
  void OnLELongTermKeyRequestEvent(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_;

  // 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 <void (ConnectionImpl::*EventHandlerMethod)(const EventPacket&)>
CommandChannel::EventCallback BindEventHandler(
    fxl::WeakPtr<ConnectionImpl> conn) {
  return [conn](const auto& event) {
    if (conn) {
      ((conn.get())->*EventHandlerMethod)(event);
    }
  };
}

}  // namespace

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

// static
std::unique_ptr<Connection> Connection::CreateLE(
    ConnectionHandle handle, Role role,
    const common::DeviceAddress& local_address,
    const common::DeviceAddress& peer_address,
    const LEConnectionParameters& params, fxl::RefPtr<Transport> hci) {
  ZX_DEBUG_ASSERT(local_address.type() != common::DeviceAddress::Type::kBREDR);
  ZX_DEBUG_ASSERT(peer_address.type() != common::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 common::DeviceAddress& local_address,
    const common::DeviceAddress& peer_address, fxl::RefPtr<Transport> hci) {
  ZX_DEBUG_ASSERT(local_address.type() == common::DeviceAddress::Type::kBREDR);
  ZX_DEBUG_ASSERT(peer_address.type() == common::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 common::DeviceAddress& local_address,
                       const common::DeviceAddress& peer_address)
    : ll_type_(ll_type),
      handle_(handle),
      role_(role),
      is_open_(true),
      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 common::DeviceAddress& local_address,
                               const common::DeviceAddress& peer_address,
                               fxl::RefPtr<Transport> hci)
    : Connection(handle, ll_type, role, local_address, peer_address),
      hci_(hci),
      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());
}

ConnectionImpl::~ConnectionImpl() {
  // Tell ACL data channel to clear all ACL buffering state related to this
  // link.
  hci_->acl_data_channel()->ClearLinkState(handle());

  // 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_);

  Close(StatusCode::kRemoteUserTerminatedConnection);
}

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

void ConnectionImpl::Close(StatusCode reason) {
  ZX_DEBUG_ASSERT(thread_checker_.IsCreationThreadCurrent());
  if (!is_open())
    return;

  // The connection is immediately marked as closed as there is no reasonable
  // way for a Disconnect procedure to fail, i.e. it always succeeds. If the
  // controller reports failure in the Disconnection Complete event, it should
  // be because we gave it an already disconnected handle which we would treat
  // as success.
  //
  // TODO(armansito): The procedure could also fail if "the command was not
  // presently allowed". Retry in that case?
  set_closed();

  // 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);
    const auto& params = event.view().payload<CommandStatusEventParams>();
    if (params.status != StatusCode::kSuccess) {
      bt_log(WARN, "hci", "ignoring failed disconnection status: %#.2x",
             params.status);
    }
  };

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

  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 (!is_open()) {
    bt_log(TRACE, "hci", "connection closed; cannot start encryption");
    return false;
  }

  if (ll_type() != LinkType::kLE) {
    bt_log(TRACE, "hci", "encrypting BR/EDR links not supported");

    // TODO(BT-374): Support this.
    return false;
  }

  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::LEStartEncryption(const LinkKey& ltk) {
  ZX_DEBUG_ASSERT(thread_checker_.IsCreationThreadCurrent());

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

  auto cmd = CommandPacket::New(kLEStartEncryption,
                                sizeof(LEStartEncryptionCommandParams));
  auto* params =
      cmd->mutable_view()->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](auto id, const EventPacket& event) {
    if (!self) {
      return;
    }

    Status status = event.ToStatus();
    if (status) {
      bt_log(TRACE, "hci-le", "began authentication procedure");
      return;
    }

    bt_log(ERROR, "hci", "failed to start LE authentication: %s",
           status.ToString().c_str());
    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) {
    Close(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(is_open());

  auto cmd = CommandPacket::New(kReadEncryptionKeySize,
                                sizeof(ReadEncryptionKeySizeParams));
  auto* params =
      cmd->mutable_view()->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(common::HostError::kInsufficientSecurity);
      }
    }
    valid_cb(status);
  };

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

void 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;
  }

  const auto& params = event.view().payload<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;
  }

  if (!is_open()) {
    bt_log(TRACE, "hci", "encryption change ignored: connection closed");
    return;
  }

  Status status(params.status);
  bool enabled = params.encryption_enabled != 0;

  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;
  }

  HandleEncryptionStatus(status, enabled);
}

void 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;
  }

  const auto& params =
      event.view().payload<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;
  }

  if (!is_open()) {
    bt_log(TRACE, "hci", "encryption key refresh ignored: connection closed");
    return;
  }

  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));
}

void ConnectionImpl::OnLELongTermKeyRequestEvent(const EventPacket& event) {
  ZX_DEBUG_ASSERT(thread_checker_.IsCreationThreadCurrent());
  ZX_DEBUG_ASSERT(event.event_code() == kLEMetaEventCode);
  ZX_DEBUG_ASSERT(event.view().payload<LEMetaEventParams>().subevent_code ==
                  kLELongTermKeyRequestSubeventCode);

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

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

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

  // 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_view()
            ->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_view()
            ->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));
}

}  // namespace hci
}  // namespace bt
