// 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_L2CAP_CHANNEL_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_CHANNEL_H_

#include <lib/async/dispatcher.h>
#include <lib/fit/function.h>
#include <lib/zx/socket.h>
#include <zircon/compiler.h>

#include <atomic>
#include <climits>
#include <list>
#include <memory>
#include <mutex>
#include <queue>

#include <fbl/macros.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>

#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/connection.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/l2cap.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/pdu.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/rx_engine.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/tx_engine.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/types.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/status.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/types.h"
#include "src/lib/fxl/synchronization/thread_checker.h"

namespace bt {
namespace l2cap {

// Represents a L2CAP channel. Each instance is owned by a service
// implementation that operates on the corresponding channel. Instances can only
// be obtained from a ChannelManager.
//
// A Channel can operate in one of 6 L2CAP Modes of Operation (see Core Spec
// v5.0, Vol 3, Part A, Section 2.4). Only Basic Mode is currently supported.
//
// USAGE:
//
// Channel is an abstract base class. There are two concrete implementations:
//
//   * internal::ChannelImpl (defined below) which implements a real L2CAP
//     channel. Instances are obtained from ChannelManager and tied to
//     internal::LogicalLink instances.
//
//   * FakeChannel, which can be used for unit testing service-layer entities
//     that operate on one or more L2CAP channel(s).
//
// Production instances are obtained from a ChannelManager. Channels are safe to
// activate, deactivate, and destroy on any thread.
//
// A Channel's owner must explicitly call Deactivate() and must not rely on
// dropping its reference to close the channel.
//
// When a LogicalLink closes, all of its active channels become deactivated
// when it closes and this is signaled by running the ClosedCallback passed to
// ActivateWithDispatcher() or ActivateOnDataDomain.
class Channel : public fbl::RefCounted<Channel> {
 public:
  // Identifier for this channel's endpoint on this device. It can be prior-
  // specified for fixed channels or allocated for dynamic channels per v5.0,
  // Vol 3, Part A, Section 2.1 "Channel Identifiers." Channels on a link will
  // have unique identifiers to each other.
  ChannelId id() const { return id_; }

  // Identifier for this channel's endpoint on the remote peer. Same value as
  // |id()| for fixed channels and allocated by the remote for dynamic channels.
  ChannelId remote_id() const { return remote_id_; }

  // The type of the logical link this channel operates on.
  hci::Connection::LinkType link_type() const { return link_type_; }

  // The connection handle of the underlying logical link.
  hci::ConnectionHandle link_handle() const { return link_handle_; }

  // Returns a value that's unique for any channel connected to this device.
  // If two channels have different unique_ids, they represent different
  // channels even if their ids match.
  using UniqueId = uint32_t;
  UniqueId unique_id() const {
    static_assert(sizeof(UniqueId) >= sizeof(hci::ConnectionHandle) + sizeof(ChannelId),
                  "UniqueId needs to be large enough to make unique IDs");
    return (link_handle() << (sizeof(ChannelId) * CHAR_BIT)) | id();
  }

  ChannelMode mode() const { return info().mode; }

  uint16_t max_rx_sdu_size() const { return info().max_rx_sdu_size; }
  uint16_t max_tx_sdu_size() const { return info().max_tx_sdu_size; }

  // Returns the current configuration parameters for this channel.
  ChannelInfo info() const { return info_; }

  // Returns the current link security properties of the underlying link.
  // Returns the lowest security level if the link is closed.
  virtual const sm::SecurityProperties security() = 0;

  // Callback invoked when this channel has been closed without an explicit
  // request from the owner of this instance. For example, this can happen when
  // the remote end closes a dynamically configured channel or when the
  // underlying logical link is terminated through other means.
  using ClosedCallback = fit::closure;

  // Callback invoked when a new packet is received on this channel. Any
  // previously buffered packets will be sent to |rx_cb| right away, provided
  // that |rx_cb| is not empty and the underlying logical link is active.
  using RxCallback = fit::function<void(ByteBufferPtr packet)>;

  // Activates this channel assigning |dispatcher| to execute |rx_callback| and |closed_callback|.
  //
  // Returns false if the channel's link has been closed.
  //
  // Each channel can be activated only once.
  //
  // NOTE: Callers shouldn't assume that this method will succeed, as the underlying link can be
  // removed at any time.
  virtual bool ActivateWithDispatcher(RxCallback rx_callback, ClosedCallback closed_callback,
                                      async_dispatcher_t* dispatcher) = 0;

  // Activates this channel as in ActivateWithDispatcher, but callbacks will be executed immediately
  // on the Data domain as L2CAP is notified of their underlying events.
  //
  // Any inbound data that has already been buffered for this channel will be drained by calling
  // |rx_callback| repeatedly, before this call returns.
  //
  // Execution of |rx_callback| may block L2CAP data routing, so care should be taken to avoid
  // introducing excessive latency.
  //
  // Each channel can be activated only once.
  virtual bool ActivateOnDataDomain(RxCallback rx_callback, ClosedCallback closed_callback) = 0;

  // Deactivates this channel. No more packets can be sent or received after
  // this is called. |rx_callback| may still be called if it has been already
  // dispatched to its task runner.
  //
  // This method is idempotent.
  virtual void Deactivate() = 0;

  // Signals that the underlying link should be disconnected. This should be
  // called when a service layer protocol error requires the connection to be
  // severed.
  //
  // The link error callback (provided to L2CAP::Register* methods) is invoked
  // as a result of this operation. The handler is responsible for actually
  // disconnecting the link.
  //
  // This does not deactivate the channel, though the channel is expected to
  // close when the link gets removed later.
  virtual void SignalLinkError() = 0;

