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