// 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 "low_energy_connection_manager.h"

#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <lib/async/time.h>
#include <zircon/assert.h>
#include <zircon/syscalls.h>

#include <optional>

#include "pairing_delegate.h"
#include "peer.h"
#include "peer_cache.h"
#include "src/connectivity/bluetooth/core/bt-host/common/status.h"
#include "src/connectivity/bluetooth/core/bt-host/gatt/local_service_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/defaults.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/hci.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/local_address_delegate.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/transport.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/util.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/channel_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/pairing_state.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/smp.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/status.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/types.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/util.h"
#include "src/lib/fxl/strings/string_printf.h"

using bt::sm::BondableMode;

namespace bt {
namespace gap {

namespace {

static const hci::LEPreferredConnectionParameters kDefaultPreferredConnectionParameters(
    hci::defaults::kLEConnectionIntervalMin, hci::defaults::kLEConnectionIntervalMax,
    /*max_latency=*/0, hci::defaults::kLESupervisionTimeout);

}  // namespace

namespace internal {

// Represents the state of an active connection. Each instance is owned
// and managed by a LowEnergyConnectionManager and is kept alive as long as
// there is at least one LowEnergyConnectionRef that references it.
class LowEnergyConnection final : public sm::PairingState::Delegate {
 public:
  LowEnergyConnection(PeerId peer_id, std::unique_ptr<hci::Connection> link,
                      async_dispatcher_t* dispatcher,
                      fxl::WeakPtr<LowEnergyConnectionManager> conn_mgr,
                      fbl::RefPtr<data::Domain> data_domain, fbl::RefPtr<gatt::GATT> gatt)
      : peer_id_(peer_id),
        link_(std::move(link)),
        dispatcher_(dispatcher),
        conn_mgr_(conn_mgr),
        data_domain_(data_domain),
        gatt_(gatt),
        conn_pause_central_expiry_(zx::time(async_now(dispatcher_)) + kLEConnectionPauseCentral),
        weak_ptr_factory_(this) {
    ZX_DEBUG_ASSERT(peer_id_.IsValid());
    ZX_DEBUG_ASSERT(link_);
    ZX_DEBUG_ASSERT(dispatcher_);
    ZX_DEBUG_ASSERT(conn_mgr_);
    ZX_DEBUG_ASSERT(data_domain_);
    ZX_DEBUG_ASSERT(gatt_);

    link_->set_peer_disconnect_callback([conn_mgr](auto conn) {
      if (conn_mgr) {
        conn_mgr->OnPeerDisconnect(conn);
      }
    });
  }

  ~LowEnergyConnection() override {
    // Unregister this link from the GATT profile and the L2CAP plane. This
    // invalidates all L2CAP channels that are associated with this link.
    gatt_->RemoveConnection(peer_id());
    data_domain_->RemoveConnection(link_->handle());

    // Notify all active references that the link is gone. This will
    // synchronously notify all refs.
    CloseRefs();
  }

  LowEnergyConnectionRefPtr AddRef() {
    LowEnergyConnectionRefPtr conn_ref(new LowEnergyConnectionRef(peer_id_, handle(), conn_mgr_));
    ZX_ASSERT(conn_ref);

    refs_.insert(conn_ref.get());

    bt_log(TRACE, "gap-le", "added ref (handle %#.4x, count: %lu)", handle(), ref_count());

    return conn_ref;
  }

  void DropRef(LowEnergyConnectionRef* ref) {
    ZX_DEBUG_ASSERT(ref);

    __UNUSED size_t res = refs_.erase(ref);
    ZX_DEBUG_ASSERT_MSG(res == 1u, "DropRef called with wrong connection reference");
    bt_log(TRACE, "gap-le", "dropped ref (handle: %#.4x, count: %lu)", handle(), ref_count());
  }

  // Registers this connection with L2CAP and initializes the fixed channel
  // protocols.
  void InitializeFixedChannels(l2cap::LEConnectionParameterUpdateCallback cp_cb,
                               l2cap::LinkErrorCallback link_error_cb, BondableMode bondable_mode) {
    auto self = weak_ptr_factory_.GetWeakPtr();
    data_domain_->AddLEConnection(
        link_->handle(), link_->role(), std::move(link_error_cb), std::move(cp_cb),
        [self, bondable_mode](auto att, auto smp) {
          if (self) {
            self->OnL2capFixedChannelsOpened(std::move(att), std::move(smp), bondable_mode);
          }
        },
        [self](auto handle, auto level, auto cb) {
          if (self) {
            bt_log(TRACE, "gap-le", "received security upgrade request on L2CAP channel");
            ZX_DEBUG_ASSERT(self->link_->handle() == handle);
            self->OnSecurityRequest(level, std::move(cb));
          }
        });
  }

  // Tells the connection's pairing state to UpgradeSecurity to the desired level.
  void OnSecurityRequest(sm::SecurityLevel level, sm::StatusCallback cb) {
    ZX_ASSERT(pairing_);
    pairing_->UpgradeSecurity(level, [cb = std::move(cb)](sm::Status status, const auto& sp) {
      bt_log(INFO, "gap-le", "pairing status: %s, properties: %s", bt_str(status), bt_str(sp));
      cb(status);
    });
  }

  // Handles a pairing request (i.e. security upgrade) received from "higher levels", likely
  // initiated from GAP. This will only be used by pairing requests that are initiated
  // in the context of testing. May only be called on an already-established connection.
  void UpgradeSecurity(sm::SecurityLevel level, sm::BondableMode bondable_mode,
                       sm::StatusCallback cb) {
    ZX_ASSERT(pairing_);
    pairing_->set_bondable_mode(bondable_mode);
    OnSecurityRequest(level, std::move(cb));
  }

  // Cancels any on-going pairing procedures and sets up SMP to use the provided
  // new I/O capabilities for future pairing procedures.
  void ResetPairingState(sm::IOCapability ioc) { pairing_->Reset(ioc); }