  // Requests to upgrade the security properties of the underlying link to the requested |level|
  // and reports the result via |callback|, run on |dispatcher|. Has no effect if the channel is
  // not active.
  virtual void UpgradeSecurity(sm::SecurityLevel level, sm::StatusCallback callback,
                               async_dispatcher_t* dispatcher) = 0;

  // Queue the given SDU payload for transmission over this channel, taking
  // ownership of |sdu|. Returns true if the SDU was queued successfully, and
  // false otherwise.
  //
  // For reasons why queuing might fail, see the documentation for the relevant
  // TxEngine's QueueSdu() method. Note: a successfully enqueued SDU may still
  // fail to reach the receiver, due to asynchronous local errors, transmission
  // failure, or remote errors.
  virtual bool Send(ByteBufferPtr sdu) = 0;

 protected:
  friend class fbl::RefPtr<Channel>;
  // TODO(1022): define a preferred MTU somewhere
  Channel(ChannelId id, ChannelId remote_id, hci::Connection::LinkType link_type,
          hci::ConnectionHandle link_handle, ChannelInfo info);
  virtual ~Channel() = default;

  const ChannelId id_;
  const ChannelId remote_id_;
  const hci::Connection::LinkType link_type_;
  const hci::ConnectionHandle link_handle_;
  const ChannelInfo info_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(Channel);
};

// A socket connected to an L2cap channel and its parameters
// params will be non-empty iff socket != ZX_INVALID_HANDLE
struct ChannelSocket {
  ChannelSocket() : socket(zx::socket()), params(std::nullopt) {}
  ChannelSocket(zx::socket socket, std::optional<ChannelInfo> params)
      : socket(std::move(socket)), params(params) {
    ZX_ASSERT(this->socket.is_valid() && this->params.has_value() ||
              !this->socket.is_valid() && !this->params.has_value());
  }
  ChannelSocket(ChannelSocket&&) = default;

  bool is_valid() const { return socket.is_valid(); }
  explicit operator bool() const { return is_valid(); }
  zx::socket socket;
  std::optional<const ChannelInfo> params;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ChannelSocket);
};

namespace internal {

class LogicalLink;

// Channel implementation used in production.
class ChannelImpl : public Channel {
 public:
  static fbl::RefPtr<ChannelImpl> CreateFixedChannel(ChannelId id,
                                                     fbl::RefPtr<internal::LogicalLink> link);

  static fbl::RefPtr<ChannelImpl> CreateDynamicChannel(ChannelId id, ChannelId peer_id,
                                                       fbl::RefPtr<internal::LogicalLink> link,
                                                       ChannelInfo info);

  // Called by |link_| to notify us when the channel can no longer process data.
  // This MUST NOT call any locking methods of |link_| as that WILL cause a
  // deadlock.
  void OnClosed();

  // Called by |link_| when a PDU targeting this channel has been received.
  // Contents of |pdu| will be moved.
  void HandleRxPdu(PDU&& pdu);

  // Channel overrides:
  const sm::SecurityProperties security() override;
  bool ActivateWithDispatcher(RxCallback rx_callback, ClosedCallback closed_callback,
                              async_dispatcher_t* dispatcher) override;
  bool ActivateOnDataDomain(RxCallback rx_callback, ClosedCallback closed_callback) override;
  void Deactivate() override;
  void SignalLinkError() override;
  bool Send(ByteBufferPtr sdu) override;
  void UpgradeSecurity(sm::SecurityLevel level, sm::StatusCallback callback,
                       async_dispatcher_t* dispatcher) override;

 private:
  friend class fbl::RefPtr<ChannelImpl>;

  ChannelImpl(ChannelId id, ChannelId remote_id, fbl::RefPtr<internal::LogicalLink> link,
              ChannelInfo info);
  ~ChannelImpl() override = default;

  // TODO(armansito): Add MPS fields when we support segmentation/flow-control.

  std::mutex mtx_;

  bool active_ __TA_GUARDED(mtx_);
  async_dispatcher_t* dispatcher_ __TA_GUARDED(mtx_);
  RxCallback rx_cb_ __TA_GUARDED(mtx_);
  ClosedCallback closed_cb_ __TA_GUARDED(mtx_);

  // The LogicalLink that this channel is associated with. A channel is always
  // created by a LogicalLink.
  //
  // |link_| is guaranteed to be valid as long as the link is active. This is
  // because when a LogicalLink is torn down, it will notify all of its
  // associated channels by calling OnLinkClosed() which sets |link_| to
  // nullptr.
  fbl::RefPtr<internal::LogicalLink> link_ __TA_GUARDED(mtx_);

  // The engine which processes received PDUs, and converts them to SDUs for
  // upper layers.
  std::unique_ptr<RxEngine> rx_engine_ __TA_GUARDED(mtx_);

  // The engine which accepts SDUs, and converts them to PDUs for lower layers.
  std::unique_ptr<TxEngine> tx_engine_ __TA_GUARDED(mtx_);

  // The pending SDUs on this channel. Received PDUs are buffered if |rx_cb_| is
  // currently not set.
  // TODO(armansito): We should avoid STL containers for data packets as they
  // all implicitly allocate. This is a reminder to fix this elsewhere
  // (especially in the HCI layer).
  std::queue<ByteBufferPtr, std::list<ByteBufferPtr>> pending_rx_sdus_ __TA_GUARDED(mtx_);

  fxl::ThreadChecker thread_checker_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ChannelImpl);
};

}  // namespace internal
}  // namespace l2cap
}  // namespace bt

#endif  // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_CHANNEL_H_
