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

#ifndef SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_ATT_BEARER_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_ATT_BEARER_H_

#include <fbl/macros.h>
#include <lib/async/cpp/task.h>
#include <lib/fit/function.h>
#include <zircon/assert.h>

#include <map>
#include <memory>
#include <unordered_map>

#include "src/connectivity/bluetooth/core/bt-host/att/att.h"
#include "src/connectivity/bluetooth/core/bt-host/att/packet.h"
#include "src/connectivity/bluetooth/core/bt-host/att/status.h"
#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/connectivity/bluetooth/core/bt-host/common/linked_list.h"
#include "src/connectivity/bluetooth/core/bt-host/common/packet_view.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/channel.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/scoped_channel.h"
#include "src/lib/fxl/functional/cancelable_callback.h"
#include "src/lib/fxl/memory/ref_counted.h"
#include "src/lib/fxl/memory/weak_ptr.h"
#include "src/lib/fxl/synchronization/thread_checker.h"

namespace bt {
namespace att {

// Implements an ATT data bearer with the following features:
//
//   * This can be used over either a LE-U or an ACL-U logical link. No
//     assumptions are made on the logical transport of the underlying L2CAP
//     channel.
//   * Can simultaneously operate in both server and client roles of the
//     protocol.
//
// Deleting a Bearer closes the underlying channel. Unlike ShutDown(), this
// does NOT notify any callbacks to prevent them from running in destructors.
//
// THREAD-SAFETY:
//
// This class is intended to be created, accessed, and destroyed on the same
// thread. All callbacks will be invoked on a Bearer's creation thread.
class Bearer final : public fxl::RefCountedThreadSafe<Bearer> {
 public:
  // Creates a new ATT Bearer. Returns nullptr if |chan| cannot be activated.
  // This can happen if the link is closed.
  static fxl::RefPtr<Bearer> Create(fbl::RefPtr<l2cap::Channel> chan);

  // Returns true if the underlying channel is open.
  bool is_open() const { return static_cast<bool>(chan_); }

  // The bi-directional (client + server) MTU currently in use. The default
  // value is kLEMinMTU.
  //
  // NOTE: This is allowed to be initialized to something smaller than kLEMinMTU
  // for unit tests.
  uint16_t mtu() const { return mtu_; }
  void set_mtu(uint16_t value) {
    bt_log(TRACE, "att", "bearer: new MTU %u", value);
    mtu_ = value;
  }

  // The preferred MTU. This is initially assigned based on the MTU of the
  // underlying L2CAP channel and will be used in future MTU Exchange
  // procedures.
  uint16_t preferred_mtu() const { return preferred_mtu_; }
  void set_preferred_mtu(uint16_t value) {
    ZX_DEBUG_ASSERT(value >= kLEMinMTU);
    preferred_mtu_ = value;
  }

  // Returns the correct minimum ATT_MTU based on the underlying link type.
  uint16_t min_mtu() const { return min_mtu_; }

  // Returns the current link security properties.
  const sm::SecurityProperties security() const {
    return chan_ ? chan_->security() : sm::SecurityProperties();
  }

  // Sets a callback to be invoked invoked when the underlying channel has
  // closed. |callback| should disconnect the underlying logical link.
  void set_closed_callback(fit::closure callback) {
    ZX_DEBUG_ASSERT(thread_checker_.IsCreationThreadCurrent());
    closed_cb_ = std::move(callback);
  }

  // Closes the channel. This should be called when a protocol transaction
  // warrants the link to be disconnected. Notifies any callback set via
  // |set_closed_callback()| and notifies the error callback of all pending HCI
  // transactions.
  //
  // Does nothing if the channel is not open.
  //
  // NOTE: Bearer internally shuts down the link on request timeouts and
  // sequential protocol violations.
  void ShutDown();