  // Set callback that will be called after the kLEConnectionPausePeripheral timeout, or now if the
  // timeout has already finished.
  void on_peripheral_pause_timeout(fit::callback<void()> callback) {
    // Check if timeout already completed.
    if (conn_pause_peripheral_timeout_.has_value() &&
        !conn_pause_peripheral_timeout_->is_pending()) {
      callback();
      return;
    }
    conn_pause_peripheral_callback_ = std::move(callback);
  }

  // Should be called as soon as connection is established.
  // Calls |conn_pause_peripheral_callback_| after kLEConnectionPausePeripheral.
  void StartConnectionPausePeripheralTimeout() {
    ZX_ASSERT(!conn_pause_peripheral_timeout_.has_value());
    conn_pause_peripheral_timeout_.emplace([self = weak_ptr_factory_.GetWeakPtr()]() {
      if (!self) {
        return;
      }

      if (self->conn_pause_peripheral_callback_) {
        self->conn_pause_peripheral_callback_();
      }
    });
    conn_pause_peripheral_timeout_->PostDelayed(dispatcher_, kLEConnectionPausePeripheral);
  }

  // Posts |callback| to be called kLEConnectionPauseCentral after this connection was established.
  void PostCentralPauseTimeoutCallback(fit::callback<void()> callback) {
    async::PostTaskForTime(
        dispatcher_,
        [self = weak_ptr_factory_.GetWeakPtr(), cb = std::move(callback)]() mutable {
          if (self) {
            cb();
          }
        },
        conn_pause_central_expiry_);
  }

  size_t ref_count() const { return refs_.size(); }

  PeerId peer_id() const { return peer_id_; }
  hci::ConnectionHandle handle() const { return link_->handle(); }
  hci::Connection* link() const { return link_.get(); }
  BondableMode bondable_mode() const {
    ZX_DEBUG_ASSERT(pairing_);
    return pairing_->bondable_mode();
  }

 private:
  // Called by the L2CAP layer once the link has been registered and the fixed
  // channels have been opened.
  void OnL2capFixedChannelsOpened(fbl::RefPtr<l2cap::Channel> att, fbl::RefPtr<l2cap::Channel> smp,
                                  BondableMode bondable_mode) {
    if (!att || !smp) {
      bt_log(TRACE, "gap-le", "link was closed before opening fixed channels");
      return;
    }

    bt_log(TRACE, "gap-le", "ATT and SMP fixed channels open");

    // Obtain existing pairing data, if any.
    std::optional<sm::LTK> ltk;
    auto* peer = conn_mgr_->peer_cache()->FindById(peer_id());
    ZX_DEBUG_ASSERT_MSG(peer, "connected peer must be present in cache!");

    if (peer->le() && peer->le()->bond_data()) {
      // |ltk| will remain as std::nullopt if bonding data contains no LTK.
      ltk = peer->le()->bond_data()->ltk;
    }

    // Obtain the local I/O capabilities from the delegate. Default to
    // NoInputNoOutput if no delegate is available.
    auto io_cap = sm::IOCapability::kNoInputNoOutput;
    if (conn_mgr_->pairing_delegate()) {
      io_cap = conn_mgr_->pairing_delegate()->io_capability();
    }

    pairing_ = std::make_unique<sm::PairingState>(link_->WeakPtr(), std::move(smp), io_cap,
                                                  weak_ptr_factory_.GetWeakPtr(), bondable_mode);

    // Encrypt the link with the current LTK if it exists.
    if (ltk) {
      bt_log(INFO, "gap-le", "assigning existing LTK");
      pairing_->AssignLongTermKey(*ltk);
    }

    // Initialize the GATT layer.
    gatt_->AddConnection(peer_id(), std::move(att));
    gatt_->DiscoverServices(peer_id());
  }

  // sm::PairingState::Delegate override:
  void OnNewPairingData(const sm::PairingData& pairing_data) override {
    // Consider the pairing temporary if no link key was received. This
    // means we'll remain encrypted with the STK without creating a bond and
    // reinitiate pairing when we reconnect in the future.
    // TODO(armansito): Support bonding with just the CSRK for LE security mode
    // 2.
    if (!pairing_data.ltk) {
      bt_log(INFO, "gap-le", "temporarily paired with peer (id: %s)", bt_str(peer_id()));
      return;
    }

    bt_log(INFO, "gap-le", "new pairing data [%s%s%s%sid: %s]", pairing_data.ltk ? "ltk " : "",
           pairing_data.irk ? "irk " : "",
           pairing_data.identity_address
               ? fxl::StringPrintf("(identity: %s) ",
                                   pairing_data.identity_address->ToString().c_str())
                     .c_str()
               : "",
           pairing_data.csrk ? "csrk " : "", bt_str(peer_id()));

    if (!conn_mgr_->peer_cache()->StoreLowEnergyBond(peer_id_, pairing_data)) {
      bt_log(ERROR, "gap-le", "failed to cache bonding data (id: %s)", bt_str(peer_id()));
    }
  }

  // sm::PairingState::Delegate override:
  void OnPairingComplete(sm::Status status) override {
    bt_log(TRACE, "gap-le", "pairing complete: %s", status.ToString().c_str());

    auto delegate = conn_mgr_->pairing_delegate();
    if (delegate) {
      delegate->CompletePairing(peer_id_, status);
    }
  }

  // sm::PairingState::Delegate override:
  void OnAuthenticationFailure(hci::Status status) override {
    // TODO(armansito): Clear bonding data from the remote peer cache as any
    // stored link key is not valid.
    bt_log(ERROR, "gap-le", "link layer authentication failed: %s", status.ToString().c_str());
  }

  // sm::PairingState::Delegate override:
  void OnNewSecurityProperties(const sm::SecurityProperties& sec) override {
    bt_log(TRACE, "gap-le", "new link security properties: %s", sec.ToString().c_str());
    // Update the data plane with the correct link security level.
    data_domain_->AssignLinkSecurityProperties(link_->handle(), sec);
  }

  // sm::PairingState::Delegate override:
  std::optional<sm::IdentityInfo> OnIdentityInformationRequest() override {
    if (!conn_mgr_->local_address_delegate()->irk()) {
      bt_log(SPEW, "gap-le", "no local identity information to exchange");
      return std::nullopt;
    }

    bt_log(TRACE, "gap-le", "will distribute local identity information");
    sm::IdentityInfo id_info;
    id_info.irk = *conn_mgr_->local_address_delegate()->irk();
    id_info.address = conn_mgr_->local_address_delegate()->identity_address();

    return id_info;
  }

  // sm::PairingState::Delegate override:
  void OnTemporaryKeyRequest(sm::PairingMethod method,
                             sm::PairingState::Delegate::TkResponse responder) override {
    bt_log(TRACE, "gap-le", "TK request - method: %s",
           sm::util::PairingMethodToString(method).c_str());

    auto delegate = conn_mgr_->pairing_delegate();
    if (!delegate) {
      bt_log(ERROR, "gap-le", "rejecting pairing without a PairingDelegate!");
      responder(false, 0);
      return;
    }

    if (method == sm::PairingMethod::kPasskeyEntryInput) {
      // The TK will be provided by the user.
      delegate->RequestPasskey(peer_id(), [responder = std::move(responder)](int64_t passkey) {
        if (passkey < 0) {
          responder(false, 0);
        } else {
          responder(true, static_cast<uint32_t>(passkey));
        }
      });
      return;
    }

    if (method == sm::PairingMethod::kPasskeyEntryDisplay) {
      // Randomly generate a 6 digit passkey.
      // TODO(armansito): Use a uniform prng.
      uint32_t passkey;
      zx_cprng_draw(&passkey, sizeof(passkey));
      passkey = passkey % 1000000;
      delegate->DisplayPasskey(peer_id(), passkey, PairingDelegate::DisplayMethod::kPeerEntry,
                               [passkey, responder = std::move(responder)](bool confirm) {
                                 responder(confirm, passkey);
                               });
      return;
    }

    // TODO(armansito): Support providing a TK out of band.
    // OnTKRequest() should only be called for legacy pairing.
    ZX_DEBUG_ASSERT(method == sm::PairingMethod::kJustWorks);

    delegate->ConfirmPairing(peer_id(), [responder = std::move(responder)](bool confirm) {
      // The TK for Just Works pairing is 0 (Vol 3,
      // Part H, 2.3.5.2).
      responder(confirm, 0);
    });
  }

  void CloseRefs() {
    for (auto* ref : refs_) {
      ref->MarkClosed();
    }

    refs_.clear();
  }

  PeerId peer_id_;
  std::unique_ptr<hci::Connection> link_;
  async_dispatcher_t* dispatcher_;
  fxl::WeakPtr<LowEnergyConnectionManager> conn_mgr_;

  // Reference to the data plane is used to update the L2CAP layer to
  // reflect the correct link security level.
  fbl::RefPtr<data::Domain> data_domain_;

  // Reference to the GATT profile layer is used to initiate service discovery
  // and register the link.
  fbl::RefPtr<gatt::GATT> gatt_;

  // SMP pairing manager.
  std::unique_ptr<sm::PairingState> pairing_;

  // Called after kLEConnectionPausePeripheral.
  std::optional<async::TaskClosure> conn_pause_peripheral_timeout_;

  // Called by |conn_pause_peripheral_timeout_|.
  fit::callback<void()> conn_pause_peripheral_callback_;

  // Set to the time when connection parameters should be sent as LE central.
  const zx::time conn_pause_central_expiry_;

  // LowEnergyConnectionManager is responsible for making sure that these
  // pointers are always valid.
  std::unordered_set<LowEnergyConnectionRef*> refs_;

