blob: cdefd8255e7c6453ceb92ecb515d8d93a62f84cc [file] [log] [blame]
// 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 "base/time/default_clock.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.h"
#include "chromeos/services/secure_channel/secure_channel_disconnector.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
// 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 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,
base::Clock* clock = base::DefaultClock::GetInstance());
private:
static Factory* test_factory_;
};
~BleConnectionManagerImpl() override;
private:
class ConnectionAttemptTimestamps {
public:
ConnectionAttemptTimestamps(ConnectionRole connection_role,
base::Clock* clock);
~ConnectionAttemptTimestamps();
void RecordAdvertisementReceived();
void RecordGattConnectionEstablished();
void RecordChannelAuthenticated();
// Resets the connection attempt metrics by setting the "start scan"
// timestamp to the current time and by and nulling out the other
// timestamps.
void Reset();
private:
void RecordEffectiveSuccessRateMetrics(bool will_continue_to_retry);
const ConnectionRole connection_role_;
base::Clock* clock_;
// Set to the current time when this object is created and updated whenever
// Reset() is called.
base::Time start_scan_timestamp_;
// Start as null timestamps and are set whenever the relevant event occurs;
// if Reset() is called, these timestamps are nulled out again.
base::Time advertisement_received_timestamp_;
base::Time gatt_connection_timestamp_;
base::Time authentication_timestamp_;
};
BleConnectionManagerImpl(
scoped_refptr<device::BluetoothAdapter> bluetooth_adapter,
BleServiceDataHelper* ble_service_data_helper,
TimerFactory* timer_factory,
base::Clock* clock);
// 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;
void OnFailureToGenerateAdvertisement(
const DeviceIdPair& device_id_pair) override;
// BleScanner::Delegate:
void OnReceivedAdvertisement(multidevice::RemoteDeviceRef remote_device,
device::BluetoothDevice* bluetooth_device,
ConnectionRole connection_role) override;
// SecureChannel::Observer:
void OnSecureChannelStatusChanged(
SecureChannel* secure_channel,
const SecureChannel::Status& old_status,
const 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<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(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);
// Starts tracking a connection attempt's duration. If a connection to
// |remote_device_id| is already in progress, this function is a no-op.
void StartConnectionAttemptTimerMetricsIfNecessary(
const std::string& remote_device_id,
ConnectionRole connection_role);
// Removes tracking for a connection attempt's duration if there are no
// remaining requests for the connection.
void RemoveConnectionAttemptTimerMetricsIfNecessary(
const std::string& remote_device_id);
scoped_refptr<device::BluetoothAdapter> bluetooth_adapter_;
BleServiceDataHelper* ble_service_data_helper_;
base::Clock* clock_;
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<SecureChannel>, ConnectionRole>;
base::flat_map<std::string, SecureChannelWithRole>
remote_device_id_to_secure_channel_map_;
base::flat_map<std::string, std::unique_ptr<ConnectionAttemptTimestamps>>
remote_device_id_to_timestamps_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_