Commit eabf9006 authored by Kyle Horimoto's avatar Kyle Horimoto Committed by Commit Bot

[CrOS MultiDevice] Re-land BleConnectionManager.

BleConnectionManager originally landed in:
https://chromium-review.googlesource.com/c/chromium/src/+/1100133

It was reverted by:
https://chromium-review.googlesource.com/c/chromium/src/+/1103917

The CL was reverted due to failures in the ASAN build.

This CL uploads the original CL as patchset 1 and fixes the failing ASAN
tests in the following patchset.

Original CL description below:

> Creates connections to remote devices over Bluetooth, using either the
> listener role (BLE scans only) or the initiator role (a combination of BLE
> advertising and scanning).
>
> When a connection is attempted, it remains active until either an
> AuthenticatedChannel is returned successfully or until the request is
> explicitly removed via one of the Cancel*() functions.

Bug: 824568, 752273
Change-Id: I45322a246d56b9b33142c010ad2755c7872574d1
Reviewed-on: https://chromium-review.googlesource.com/1104792Reviewed-by: default avatarRyan Hansberry <hansberry@chromium.org>
Commit-Queue: Kyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568156}
parent df18b96b
...@@ -18,6 +18,10 @@ static_library("secure_channel") { ...@@ -18,6 +18,10 @@ static_library("secure_channel") {
"ble_advertiser.h", "ble_advertiser.h",
"ble_advertiser_impl.cc", "ble_advertiser_impl.cc",
"ble_advertiser_impl.h", "ble_advertiser_impl.h",
"ble_connection_manager.cc",
"ble_connection_manager.h",
"ble_connection_manager_impl.cc",
"ble_connection_manager_impl.h",
"ble_constants.h", "ble_constants.h",
"ble_initiator_failure_type.cc", "ble_initiator_failure_type.cc",
"ble_initiator_failure_type.h", "ble_initiator_failure_type.h",
...@@ -129,6 +133,8 @@ static_library("test_support") { ...@@ -129,6 +133,8 @@ static_library("test_support") {
"fake_active_connection_manager.h", "fake_active_connection_manager.h",
"fake_ble_advertiser.cc", "fake_ble_advertiser.cc",
"fake_ble_advertiser.h", "fake_ble_advertiser.h",
"fake_ble_connection_manager.cc",
"fake_ble_connection_manager.h",
"fake_ble_scanner.cc", "fake_ble_scanner.cc",
"fake_ble_scanner.h", "fake_ble_scanner.h",
"fake_ble_service_data_helper.cc", "fake_ble_service_data_helper.cc",
...@@ -187,6 +193,7 @@ source_set("unit_tests") { ...@@ -187,6 +193,7 @@ source_set("unit_tests") {
"active_connection_manager_impl_unittest.cc", "active_connection_manager_impl_unittest.cc",
"authenticated_channel_impl_unittest.cc", "authenticated_channel_impl_unittest.cc",
"ble_advertiser_impl_unittest.cc", "ble_advertiser_impl_unittest.cc",
"ble_connection_manager_impl_unittest.cc",
"ble_initiator_operation_unittest.cc", "ble_initiator_operation_unittest.cc",
"ble_listener_operation_unittest.cc", "ble_listener_operation_unittest.cc",
"ble_scanner_impl_unittest.cc", "ble_scanner_impl_unittest.cc",
......
This diff is collapsed.
// Copyright 2018 The Chromium 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 CHROMEOS_SERVICES_SECURE_CHANNEL_BLE_CONNECTION_MANAGER_H_
#define CHROMEOS_SERVICES_SECURE_CHANNEL_BLE_CONNECTION_MANAGER_H_
#include <memory>
#include "base/callback.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "chromeos/services/secure_channel/ble_initiator_failure_type.h"
#include "chromeos/services/secure_channel/ble_listener_failure_type.h"
#include "chromeos/services/secure_channel/connection_attempt_details.h"
#include "chromeos/services/secure_channel/connection_role.h"
#include "chromeos/services/secure_channel/device_id_pair.h"
#include "chromeos/services/secure_channel/public/cpp/shared/connection_priority.h"
namespace chromeos {
namespace secure_channel {
class AuthenticatedChannel;
// Creates connections to remote devices over Bluetooth, using either the
// listener role (BLE scans only) or the initiator role (a combination of BLE
// advertising and scanning).
//
// When a connection is attempted, it remains active until either an
// AuthenticatedChannel is returned successfully or until the request is
// explicitly removed via one of the Cancel*() functions.
//
// When a failure occurs, the client is notified, but the connection attempt
// remains active. This ensures that when attempts are retried after a failure,
// this class does not need to internally stop and then restart
// scanning/advertising.
class BleConnectionManager {
public:
virtual ~BleConnectionManager();
using ConnectionSuccessCallback =
base::OnceCallback<void(std::unique_ptr<AuthenticatedChannel>)>;
using BleInitiatorFailureCallback =
base::RepeatingCallback<void(BleInitiatorFailureType)>;
using BleListenerFailureCallback =
base::RepeatingCallback<void(BleListenerFailureType)>;
void AttemptBleInitiatorConnection(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority,
ConnectionSuccessCallback success_callback,
const BleInitiatorFailureCallback& failure_callback);
void UpdateBleInitiatorConnectionPriority(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority);
void CancelBleInitiatorConnectionAttempt(const DeviceIdPair& device_id_pair);
void AttemptBleListenerConnection(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority,
ConnectionSuccessCallback success_callback,
const BleListenerFailureCallback& failure_callback);
void UpdateBleListenerConnectionPriority(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority);
void CancelBleListenerConnectionAttempt(const DeviceIdPair& device_id_pair);
protected:
BleConnectionManager();
virtual void PerformAttemptBleInitiatorConnection(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority) = 0;
virtual void PerformUpdateBleInitiatorConnectionPriority(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority) = 0;
virtual void PerformCancelBleInitiatorConnectionAttempt(
const DeviceIdPair& device_id_pair) = 0;
virtual void PerformAttemptBleListenerConnection(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority) = 0;
virtual void PerformUpdateBleListenerConnectionPriority(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority) = 0;
virtual void PerformCancelBleListenerConnectionAttempt(
const DeviceIdPair& device_id_pair) = 0;
ConnectionPriority GetPriorityForAttempt(const DeviceIdPair& device_id_pair,
ConnectionRole connection_role);
const base::flat_set<ConnectionAttemptDetails>& GetDetailsForRemoteDevice(
const std::string& remote_device_id);
bool DoesAttemptExist(const DeviceIdPair& device_id_pair,
ConnectionRole connection_role);
void NotifyBleInitiatorFailure(const DeviceIdPair& device_id_pair,
BleInitiatorFailureType failure_type);
void NotifyBleListenerFailure(const DeviceIdPair& device_id_pair,
BleListenerFailureType failure_type);
void NotifyConnectionSuccess(
const DeviceIdPair& device_id_pair,
ConnectionRole connection_role,
std::unique_ptr<AuthenticatedChannel> authenticated_channel);
private:
struct InitiatorConnectionAttemptMetadata {
InitiatorConnectionAttemptMetadata(
ConnectionPriority connection_priority,
ConnectionSuccessCallback success_callback,
const BleInitiatorFailureCallback& failure_callback);
~InitiatorConnectionAttemptMetadata();
ConnectionPriority connection_priority;
ConnectionSuccessCallback success_callback;
BleInitiatorFailureCallback failure_callback;
};
struct ListenerConnectionAttemptMetadata {
ListenerConnectionAttemptMetadata(
ConnectionPriority connection_priority,
ConnectionSuccessCallback success_callback,
const BleListenerFailureCallback& failure_callback);
~ListenerConnectionAttemptMetadata();
ConnectionPriority connection_priority;
ConnectionSuccessCallback success_callback;
BleListenerFailureCallback failure_callback;
};
InitiatorConnectionAttemptMetadata& GetInitiatorEntry(
const DeviceIdPair& device_id_pair);
ListenerConnectionAttemptMetadata& GetListenerEntry(
const DeviceIdPair& device_id_pair);
void RemoveRequestMetadata(const DeviceIdPair& device_id_pair,
ConnectionRole connection_role);
base::flat_map<std::string, base::flat_set<ConnectionAttemptDetails>>
remote_device_id_to_details_map_;
base::flat_map<DeviceIdPair,
std::unique_ptr<InitiatorConnectionAttemptMetadata>>
id_pair_to_initiator_metadata_map_;
base::flat_map<DeviceIdPair,
std::unique_ptr<ListenerConnectionAttemptMetadata>>
id_pair_to_listener_metadata_map_;
DISALLOW_COPY_AND_ASSIGN(BleConnectionManager);
};
} // namespace secure_channel
} // namespace chromeos
#endif // CHROMEOS_SERVICES_SECURE_CHANNEL_BLE_CONNECTION_MANAGER_H_
// Copyright 2018 The Chromium 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 CHROMEOS_SERVICES_SECURE_CHANNEL_BLE_CONNECTION_MANAGER_IMPL_H_
#define CHROMEOS_SERVICES_SECURE_CHANNEL_BLE_CONNECTION_MANAGER_IMPL_H_
#include <memory>
#include <utility>
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "chromeos/services/secure_channel/ble_advertiser.h"
#include "chromeos/services/secure_channel/ble_connection_manager.h"
#include "chromeos/services/secure_channel/ble_scanner.h"
#include "chromeos/services/secure_channel/connection_role.h"
#include "chromeos/services/secure_channel/device_id_pair.h"
#include "chromeos/services/secure_channel/public/cpp/shared/connection_priority.h"
#include "chromeos/services/secure_channel/secure_channel_disconnector.h"
#include "components/cryptauth/secure_channel.h"
namespace device {
class BluetoothAdapter;
} // namespace device
namespace chromeos {
namespace secure_channel {
class BleServiceDataHelper;
class BleSynchronizerBase;
class SecureChannelDisconnector;
class TimerFactory;
// Concrete BleConnectionManager implementation. This class initializes
// BleAdvertiser and BleScanner objects and utilizes them to bootstrap
// connections. Once a connection is found, BleConnectionManagerImpl creates a
// cryptauth::SecureChannel and waits for it to authenticate successfully. Once
// this process is complete, an AuthenticatedChannel is returned to the client.
class BleConnectionManagerImpl : public BleConnectionManager,
public BleAdvertiser::Delegate,
public BleScanner::Delegate,
public cryptauth::SecureChannel::Observer {
public:
class Factory {
public:
static Factory* Get();
static void SetFactoryForTesting(Factory* test_factory);
virtual ~Factory();
virtual std::unique_ptr<BleConnectionManager> BuildInstance(
scoped_refptr<device::BluetoothAdapter> bluetooth_adapter,
BleServiceDataHelper* ble_service_data_helper,
TimerFactory* timer_factory);
private:
static Factory* test_factory_;
};
~BleConnectionManagerImpl() override;
private:
BleConnectionManagerImpl(
scoped_refptr<device::BluetoothAdapter> bluetooth_adapter,
BleServiceDataHelper* ble_service_data_helper,
TimerFactory* timer_factory);
// BleConnectionManager:
void PerformAttemptBleInitiatorConnection(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority) override;
void PerformUpdateBleInitiatorConnectionPriority(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority) override;
void PerformCancelBleInitiatorConnectionAttempt(
const DeviceIdPair& device_id_pair) override;
void PerformAttemptBleListenerConnection(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority) override;
void PerformUpdateBleListenerConnectionPriority(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority) override;
void PerformCancelBleListenerConnectionAttempt(
const DeviceIdPair& device_id_pair) override;
// BleAdvertiser::Delegate:
void OnAdvertisingSlotEnded(
const DeviceIdPair& device_id_pair,
bool replaced_by_higher_priority_advertisement) override;
// BleScanner::Delegate:
void OnReceivedAdvertisement(cryptauth::RemoteDeviceRef remote_device,
device::BluetoothDevice* bluetooth_device,
ConnectionRole connection_role) override;
// cryptauth::SecureChannel::Observer:
void OnSecureChannelStatusChanged(
cryptauth::SecureChannel* secure_channel,
const cryptauth::SecureChannel::Status& old_status,
const cryptauth::SecureChannel::Status& new_status) override;
// Returns whether a channel exists connecting to |remote_device_id|,
// regardless of the local device ID or the role used to create the
// connection.
bool DoesAuthenticatingChannelExist(const std::string& remote_device_id);
// Adds |secure_channel| to |remote_device_id_to_secure_channel_map_| and
// pauses any ongoing attempts to |remote_device_id|, since a connection has
// already been established to that device.
void SetAuthenticatingChannel(
const std::string& remote_device_id,
std::unique_ptr<cryptauth::SecureChannel> secure_channel,
ConnectionRole connection_role);
// Pauses pending connection attempts (scanning and/or advertising) to
// |remote_device_id|.
void PauseConnectionAttemptsToDevice(const std::string& remote_device_id);
// Restarts connections which were paused as part of
// PauseConnectionAttemptsToDevice();
void RestartPausedAttemptsToDevice(const std::string& remote_device_id);
// Checks to see if there is a leftover channel authenticating with
// |remote_device_id| even though there are no pending requests for a
// connection to that device. This situation arises when an active request is
// canceled after a connection has been established but before that connection
// has been fully authenticated. This function disconnects the channel in the
// case that it finds one.
void ProcessPotentialLingeringChannel(const std::string& remote_device_id);
std::string GetRemoteDeviceIdForSecureChannel(
cryptauth::SecureChannel* secure_channel);
void HandleSecureChannelDisconnection(const std::string& remote_device_id,
bool was_authenticating);
void HandleChannelAuthenticated(const std::string& remote_device_id);
// Chooses the connection attempt which will receive the success callback.
// It is possible that there is more than one possible recipient in the case
// that two attempts are made with the same remote device ID and connection
// role but different local device IDs. In the case of multiple possible
// recipients, we arbitrarily choose the one which was registered first.
ConnectionAttemptDetails ChooseChannelRecipient(
const std::string& remote_device_id,
ConnectionRole connection_role);
scoped_refptr<device::BluetoothAdapter> bluetooth_adapter_;
BleServiceDataHelper* ble_service_data_helper_;
std::unique_ptr<BleSynchronizerBase> ble_synchronizer_;
std::unique_ptr<BleAdvertiser> ble_advertiser_;
std::unique_ptr<BleScanner> ble_scanner_;
std::unique_ptr<SecureChannelDisconnector> secure_channel_disconnector_;
using SecureChannelWithRole =
std::pair<std::unique_ptr<cryptauth::SecureChannel>, ConnectionRole>;
base::flat_map<std::string, SecureChannelWithRole>
remote_device_id_to_secure_channel_map_;
base::Optional<std::string> notifying_remote_device_id_;
DISALLOW_COPY_AND_ASSIGN(BleConnectionManagerImpl);
};
} // namespace secure_channel
} // namespace chromeos
#endif // CHROMEOS_SERVICES_SECURE_CHANNEL_BLE_CONNECTION_MANAGER_IMPL_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/services/secure_channel/fake_ble_connection_manager.h"
namespace chromeos {
namespace secure_channel {
FakeBleConnectionManager::FakeBleConnectionManager() = default;
FakeBleConnectionManager::~FakeBleConnectionManager() = default;
void FakeBleConnectionManager::PerformAttemptBleInitiatorConnection(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority) {}
void FakeBleConnectionManager::PerformUpdateBleInitiatorConnectionPriority(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority) {}
void FakeBleConnectionManager::PerformCancelBleInitiatorConnectionAttempt(
const DeviceIdPair& device_id_pair) {}
void FakeBleConnectionManager::PerformAttemptBleListenerConnection(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority) {}
void FakeBleConnectionManager::PerformUpdateBleListenerConnectionPriority(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority) {}
void FakeBleConnectionManager::PerformCancelBleListenerConnectionAttempt(
const DeviceIdPair& device_id_pair) {}
} // namespace secure_channel
} // namespace chromeos
// Copyright 2018 The Chromium 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 CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_BLE_CONNECTION_MANAGER_H_
#define CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_BLE_CONNECTION_MANAGER_H_
#include "base/macros.h"
#include "chromeos/services/secure_channel/ble_connection_manager.h"
#include "chromeos/services/secure_channel/connection_role.h"
#include "chromeos/services/secure_channel/device_id_pair.h"
#include "chromeos/services/secure_channel/public/cpp/shared/connection_priority.h"
namespace chromeos {
namespace secure_channel {
// Test BleConnectionManager implementation. Each of the overridden functions
// has an empty body.
class FakeBleConnectionManager : public BleConnectionManager {
public:
FakeBleConnectionManager();
~FakeBleConnectionManager() override;
// Make public for testing.
using BleConnectionManager::GetPriorityForAttempt;
using BleConnectionManager::GetDetailsForRemoteDevice;
using BleConnectionManager::DoesAttemptExist;
using BleConnectionManager::NotifyBleInitiatorFailure;
using BleConnectionManager::NotifyBleListenerFailure;
using BleConnectionManager::NotifyConnectionSuccess;
private:
// BleConnectionManager:
void PerformAttemptBleInitiatorConnection(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority) override;
void PerformUpdateBleInitiatorConnectionPriority(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority) override;
void PerformCancelBleInitiatorConnectionAttempt(
const DeviceIdPair& device_id_pair) override;
void PerformAttemptBleListenerConnection(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority) override;
void PerformUpdateBleListenerConnectionPriority(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority) override;
void PerformCancelBleListenerConnectionAttempt(
const DeviceIdPair& device_id_pair) override;
DISALLOW_COPY_AND_ASSIGN(FakeBleConnectionManager);
};
} // namespace secure_channel
} // namespace chromeos
#endif // CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_BLE_CONNECTION_MANAGER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment