blob: b9c84978b5036a50eb3a5f22d0bc4d2634fa324a [file] [log] [blame]
// Copyright 2019 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_BREDR_CONNECTION_REQUEST_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GAP_BREDR_CONNECTION_REQUEST_H_
#include <lib/async/cpp/task.h>
#include <lib/fit/function.h>
#include <lib/zx/time.h>
#include <list>
#include "fbl/macros.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/peer.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/protocol.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/error.h"
namespace bt::gap {
class BrEdrConnection;
// A |BrEdrConnectionRequest| represents a request for the GAP to connect to a given
// |DeviceAddress| by one or more clients. BrEdrConnectionManager
// is responsible for tracking ConnectionRequests and passing them to the
// Connector when ready.
//
// There is at most One BrEdrConnectionRequest per address at any given time; if
// multiple clients wish to connect, they each append a callback to the list in
// the ConnectionRequest for the device they are interested in.
//
// If a remote peer makes an incoming request for a connection, we track that
// here also - whether an incoming request is pending is indicated by
// HasIncoming()
class BrEdrConnectionRequest final {
public:
using OnComplete = fit::function<void(hci::Result<>, BrEdrConnection*)>;
using RefFactory = fit::function<BrEdrConnection*()>;
// Construct without a callback. Can be used for incoming only requests
BrEdrConnectionRequest(const DeviceAddress& addr, PeerId peer_id,
Peer::InitializingConnectionToken token);
BrEdrConnectionRequest(const DeviceAddress& addr, PeerId peer_id,
Peer::InitializingConnectionToken token, OnComplete&& callback);
BrEdrConnectionRequest(BrEdrConnectionRequest&&) = default;
BrEdrConnectionRequest& operator=(BrEdrConnectionRequest&&) = default;
void RecordHciCreateConnectionAttempt();
bool ShouldRetry(hci::Error failure_mode);
void AddCallback(OnComplete cb) { callbacks_.Mutable()->push_back(std::move(cb)); }
// Notifies all elements in |callbacks| with |status| and the result of
// |generate_ref|. Called by the appropriate manager once a connection request
// has completed, successfully or otherwise
void NotifyCallbacks(hci::Result<> status, const RefFactory& generate_ref);
void BeginIncoming() { has_incoming_.Set(true); }
void CompleteIncoming() { has_incoming_.Set(false); }
bool HasIncoming() const { return *has_incoming_; }
bool AwaitingOutgoing() { return !callbacks_->empty(); }
// Attach request inspect node as a child of |parent| named |name|.
void AttachInspect(inspect::Node& parent, std::string name);
DeviceAddress address() const { return address_; }
// If a role change occurs while this request is still pending, set it here so that the correct
// role is used when connection establishment completes.
void set_role_change(hci_spec::ConnectionRole role) { role_change_ = role; }
// If the default role of the requested connection is changed during connection establishment, the
// new role will be returned.
const std::optional<hci_spec::ConnectionRole>& role_change() const { return role_change_; }
Peer::InitializingConnectionToken take_peer_init_token() {
ZX_ASSERT(peer_init_conn_token_);
return std::exchange(peer_init_conn_token_, std::nullopt).value();
}
private:
PeerId peer_id_;
DeviceAddress address_;
UintInspectable<std::list<OnComplete>> callbacks_;
BoolInspectable<bool> has_incoming_;
std::optional<hci_spec::ConnectionRole> role_change_;
// Used to determine whether an outbound connection request should be retried. If empty, no HCI
// Create Connection Requests associated with this object have been made, otherwise stores the
// time at which the first HCI request associated with this object was made.
IntInspectable<std::optional<zx::time>> first_create_connection_req_made_;
inspect::StringProperty peer_id_property_;
inspect::Node inspect_node_;
std::optional<Peer::InitializingConnectionToken> peer_init_conn_token_;
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(BrEdrConnectionRequest);
};
} // namespace bt::gap
#endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GAP_BREDR_CONNECTION_REQUEST_H_