// Copyright 2018 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_DYNAMIC_CHANNEL_REGISTRY_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_DYNAMIC_CHANNEL_REGISTRY_H_

#include <lib/fit/function.h>

#include <random>
#include <unordered_map>

#include "src/connectivity/bluetooth/core/bt-host/common/random.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/dynamic_channel.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/l2cap_defs.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/signaling_channel.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/types.h"
#include "src/lib/fxl/memory/weak_ptr.h"

namespace bt::l2cap::internal {

// Base class for registries of dynamic L2CAP channels. It serves both as the
// factory and owner of dynamic channels created on a logical link, including
// assigning and tracking dynamic channel IDs.
//
// Registry entries are DynamicChannels that do not implement the l2cap::Channel
// interface used for user data transfer.
//
// This class is not thread-safe and is intended to be created and run on the
// L2CAP thread for each logical link connected.
class DynamicChannelRegistry {
 public:
  // Used to pass an optional channel to clients of the registry. |channel| may
  // be nullptr upon failure to open. Otherwise, it points to an instance owned
  // by the registry and should not be retained by the callee.
  using DynamicChannelCallback = fit::function<void(const DynamicChannel* channel)>;
  using ServiceInfo = ServiceInfo<DynamicChannelCallback>;

  // Used to query the upper layers for the presence of a service that is
  // accepting channels. If the service exists, it should return a callback
  // that accepts the inbound dynamic channel opened.
  using ServiceRequestCallback = fit::function<std::optional<ServiceInfo>(PSM psm)>;

  virtual ~DynamicChannelRegistry();

  // Create and connect a dynamic channel. The result will be returned by
  // calling |open_cb| on the L2CAP thread the channel is ready for data
  // transfer, with a nullptr if unsuccessful. The DynamicChannel passed will
  // contain the local and remote channel IDs to be used for user data transfer
  // over the new channel. Preferred channel parameters can be set in |params|.
  void OpenOutbound(PSM psm, ChannelParameters params, DynamicChannelCallback open_cb);

  // Disconnect and remove the channel identified by |local_cid|. After this call completes,
  // incoming PDUs with |local_cid| should be discarded as in error or considered to belong to a
  // subsequent channel with that ID. Any outbound PDUs passed to the Channel interface for this
  // channel should be discarded. When the close operation completes, |close_cb| will be called, the
  // internal channel will be destroyed, and |local_cid| may be recycled for another dynamic
  // channel. |close_cb| will be called immediately if the channel doesn't exist.
  void CloseChannel(ChannelId local_cid, fit::closure close_cb);

 protected:
  // |max_num_channels| is the number of dynamic channel IDs that can be
  // allocated on this link, and must be non-zero and less than 65473.
  //
  // |close_cb| will be called upon a remote-initiated closure of an open
  // channel. The registry's internal channel is passed as a parameter, and it
  // will be closed for user data transfer before the callback fires. When the
  // callback returns, the channel is destroyed and its ID may be recycled for
  // another dynamic channel. Channels that fail to open due to error or are
  // closed using CloseChannel will not trigger this callback.
  //
  // |service_request_cb| will be called upon remote-initiated channel requests.
  // For services accepting channels, it shall return a callback to accept the
  // opened channel, which only be called if the channel successfully opens. To
  // deny the channel creation, |service_request_cb| should return a nullptr.
  //
  // If |random_channel_ids| is true then the channel IDs assigned will be randomized.
  // Otherwise, they will be assigned starting at the lowest available dynamic channel id.
  DynamicChannelRegistry(uint16_t max_num_channels, DynamicChannelCallback close_cb,
                         ServiceRequestCallback service_request_cb, bool random_channel_ids);

  // Factory method for a DynamicChannel implementation that represents an
  // outbound channel with an endpoint on this device identified by |local_cid|.
  virtual DynamicChannelPtr MakeOutbound(PSM psm, ChannelId local_cid,
                                         ChannelParameters params) = 0;

  // Factory method for a DynamicChannel implementation that represents an
  // inbound channel from a remote endpoint identified by |remote_cid| to an
  // endpoint on this device identified by |local_cid|.
  virtual DynamicChannelPtr MakeInbound(PSM psm, ChannelId local_cid, ChannelId remote_cid,
                                        ChannelParameters params) = 0;

  // Open an inbound channel for a service |psm| from the remote endpoint
  // identified by |remote_cid| to the local endpoint by |local_cid|.
  DynamicChannel* RequestService(PSM psm, ChannelId local_cid, ChannelId remote_cid);

  // In the range starting at kFirstDynamicChannelId with |max_num_channels_|, pick a dynamic
  // channel ID that is available on this link.
  // Returns kInvalidChannelId if all IDs have been exhausted.
  ChannelId FindAvailableChannelId();

  // Return the number of alive channels on this link.
  size_t AliveChannelCount() const;

  // Returns null if not found. Can be downcast to the derived DynamicChannel
  // created by MakeOutbound.
  DynamicChannel* FindChannelByLocalId(ChannelId local_cid) const;

  // Searches for alive dynamic channel with given remote channel id.
  // Returns null if not found.
  DynamicChannel* FindChannelByRemoteId(ChannelId remote_cid) const;

  // Iterates over all channels, running |f| on each entry synchronously.
  void ForEach(fit::function<void(DynamicChannel*)> f) const;

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

 private:
  friend class DynamicChannel;

  // Open a newly-created channel. If |pass_failed| is true, always invoke
  // |open_cb| with the result of the operation, including with nullptr if the
  // channel failed to open. Otherwise if |pass_failed| is false, only invoke
  // |open_cb| for successfully-opened channels.
  void ActivateChannel(DynamicChannel* channel, DynamicChannelCallback open_cb, bool pass_failed);

  // Signal a remote-initiated closure of a channel owned by this registry, then
  // delete it. |close_cb_| is invoked if the channel was ever open (see
  // |DynamicChannel::opened|).
  void OnChannelDisconnected(DynamicChannel* channel);

  // Delete a channel owned by this registry. Then, after this returns,
  // |local_cid| may be recycled for another dynamic channel.
  void RemoveChannel(DynamicChannel* channel);

  // Greatest dynamic channel ID that can be assigned on the kind of logical
  // link associated to this registry.
  const uint16_t max_num_channels_;

  // Called only for channels that were already open (see
  // |DynamicChannel::opened|).
  DynamicChannelCallback close_cb_;
  ServiceRequestCallback service_request_cb_;

  // Maps local CIDs to alive dynamic channels on this logical link.
  using ChannelMap = std::unordered_map<ChannelId, DynamicChannelPtr>;
  ChannelMap channels_;

  std::optional<std::default_random_engine> rng_;

  fxl::WeakPtrFactory<DynamicChannelRegistry> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(DynamicChannelRegistry);
};

}  // namespace bt::l2cap::internal

#endif  // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_DYNAMIC_CHANNEL_REGISTRY_H_
