// Copyright 2020 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.

#ifndef SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GAP_LOW_ENERGY_CONNECTION_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GAP_LOW_ENERGY_CONNECTION_H_

#include <lib/async/dispatcher.h>
#include <lib/sys/inspect/cpp/component.h>

#include "gap.h"
#include "low_energy_connection_handle.h"
#include "low_energy_connection_request.h"
#include "src/connectivity/bluetooth/core/bt-host/common/identifier.h"
#include "src/connectivity/bluetooth/core/bt-host/common/inspectable.h"
#include "src/connectivity/bluetooth/core/bt-host/gap/generic_access_client.h"
#include "src/connectivity/bluetooth/core/bt-host/gatt/gatt.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/protocol.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/low_energy_connection.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/l2cap.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/security_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/types.h"
#include "src/lib/fxl/memory/weak_ptr.h"

namespace bt::gap {

class LowEnergyConnectionManager;

namespace internal {

// LowEnergyConnector constructs LowEnergyConnection instances immediately upon successful
// completion of the link layer connection procedure (to hook up HCI event callbacks). However,
// LowEnergyConnections aren't exposed to the rest of the stack (including the
// LowEnergyConnectionManager) until fully interrogated, as completion of the link-layer connection
// process is insufficient to guarantee a working connection. Thus this class represents the state
// of an active *AND* (outside of LowEnergyConnector) known-functional connection.
//
// Instances are kept alive as long as there is at least one LowEnergyConnectionHandle that
// references them. Instances are expected to be destroyed immediately after a peer disconnect
// event is received (as indicated by peer_disconnect_cb).
class LowEnergyConnection final : public sm::Delegate {
 public:
  // |peer| is the peer that this connection is connected to.
  // |link| is the underlying LE HCI connection that this connection corresponds to.
  // |peer_disconnect_cb| will be called when the peer disconnects.
  // |error_cb| will be called when a fatal connection error occurs and the connection should be
  // closed (e.g. when L2CAP reports an error).
  // |conn_mgr| is the LowEnergyConnectionManager that owns this connection.
  // |l2cap|, |gatt|, and |transport| are pointers to the interfaces of the corresponding layers.
  using PeerDisconnectCallback = fit::callback<void(hci_spec::StatusCode)>;
  using ErrorCallback = fit::callback<void()>;
  LowEnergyConnection(fxl::WeakPtr<Peer> peer, std::unique_ptr<hci::LowEnergyConnection> link,
                      LowEnergyConnectionOptions connection_options,
                      PeerDisconnectCallback peer_disconnect_cb, ErrorCallback error_cb,
                      fxl::WeakPtr<LowEnergyConnectionManager> conn_mgr, l2cap::L2cap* l2cap,
                      fxl::WeakPtr<gatt::GATT> gatt, fxl::WeakPtr<hci::Transport> transport);

  // Notifies request callbacks and connection refs of the disconnection.
  ~LowEnergyConnection() override;

  // Create a reference to this connection. When the last reference is dropped, this connection will
  // be disconnected.
  std::unique_ptr<LowEnergyConnectionHandle> AddRef();

  // Decrements the ref count. Must be called when a LowEnergyConnectionHandle is
  // released/destroyed.
  void DropRef(LowEnergyConnectionHandle* ref);

  // Used to respond to protocol/service requests for increased security.
  void OnSecurityRequest(sm::SecurityLevel level, sm::ResultFunction<> cb);

  // 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::ResultFunction<> cb);

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

  // Must be called when interrogation has completed. May update connection parameters if all
  // initialization procedures have completed.
  void OnInterrogationComplete();

  // Attach connection as child node of |parent| with specified |name|.
  void AttachInspect(inspect::Node& parent, std::string name);

  void set_security_mode(LESecurityMode mode) {
    ZX_ASSERT(sm_);
    sm_->set_security_mode(mode);
  }

  // Sets a callback that will be called when the peer disconnects.
  void set_peer_disconnect_callback(PeerDisconnectCallback cb) {
    ZX_ASSERT(cb);
    peer_disconnect_callback_ = std::move(cb);
  }

  // |peer_conn_token| is a token generated by the connected Peer, and is used to
  // synchronize connection state.
  void set_peer_conn_token(Peer::ConnectionToken peer_conn_token) {
    ZX_ASSERT(interrogation_completed_);
    ZX_ASSERT(!peer_conn_token_);
    peer_conn_token_ = std::move(peer_conn_token);
  }