  // Initiates an asynchronous transaction and invokes |callback| on this
  // Bearer's creation thread when the transaction completes. |pdu| must
  // correspond to a request or indication.
  //
  // TransactionCallback is used to report the end of a request or indication
  // transaction. |packet| will contain a matching response or confirmation PDU
  // depending on the transaction in question.
  //
  // If the transaction ends with an error or cannot complete (e.g. due to a
  // timeout), |error_callback| will be called instead of |callback| if
  // provided.
  //
  // Returns false if |pdu| is empty, exceeds the current MTU, or does not
  // correspond to a request or indication.
  using TransactionCallback = fit::function<void(const PacketReader& packet)>;
  using ErrorCallback = fit::function<void(Status, Handle attr_in_error)>;
  bool StartTransaction(ByteBufferPtr pdu, TransactionCallback callback,
                        ErrorCallback error_callback);

  // Sends |pdu| without initiating a transaction. Used for command and
  // notification PDUs which do not have flow control.
  //
  // Returns false if the packet is malformed or does not correspond to a
  // command or notification.
  bool SendWithoutResponse(ByteBufferPtr pdu);

  // A Handler is a function that gets invoked when the Bearer receives a PDU
  // that is not tied to a locally initiated transaction (see
  // StartTransaction()).
  //
  //   * |tid| will be set to kInvalidTransactionId for command and notification
  //     PDUs. These do not require a response and are not part of a
  //     transaction.
  //
  //   * A valid |tid| will be provided for request and indication PDUs. These
  //     require a response which can be sent by calling Reply().
  using TransactionId = size_t;
  static constexpr TransactionId kInvalidTransactionId = 0u;
  using Handler = fit::function<void(TransactionId tid, const PacketReader& packet)>;

  // Handler: called when |pdu| does not need flow control. This will be
  // called for commands and notifications.
  using HandlerId = size_t;
  static constexpr HandlerId kInvalidHandlerId = 0u;
  HandlerId RegisterHandler(OpCode opcode, Handler handler);

  // Unregisters a handler. |id| cannot be zero.
  void UnregisterHandler(HandlerId id);

  // Ends a currently pending transaction with the given response or
  // confirmation |pdu|. Returns false if |pdu| is malformed or if |id| and
  // |pdu| do not match a pending transaction.
  bool Reply(TransactionId tid, ByteBufferPtr pdu);

  // Ends a request transaction with an error response.
  bool ReplyWithError(TransactionId id, Handle handle, ErrorCode error_code);

 private:
  FRIEND_REF_COUNTED_THREAD_SAFE(Bearer);

  explicit Bearer(fbl::RefPtr<l2cap::Channel> chan);
  ~Bearer();

  // Returns false if activation fails. This is called by the factory method.
  bool Activate();

  // Represents a locally initiated pending request or indication transaction.
  struct PendingTransaction : LinkedListable<PendingTransaction> {
    PendingTransaction(OpCode opcode, TransactionCallback callback, ErrorCallback error_callback,
                       ByteBufferPtr pdu);

    // Required fields
    OpCode opcode;
    TransactionCallback callback;

    // Optional error callback
    ErrorCallback error_callback;

    // Holds the pdu while the transaction is in the send queue.
    ByteBufferPtr pdu;

    // Contains the most recently requested security upgrade level under which
    // this transaction has been retried following an ATT security error. The
    // states look like the following:
    //
    //   - sm::SecurityLevel::kNoSecurity: The transaction has not been retried.
    //   - sm::SecurityLevel::kEncrypted: The request has been queued following
    //     a security upgrate to level "Encrypted".
    //   - sm::SecurityLevel::kAuthenticated: The request has been queued
    //     following a security upgrate to level "Authenticated".
    //
    // and so on.
    sm::SecurityLevel security_retry_level;
  };
  using PendingTransactionPtr = std::unique_ptr<PendingTransaction>;

  // Represents a remote initiated pending request or indication transaction.
  struct PendingRemoteTransaction {
    PendingRemoteTransaction(TransactionId id, OpCode opcode);
    PendingRemoteTransaction() = default;

    TransactionId id;
    OpCode opcode;
  };

  // Used the represent the state of active ATT protocol request and indication
  // transactions.
  class TransactionQueue {
   public:
    TransactionQueue() = default;
    ~TransactionQueue() = default;

