From 421dca85931026fd9053b9078ea7b92f9d0e496d Mon Sep 17 00:00:00 2001 From: hai007 Date: Fri, 13 Nov 2020 15:10:03 -0800 Subject: [PATCH] Roll forward to cl/342344386 Signed-off-by: hai007 --- cpp/core/core.h | 3 +- cpp/core/internal/BUILD | 7 +- cpp/core/internal/base_endpoint_channel.cc | 2 + .../injected_bluetooth_device_store.cc | 88 ++++++++++++++ .../injected_bluetooth_device_store.h | 57 ++++++++++ .../injected_bluetooth_device_store_test.cc | 107 ++++++++++++++++++ .../internal/offline_service_controller.h | 4 +- cpp/core/internal/p2p_cluster_pcp_handler.cc | 23 ++-- cpp/core/internal/p2p_cluster_pcp_handler.h | 11 +- .../internal/p2p_cluster_pcp_handler_test.cc | 25 ++-- .../p2p_point_to_point_pcp_handler.cc | 5 +- .../internal/p2p_point_to_point_pcp_handler.h | 9 +- cpp/core/internal/p2p_star_pcp_handler.cc | 11 +- cpp/core/internal/p2p_star_pcp_handler.h | 9 +- cpp/core/internal/pcp_manager.cc | 19 ++-- cpp/core/internal/pcp_manager.h | 4 +- .../internal/service_controller_router.cc | 22 ++++ .../service_controller_router_test.cc | 4 + cpp/core/internal/simulation_user.h | 4 +- cpp/core/options.h | 13 +++ cpp/platform/api/BUILD | 1 + 21 files changed, 377 insertions(+), 51 deletions(-) create mode 100644 cpp/core/internal/injected_bluetooth_device_store.cc create mode 100644 cpp/core/internal/injected_bluetooth_device_store.h create mode 100644 cpp/core/internal/injected_bluetooth_device_store_test.cc diff --git a/cpp/core/core.h b/cpp/core/core.h index 3b94a1fd..90bcf186 100644 --- a/cpp/core/core.h +++ b/cpp/core/core.h @@ -96,7 +96,8 @@ class Core { // available. // Possible status codes include: // Status::kSuccess if endpoint injection was attempted. - // Status::kError if bluetooth_mac_address is malformed. + // Status::kError if endpoint_id, endpoint_info, or + // remote_bluetooth_mac_address are malformed. // Status::kOutOfOrderApiCall if the app is not discovering. void InjectEndpoint(absl::string_view service_id, OutOfBandConnectionMetadata metadata, diff --git a/cpp/core/internal/BUILD b/cpp/core/internal/BUILD index 918b699a..c474a456 100644 --- a/cpp/core/internal/BUILD +++ b/cpp/core/internal/BUILD @@ -13,6 +13,7 @@ cc_library( "encryption_runner.cc", "endpoint_channel_manager.cc", "endpoint_manager.cc", + "injected_bluetooth_device_store.cc", "internal_payload.cc", "internal_payload_factory.cc", "offline_frames.cc", @@ -46,6 +47,7 @@ cc_library( "endpoint_channel.h", "endpoint_channel_manager.h", "endpoint_manager.h", + "injected_bluetooth_device_store.h", "internal_payload.h", "internal_payload_factory.h", "offline_frames.h", @@ -70,12 +72,13 @@ cc_library( "//core:__pkg__", ], deps = [ + ":message_lite", "//core:core_types", - "//core/internal:message_lite", "//core/internal/mediums", "//core/internal/mediums:utils", "//core/internal/mediums/webrtc", "//proto/connections:offline_wire_formats_portable_proto", + "//platform/api:comm", "//platform/base", "//platform/base:util", "//platform/public:comm", @@ -149,6 +152,7 @@ cc_test( "encryption_runner_test.cc", "endpoint_channel_manager_test.cc", "endpoint_manager_test.cc", + "injected_bluetooth_device_store_test.cc", "internal_payload_factory_test.cc", "offline_frames_test.cc", "offline_frames_validator_test.cc", @@ -169,6 +173,7 @@ cc_test( "//platform/base", "//platform/base:test_util", "//platform/impl/g3", # build_cleaner: keep + "//platform/public:comm", "//platform/public:logging", "//platform/public:types", "//proto:connections_enums_portable_proto", diff --git a/cpp/core/internal/base_endpoint_channel.cc b/cpp/core/internal/base_endpoint_channel.cc index 26184958..c5d0fb66 100644 --- a/cpp/core/internal/base_endpoint_channel.cc +++ b/cpp/core/internal/base_endpoint_channel.cc @@ -234,6 +234,8 @@ std::string BaseEndpointChannel::GetType() const { return absl::StrCat(subtype, "WIFI_HOTSPOT"); case proto::connections::Medium::WIFI_LAN: return absl::StrCat(subtype, "WIFI_LAN"); + case proto::connections::Medium::WEB_RTC: + return absl::StrCat(subtype, "WEB_RTC"); default: return "UNKNOWN"; } diff --git a/cpp/core/internal/injected_bluetooth_device_store.cc b/cpp/core/internal/injected_bluetooth_device_store.cc new file mode 100644 index 00000000..cea55407 --- /dev/null +++ b/cpp/core/internal/injected_bluetooth_device_store.cc @@ -0,0 +1,88 @@ +#include "core/internal/injected_bluetooth_device_store.h" + +#include + +#include "core/internal/bluetooth_device_name.h" +#include "platform/api/bluetooth_classic.h" +#include "platform/base/bluetooth_utils.h" + +namespace location { +namespace nearby { +namespace connections { +namespace { + +// api::BluetoothDevice implementation which stores a name and address passed to +// its constructor and trivially returns them to implement virtual functions. +class InjectedBluetoothDevice : public api::BluetoothDevice { + public: + InjectedBluetoothDevice(const std::string& name, + const std::string& mac_address) + : name_(name), mac_address_(mac_address) {} + + ~InjectedBluetoothDevice() override = default; + + // api::BluetoothDevice: + std::string GetName() const override { + return name_; + } + + std::string GetMacAddress() const override { + return mac_address_; + } + + private: + const std::string name_; + const std::string mac_address_; +}; + +} // namespace + +InjectedBluetoothDeviceStore::InjectedBluetoothDeviceStore() = default; + +InjectedBluetoothDeviceStore::~InjectedBluetoothDeviceStore() = default; + +BluetoothDevice +InjectedBluetoothDeviceStore::CreateInjectedBluetoothDevice( + const ByteArray& remote_bluetooth_mac_address, + const std::string& endpoint_id, + const ByteArray& endpoint_info, + const ByteArray& service_id_hash, + Pcp pcp) { + std::string remote_bluetooth_mac_address_str = + BluetoothUtils::ToString(remote_bluetooth_mac_address); + + // Valid MAC address is required. + if (remote_bluetooth_mac_address_str.empty()) + return BluetoothDevice(/*device=*/nullptr); + + // Non-empty endpoint info is required. + if (endpoint_info.Empty()) + return BluetoothDevice(/*device=*/nullptr); + + BluetoothDeviceName name(BluetoothDeviceName::Version::kV1, + pcp, + endpoint_id, + service_id_hash, + endpoint_info, + /*uwb_address=*/ByteArray(), + WebRtcState::kConnectable); + + // Note: BluetoothDeviceName internally verifies that |endpoint_id| and + // |service_id_hash| are valid; the check below will fail if they are + // malformed. + if (!name.IsValid()) + return BluetoothDevice(/*device=*/nullptr); + + auto injected_device = std::make_unique( + static_cast(name), remote_bluetooth_mac_address_str); + BluetoothDevice device_to_return(injected_device.get()); + + // Store underlying device to ensure that it is kept alive for future use. + devices_.emplace_back(std::move(injected_device)); + + return device_to_return; +} + +} // namespace connections +} // namespace nearby +} // namespace location diff --git a/cpp/core/internal/injected_bluetooth_device_store.h b/cpp/core/internal/injected_bluetooth_device_store.h new file mode 100644 index 00000000..6d4aa9d2 --- /dev/null +++ b/cpp/core/internal/injected_bluetooth_device_store.h @@ -0,0 +1,57 @@ +#ifndef CORE_INTERNAL_INJECTED_BLUETOOTH_DEVICE_STORE_H_ +#define CORE_INTERNAL_INJECTED_BLUETOOTH_DEVICE_STORE_H_ + +#include +#include + +#include "core/internal/pcp.h" +#include "platform/base/byte_array.h" +#include "platform/public/bluetooth_adapter.h" + +namespace location { +namespace nearby { +namespace connections { + +// Creates and stores BluetoothDevice objects which have been "injected" (i.e., +// passed to Nearby Connections manually by the client instead of through the +// normal discovery flow). +class InjectedBluetoothDeviceStore { + public: + InjectedBluetoothDeviceStore(); + ~InjectedBluetoothDeviceStore(); + + // Creates an injected BluetoothDevice given the provided parameters: + // |remote_bluetooth_mac_address|: A 6-byte MAC address. + // |endpoint_id|: A string of length 4. + // |endpoint_info|: A non-empty ByteArray whose length is <=131 bytes. + // |service_id_hash|: A ByteArray whose length is 3. + // |pcp|: PCP value to be used for the connection to this device. + // + // If the provided parameters are malformed or of incorrect length, this + // function returns an invalid BluetoothDevice. Clients should use + // BluetoothDevice::IsValid() with the returned device to verify that the + // parameters were successfully processed. + // + // Note that successfully-injected devices stay valid for the lifetime of the + // InjectedBluetoothDeviceStore and are not cleared until this object is + // deleted. + BluetoothDevice CreateInjectedBluetoothDevice( + const ByteArray& remote_bluetooth_mac_address, + const std::string& endpoint_id, + const ByteArray& endpoint_info, + const ByteArray& service_id_hash, + Pcp pcp); + + private: + // Devices created by this class. BluetoothDevice objects returned by + // CreateInjectedBluetoothDevice() store pointers to underlying + // api::BluetoothDevice objects, so this maintains these underlying devices + // to ensure that they are not deleted before they are referenced. + std::vector> devices_; +}; + +} // namespace connections +} // namespace nearby +} // namespace location + +#endif // CORE_INTERNAL_INJECTED_BLUETOOTH_DEVICE_STORE_H_ diff --git a/cpp/core/internal/injected_bluetooth_device_store_test.cc b/cpp/core/internal/injected_bluetooth_device_store_test.cc new file mode 100644 index 00000000..d4e5375b --- /dev/null +++ b/cpp/core/internal/injected_bluetooth_device_store_test.cc @@ -0,0 +1,107 @@ +#include "core/internal/injected_bluetooth_device_store.h" + +#include + +#include "core/internal/bluetooth_device_name.h" +#include "platform/base/bluetooth_utils.h" +#include "platform/base/byte_array.h" +#include "platform/public/bluetooth_adapter.h" +#include "gtest/gtest.h" + +namespace location { +namespace nearby { +namespace connections { +namespace { + +constexpr std::array + kTestRemoteBluetoothMacAddress{0x01, 0x23, 0x45, 0x67, 0x89, 0xab}; +constexpr std::array kTestEndpointInfo {0xcd, 0xef}; +constexpr std::array kTestServiceIdHash{0x01, 0x23, 0x45}; + +const char kTestEndpointId[] = "abcd"; + +class InjectedBluetoothDeviceStoreTest : public testing::Test { + protected: + InjectedBluetoothDeviceStore store_; +}; + +TEST_F(InjectedBluetoothDeviceStoreTest, Success) { + ByteArray remote_bluetooth_mac_address(kTestRemoteBluetoothMacAddress); + ByteArray endpoint_info(kTestEndpointInfo); + ByteArray service_id_hash(kTestServiceIdHash); + + BluetoothDevice device = store_.CreateInjectedBluetoothDevice( + remote_bluetooth_mac_address, kTestEndpointId, endpoint_info, + service_id_hash, Pcp::kP2pPointToPoint); + EXPECT_TRUE(device.IsValid()); + + EXPECT_EQ(BluetoothUtils::ToString(remote_bluetooth_mac_address), + device.GetMacAddress()); + + BluetoothDeviceName name(device.GetName()); + EXPECT_TRUE(name.IsValid()); + EXPECT_EQ(kTestEndpointId, name.GetEndpointId()); + EXPECT_EQ(endpoint_info, name.GetEndpointInfo()); + EXPECT_EQ(service_id_hash, name.GetServiceIdHash()); + EXPECT_EQ(Pcp::kP2pPointToPoint, name.GetPcp()); +} + +TEST_F(InjectedBluetoothDeviceStoreTest, Fail_InvalidBluetoothMac) { + // Use address with only 1 byte. + ByteArray remote_bluetooth_mac_address(std::array{0x00}); + ByteArray endpoint_info(kTestEndpointInfo); + ByteArray service_id_hash(kTestServiceIdHash); + + BluetoothDevice device = store_.CreateInjectedBluetoothDevice( + remote_bluetooth_mac_address, kTestEndpointId, endpoint_info, + service_id_hash, Pcp::kP2pPointToPoint); + EXPECT_FALSE(device.IsValid()); +} + +TEST_F(InjectedBluetoothDeviceStoreTest, Fail_InvalidEndpointId) { + ByteArray remote_bluetooth_mac_address(kTestRemoteBluetoothMacAddress); + ByteArray endpoint_info(kTestEndpointInfo); + ByteArray service_id_hash(kTestServiceIdHash); + + // Use empty endpoint ID. + BluetoothDevice device1 = store_.CreateInjectedBluetoothDevice( + remote_bluetooth_mac_address, /*endpoint_id=*/std::string(), + endpoint_info, service_id_hash, Pcp::kP2pPointToPoint); + EXPECT_FALSE(device1.IsValid()); + + // Use endpoint ID of wrong length. + const std::string too_long_endpoint_id = "abcde"; + BluetoothDevice device2 = store_.CreateInjectedBluetoothDevice( + remote_bluetooth_mac_address, too_long_endpoint_id, endpoint_info, + service_id_hash, Pcp::kP2pPointToPoint); + EXPECT_FALSE(device2.IsValid()); +} + +TEST_F(InjectedBluetoothDeviceStoreTest, Fail_EmptyEndpointInfo) { + ByteArray remote_bluetooth_mac_address(kTestRemoteBluetoothMacAddress); + // Use empty endpoint info. + ByteArray endpoint_info; + ByteArray service_id_hash(kTestServiceIdHash); + + BluetoothDevice device = store_.CreateInjectedBluetoothDevice( + remote_bluetooth_mac_address, kTestEndpointId, endpoint_info, + service_id_hash, Pcp::kP2pPointToPoint); + EXPECT_FALSE(device.IsValid()); +} + +TEST_F(InjectedBluetoothDeviceStoreTest, Fail_InvalidServiceIdHash) { + ByteArray remote_bluetooth_mac_address(kTestRemoteBluetoothMacAddress); + ByteArray endpoint_info(kTestEndpointInfo); + // Use address with only 1 byte. + ByteArray service_id_hash(std::array{0x00}); + + BluetoothDevice device = store_.CreateInjectedBluetoothDevice( + remote_bluetooth_mac_address, kTestEndpointId, endpoint_info, + service_id_hash, Pcp::kP2pPointToPoint); + EXPECT_FALSE(device.IsValid()); +} + +} // namespace +} // namespace connections +} // namespace nearby +} // namespace location diff --git a/cpp/core/internal/offline_service_controller.h b/cpp/core/internal/offline_service_controller.h index 2a70eef4..bc77e201 100644 --- a/cpp/core/internal/offline_service_controller.h +++ b/cpp/core/internal/offline_service_controller.h @@ -9,6 +9,7 @@ #include "core/internal/client_proxy.h" #include "core/internal/endpoint_channel_manager.h" #include "core/internal/endpoint_manager.h" +#include "core/internal/injected_bluetooth_device_store.h" #include "core/internal/mediums/mediums.h" #include "core/internal/payload_manager.h" #include "core/internal/pcp_manager.h" @@ -73,8 +74,9 @@ class OfflineServiceController : public ServiceController { PayloadManager payload_manager_{endpoint_manager_}; BwuManager bwu_manager_{ mediums_, endpoint_manager_, channel_manager_, {}, {}}; + InjectedBluetoothDeviceStore injected_bluetooth_device_store_; PcpManager pcp_manager_{mediums_, channel_manager_, endpoint_manager_, - bwu_manager_}; + bwu_manager_, injected_bluetooth_device_store_}; }; } // namespace connections diff --git a/cpp/core/internal/p2p_cluster_pcp_handler.cc b/cpp/core/internal/p2p_cluster_pcp_handler.cc index 17ba3bcd..964fb569 100644 --- a/cpp/core/internal/p2p_cluster_pcp_handler.cc +++ b/cpp/core/internal/p2p_cluster_pcp_handler.cc @@ -37,6 +37,7 @@ bool P2pClusterPcpHandler::ShouldAcceptBluetoothConnections( P2pClusterPcpHandler::P2pClusterPcpHandler( Mediums* mediums, EndpointManager* endpoint_manager, EndpointChannelManager* endpoint_channel_manager, BwuManager* bwu_manager, + InjectedBluetoothDeviceStore& injected_bluetooth_device_store, Pcp pcp) : BasePcpHandler(mediums, endpoint_manager, endpoint_channel_manager, bwu_manager, pcp), @@ -44,7 +45,8 @@ P2pClusterPcpHandler::P2pClusterPcpHandler( bluetooth_medium_(mediums->GetBluetoothClassic()), ble_medium_(mediums->GetBle()), wifi_lan_medium_(mediums->GetWifiLan()), - webrtc_medium_(mediums->GetWebRtc()) {} + webrtc_medium_(mediums->GetWebRtc()), + injected_bluetooth_device_store_(injected_bluetooth_device_store) {} // Returns a vector or mediums sorted in order or decreasing priority for // all the supported mediums. @@ -624,21 +626,20 @@ Status P2pClusterPcpHandler::InjectEndpointImpl( NEARBY_LOG(INFO, "InjectEndpoint"); // Bluetooth is the only supported out-of-band connection medium. if (metadata.medium != Medium::BLUETOOTH) { - NEARBY_LOG(WARNING, "StartDiscoveryImpl: Only Bluetooth is supported"); + NEARBY_LOG(WARNING, "InjectEndpointImpl: Only Bluetooth is supported"); return {Status::kError}; } - std::string remote_bluetooth_mac_address = - BluetoothUtils::ToString(metadata.remote_bluetooth_mac_address); - if (remote_bluetooth_mac_address.empty()) { - NEARBY_LOG(WARNING, "StartDiscoveryImpl: Missing Bluetooth MAC"); - return {Status::kError}; - } + BluetoothDevice remote_bluetooth_device = + injected_bluetooth_device_store_.CreateInjectedBluetoothDevice( + metadata.remote_bluetooth_mac_address, + metadata.endpoint_id, + metadata.endpoint_info, + GenerateHash(service_id, BluetoothDeviceName::kServiceIdHashLength), + GetPcp()); - auto remote_bluetooth_device = - GetRemoteBluetoothDevice(remote_bluetooth_mac_address); if (!remote_bluetooth_device.IsValid()) { - NEARBY_LOG(WARNING, "StartDiscoveryImpl: Invalid Bluetooth MAC"); + NEARBY_LOG(WARNING, "InjectEndpointImpl: Invalid parameters"); return {Status::kError}; } diff --git a/cpp/core/internal/p2p_cluster_pcp_handler.h b/cpp/core/internal/p2p_cluster_pcp_handler.h index 58fe7d23..97fb698a 100644 --- a/cpp/core/internal/p2p_cluster_pcp_handler.h +++ b/cpp/core/internal/p2p_cluster_pcp_handler.h @@ -11,6 +11,7 @@ #include "core/internal/client_proxy.h" #include "core/internal/endpoint_channel_manager.h" #include "core/internal/endpoint_manager.h" +#include "core/internal/injected_bluetooth_device_store.h" #include "core/internal/mediums/bluetooth_classic.h" #include "core/internal/mediums/mediums.h" #include "core/internal/mediums/webrtc.h" @@ -37,10 +38,11 @@ namespace connections { // connects over Bluetooth. class P2pClusterPcpHandler : public BasePcpHandler { public: - P2pClusterPcpHandler(Mediums* mediums, EndpointManager* endpoint_manager, - EndpointChannelManager* channel_manager, - BwuManager* bwu_manager, - Pcp pcp = Pcp::kP2pCluster); + P2pClusterPcpHandler( + Mediums* mediums, EndpointManager* endpoint_manager, + EndpointChannelManager* channel_manager, BwuManager* bwu_manager, + InjectedBluetoothDeviceStore& injected_bluetooth_device_store, + Pcp pcp = Pcp::kP2pCluster); ~P2pClusterPcpHandler() override = default; protected: @@ -204,6 +206,7 @@ class P2pClusterPcpHandler : public BasePcpHandler { Ble& ble_medium_; WifiLan& wifi_lan_medium_; mediums::WebRtc& webrtc_medium_; + InjectedBluetoothDeviceStore& injected_bluetooth_device_store_; }; } // namespace connections diff --git a/cpp/core/internal/p2p_cluster_pcp_handler_test.cc b/cpp/core/internal/p2p_cluster_pcp_handler_test.cc index 7efe4e6f..07c863fd 100644 --- a/cpp/core/internal/p2p_cluster_pcp_handler_test.cc +++ b/cpp/core/internal/p2p_cluster_pcp_handler_test.cc @@ -3,6 +3,7 @@ #include #include "core/internal/bwu_manager.h" +#include "core/internal/injected_bluetooth_device_store.h" #include "core/options.h" #include "platform/base/medium_environment.h" #include "platform/public/count_down_latch.h" @@ -63,7 +64,8 @@ TEST_P(P2pClusterPcpHandlerTest, CanConstructOne) { EndpointChannelManager ecm; EndpointManager em(&ecm); BwuManager bwu(mediums, em, ecm, {}, {}); - P2pClusterPcpHandler handler(&mediums, &em, &ecm, &bwu); + InjectedBluetoothDeviceStore ibds; + P2pClusterPcpHandler handler(&mediums, &em, &ecm, &bwu, ibds); env_.Stop(); } @@ -77,8 +79,10 @@ TEST_P(P2pClusterPcpHandlerTest, CanConstructMultiple) { EndpointManager em_b(&ecm_b); BwuManager bwu_a(mediums_a, em_a, ecm_a, {}, {}); BwuManager bwu_b(mediums_b, em_b, ecm_b, {}, {}); - P2pClusterPcpHandler handler_a(&mediums_a, &em_a, &ecm_a, &bwu_a); - P2pClusterPcpHandler handler_b(&mediums_b, &em_b, &ecm_b, &bwu_b); + InjectedBluetoothDeviceStore ibds_a; + InjectedBluetoothDeviceStore ibds_b; + P2pClusterPcpHandler handler_a(&mediums_a, &em_a, &ecm_a, &bwu_a, ibds_a); + P2pClusterPcpHandler handler_b(&mediums_b, &em_b, &ecm_b, &bwu_b, ibds_b); env_.Stop(); } @@ -89,7 +93,8 @@ TEST_P(P2pClusterPcpHandlerTest, CanAdvertise) { EndpointChannelManager ecm_a; EndpointManager em_a(&ecm_a); BwuManager bwu_a(mediums_a, em_a, ecm_a, {}, {}); - P2pClusterPcpHandler handler_a(&mediums_a, &em_a, &ecm_a, &bwu_a); + InjectedBluetoothDeviceStore ibds_a; + P2pClusterPcpHandler handler_a(&mediums_a, &em_a, &ecm_a, &bwu_a, ibds_a); EXPECT_EQ( handler_a.StartAdvertising(&client_a_, service_id_, options_, {.endpoint_info = ByteArray{endpoint_name}}), @@ -108,8 +113,10 @@ TEST_P(P2pClusterPcpHandlerTest, CanDiscover) { EndpointManager em_b(&ecm_b); BwuManager bwu_a(mediums_a, em_a, ecm_a, {}, {}); BwuManager bwu_b(mediums_b, em_b, ecm_b, {}, {}); - P2pClusterPcpHandler handler_a(&mediums_a, &em_a, &ecm_a, &bwu_a); - P2pClusterPcpHandler handler_b(&mediums_b, &em_b, &ecm_b, &bwu_b); + InjectedBluetoothDeviceStore ibds_a; + InjectedBluetoothDeviceStore ibds_b; + P2pClusterPcpHandler handler_a(&mediums_a, &em_a, &ecm_a, &bwu_a, ibds_a); + P2pClusterPcpHandler handler_b(&mediums_b, &em_b, &ecm_b, &bwu_b, ibds_b); CountDownLatch latch(1); EXPECT_EQ( handler_a.StartAdvertising(&client_a_, service_id_, options_, @@ -152,8 +159,10 @@ TEST_P(P2pClusterPcpHandlerTest, CanConnect) { {.allow_upgrade_to = {.bluetooth = true}}); BwuManager bwu_b(mediums_b, em_b, ecm_b, {}, {.allow_upgrade_to = {.bluetooth = true}}); - P2pClusterPcpHandler handler_a(&mediums_a, &em_a, &ecm_a, &bwu_a); - P2pClusterPcpHandler handler_b(&mediums_b, &em_b, &ecm_b, &bwu_b); + InjectedBluetoothDeviceStore ibds_a; + InjectedBluetoothDeviceStore ibds_b; + P2pClusterPcpHandler handler_a(&mediums_a, &em_a, &ecm_a, &bwu_a, ibds_a); + P2pClusterPcpHandler handler_b(&mediums_b, &em_b, &ecm_b, &bwu_b, ibds_b); CountDownLatch discover_latch(1); CountDownLatch connect_latch(2); struct DiscoveredInfo { diff --git a/cpp/core/internal/p2p_point_to_point_pcp_handler.cc b/cpp/core/internal/p2p_point_to_point_pcp_handler.cc index 18013b4c..1e411533 100644 --- a/cpp/core/internal/p2p_point_to_point_pcp_handler.cc +++ b/cpp/core/internal/p2p_point_to_point_pcp_handler.cc @@ -6,9 +6,10 @@ namespace connections { P2pPointToPointPcpHandler::P2pPointToPointPcpHandler( Mediums& mediums, EndpointManager& endpoint_manager, - EndpointChannelManager& channel_manager, BwuManager& bwu_manager, Pcp pcp) + EndpointChannelManager& channel_manager, BwuManager& bwu_manager, + InjectedBluetoothDeviceStore& injected_bluetooth_device_store, Pcp pcp) : P2pStarPcpHandler(mediums, endpoint_manager, channel_manager, bwu_manager, - pcp) {} + injected_bluetooth_device_store, pcp) {} std::vector P2pPointToPointPcpHandler::GetConnectionMediumsByPriority() { diff --git a/cpp/core/internal/p2p_point_to_point_pcp_handler.h b/cpp/core/internal/p2p_point_to_point_pcp_handler.h index abf89a70..2bea354b 100644 --- a/cpp/core/internal/p2p_point_to_point_pcp_handler.h +++ b/cpp/core/internal/p2p_point_to_point_pcp_handler.h @@ -20,10 +20,11 @@ namespace connections { // and connects over Bluetooth. class P2pPointToPointPcpHandler : public P2pStarPcpHandler { public: - P2pPointToPointPcpHandler(Mediums& mediums, EndpointManager& endpoint_manager, - EndpointChannelManager& channel_manager, - BwuManager& bwu_manager, - Pcp pcp = Pcp::kP2pPointToPoint); + P2pPointToPointPcpHandler( + Mediums& mediums, EndpointManager& endpoint_manager, + EndpointChannelManager& channel_manager, BwuManager& bwu_manager, + InjectedBluetoothDeviceStore& injected_bluetooth_device_store, + Pcp pcp = Pcp::kP2pPointToPoint); protected: std::vector GetConnectionMediumsByPriority() diff --git a/cpp/core/internal/p2p_star_pcp_handler.cc b/cpp/core/internal/p2p_star_pcp_handler.cc index 11941b4e..280e1cf7 100644 --- a/cpp/core/internal/p2p_star_pcp_handler.cc +++ b/cpp/core/internal/p2p_star_pcp_handler.cc @@ -6,12 +6,13 @@ namespace location { namespace nearby { namespace connections { -P2pStarPcpHandler::P2pStarPcpHandler(Mediums& mediums, - EndpointManager& endpoint_manager, - EndpointChannelManager& channel_manager, - BwuManager& bwu_manager, Pcp pcp) +P2pStarPcpHandler::P2pStarPcpHandler( + Mediums& mediums, EndpointManager& endpoint_manager, + EndpointChannelManager& channel_manager, BwuManager& bwu_manager, + InjectedBluetoothDeviceStore& injected_bluetooth_device_store, Pcp pcp) : P2pClusterPcpHandler(&mediums, &endpoint_manager, &channel_manager, - &bwu_manager, pcp) {} + &bwu_manager, injected_bluetooth_device_store, + pcp) {} std::vector P2pStarPcpHandler::GetConnectionMediumsByPriority() { diff --git a/cpp/core/internal/p2p_star_pcp_handler.h b/cpp/core/internal/p2p_star_pcp_handler.h index caa5fc61..c9307574 100644 --- a/cpp/core/internal/p2p_star_pcp_handler.h +++ b/cpp/core/internal/p2p_star_pcp_handler.h @@ -23,10 +23,11 @@ namespace connections { // and connects over Bluetooth. class P2pStarPcpHandler : public P2pClusterPcpHandler { public: - P2pStarPcpHandler(Mediums& mediums, EndpointManager& endpoint_manager, - EndpointChannelManager& channel_manager, - BwuManager& bwu_manager, - Pcp pcp = Pcp::kP2pStar); + P2pStarPcpHandler( + Mediums& mediums, EndpointManager& endpoint_manager, + EndpointChannelManager& channel_manager, BwuManager& bwu_manager, + InjectedBluetoothDeviceStore& injected_bluetooth_device_store, + Pcp pcp = Pcp::kP2pStar); protected: std::vector GetConnectionMediumsByPriority() diff --git a/cpp/core/internal/pcp_manager.cc b/cpp/core/internal/pcp_manager.cc index d896048b..db06689b 100644 --- a/cpp/core/internal/pcp_manager.cc +++ b/cpp/core/internal/pcp_manager.cc @@ -9,17 +9,20 @@ namespace location { namespace nearby { namespace connections { -PcpManager::PcpManager(Mediums& mediums, - EndpointChannelManager& channel_manager, - EndpointManager& endpoint_manager, - BwuManager& bwu_manager) { +PcpManager::PcpManager( + Mediums& mediums, EndpointChannelManager& channel_manager, + EndpointManager& endpoint_manager, BwuManager& bwu_manager, + InjectedBluetoothDeviceStore& injected_bluetooth_device_store) { handlers_[Pcp::kP2pCluster] = std::make_unique( - &mediums, &endpoint_manager, &channel_manager, &bwu_manager); + &mediums, &endpoint_manager, &channel_manager, &bwu_manager, + injected_bluetooth_device_store); handlers_[Pcp::kP2pStar] = std::make_unique( - mediums, endpoint_manager, channel_manager, bwu_manager); + mediums, endpoint_manager, channel_manager, bwu_manager, + injected_bluetooth_device_store); handlers_[Pcp::kP2pPointToPoint] = - std::make_unique(mediums, endpoint_manager, - channel_manager, bwu_manager); + std::make_unique( + mediums, endpoint_manager, channel_manager, bwu_manager, + injected_bluetooth_device_store); } void PcpManager::DisconnectFromEndpointManager() { diff --git a/cpp/core/internal/pcp_manager.h b/cpp/core/internal/pcp_manager.h index 8e46e2cf..1e04e22e 100644 --- a/cpp/core/internal/pcp_manager.h +++ b/cpp/core/internal/pcp_manager.h @@ -8,6 +8,7 @@ #include "core/internal/client_proxy.h" #include "core/internal/endpoint_channel_manager.h" #include "core/internal/endpoint_manager.h" +#include "core/internal/injected_bluetooth_device_store.h" #include "core/internal/mediums/mediums.h" #include "core/listeners.h" #include "core/options.h" @@ -30,7 +31,8 @@ namespace connections { class PcpManager { public: PcpManager(Mediums& mediums, EndpointChannelManager& channel_manager, - EndpointManager& endpoint_manager, BwuManager& bwu_manager); + EndpointManager& endpoint_manager, BwuManager& bwu_manager, + InjectedBluetoothDeviceStore& injected_bluetooth_device_store); ~PcpManager(); Status StartAdvertising(ClientProxy* client, const string& service_id, diff --git a/cpp/core/internal/service_controller_router.cc b/cpp/core/internal/service_controller_router.cc index 42fb263b..8c716828 100644 --- a/cpp/core/internal/service_controller_router.cc +++ b/cpp/core/internal/service_controller_router.cc @@ -17,7 +17,18 @@ namespace location { namespace nearby { namespace connections { namespace { +// Length of a MAC address, which consists of 6 bytes uniquely identifying a +// hardware interface. const std::size_t kMacAddressLength = 6u; + +// Length used for an endpoint ID, which identifies a device discovery and +// associated connection request. +const std::size_t kEndpointIdLength = 4u; + +// Maximum length for information describing an endpoint; this information is +// advertised by one device and can be used by the other device to identify the +// advertiser. +const std::size_t kMaxEndpointInfoLength = 131u; } // namespace ServiceControllerRouter::~ServiceControllerRouter() { @@ -108,6 +119,17 @@ void ServiceControllerRouter::InjectEndpoint( return; } + if (metadata.endpoint_id.size() != kEndpointIdLength) { + callback.result_cb({Status::kError}); + return; + } + + if (metadata.endpoint_info.Empty() || + metadata.endpoint_info.size() > kMaxEndpointInfoLength) { + callback.result_cb({Status::kError}); + return; + } + if (!ClientHasAcquiredServiceController(client) || !client->IsDiscovering()) { callback.result_cb({Status::kOutOfOrderApiCall}); diff --git a/cpp/core/internal/service_controller_router_test.cc b/cpp/core/internal/service_controller_router_test.cc index aa4a8c62..36967b98 100644 --- a/cpp/core/internal/service_controller_router_test.cc +++ b/cpp/core/internal/service_controller_router_test.cc @@ -28,6 +28,8 @@ namespace connections { namespace { using ::testing::Return; constexpr std::array kFakeMacAddress = {'a', 'b', 'c', 'd', 'e', 'f'}; +constexpr std::array kFakeInjectedEndpointInfo = {'g', 'h', 'i'}; +const char kFakeInejctedEndpointId[] = "abcd"; } // namespace // This class must be in the same namespace as ServiceControllerRouter for @@ -256,6 +258,8 @@ class ServiceControllerRouterTest : public testing::Test { }; const OutOfBandConnectionMetadata kOutOfBandConnectionMetadata{ .medium = Medium::BLUETOOTH, + .endpoint_id = kFakeInejctedEndpointId, + .endpoint_info = ByteArray(kFakeInjectedEndpointInfo), .remote_bluetooth_mac_address = ByteArray(kFakeMacAddress), }; diff --git a/cpp/core/internal/simulation_user.h b/cpp/core/internal/simulation_user.h index 65c8f5b2..7b7ecb76 100644 --- a/cpp/core/internal/simulation_user.h +++ b/cpp/core/internal/simulation_user.h @@ -7,6 +7,7 @@ #include "core/internal/client_proxy.h" #include "core/internal/endpoint_channel_manager.h" #include "core/internal/endpoint_manager.h" +#include "core/internal/injected_bluetooth_device_store.h" #include "core/internal/payload_manager.h" #include "core/internal/pcp_manager.h" #include "core/options.h" @@ -137,7 +138,8 @@ class SimulationUser { EndpointChannelManager ecm_; EndpointManager em_{&ecm_}; BwuManager bwu_{mediums_, em_, ecm_, {}, {}}; - PcpManager mgr_{mediums_, ecm_, em_, bwu_}; + InjectedBluetoothDeviceStore injected_bluetooth_device_store_; + PcpManager mgr_{mediums_, ecm_, em_, bwu_, injected_bluetooth_device_store_}; PayloadManager pm_{em_}; }; diff --git a/cpp/core/options.h b/cpp/core/options.h index bb65b4b8..cf5f3061 100644 --- a/cpp/core/options.h +++ b/cpp/core/options.h @@ -128,6 +128,19 @@ struct OutOfBandConnectionMetadata { // Medium to use for the out-of-band connection. Medium medium; + // Endpoint ID to use for the injected connection; will be included in the + // endpoint_found_cb callback. Must be exactly 4 bytes and should be randomly- + // generated such that no two IDs are identical. + std::string endpoint_id; + + // Endpoint info to use for the injected connection; will be included in the + // endpoint_found_cb callback. Should uniquely identify the InjectEndpoint() + // call so that the client which made the call can verify the endpoint + // that was found is the one that was injected. + // + // Cannot be empty, and must be <131 bytes. + ByteArray endpoint_info; + // Used for Bluetooth connections. ByteArray remote_bluetooth_mac_address; }; diff --git a/cpp/platform/api/BUILD b/cpp/platform/api/BUILD index 6eafb5e3..98cfa75b 100644 --- a/cpp/platform/api/BUILD +++ b/cpp/platform/api/BUILD @@ -45,6 +45,7 @@ cc_library( "wifi_lan.h", ], visibility = [ + "//core/internal:__subpackages__", "//platform/base:__pkg__", "//platform/impl:__subpackages__", "//platform/public:__pkg__",