  // Sets a callback that will be called when a fatal connection error occurs.
  void set_error_callback(ErrorCallback cb) {
    ZX_ASSERT(cb);
    error_callback_ = std::move(cb);
  }

  size_t ref_count() const { return refs_->size(); }

  PeerId peer_id() const { return peer_->identifier(); }
  hci_spec::ConnectionHandle handle() const { return link_->handle(); }
  hci::LowEnergyConnection* link() const { return link_.get(); }
  sm::BondableMode bondable_mode() const {
    ZX_ASSERT(sm_);
    return sm_->bondable_mode();
  }

  sm::SecurityProperties security() const {
    ZX_ASSERT(sm_);
    return sm_->security();
  }

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

 private:
  // Registers this connection with L2CAP and initializes the fixed channel
  // protocols.
  void InitializeFixedChannels();

  // Register handlers for HCI events that correspond to this connection.
  void RegisterEventHandlers();

  // Start kLEConnectionPauseCentral/Peripheral timeout that will update connection parameters.
  // Should be called as soon as this GAP connection is established.
  void StartConnectionPauseTimeout();

  // Start kLEConnectionPausePeripheral timeout that will send a connection parameter update
  // request. Should be called as soon as connection is established.
  void StartConnectionPausePeripheralTimeout();

  // Start kLEConnectionPauseCentral timeout that will update connection parameters.
  // Should be called as soon as connection is established.
  void StartConnectionPauseCentralTimeout();

  // 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,
                                  LowEnergyConnectionOptions connection_options);

  // Called when the preferred connection parameters have been received for a LE
  // peripheral. This can happen in the form of:
  //
  //   1. <<Peripheral Connection Interval Range>> advertising data field
  //   2. "Peripheral Preferred Connection Parameters" GATT characteristic
  //      (under "GAP" service)
  //   3. HCI LE Remote Connection Parameter Request Event
  //   4. L2CAP Connection Parameter Update request
  //
  // TODO(fxbug.dev/68803): Support #1 above.
  // TODO(fxbug.dev/68804): Support #3 above.
  //
  // This method caches |params| for later connection attempts and sends the
  // parameters to the controller if the initializing procedures are complete
  // (since we use more agressing initial parameters for pairing and service
  // discovery, as recommended by the specification in v5.0, Vol 3, Part C,
  // Section 9.3.12.1).
  //
  // |peer_id| uniquely identifies the peer. |handle| represents
  // the logical link that |params| should be applied to.
  void OnNewLEConnectionParams(const hci_spec::LEPreferredConnectionParameters& params);

  // As an LE peripheral, request that the connection parameters |params| be used on the given
  // connection |conn| with peer |peer_id|. This may send an HCI LE Connection Update command or an
  // L2CAP Connection Parameter Update Request depending on what the local and remote controllers
  // support.
  //
  // Interrogation must have completed before this may be called.
  void RequestConnectionParameterUpdate(const hci_spec::LEPreferredConnectionParameters& params);

  // Handler for connection parameter update command sent when an update is requested by
  // RequestConnectionParameterUpdate.
  //
  // If the HCI LE Connection Update command fails with status kUnsupportedRemoteFeature, the update
  // will be retried with an L2CAP Connection Parameter Update Request.
  void HandleRequestConnectionParameterUpdateCommandStatus(
      hci_spec::LEPreferredConnectionParameters params, hci::Result<> status);

  // As an LE peripheral, send an L2CAP Connection Parameter Update Request requesting |params| on
  // the LE signaling channel of the given logical link |handle|.
  //
  // NOTE: This should only be used if the LE peripheral and/or LE central do not support the
  // Connection Parameters Request Link Layer Control Procedure (Core Spec v5.2  Vol 3, Part A,
  // Sec 4.20). If they do, UpdateConnectionParams(...) should be used instead.
  void L2capRequestConnectionParameterUpdate(
      const hci_spec::LEPreferredConnectionParameters& params);

  // Requests that the controller use the given connection |params| by sending an HCI LE Connection
  // Update command. This may be issued on both the LE peripheral and the LE central.
  //
  // The link layer may modify the preferred parameters |params| before initiating the Connection
  // Parameters Request Link Layer Control Procedure (Core Spec v5.2, Vol 6, Part B, Sec 5.1.7).
  //
  // If non-null, |status_cb| will be called when the HCI Command Status event is received.
  //
  // The HCI LE Connection Update Complete event will be generated after the parameters have been
  // applied or if the update fails, and will indicate the (possibly modified) parameter values.
  //
  // NOTE: If the local host is an LE peripheral, then the local controller and the remote
  // LE central must have indicated support for this procedure in the LE feature mask. Otherwise,
  // L2capRequestConnectionParameterUpdate(...) should be used instead.
  using StatusCallback = hci::ResultCallback<>;
  void UpdateConnectionParams(const hci_spec::LEPreferredConnectionParameters& params,
                              StatusCallback status_cb = nullptr);