  fxl::WeakPtrFactory<LowEnergyConnection> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(LowEnergyConnection);
};

}  // namespace internal

LowEnergyConnectionRef::LowEnergyConnectionRef(PeerId peer_id, hci::ConnectionHandle handle,
                                               fxl::WeakPtr<LowEnergyConnectionManager> manager)
    : active_(true), peer_id_(peer_id), handle_(handle), manager_(manager) {
  ZX_DEBUG_ASSERT(peer_id_.IsValid());
  ZX_DEBUG_ASSERT(manager_);
  ZX_DEBUG_ASSERT(handle_);
}

LowEnergyConnectionRef::~LowEnergyConnectionRef() {
  ZX_DEBUG_ASSERT(thread_checker_.IsCreationThreadCurrent());
  if (active_) {
    Release();
  }
}

void LowEnergyConnectionRef::Release() {
  ZX_DEBUG_ASSERT(thread_checker_.IsCreationThreadCurrent());
  ZX_DEBUG_ASSERT(active_);
  active_ = false;
  if (manager_) {
    manager_->ReleaseReference(this);
  }
}

void LowEnergyConnectionRef::MarkClosed() {
  active_ = false;
  if (closed_cb_) {
    // Move the callback out of |closed_cb_| to prevent it from deleting itself
    // by deleting |this|.
    auto f = std::move(closed_cb_);
    f();
  }
}

BondableMode LowEnergyConnectionRef::bondable_mode() const {
  ZX_DEBUG_ASSERT(manager_);
  auto conn_iter = manager_->connections_.find(peer_id_);
  ZX_DEBUG_ASSERT(conn_iter != manager_->connections_.end());
  return conn_iter->second->bondable_mode();
}

LowEnergyConnectionManager::PendingRequestData::PendingRequestData(
    const DeviceAddress& address, ConnectionResultCallback first_callback,
    BondableMode bondable_mode)
    : address_(address), bondable_mode_(bondable_mode) {
  callbacks_.push_back(std::move(first_callback));
}

void LowEnergyConnectionManager::PendingRequestData::NotifyCallbacks(hci::Status status,
                                                                     const RefFunc& func) {
  ZX_DEBUG_ASSERT(!callbacks_.empty());
  for (const auto& callback : callbacks_) {
    callback(status, func());
  }
}

LowEnergyConnectionManager::LowEnergyConnectionManager(fxl::RefPtr<hci::Transport> hci,
                                                       hci::LocalAddressDelegate* addr_delegate,
                                                       hci::LowEnergyConnector* connector,
                                                       PeerCache* peer_cache,
                                                       fbl::RefPtr<data::Domain> data_domain,
                                                       fbl::RefPtr<gatt::GATT> gatt)
    : hci_(hci),
      request_timeout_(kLECreateConnectionTimeout),
      dispatcher_(async_get_default_dispatcher()),
      peer_cache_(peer_cache),
      data_domain_(data_domain),
      gatt_(gatt),
      connector_(connector),
      local_address_delegate_(addr_delegate),
      interrogator_(peer_cache, hci, dispatcher_),
      weak_ptr_factory_(this) {
  ZX_DEBUG_ASSERT(dispatcher_);
  ZX_DEBUG_ASSERT(peer_cache_);
  ZX_DEBUG_ASSERT(data_domain_);
  ZX_DEBUG_ASSERT(gatt_);
  ZX_DEBUG_ASSERT(hci_);
  ZX_DEBUG_ASSERT(connector_);
  ZX_DEBUG_ASSERT(local_address_delegate_);

  auto self = weak_ptr_factory_.GetWeakPtr();

  conn_update_cmpl_handler_id_ = hci_->command_channel()->AddLEMetaEventHandler(
      hci::kLEConnectionUpdateCompleteSubeventCode,
      [self](const auto& event) {
        if (self) {
          return self->OnLEConnectionUpdateComplete(event);
        }
        return hci::CommandChannel::EventCallbackResult::kRemove;
      },
      dispatcher_);
}

LowEnergyConnectionManager::~LowEnergyConnectionManager() {
  hci_->command_channel()->RemoveEventHandler(conn_update_cmpl_handler_id_);

  bt_log(TRACE, "gap-le", "connection manager shutting down");

  weak_ptr_factory_.InvalidateWeakPtrs();

  // This will cancel any pending request.
  if (connector_->request_pending()) {
    connector_->Cancel();
  }

  // Clear |pending_requests_| and notify failure.
  for (auto& iter : pending_requests_) {
    iter.second.NotifyCallbacks(hci::Status(HostError::kFailed), [] { return nullptr; });
  }
  pending_requests_.clear();

  // Clean up all connections.
  for (auto& iter : connections_) {
    CleanUpConnection(std::move(iter.second));
  }

  connections_.clear();
}

bool LowEnergyConnectionManager::Connect(PeerId peer_id, ConnectionResultCallback callback,
                                         BondableMode bondable_mode) {
  if (!connector_) {
    bt_log(WARN, "gap-le", "connect called during shutdown!");
    return false;
  }

  Peer* peer = peer_cache_->FindById(peer_id);
  if (!peer) {
    bt_log(WARN, "gap-le", "peer not found (id: %s)", bt_str(peer_id));
    return false;
  }

  if (peer->technology() == TechnologyType::kClassic) {
    bt_log(ERROR, "gap-le", "peer does not support LE: %s", peer->ToString().c_str());
    return false;
  }

  if (!peer->connectable()) {
    bt_log(ERROR, "gap-le", "peer not connectable: %s", peer->ToString().c_str());
    return false;
  }

  // If we are already waiting to connect to |peer_id| then we store
  // |callback| to be processed after the connection attempt completes (in
  // either success of failure).
  auto pending_iter = pending_requests_.find(peer_id);
  if (pending_iter != pending_requests_.end()) {
    ZX_DEBUG_ASSERT(connections_.find(peer_id) == connections_.end());
    ZX_DEBUG_ASSERT(connector_->request_pending());

    pending_iter->second.AddCallback(std::move(callback));
    return true;
  }

  // If there is already an active connection then we add a new reference and
  // succeed.
  auto conn_ref = AddConnectionRef(peer_id);
  if (conn_ref) {
    async::PostTask(dispatcher_,
                    [conn_ref = std::move(conn_ref), callback = std::move(callback)]() mutable {
                      // Do not report success if the link has been disconnected (e.g. via
                      // Disconnect() or other circumstances).
                      if (!conn_ref->active()) {
                        bt_log(TRACE, "gap-le", "link disconnected, ref is inactive");
                        callback(hci::Status(HostError::kFailed), nullptr);
                      } else {
                        callback(hci::Status(), std::move(conn_ref));
                      }
                    });

    return true;
  }

  peer->MutLe().SetConnectionState(Peer::ConnectionState::kInitializing);
  pending_requests_[peer_id] =
      PendingRequestData(peer->address(), std::move(callback), bondable_mode);

  TryCreateNextConnection();

  return true;
}

bool LowEnergyConnectionManager::Disconnect(PeerId peer_id) {
  // TODO(BT-873): When connection requests can be canceled, do so here.
  if (pending_requests_.find(peer_id) != pending_requests_.end()) {
    bt_log(WARN, "gap-le", "Can't disconnect peer %s because it's being connected to",
           bt_str(peer_id));
    return false;
  }

  auto iter = connections_.find(peer_id);
  if (iter == connections_.end()) {
    bt_log(WARN, "gap-le", "peer not connected (id: %s)", bt_str(peer_id));
    return true;
  }

  // Remove the connection state from the internal map right away.
  auto conn = std::move(iter->second);
  connections_.erase(iter);

  // Since this was an intentional disconnect, update the auto-connection behavior
  // appropriately.
  peer_cache_->SetAutoConnectBehaviorForIntentionalDisconnect(peer_id);

  bt_log(INFO, "gap-le", "disconnecting link: %s", bt_str(*conn->link()));
  CleanUpConnection(std::move(conn));
  return true;
}

void LowEnergyConnectionManager::Pair(PeerId peer_id, sm::SecurityLevel pairing_level,
                                      sm::BondableMode bondable_mode, sm::StatusCallback cb) {
  auto iter = connections_.find(peer_id);
  if (iter == connections_.end()) {
    bt_log(WARN, "gap-le", "cannot pair: peer not connected (id: %s)", bt_str(peer_id));
    cb(bt::sm::Status(bt::HostError::kNotFound));
    return;
  }
  bt_log(TRACE, "gap-le", "pairing with security level: %d", pairing_level);
  iter->second->UpgradeSecurity(pairing_level, bondable_mode, std::move(cb));
}

void LowEnergyConnectionManager::RegisterRemoteInitiatedLink(hci::ConnectionPtr link,
                                                             BondableMode bondable_mode,
                                                             ConnectionResultCallback callback) {
  ZX_DEBUG_ASSERT(link);
  bt_log(TRACE, "gap-le", "new remote-initiated link (local addr: %s): %s",
         bt_str(link->local_address()), bt_str(*link));

  Peer* peer = UpdatePeerWithLink(*link);
  auto peer_id = peer->identifier();

  // TODO(armansito): Use own address when storing the connection (NET-321).
  // Currently this will refuse the connection and disconnect the link if |peer|
  // is already connected to us by a different local address.
  InitializeConnection(peer_id, std::move(link), bondable_mode,
                       [peer_id, cb = std::move(callback), this](
                           hci::Status status, LowEnergyConnectionRefPtr conn_ref) {
                         auto peer = peer_cache_->FindById(peer_id);
                         if (conn_ref && peer) {
                           peer->MutLe().SetConnectionState(Peer::ConnectionState::kConnected);
                         }
                         cb(status, std::move(conn_ref));
                       });
}

void LowEnergyConnectionManager::SetPairingDelegate(fxl::WeakPtr<PairingDelegate> delegate) {
  // TODO(armansito): Add a test case for this once NET-1179 is done.
  pairing_delegate_ = delegate;

  // Tell existing connections to abort ongoing pairing procedures. The new
  // delegate will receive calls to PairingDelegate::CompletePairing, unless it
  // is null.
  for (auto& iter : connections_) {
    iter.second->ResetPairingState(delegate ? delegate->io_capability()
                                            : sm::IOCapability::kNoInputNoOutput);
  }
}

void LowEnergyConnectionManager::SetConnectionParametersCallbackForTesting(
    ConnectionParametersCallback callback) {
  test_conn_params_cb_ = std::move(callback);
}

void LowEnergyConnectionManager::SetDisconnectCallbackForTesting(DisconnectCallback callback) {
  test_disconn_cb_ = std::move(callback);
}

void LowEnergyConnectionManager::ReleaseReference(LowEnergyConnectionRef* conn_ref) {
  ZX_DEBUG_ASSERT(conn_ref);

  auto iter = connections_.find(conn_ref->peer_identifier());
  ZX_DEBUG_ASSERT(iter != connections_.end());

  iter->second->DropRef(conn_ref);
  if (iter->second->ref_count() != 0u)
    return;

  // Move the connection object before erasing the entry.
  auto conn = std::move(iter->second);
  connections_.erase(iter);

  bt_log(INFO, "gap-le", "all refs dropped on connection: %s", conn->link()->ToString().c_str());
  CleanUpConnection(std::move(conn));
}

void LowEnergyConnectionManager::TryCreateNextConnection() {
  // There can only be one outstanding LE Create Connection request at a time.
  if (connector_->request_pending()) {
    bt_log(TRACE, "gap-le", "HCI_LE_Create_Connection command pending");
    return;
  }

  // TODO(armansito): Perform either the General or Auto Connection
  // Establishment procedure here (see NET-187).

  if (pending_requests_.empty()) {
    bt_log(SPEW, "gap-le", "no pending requests remaining");

    // TODO(armansito): Unpause discovery and disable background scanning if
    // there aren't any peers to auto-connect to.
    return;
  }

  for (auto& iter : pending_requests_) {
    const auto& next_peer_addr = iter.second.address();
    Peer* peer = peer_cache_->FindByAddress(next_peer_addr);
    if (peer) {
      RequestCreateConnection(peer, iter.second.bondable_mode());
      break;
    }

    bt_log(TRACE, "gap-le", "deferring connection attempt for peer: %s",
           next_peer_addr.ToString().c_str());

    // TODO(armansito): For now the requests for this peer won't complete
    // until the next peer discovery. This will no longer be an issue when we
    // use background scanning (see NET-187).
  }
}

void LowEnergyConnectionManager::RequestCreateConnection(Peer* peer, BondableMode bondable_mode) {
  ZX_DEBUG_ASSERT(peer);

  // During the initial connection to a peripheral we use the initial high
  // duty-cycle parameters to ensure that initiating procedures (bonding,
  // encryption setup, service discovery) are completed quickly. Once these
  // procedures are complete, we will change the connection interval to the
  // peripheral's preferred connection parameters (see v5.0, Vol 3, Part C,
  // Section 9.3.12).

  // TODO(armansito): Initiate the connection using the cached preferred
  // connection parameters if we are bonded.
  hci::LEPreferredConnectionParameters initial_params(kLEInitialConnIntervalMin,
                                                      kLEInitialConnIntervalMax, 0,
                                                      hci::defaults::kLESupervisionTimeout);

  auto self = weak_ptr_factory_.GetWeakPtr();
  auto status_cb = [bondable_mode, self, peer_id = peer->identifier()](hci::Status status,
                                                                       auto link) {
    if (self)
      self->OnConnectResult(peer_id, status, std::move(link), bondable_mode);
  };

  // We set the scan window and interval to the same value for continuous
  // scanning.
  connector_->CreateConnection(false /* use_whitelist */, peer->address(), kLEScanFastInterval,
                               kLEScanFastInterval, initial_params, status_cb, request_timeout_);
}

void LowEnergyConnectionManager::InitializeConnection(PeerId peer_id,
                                                      std::unique_ptr<hci::Connection> link,
                                                      BondableMode bondable_mode,
                                                      ConnectionResultCallback callback) {
  ZX_DEBUG_ASSERT(link);
  ZX_DEBUG_ASSERT(link->ll_type() == hci::Connection::LinkType::kLE);

  auto handle = link->handle();
  auto role = link->role();

  // TODO(armansito): For now reject having more than one link with the same
  // peer. This should change once this has more context on the local
  // destination for remote initiated connections (see NET-321).
  if (connections_.find(peer_id) != connections_.end()) {
    bt_log(TRACE, "gap-le", "multiple links from peer; connection refused");
    callback(hci::Status(HostError::kFailed), nullptr);
    return;
  }

  // Add the connection to the L2CAP table. Incoming data will be buffered until
  // the channels are open.
  auto self = weak_ptr_factory_.GetWeakPtr();
  auto conn_param_update_cb = [self, handle, peer_id](const auto& params) {
    if (self) {
      self->OnNewLEConnectionParams(peer_id, handle, params);
    }
  };

  auto link_error_cb = [self, peer_id] {
    bt_log(TRACE, "gap", "link error received from L2CAP");
    if (self) {
      self->Disconnect(peer_id);
    }
  };

  // Initialize connection.
  auto conn = std::make_unique<internal::LowEnergyConnection>(peer_id, std::move(link), dispatcher_,
                                                              self, data_domain_, gatt_);
  conn->InitializeFixedChannels(std::move(conn_param_update_cb), std::move(link_error_cb),
                                bondable_mode);
  conn->StartConnectionPausePeripheralTimeout();
  auto first_ref = conn->AddRef();
  connections_[peer_id] = std::move(conn);

  // TODO(armansito): Should complete a few more things before returning the
  // connection:
  //    1. If this is the first time we connected to this peer:
  //      a. If master, obtain Peripheral Preferred Connection Parameters via
  //         GATT if available
  //      b. Initiate name discovery over GATT if complete name is unknown
  //      c. If master, allow slave to initiate procedures (service discovery,
  //         encryption setup, etc) for kLEConnectionPauseCentral before
  //         updating the connection parameters to the slave's preferred values.

  if (role == hci::Connection::Role::kMaster) {
    // After the Central device has no further pending actions to perform and the
    // Peripheral device has not initiated any other actions within
    // kLEConnectionPauseCentral, then the Central device should update the connection parameters to
    // either the Peripheral Preferred Connection Parameters or self-determined values (Core Spec
    // v5.2, Vol 3, Part C, Sec 9.3.12).
    connections_[peer_id]->PostCentralPauseTimeoutCallback([this, handle]() {
      UpdateConnectionParams(handle, kDefaultPreferredConnectionParameters);
    });
  }

  interrogator_.Start(peer_id, handle,
                      [peer_id, conn_ref = std::move(first_ref), cb = std::move(callback),
                       self](hci::Status status) mutable {
                        if (!self) {
                          return;
                        }

                        if (!status.is_success()) {
                          // Releasing ref will disconnect.
                          conn_ref.release();
                          cb(status, nullptr);
                          return;
                        }

                        self->OnInterrogationComplete(peer_id);

                        cb(status, std::move(conn_ref));
                      });
}

void LowEnergyConnectionManager::OnInterrogationComplete(PeerId peer_id) {
  auto it = connections_.find(peer_id);
  if (it == connections_.end()) {
    bt_log(INFO, "gap", "OnInterrogationComplete called for non-connected peer");
  }
  auto& conn = it->second;

  if (conn->link()->role() == hci::Connection::Role::kSlave) {
    // "The peripheral device should not perform a connection parameter update procedure within
    // kLEConnectionPausePeripheral after establishing a connection." (Core Spec v5.2, Vol 3, Part
    // C, Sec 9.3.12).
    conn->on_peripheral_pause_timeout([&conn, peer_id, this]() {
      RequestConnectionParameterUpdate(peer_id, *conn, kDefaultPreferredConnectionParameters);
    });
  }
}

LowEnergyConnectionRefPtr LowEnergyConnectionManager::AddConnectionRef(PeerId peer_id) {
  auto iter = connections_.find(peer_id);
  if (iter == connections_.end())
    return nullptr;

  return iter->second->AddRef();
}

void LowEnergyConnectionManager::CleanUpConnection(
    std::unique_ptr<internal::LowEnergyConnection> conn) {
  ZX_DEBUG_ASSERT(conn);

  // Mark the peer peer as no longer connected.
  Peer* peer = peer_cache_->FindById(conn->peer_id());
  ZX_DEBUG_ASSERT_MSG(peer, "A connection was active for an unknown peer! (id: %s)",
                      bt_str(conn->peer_id()));
  peer->MutLe().SetConnectionState(Peer::ConnectionState::kNotConnected);

  conn.reset();
}

void LowEnergyConnectionManager::RegisterLocalInitiatedLink(std::unique_ptr<hci::Connection> link,
                                                            BondableMode bondable_mode) {
  ZX_DEBUG_ASSERT(link);
  ZX_DEBUG_ASSERT(link->ll_type() == hci::Connection::LinkType::kLE);
  bt_log(INFO, "gap-le", "new connection %s", bt_str(*link));

  Peer* peer = UpdatePeerWithLink(*link);

  // Initialize the connection  and obtain the initial reference.
  // On successful initialization, this reference lasts until this method returns to prevent it from
  // dropping to 0 due to an unclaimed reference while notifying pending callbacks and listeners
  // below.
  InitializeConnection(peer->identifier(), std::move(link), bondable_mode,
                       [this, peer_id = peer->identifier()](hci::Status status,
                                                            LowEnergyConnectionRefPtr first_ref) {
                         OnLocalInitiatedLinkInitialized(status, std::move(first_ref), peer_id);
                       });
}

void LowEnergyConnectionManager::OnLocalInitiatedLinkInitialized(hci::Status status,
                                                                 LowEnergyConnectionRefPtr conn_ref,
                                                                 PeerId peer_id) {
  if (!status.is_success()) {
    ZX_ASSERT(!conn_ref);

    auto iter = pending_requests_.find(peer_id);
    if (iter != pending_requests_.end()) {
      // Remove the entry from |pending_requests_| before notifying the
      // callbacks.
      auto pending_req_data = std::move(iter->second);
      pending_requests_.erase(iter);

      pending_req_data.NotifyCallbacks(status, [] { return nullptr; });
    }
  } else {
    // We take care never to initiate more than one connection to the same
    // peer.
    ZX_ASSERT(conn_ref);

    auto conn_iter = connections_.find(peer_id);
    ZX_ASSERT(conn_iter != connections_.end());

    auto peer = peer_cache_->FindById(peer_id);
    ZX_ASSERT(peer);

    // For now, jump to the initialized state.
    peer->MutLe().SetConnectionState(Peer::ConnectionState::kConnected);

    auto iter = pending_requests_.find(peer_id);
    if (iter != pending_requests_.end()) {
      // Remove the entry from |pending_requests_| before notifying the
      // callbacks.
      auto pending_req_data = std::move(iter->second);
      pending_requests_.erase(iter);

      pending_req_data.NotifyCallbacks(status,
                                       [&conn_iter] { return conn_iter->second->AddRef(); });
    }

    // Release the extra reference before attempting the next connection.
    // This will disconnect the link if no callback retained its reference.
    conn_ref = nullptr;
  }

  ZX_ASSERT(!connector_->request_pending());
  TryCreateNextConnection();
}

Peer* LowEnergyConnectionManager::UpdatePeerWithLink(const hci::Connection& link) {
  Peer* peer = peer_cache_->FindByAddress(link.peer_address());
  if (!peer) {
    peer = peer_cache_->NewPeer(link.peer_address(), true /* connectable */);
  }
  peer->MutLe().SetConnectionParameters(link.low_energy_parameters());
  peer_cache_->SetAutoConnectBehaviorForSuccessfulConnection(peer->identifier());

  return peer;
}

void LowEnergyConnectionManager::OnConnectResult(PeerId peer_id, hci::Status status,
                                                 hci::ConnectionPtr link,
                                                 BondableMode bondable_mode) {
  ZX_DEBUG_ASSERT(connections_.find(peer_id) == connections_.end());

  if (status) {
    bt_log(TRACE, "gap-le", "connection request successful");
    RegisterLocalInitiatedLink(std::move(link), bondable_mode);
    return;
  }

  // The request failed or timed out.
  bt_log(ERROR, "gap-le", "failed to connect to peer (id: %s)", bt_str(peer_id));
  Peer* peer = peer_cache_->FindById(peer_id);
  ZX_ASSERT(peer);
  peer->MutLe().SetConnectionState(Peer::ConnectionState::kNotConnected);

  // Notify the matching pending callbacks about the failure.
  auto iter = pending_requests_.find(peer_id);
  ZX_DEBUG_ASSERT(iter != pending_requests_.end());

  // Remove the entry from |pending_requests_| before notifying callbacks.
  auto pending_req_data = std::move(iter->second);
  pending_requests_.erase(iter);
  pending_req_data.NotifyCallbacks(status, [] { return nullptr; });

  // Process the next pending attempt.
  ZX_DEBUG_ASSERT(!connector_->request_pending());
  TryCreateNextConnection();
}

void LowEnergyConnectionManager::OnPeerDisconnect(const hci::Connection* connection) {
  auto handle = connection->handle();
  if (test_disconn_cb_) {
    test_disconn_cb_(handle);
  }

  // See if we can find a connection with a matching handle by walking the
  // connections list.
  auto iter = FindConnection(handle);
  if (iter == connections_.end()) {
    bt_log(SPEW, "gap-le", "disconnect from unknown connection handle: %#.4x", handle);
    return;
  }

  // Found the connection. Remove the entry from |connections_| before notifying
  // the "closed" handlers.
  auto conn = std::move(iter->second);
  connections_.erase(iter);

  bt_log(INFO, "gap-le", "peer %s disconnected (handle: %#.4x)", bt_str(conn->peer_id()), handle);
  ZX_DEBUG_ASSERT(conn->ref_count());

  CleanUpConnection(std::move(conn));
}

hci::CommandChannel::EventCallbackResult LowEnergyConnectionManager::OnLEConnectionUpdateComplete(
    const hci::EventPacket& event) {
  ZX_DEBUG_ASSERT(event.event_code() == hci::kLEMetaEventCode);
  ZX_DEBUG_ASSERT(event.params<hci::LEMetaEventParams>().subevent_code ==
                  hci::kLEConnectionUpdateCompleteSubeventCode);

  auto payload = event.le_event_params<hci::LEConnectionUpdateCompleteSubeventParams>();
  ZX_ASSERT(payload);
  hci::ConnectionHandle handle = le16toh(payload->connection_handle);

  // This event may be the result of the LE Connection Update command.
  if (le_conn_update_complete_command_callback_) {
    le_conn_update_complete_command_callback_(handle, payload->status);
  }

  if (payload->status != hci::StatusCode::kSuccess) {
    bt_log(WARN, "gap-le",
           "HCI LE Connection Update Complete event with error "
           "(status: %#.2x, handle: %#.4x)",
           payload->status, handle);

    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  auto iter = FindConnection(handle);
  if (iter == connections_.end()) {
    bt_log(TRACE, "gap-le", "conn. parameters received for unknown link (handle: %#.4x)", handle);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  const auto& conn = *iter->second;
  ZX_DEBUG_ASSERT(conn.handle() == handle);

  bt_log(INFO, "gap-le", "conn. parameters updated (id: %s, handle: %#.4x)", bt_str(conn.peer_id()),
         handle);
  hci::LEConnectionParameters params(le16toh(payload->conn_interval),
                                     le16toh(payload->conn_latency),
                                     le16toh(payload->supervision_timeout));
  conn.link()->set_low_energy_parameters(params);

  Peer* peer = peer_cache_->FindById(conn.peer_id());
  if (!peer) {
    bt_log(ERROR, "gap-le", "conn. parameters updated for unknown peer!");
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  peer->MutLe().SetConnectionParameters(params);

  if (test_conn_params_cb_)
    test_conn_params_cb_(*peer);

  return hci::CommandChannel::EventCallbackResult::kContinue;
}

void LowEnergyConnectionManager::OnNewLEConnectionParams(
    PeerId peer_id, hci::ConnectionHandle handle,
    const hci::LEPreferredConnectionParameters& params) {
  bt_log(TRACE, "gap-le", "conn. parameters received (handle: %#.4x)", handle);

  Peer* peer = peer_cache_->FindById(peer_id);
  if (!peer) {
    bt_log(ERROR, "gap-le", "conn. parameters received from unknown peer!");
    return;
  }

  peer->MutLe().SetPreferredConnectionParameters(params);

  // Use the new parameters if we're not performing service discovery or
  // bonding.
  if (peer->le()->connected()) {
    UpdateConnectionParams(handle, params);
  }
}

void LowEnergyConnectionManager::RequestConnectionParameterUpdate(
    PeerId peer_id, const internal::LowEnergyConnection& conn,
    const hci::LEPreferredConnectionParameters& params) {
  ZX_ASSERT_MSG(conn.link()->role() == hci::Connection::Role::kSlave,
                "tried to send connection parameter update request as master");

  Peer* peer = peer_cache_->FindById(peer_id);
  // Ensure interrogation has completed.
  ZX_ASSERT(peer->le()->features().has_value());

  // TODO(49714): check local controller support for LL Connection Parameters Request procedure
  // (mask is currently in Adapter le state, consider propagating down)
  bool ll_connection_parameters_req_supported =
      peer->le()->features()->le_features &
      static_cast<uint64_t>(hci::LESupportedFeature::kConnectionParametersRequestProcedure);

  bt_log(SPEW, "gap-le", "ll connection parameters req procedure supported: %s",
         ll_connection_parameters_req_supported ? "true" : "false");

  if (ll_connection_parameters_req_supported) {
    auto status_cb = [self = weak_ptr_factory_.GetWeakPtr(), peer_id, params](hci::Status status) {
      if (!self) {
        return;
      }

      auto it = self->connections_.find(peer_id);
      if (it == self->connections_.end()) {
        bt_log(SPEW, "gap-le",
               "connection update command status for non-connected peer (peer id: %s)",
               bt_str(peer_id));
        return;
      }
      auto& conn = it->second;

      // The next LE Connection Update complete event is for this command iff the command status
      // is success.
      if (status.is_success()) {
        self->le_conn_update_complete_command_callback_ = [self, params, peer_id,
                                                           expected_handle = conn->handle()](
                                                              hci::ConnectionHandle handle,
                                                              hci::StatusCode status) {
          if (!self) {
            return;
          }

          if (handle != expected_handle) {
            bt_log(WARN, "gap-le",
                   "handle in conn update complete command callback (%#.4x) does not match handle "
                   "in command (%#.4x)",
                   handle, expected_handle);
            return;
          }

          auto it = self->connections_.find(peer_id);
          if (it == self->connections_.end()) {
            bt_log(SPEW, "gap-le",
                   "connection update complete event for non-connected peer (peer id: %s)",
                   bt_str(peer_id));
            return;
          }
          auto& conn = it->second;

          // Retry connection parameter update with l2cap if the peer doesn't support LL procedure.
          if (status == hci::StatusCode::kUnsupportedRemoteFeature) {
            bt_log(SPEW, "gap-le",
                   "peer does not support HCI LE Connection Update command, trying l2cap request");
            self->L2capRequestConnectionParameterUpdate(*conn, params);
          }
        };

      } else if (status.protocol_error() == hci::StatusCode::kUnsupportedRemoteFeature) {
        // Retry connection parameter update with l2cap if the peer doesn't support LL procedure.
        bt_log(SPEW, "gap-le",
               "peer does not support HCI LE Connection Update command, trying l2cap request");
        self->L2capRequestConnectionParameterUpdate(*conn, params);
      }
    };

    UpdateConnectionParams(conn.handle(), params, std::move(status_cb));
  } else {
    L2capRequestConnectionParameterUpdate(conn, params);
  }
}

void LowEnergyConnectionManager::UpdateConnectionParams(
    hci::ConnectionHandle handle, const hci::LEPreferredConnectionParameters& params,
    StatusCallback status_cb) {
  bt_log(TRACE, "gap-le", "updating connection parameters (handle: %#.4x)", handle);
  auto command = hci::CommandPacket::New(hci::kLEConnectionUpdate,
                                         sizeof(hci::LEConnectionUpdateCommandParams));
  auto event_params = command->mutable_payload<hci::LEConnectionUpdateCommandParams>();

  event_params->connection_handle = htole16(handle);
  event_params->conn_interval_min = htole16(params.min_interval());
  event_params->conn_interval_max = htole16(params.max_interval());
  event_params->conn_latency = htole16(params.max_latency());
  event_params->supervision_timeout = htole16(params.supervision_timeout());
  event_params->minimum_ce_length = 0x0000;
  event_params->maximum_ce_length = 0x0000;

  auto status_cb_wrapper = [handle, cb = std::move(status_cb)](
                               auto id, const hci::EventPacket& event) mutable {
    ZX_ASSERT(event.event_code() == hci::kCommandStatusEventCode);
    hci_is_error(event, TRACE, "gap-le",
                 "controller rejected connection parameters (handle: %#.4x)", handle);
    if (cb) {
      cb(event.ToStatus());
    }
  };

  hci_->command_channel()->SendCommand(std::move(command), dispatcher_,
                                       std::move(status_cb_wrapper), hci::kCommandStatusEventCode);
}

void LowEnergyConnectionManager::L2capRequestConnectionParameterUpdate(
    const internal::LowEnergyConnection& conn, const hci::LEPreferredConnectionParameters& params) {
  ZX_ASSERT_MSG(conn.link()->role() == hci::Connection::Role::kSlave,
                "tried to send l2cap connection parameter update request as master");

  bt_log(TRACE, "gap-le", "sending l2cap connection parameter update request");

  auto handle = conn.handle();
  auto response_cb = [handle](bool accepted) {
    bt_log(TRACE, "gap-le", "peer %s l2cap connection parameter update request (handle: %#.4x)",
           accepted ? "accepted" : "rejected", handle);
  };

  // TODO(49717): don't send request until after kLEConnectionParameterTimeout of an l2cap conn
  // parameter update response being received (Core Spec v5.2, Vol 3, Part C, Sec 9.3.9).
  data_domain_->RequestConnectionParameterUpdate(handle, params, std::move(response_cb),
                                                 dispatcher_);
}

LowEnergyConnectionManager::ConnectionMap::iterator LowEnergyConnectionManager::FindConnection(
    hci::ConnectionHandle handle) {
  auto iter = connections_.begin();
  for (; iter != connections_.end(); ++iter) {
    const auto& conn = *iter->second;
    if (conn.handle() == handle)
      break;
  }
  return iter;
}

}  // namespace gap
}  // namespace bt
