blob: 175e2b38862f03f690456cc0d51f6a1b095a394b [file] [log] [blame]
// 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_GAP_LOW_ENERGY_ADDRESS_MANAGER_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GAP_LOW_ENERGY_ADDRESS_MANAGER_H_
#include <fbl/macros.h>
#include <lib/async/cpp/task.h>
#include <optional>
#include <queue>
#include "src/connectivity/bluetooth/core/bt-host/common/device_address.h"
#include "src/connectivity/bluetooth/core/bt-host/common/uint128.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/local_address_delegate.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/status.h"
#include "src/lib/fxl/memory/ref_ptr.h"
#include "src/lib/fxl/memory/weak_ptr.h"
namespace bt {
namespace hci {
class Transport;
} // namespace hci
namespace gap {
// Manages the local LE device address used in scan, legacy advertising, and
// connection initiation procedures. The primary purpose of this class is to
// defer updating the random device address if we believe that doing so is
// disallowed by the controller. This is the case when scanning or legacy
// advertising is enabled, according to Vol 2, Part E, 7.8.4.
//
// Procedures that need to know the value of the local address (both connection
// and advertising procedures need to assign this to any resultant
// hci::Connection object for SMP pairing to function correctly) should call the
// EnsureLocalAddress() method to obtain it and to lazily refresh the address
// if required.
//
// The type and value of the local address depends on whether or not the privacy
// feature is in use. The potential states are as follows:
//
// * When privacy is DISABLED, the local address type and its value match
// the public device address that this object gets initialized with.
//
// * When privacy is ENABLED, the exact type and value depends on the state of
// link layer procedures at that time. The "HCI LE Set Random Address"
// command is used to assign the controller a random address, which it will
// use for the next active scan, legacy advertising, or initiation command
// with a random address type. A new local random address will be generated
// at a regular interval (see kPrivateAddressTimeout in gap.h).
//
// According to Vol 2, Part E, 7.8.4 the "HCI LE Set Random Address"
// command is disallowed when scanning or legacy advertising are enabled.
// Before any one of these procedures gets started, the EnsureLocalAddress()
// method should be called to update the random address if it is allowed by
// the controller (and the address needs a refresh). This function
// asynchronously returns the device address that should be used by the
// procedure.
//
// The state requested by EnablePrivacy() (enabled or disabled) may not take
// effect immediately if a scan, advertising, or connection procedure is in
// progress. The requested address type (public or private) will apply
// eventually when the controller allows it.
class LowEnergyAddressManager final : public hci::LocalAddressDelegate {
public:
// Function called when privacy is in use to determine if it is allowed to
// assign a new random address to the controller. This must return false if
// if scan, legacy advertising, and/or initiation procedures are in progress.
using StateQueryDelegate = fit::function<bool()>;
LowEnergyAddressManager(const DeviceAddress& public_address,
StateQueryDelegate delegate,
fxl::RefPtr<hci::Transport> hci);
~LowEnergyAddressManager();
// Assigns the IRK to generate a RPA for the next address refresh when privacy
// is enabled.
void set_irk(const std::optional<UInt128>& irk) { irk_ = irk; }
// Enable or disable the privacy feature. When enabled, the controller will be
// configured to use a new random address if it is currently allowed to do so.
// If setting the random address is not allowed the update will be deferred
// until the the next successful attempt triggered by a call to
// TryRefreshRandomAddress().
//
// If an IRK has been assigned and |enabled| is true, then the generated
// random addresses will each be a Resolvable Private Address that can be
// resolved with the IRK. Otherwise, Non-resolvable Private Addresses will be
// used.
void EnablePrivacy(bool enabled);
// LocalAddressDelegate overrides:
std::optional<UInt128> irk() const override { return irk_; }
DeviceAddress identity_address() const override { return public_; }
void EnsureLocalAddress(AddressCallback callback) override;
private:
// Return the current address.
const DeviceAddress& current_address() const {
return (privacy_enabled_ && random_) ? *random_ : public_;
}
// Attempt to reconfigure the current random device address.
void TryRefreshRandomAddress();
// Clears all privacy related state such that the random address will not be
// refreshed until privacy is re-enabled. |random_| is not modified and
// continues to reflect the most recently configured random address.
void CleanUpPrivacyState();
void CancelExpiry();
bool CanUpdateRandomAddress() const;
void ResolveAddressRequests();
StateQueryDelegate delegate_;
fxl::RefPtr<hci::Transport> hci_;
bool privacy_enabled_;
// The public device address (i.e. BD_ADDR) that is assigned to the
// controller.
const DeviceAddress public_;
// The random device address assigned to the controller by the most recent
// successful HCI_LE_Set_Random_Address command. std::nullopt if the command
// was never run successfully.
std::optional<DeviceAddress> random_;
// True if the random address needs a refresh. This is the case when
// a. Privacy is enabled and the random device address needs to get rotated;
// or
// b. Privacy has recently been enabled and the controller hasn't been
// programmed with the new address yet
bool needs_refresh_;
// True if a HCI command to update the random address is in progress.
bool refreshing_;
// The local identity resolving key. If present, it is used to generate RPAs
// when privacy is enabled.
std::optional<UInt128> irk_;
// Callbacks waiting to be notified of the local address.
std::queue<AddressCallback> address_callbacks_;
// The task that executes when a random address expires and needs to be
// refreshed.
async::Task random_address_expiry_task_;
fxl::WeakPtrFactory<LowEnergyAddressManager> weak_ptr_factory_;
DISALLOW_COPY_ASSIGN_AND_MOVE(LowEnergyAddressManager);
};
} // namespace gap
} // namespace bt
#endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GAP_LOW_ENERGY_ADDRESS_MANAGER_H_