  // This event may be generated without host interaction by the Link Layer, or as the result of a
  // Connection Update Command sent by either device, which is why it is not simply handled by the
  // command handler. (See Core Spec v5.2, Vol 6, Part B, Sec 5.1.7.1).
  void OnLEConnectionUpdateComplete(const hci::EventPacket& event);

  // Updates or requests an update of the connection parameters, for central and peripheral roles
  // respectively, if interrogation has completed.
  // TODO(fxbug.dev/79491): Wait to update connection parameters until all initialization
  // procedures have completed.
  void MaybeUpdateConnectionParameters();

  // Registers the peer with GATT and initiates service discovery. If |service_uuid| is specified,
  // only discover the indicated service and the GAP service.
  void InitializeGatt(fbl::RefPtr<l2cap::Channel> att, std::optional<UUID> service_uuid);

  // Called when service discovery completes. |services| will only include services with the GAP
  // UUID (there should only be one, but this is not guaranteed).
  void OnGattServicesResult(att::Result<> status, gatt::ServiceList services);

  // Notifies all connection refs of disconnection.
  void CloseRefs();

  // sm::Delegate overrides:
  void OnNewPairingData(const sm::PairingData& pairing_data) override;
  void OnPairingComplete(sm::Result<> status) override;
  void OnAuthenticationFailure(hci::Result<> status) override;
  void OnNewSecurityProperties(const sm::SecurityProperties& sec) override;
  std::optional<sm::IdentityInfo> OnIdentityInformationRequest() override;
  void ConfirmPairing(ConfirmCallback confirm) override;
  void DisplayPasskey(uint32_t passkey, sm::Delegate::DisplayMethod method,
                      ConfirmCallback confirm) override;
  void RequestPasskey(PasskeyResponseCallback respond) override;

  // Notifies Peer of connection destruction. This should be ordered first so that it is
  // destroyed last.
  std::optional<Peer::ConnectionToken> peer_conn_token_;

  fxl::WeakPtr<Peer> peer_;
  std::unique_ptr<hci::LowEnergyConnection> link_;
  LowEnergyConnectionOptions connection_options_;
  fxl::WeakPtr<LowEnergyConnectionManager> conn_mgr_;

  struct InspectProperties {
    inspect::StringProperty peer_id;
    inspect::StringProperty peer_address;
  };
  InspectProperties inspect_properties_;
  inspect::Node inspect_node_;

  // Used to update the L2CAP layer to reflect the correct link security level.
  l2cap::L2cap* l2cap_;

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

  // SMP pairing manager.
  std::unique_ptr<sm::SecurityManager> sm_;

  fxl::WeakPtr<hci::Transport> transport_;

  // Called when the peer disconnects.
  PeerDisconnectCallback peer_disconnect_callback_;

  // Called when a fatal connection error occurs and the connection should be
  // closed (e.g. when L2CAP reports an error).
  ErrorCallback error_callback_;

  // Event handler ID for the HCI LE Connection Update Complete event.
  hci::CommandChannel::EventHandlerId conn_update_cmpl_handler_id_;

  // Called with the status of the next HCI LE Connection Update Complete event.
  // The HCI LE Connection Update command does not have its own complete event handler because the
  // HCI LE Connection Complete event can be generated for other reasons.
  fit::callback<void(hci_spec::StatusCode)> le_conn_update_complete_command_callback_;

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

  // Called after kLEConnectionPauseCentral.
  std::optional<async::TaskClosure> conn_pause_central_timeout_;

  // Set to true when a request to update the connection parameters has been sent.
  bool connection_parameters_update_requested_ = false;

  bool interrogation_completed_ = false;

  // LowEnergyConnectionManager is responsible for making sure that these
  // pointers are always valid.
  using ConnectionHandleSet = std::unordered_set<LowEnergyConnectionHandle*>;
  IntInspectable<ConnectionHandleSet> refs_;

  // Null until service discovery completes.
  std::optional<GenericAccessClient> gap_service_client_;

  fxl::WeakPtrFactory<LowEnergyConnection> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(LowEnergyConnection);
};

}  // namespace internal
}  // namespace bt::gap

#endif  // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GAP_LOW_ENERGY_CONNECTION_H_