    TransactionQueue(TransactionQueue&& other);

    // Returns the transaction that has been sent to the peer and is currently
    // pending completion.
    inline PendingTransaction* current() const { return current_.get(); }

    // Clears the currently pending transaction data and cancels its transaction
    // timeout task. Returns ownership of any pending transaction to the caller.
    PendingTransactionPtr ClearCurrent();

    // Tries to initiate the next transaction. Sends the PDU over |chan| if
    // successful.
    void TrySendNext(l2cap::Channel* chan, async::Task::Handler timeout_cb, zx::duration timeout);

    // Adds |next| to the transaction queue.
    void Enqueue(PendingTransactionPtr transaction);

    // Resets the contents of this queue to their default state.
    void Reset();

    // Invokes the error callbacks of all transactions with |status|.
    void InvokeErrorAll(Status status);

   private:
    LinkedList<PendingTransaction> queue_;
    PendingTransactionPtr current_;
    async::Task timeout_task_;
  };

  bool SendInternal(ByteBufferPtr pdu, TransactionCallback callback, ErrorCallback error_callback);

  // Shuts down the link.
  void ShutDownInternal(bool due_to_timeout);

  // Returns false if |pdu| is malformed.
  bool IsPacketValid(const ByteBuffer& pdu);

  // Tries to initiate the next transaction from the given |queue|.
  void TryStartNextTransaction(TransactionQueue* tq);

  // Sends out an immediate error response.
  void SendErrorResponse(OpCode request_opcode, Handle attribute_handle, ErrorCode error_code);

  // Called when the peer sends us a response or confirmation PDU.
  void HandleEndTransaction(TransactionQueue* tq, const PacketReader& packet);

  // Returns the next handler ID and increments the counter.
  HandlerId NextHandlerId();

  // Returns the next remote-initiated transaction ID.
  TransactionId NextRemoteTransactionId();

  using RemoteTransaction = std::optional<PendingRemoteTransaction>;

  // Called when the peer initiates a request or indication transaction.
  void HandleBeginTransaction(RemoteTransaction* currently_pending, const PacketReader& packet);

  // Returns any pending peer-initiated transaction that matches |id|. Returns
  // nullptr otherwise.
  RemoteTransaction* FindRemoteTransaction(TransactionId id);

  // Called when the peer sends us a PDU that has no flow control (i.e. command
  // or notification). Routes the packet to the corresponding handler. Drops the
  // packet if no handler exists.
  void HandlePDUWithoutResponse(const PacketReader& packet);

  // l2cap::Channel callbacks:
  void OnChannelClosed();
  void OnRxBFrame(ByteBufferPtr sdu);

  l2cap::ScopedChannel chan_;
  uint16_t mtu_;
  uint16_t preferred_mtu_;
  uint16_t min_mtu_;

  // Callback passed to l2cap::Channel::OnRxBFrame().
  fxl::CancelableCallback<void(ByteBufferPtr sdu)> rx_task_;

  // Callback that wraps our internal OnChannelClosed handler.
  fxl::CancelableClosure chan_closed_cb_;

  // Channel closed callback assigned to us via set_closed_callback().
  fit::closure closed_cb_;

  // The state of outgoing ATT requests and indications
  TransactionQueue request_queue_;
  TransactionQueue indication_queue_;

  // The transaction identifier that will be assigned to the next
  // remote-initiated request or indication transaction.
  TransactionId next_remote_transaction_id_;

  // The next available remote-initiated PDU handler id.
  HandlerId next_handler_id_;

  // Data about currently registered handlers.
  std::unordered_map<HandlerId, OpCode> handler_id_map_;
  std::unordered_map<OpCode, Handler> handlers_;

  // Remote-initiated transactions in progress.
  RemoteTransaction remote_request_;
  RemoteTransaction remote_indication_;

  fxl::ThreadChecker thread_checker_;
  fxl::WeakPtrFactory<Bearer> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(Bearer);
};

}  // namespace att
}  // namespace bt

#endif  // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_ATT_BEARER_H_
