// 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_SM_PHASE_1_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_SM_PHASE_1_H_

#include <lib/async/cpp/task.h>
#include <lib/fit/function.h>

#include "src/connectivity/bluetooth/core/bt-host/hci/connection.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/channel.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/pairing_phase.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/smp.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/memory/weak_ptr.h"

namespace bt::sm {
// Responsible for Phase 1 of SMP pairing, the feature exchange. Takes in the current SM settings
// and notifies a constructor-provided callback with the negotiated features upon completion.
//
// This class is not thread safe and is meant to be accessed on the thread it was created on. All
// callbacks will be run by the default dispatcher of a Phase1's creation thread.
class Phase1 final : public PairingPhase, public PairingChannelHandler {
 public:
  // Called when Phase 1 completes successfully. |features| are the negotiated features. |preq| and
  // |pres| are the SMP "Pairing Request" and "Pairing Response" payloads exchanged by the devices,
  // which are returned for use in Phase 2 crypto calculations.
  using CompleteCallback = fit::function<void(PairingFeatures features, PairingRequestParams preq,
                                              PairingResponseParams pres)>;

  // Returns a Phase 1 that starts pairing to |requested_level|. Note the lack of a `preq`
  // parameter: Phase 1 builds & sends the Pairing Request as initiator.
  static std::unique_ptr<Phase1> CreatePhase1Initiator(fxl::WeakPtr<PairingChannel> chan,
                                                       fxl::WeakPtr<Listener> listener,
                                                       IOCapability io_capability,
                                                       BondableMode bondable_mode,
                                                       SecurityLevel requested_level,
                                                       CompleteCallback on_complete);

  // Returns a Phase 1 in the responder role. Note the `preq` parameter: Phase 1 is supplied the
  // Pairing Request from the remote as responder. See private ctor for parameter descriptions.
  static std::unique_ptr<Phase1> CreatePhase1Responder(
      fxl::WeakPtr<PairingChannel> chan, fxl::WeakPtr<Listener> listener, PairingRequestParams preq,
      IOCapability io_capability, BondableMode bondable_mode, SecurityLevel requested_level,
      CompleteCallback on_complete);

  ~Phase1() override = default;

  // Runs the Phase 1 state machine, performing the feature exchange.
  void Start() final;

 private:
  //   |chan|, |listener|, and |role|: used to construct the base PairingPhase
  //   |preq|: If empty, the device is in the initiator role and starts the pairing.
  //           If present, the device is in the responder role, and will respond to |preq|, the
  //           peer initiator's pairing request.
  //   |bondable_mode|: the bondable mode of the local device (see V5.1 Vol. 3 Part C Section 9.4).
  //   |requested_level|: The minimum security level required by the local device for this pairing.
  //                      Must be at least SecurityLevel::kEncrypted. If authenticated, the ctor
  //                      ASSERTs that |io_capabilities| can perform authenticated pairing.
  //   |on_complete|: called at the end of Phase 1 with the resulting features.
  Phase1(fxl::WeakPtr<PairingChannel> chan, fxl::WeakPtr<Listener> listener, Role role,
         std::optional<PairingRequestParams> preq, IOCapability io_capability,
         BondableMode bondable_mode, SecurityLevel requested_level, CompleteCallback on_complete);

  // Start the feature exchange by sending the Pairing Request. The local device must be in the SMP
  // initiator role (V5.1 Vol 3, Part H, 2.3).
  void InitiateFeatureExchange();

  // Handle the peer-initiated feature exchange. The local device must be in the SMP responder role
  // (V5.1 Vol 3, Part H, 2.3).
  void RespondToPairingRequest(const PairingRequestParams& req_params);

  // The returned `LocalPairingParams` contains the locally-preferred pairing parameters for the LE
  // transport. The caller is responsible for making any adjustments necessary (e.g. due to peer
  // preferences) before converting the `LocalPairingParams` to SMP Pairing(Response|Request) PDUs.
  LocalPairingParams BuildPairingParameters();

  // Called to complete a feature exchange. Returns the resulting PairingFeatures if the parameters
  // should be accepted, or an error code if the parameters are rejected and pairing should abort.
  fpromise::result<PairingFeatures, ErrorCode> ResolveFeatures(bool local_initiator,
                                                               const PairingRequestParams& preq,
                                                               const PairingResponseParams& pres);

  // Called for SMP commands sent by the peer.
  void OnPairingResponse(const PairingResponseParams& response_params);

  // PairingChannelHandler callbacks:
  void OnRxBFrame(ByteBufferPtr sdu) final;
  void OnChannelClosed() final { PairingPhase::HandleChannelClosed(); }

  // PairingPhase overrides
  fxl::WeakPtr<PairingChannelHandler> AsChannelHandler() final {
    return weak_ptr_factory_.GetWeakPtr();
  }

  std::string ToStringInternal() override {
    return bt_lib_cpp_string::StringPrintf(
        "Pairing Phase 1 (feature exchange) - pairing to %s security with \"%s\" IOCapabilities",
        LevelToString(requested_level_), util::IOCapabilityToString(io_capability_).c_str());
  }

  // If acting as the Responder to a peer-initiatied pairing, then |preq_| is the |preq| ctor
  // parameter. Otherwise, these are generated and exchanged during Phase 1.
  std::optional<PairingRequestParams> preq_;
  std::optional<PairingResponseParams> pres_;

  // Phase 1 ensures that the feature exchange results in a pairing that supports this level of
  // security. If this is impossible, pairing will abort.
  SecurityLevel requested_level_;

  // Local feature flags that determine the feature exchange negotiation with the peer.
  bool oob_available_;
  IOCapability io_capability_;
  BondableMode bondable_mode_;

  CompleteCallback on_complete_;

  fxl::WeakPtrFactory<Phase1> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(Phase1);
};

}  // namespace bt::sm

#endif  // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_SM_PHASE_1_H_
