mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
Enforce out-of-band mode for InjectEndpoint and relax discovery checks for Bluetooth callbacks.
PiperOrigin-RevId: 798228332
This commit is contained in:
committed by
Copybara-Service
parent
9c7c7a9f6f
commit
9d06831a9c
@@ -310,6 +310,7 @@ cc_test(
|
||||
"//internal/interop:authentication_transport_interface",
|
||||
"//internal/interop:device",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:mac_address",
|
||||
"//internal/platform:test_util",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform/implementation/g3", # build_cleaner: keep
|
||||
@@ -550,6 +551,7 @@ cc_test(
|
||||
],
|
||||
deps = [
|
||||
":internal",
|
||||
":types",
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:comm",
|
||||
"//internal/platform:mac_address",
|
||||
|
||||
@@ -15,10 +15,16 @@
|
||||
#include "connections/implementation/injected_bluetooth_device_store.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/status/statusor.h"
|
||||
#include "connections/implementation/bluetooth_device_name.h"
|
||||
#include "connections/implementation/pcp.h"
|
||||
#include "connections/implementation/webrtc_state.h"
|
||||
#include "internal/platform/bluetooth_adapter.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/implementation/bluetooth_classic.h"
|
||||
#include "internal/platform/mac_address.h"
|
||||
|
||||
@@ -65,8 +71,8 @@ BluetoothDevice InjectedBluetoothDeviceStore::CreateInjectedBluetoothDevice(
|
||||
|
||||
MacAddress remote_mac_address;
|
||||
if (!MacAddress::FromUint64(bluetooth_mac_address_bytes_uint64.value(),
|
||||
remote_mac_address)
|
||||
|| !remote_mac_address.IsSet()) {
|
||||
remote_mac_address) ||
|
||||
!remote_mac_address.IsSet()) {
|
||||
return BluetoothDevice(/*device=*/nullptr);
|
||||
}
|
||||
|
||||
@@ -93,5 +99,15 @@ BluetoothDevice InjectedBluetoothDeviceStore::CreateInjectedBluetoothDevice(
|
||||
return device_to_return;
|
||||
}
|
||||
|
||||
bool InjectedBluetoothDeviceStore::IsInjectedDevice(
|
||||
const std::string& mac_address) {
|
||||
for (const auto& device : devices_) {
|
||||
if (device->GetMacAddress() == mac_address) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
#define CORE_INTERNAL_INJECTED_BLUETOOTH_DEVICE_STORE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "connections/implementation/pcp.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/bluetooth_adapter.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/implementation/bluetooth_classic.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
@@ -53,6 +55,10 @@ class InjectedBluetoothDeviceStore {
|
||||
const std::string& endpoint_id, const ByteArray& endpoint_info,
|
||||
const ByteArray& service_id_hash, Pcp pcp);
|
||||
|
||||
// Returns true if the provided MAC address(format as "A0:12:34:56:78:90") is
|
||||
// associated with an injected BluetoothDevice.
|
||||
bool IsInjectedDevice(const std::string& mac_address);
|
||||
|
||||
private:
|
||||
// Devices created by this class. BluetoothDevice objects returned by
|
||||
// CreateInjectedBluetoothDevice() store pointers to underlying
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
#include "connections/implementation/injected_bluetooth_device_store.h"
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "connections/implementation/bluetooth_device_name.h"
|
||||
#include "connections/implementation/pcp.h"
|
||||
#include "internal/platform/bluetooth_adapter.h"
|
||||
#include "internal/platform/bluetooth_utils.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/bluetooth_adapter.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
@@ -49,6 +51,7 @@ TEST_F(InjectedBluetoothDeviceStoreTest, Success) {
|
||||
remote_bluetooth_mac_address, kTestEndpointId, endpoint_info,
|
||||
service_id_hash, Pcp::kP2pPointToPoint);
|
||||
EXPECT_TRUE(device.IsValid());
|
||||
EXPECT_TRUE(store_.IsInjectedDevice(device.GetMacAddress()));
|
||||
|
||||
EXPECT_EQ(BluetoothUtils::ToString(remote_bluetooth_mac_address),
|
||||
device.GetMacAddress());
|
||||
@@ -71,6 +74,8 @@ TEST_F(InjectedBluetoothDeviceStoreTest, Fail_InvalidBluetoothMac) {
|
||||
remote_bluetooth_mac_address, kTestEndpointId, endpoint_info,
|
||||
service_id_hash, Pcp::kP2pPointToPoint);
|
||||
EXPECT_FALSE(device.IsValid());
|
||||
EXPECT_FALSE(
|
||||
store_.IsInjectedDevice(remote_bluetooth_mac_address.string_data()));
|
||||
}
|
||||
|
||||
TEST_F(InjectedBluetoothDeviceStoreTest, Fail_InvalidEndpointId) {
|
||||
|
||||
@@ -435,7 +435,8 @@ void P2pClusterPcpHandler::BluetoothDeviceDiscoveredHandler(
|
||||
}
|
||||
|
||||
// Make sure we are still discovering before proceeding.
|
||||
if (!bluetooth_medium_.IsDiscovering(service_id)) {
|
||||
if (!bluetooth_medium_.IsDiscovering(service_id) &&
|
||||
!client->GetDiscoveryOptions().is_out_of_band_connection) {
|
||||
LOG(WARNING) << "Skipping discovered Bluetooth device due to "
|
||||
"no longer discovering.";
|
||||
return;
|
||||
@@ -483,7 +484,8 @@ void P2pClusterPcpHandler::BluetoothNameChangedHandler(
|
||||
return;
|
||||
}
|
||||
|
||||
if (!bluetooth_medium_.IsDiscovering(service_id)) {
|
||||
if (!bluetooth_medium_.IsDiscovering(service_id) &&
|
||||
!client->GetDiscoveryOptions().is_out_of_band_connection) {
|
||||
LOG(WARNING) << "Ignoring name changed Bluetooth device due to no "
|
||||
"longer discovering.";
|
||||
return;
|
||||
@@ -563,7 +565,8 @@ void P2pClusterPcpHandler::BluetoothDeviceLostHandler(
|
||||
"p2p-bt-device-lost", [this, client, service_id,
|
||||
device_name_string]() RUN_ON_PCP_HANDLER_THREAD() {
|
||||
// Make sure we are still discovering before proceeding.
|
||||
if (!bluetooth_medium_.IsDiscovering(service_id)) {
|
||||
if (!bluetooth_medium_.IsDiscovering(service_id) &&
|
||||
!client->GetDiscoveryOptions().is_out_of_band_connection) {
|
||||
LOG(WARNING) << "Ignoring lost Bluetooth device due to no "
|
||||
"longer discovering.";
|
||||
return;
|
||||
@@ -1442,6 +1445,13 @@ Status P2pClusterPcpHandler::InjectEndpointImpl(
|
||||
return {Status::kError};
|
||||
}
|
||||
|
||||
// Make sure discovery is in out-of-band mode from the API definition in
|
||||
// core.h.
|
||||
if (!client->GetDiscoveryOptions().is_out_of_band_connection) {
|
||||
LOG(WARNING) << "InjectEndpointImpl: Discovery is not in out-of-band mode.";
|
||||
return {Status::kError};
|
||||
}
|
||||
|
||||
BluetoothDevice remote_bluetooth_device =
|
||||
injected_bluetooth_device_store_.CreateInjectedBluetoothDevice(
|
||||
metadata.remote_bluetooth_mac_address, metadata.endpoint_id,
|
||||
@@ -3123,8 +3133,7 @@ ErrorOr<Medium> P2pClusterPcpHandler::StartAwdlAdvertising(
|
||||
<< ", endpoint_info="
|
||||
<< absl::BytesToHexString(local_endpoint_info.data()) << "}.";
|
||||
awdl_medium_.StopAcceptingConnections(service_id);
|
||||
return {
|
||||
Error(OperationResultCode::NEARBY_AWDL_ADVERTISE_TO_BYTES_FAILURE)};
|
||||
return {Error(OperationResultCode::NEARBY_AWDL_ADVERTISE_TO_BYTES_FAILURE)};
|
||||
}
|
||||
LOG(INFO) << "In StartAwdlAdvertising("
|
||||
<< absl::BytesToHexString(local_endpoint_info.data())
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "connections/implementation/mediums/mediums.h"
|
||||
#include "connections/listeners.h"
|
||||
#include "connections/medium_selector.h"
|
||||
#include "connections/out_of_band_connection_metadata.h"
|
||||
#include "connections/status.h"
|
||||
#include "connections/strategy.h"
|
||||
#include "connections/v3/connection_listening_options.h"
|
||||
@@ -42,6 +43,7 @@
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/count_down_latch.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/mac_address.h"
|
||||
#include "internal/platform/medium_environment.h"
|
||||
|
||||
namespace nearby {
|
||||
@@ -143,6 +145,16 @@ class P2pClusterPcpHandlerTest : public testing::Test {
|
||||
};
|
||||
}
|
||||
|
||||
// Returns a 6 bytes mac address from a given address.
|
||||
// address: it is in format of "01:02:03:04:05:06".
|
||||
ByteArray GetSixBytesMacAddress(std::string address) {
|
||||
MacAddress mac_address;
|
||||
MacAddress::FromString(address, mac_address);
|
||||
uint8_t bytes[6];
|
||||
mac_address.ToBytes(bytes);
|
||||
return ByteArray(reinterpret_cast<char*>(bytes), 6);
|
||||
}
|
||||
|
||||
ClientProxy client_a_;
|
||||
ClientProxy client_b_;
|
||||
ClientProxy client_c_;
|
||||
@@ -1341,6 +1353,192 @@ TEST_P(P2pClusterPcpHandlerTestWithParam, CanUpdateAwdlAdvertisingOptions) {
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
TEST_F(P2pClusterPcpHandlerTest, FailedToInjectEndpointWithoutDiscovery) {
|
||||
env_.Start();
|
||||
std::string endpoint_name{"endpoint_name"};
|
||||
Mediums mediums_a;
|
||||
EndpointChannelManager ecm_a;
|
||||
EndpointManager em_a(&ecm_a);
|
||||
BwuManager bwu_a(mediums_a, em_a, ecm_a, {}, {});
|
||||
InjectedBluetoothDeviceStore ibds_a;
|
||||
P2pClusterPcpHandler handler_a(&mediums_a, &em_a, &ecm_a, &bwu_a, ibds_a);
|
||||
|
||||
OutOfBandConnectionMetadata metadata = {
|
||||
.medium = location::nearby::proto::connections::Medium::BLUETOOTH,
|
||||
.endpoint_id = "ABCD",
|
||||
.endpoint_info = ByteArray("endpoint_info"),
|
||||
.remote_bluetooth_mac_address = ByteArray("\x01\x02\x03\x04\x05\x06"),
|
||||
};
|
||||
|
||||
handler_a.InjectEndpoint(&client_a_, service_id_, metadata);
|
||||
env_.Sync();
|
||||
|
||||
EXPECT_FALSE(ibds_a.IsInjectedDevice("01:02:03:04:05:06"));
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
TEST_F(P2pClusterPcpHandlerTest, CanInjectEndpoint) {
|
||||
env_.Start();
|
||||
Mediums mediums_a;
|
||||
EndpointChannelManager ecm_a;
|
||||
EndpointManager em_a(&ecm_a);
|
||||
BwuManager bwu_a(mediums_a, em_a, ecm_a, {}, {});
|
||||
InjectedBluetoothDeviceStore ibds_a;
|
||||
P2pClusterPcpHandler handler_a(&mediums_a, &em_a, &ecm_a, &bwu_a, ibds_a);
|
||||
|
||||
DiscoveryOptions discovery_options{
|
||||
{Strategy::kP2pCluster,
|
||||
BooleanMediumSelector{
|
||||
.bluetooth = true,
|
||||
}},
|
||||
/* auto_upgrade_bandwidth= */ false,
|
||||
/* enforce_topology_constraints= */ false,
|
||||
/* is_out_of_band_connection= */ true,
|
||||
};
|
||||
|
||||
CountDownLatch found_latch(1);
|
||||
std::string found_endpoint_id;
|
||||
|
||||
EXPECT_EQ(
|
||||
handler_a.StartDiscovery(&client_a_, service_id_, discovery_options,
|
||||
{
|
||||
.endpoint_found_cb =
|
||||
[&](const std::string& endpoint_id,
|
||||
const ByteArray& endpoint_info,
|
||||
const std::string& service_id) {
|
||||
found_endpoint_id = endpoint_id;
|
||||
found_latch.CountDown();
|
||||
},
|
||||
}),
|
||||
Status{Status::kSuccess});
|
||||
|
||||
std::string endpoint_id = "ABCD";
|
||||
std::string endpoint_info_name = "endpoint_info";
|
||||
ByteArray endpoint_info(endpoint_info_name);
|
||||
|
||||
OutOfBandConnectionMetadata metadata = {
|
||||
.medium = location::nearby::proto::connections::Medium::BLUETOOTH,
|
||||
.endpoint_id = endpoint_id,
|
||||
.endpoint_info = endpoint_info,
|
||||
.remote_bluetooth_mac_address = GetSixBytesMacAddress(
|
||||
mediums_a.GetBluetoothRadio().GetBluetoothAdapter().GetMacAddress()),
|
||||
};
|
||||
|
||||
handler_a.InjectEndpoint(&client_a_, service_id_, metadata);
|
||||
|
||||
EXPECT_TRUE(found_latch.Await(absl::Milliseconds(1000)).result());
|
||||
EXPECT_EQ(found_endpoint_id, endpoint_id);
|
||||
EXPECT_TRUE(ibds_a.IsInjectedDevice(
|
||||
mediums_a.GetBluetoothRadio().GetBluetoothAdapter().GetMacAddress()));
|
||||
|
||||
handler_a.StopDiscovery(&client_a_);
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
TEST_F(P2pClusterPcpHandlerTest, CanConnectToInjectedEndpoint) {
|
||||
env_.Start();
|
||||
// Setup handler_a (advertiser)
|
||||
Mediums mediums_a;
|
||||
EndpointChannelManager ecm_a;
|
||||
EndpointManager em_a(&ecm_a);
|
||||
BwuManager bwu_a(mediums_a, em_a, ecm_a, {}, {});
|
||||
InjectedBluetoothDeviceStore ibds_a;
|
||||
P2pClusterPcpHandler handler_a(&mediums_a, &em_a, &ecm_a, &bwu_a, ibds_a);
|
||||
mediums_a.GetBluetoothRadio().GetBluetoothAdapter().SetName("Device A");
|
||||
|
||||
// Setup handler_b (discoverer)
|
||||
Mediums mediums_b;
|
||||
EndpointChannelManager ecm_b;
|
||||
EndpointManager em_b(&ecm_b);
|
||||
BwuManager bwu_b(mediums_b, em_b, ecm_b, {}, {});
|
||||
InjectedBluetoothDeviceStore ibds_b;
|
||||
P2pClusterPcpHandler handler_b(&mediums_b, &em_b, &ecm_b, &bwu_b, ibds_b);
|
||||
mediums_b.GetBluetoothRadio().GetBluetoothAdapter().SetName("Device B");
|
||||
|
||||
CountDownLatch found_latch(1);
|
||||
CountDownLatch connect_latch(2);
|
||||
|
||||
std::string discovered_endpoint_id;
|
||||
ByteArray discovered_endpoint_info;
|
||||
|
||||
// 1. Advertiser starts advertising
|
||||
std::string endpoint_info_name = "Advertiser Info";
|
||||
EXPECT_EQ(handler_a.StartAdvertising(
|
||||
&client_a_, service_id_, GetBluetoothOnlyAdvertisingOptions(),
|
||||
{
|
||||
.endpoint_info = ByteArray{endpoint_info_name},
|
||||
.listener =
|
||||
{
|
||||
.initiated_cb =
|
||||
[&](const std::string& endpoint_id,
|
||||
const ConnectionResponseInfo& info) {
|
||||
connect_latch.CountDown();
|
||||
},
|
||||
},
|
||||
}),
|
||||
Status{Status::kSuccess});
|
||||
|
||||
// 2. Discoverer starts out-of-band discovery
|
||||
DiscoveryOptions discovery_options{
|
||||
{Strategy::kP2pCluster,
|
||||
BooleanMediumSelector{
|
||||
.bluetooth = true,
|
||||
}},
|
||||
/* auto_upgrade_bandwidth= */ false,
|
||||
/* enforce_topology_constraints= */ false,
|
||||
/* is_out_of_band_connection= */ true,
|
||||
};
|
||||
|
||||
EXPECT_EQ(handler_b.StartDiscovery(
|
||||
&client_b_, service_id_, discovery_options,
|
||||
{
|
||||
.endpoint_found_cb =
|
||||
[&](const std::string& endpoint_id,
|
||||
const ByteArray& endpoint_info,
|
||||
const std::string& service_id) {
|
||||
discovered_endpoint_id = endpoint_id;
|
||||
discovered_endpoint_info = endpoint_info;
|
||||
found_latch.CountDown();
|
||||
},
|
||||
}),
|
||||
Status{Status::kSuccess});
|
||||
|
||||
// 3. Inject the endpoint into the discoverer
|
||||
OutOfBandConnectionMetadata metadata = {
|
||||
.medium = location::nearby::proto::connections::Medium::BLUETOOTH,
|
||||
.endpoint_id = client_a_.GetLocalEndpointId(),
|
||||
.endpoint_info = ByteArray{endpoint_info_name},
|
||||
.remote_bluetooth_mac_address = GetSixBytesMacAddress(
|
||||
mediums_a.GetBluetoothRadio().GetBluetoothAdapter().GetMacAddress()),
|
||||
};
|
||||
|
||||
handler_b.InjectEndpoint(&client_b_, service_id_, metadata);
|
||||
|
||||
EXPECT_TRUE(found_latch.Await(absl::Milliseconds(1000)).result());
|
||||
EXPECT_EQ(discovered_endpoint_id, client_a_.GetLocalEndpointId());
|
||||
|
||||
// 4. Discoverer requests connection to the injected endpoint
|
||||
client_b_.AddCancellationFlag(discovered_endpoint_id);
|
||||
handler_b.RequestConnection(
|
||||
&client_b_, discovered_endpoint_id,
|
||||
{.endpoint_info = discovered_endpoint_info,
|
||||
.listener =
|
||||
{
|
||||
.initiated_cb =
|
||||
[&](const std::string& endpoint_id,
|
||||
const ConnectionResponseInfo& info) {
|
||||
connect_latch.CountDown();
|
||||
},
|
||||
}},
|
||||
{});
|
||||
|
||||
EXPECT_TRUE(connect_latch.Await(absl::Milliseconds(2000)).result());
|
||||
|
||||
handler_a.StopAdvertising(&client_a_);
|
||||
handler_b.StopDiscovery(&client_b_);
|
||||
env_.Stop();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
ParametrisedPcpHandlerTest, P2pClusterPcpHandlerTestWithParam,
|
||||
::testing::Combine(/*mediums=*/::testing::ValuesIn(kTestCases),
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "internal/platform/implementation/g3/bluetooth_adapter.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/medium_environment.h"
|
||||
#include "internal/platform/types.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace g3 {
|
||||
@@ -173,10 +174,21 @@ std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
|
||||
LOG(INFO) << "G3 ConnectToService [self]: medium=" << this
|
||||
<< ", adapter=" << &GetAdapter()
|
||||
<< ", device=" << &GetAdapter().GetDevice();
|
||||
// First, find an instance of remote medium, that exposed this device.
|
||||
auto& adapter = static_cast<BluetoothDevice&>(remote_device).GetAdapter();
|
||||
|
||||
// Find the device in the MediumEnvironment, so that injected devices are
|
||||
// supported in tests.
|
||||
api::BluetoothDevice* device =
|
||||
MediumEnvironment::Instance().FindBluetoothDevice(
|
||||
remote_device.GetMacAddress());
|
||||
if (device == nullptr) {
|
||||
LOG(ERROR) << "G3 ConnectToService [peer]: device=" << &remote_device
|
||||
<< " not found";
|
||||
return {};
|
||||
}
|
||||
|
||||
auto& adapter = down_cast<BluetoothDevice*>(device)->GetAdapter();
|
||||
auto* medium =
|
||||
static_cast<BluetoothClassicMedium*>(adapter.GetBluetoothClassicMedium());
|
||||
down_cast<BluetoothClassicMedium*>(adapter.GetBluetoothClassicMedium());
|
||||
|
||||
if (!medium) return {}; // Adapter is not bound to medium. Bail out.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user