From d5bed12d400839a0c200987ca6ad3c0c739a9c90 Mon Sep 17 00:00:00 2001 From: Alexey Polyudov Date: Thu, 3 Sep 2020 02:08:42 -0700 Subject: [PATCH] Roll forward to cl/329875420 Signed-off-by: Alexey Polyudov Change-Id: I50e284b30472160a409829957b2cb3926babfede --- cpp/core/internal/mediums/BUILD | 4 - cpp/core_v2/internal/BUILD | 1 + cpp/core_v2/internal/mediums/BUILD | 17 +- .../internal/mediums/ble_advertisement.cc | 173 ------ .../mediums/ble_advertisement_test.cc | 219 -------- cpp/core_v2/internal/mediums/ble_test.cc | 49 +- cpp/core_v2/internal/mediums/ble_v2/BUILD | 49 ++ .../{ => ble_v2}/advertisement_read_result.cc | 2 +- .../{ => ble_v2}/advertisement_read_result.h | 6 +- .../advertisement_read_result_test.cc | 2 +- .../mediums/ble_v2/ble_advertisement.cc | 244 +++++++++ .../mediums/{ => ble_v2}/ble_advertisement.h | 62 ++- .../{ => ble_v2}/ble_advertisement_header.cc | 2 +- .../{ => ble_v2}/ble_advertisement_header.h | 6 +- .../ble_advertisement_header_test.cc | 2 +- .../mediums/ble_v2/ble_advertisement_test.cc | 505 ++++++++++++++++++ .../mediums/{ => ble_v2}/ble_packet.cc | 2 +- .../mediums/{ => ble_v2}/ble_packet.h | 6 +- .../mediums/{ => ble_v2}/ble_packet_test.cc | 2 +- .../mediums/{ => ble_v2}/ble_peripheral.h | 6 +- .../{ => ble_v2}/ble_peripheral_test.cc | 2 +- .../ble_v2/discovered_peripheral_callback.h | 31 ++ cpp/core_v2/internal/mediums/utils.cc | 6 +- cpp/core_v2/internal/mediums/utils.h | 1 + cpp/core_v2/internal/mediums/webrtc.cc | 3 + cpp/core_v2/internal/mediums/webrtc.h | 4 +- .../mediums/webrtc/connection_flow.cc | 9 +- .../mediums/webrtc/connection_flow_test.cc | 10 + cpp/core_v2/internal/mediums/webrtc_test.cc | 32 ++ .../internal/p2p_cluster_pcp_handler.cc | 88 +-- .../internal/p2p_cluster_pcp_handler.h | 9 +- cpp/core_v2/options.h | 3 +- cpp/platform_v2/base/medium_environment.cc | 145 ++--- cpp/platform_v2/base/medium_environment.h | 10 +- cpp/platform_v2/impl/g3/webrtc.cc | 6 + cpp/platform_v2/public/ble.cc | 3 +- cpp/platform_v2/public/ble.h | 5 +- cpp/platform_v2/public/ble_test.cc | 76 +-- proto/error_code_enums.proto | 30 ++ 39 files changed, 1210 insertions(+), 622 deletions(-) delete mode 100644 cpp/core_v2/internal/mediums/ble_advertisement.cc delete mode 100644 cpp/core_v2/internal/mediums/ble_advertisement_test.cc create mode 100644 cpp/core_v2/internal/mediums/ble_v2/BUILD rename cpp/core_v2/internal/mediums/{ => ble_v2}/advertisement_read_result.cc (98%) rename cpp/core_v2/internal/mediums/{ => ble_v2}/advertisement_read_result.h (93%) rename cpp/core_v2/internal/mediums/{ => ble_v2}/advertisement_read_result_test.cc (98%) create mode 100644 cpp/core_v2/internal/mediums/ble_v2/ble_advertisement.cc rename cpp/core_v2/internal/mediums/{ => ble_v2}/ble_advertisement.h (52%) rename cpp/core_v2/internal/mediums/{ => ble_v2}/ble_advertisement_header.cc (98%) rename cpp/core_v2/internal/mediums/{ => ble_v2}/ble_advertisement_header.h (93%) rename cpp/core_v2/internal/mediums/{ => ble_v2}/ble_advertisement_header_test.cc (99%) create mode 100644 cpp/core_v2/internal/mediums/ble_v2/ble_advertisement_test.cc rename cpp/core_v2/internal/mediums/{ => ble_v2}/ble_packet.cc (96%) rename cpp/core_v2/internal/mediums/{ => ble_v2}/ble_packet.h (88%) rename cpp/core_v2/internal/mediums/{ => ble_v2}/ble_packet_test.cc (97%) rename cpp/core_v2/internal/mediums/{ => ble_v2}/ble_peripheral.h (82%) rename cpp/core_v2/internal/mediums/{ => ble_v2}/ble_peripheral_test.cc (91%) create mode 100644 cpp/core_v2/internal/mediums/ble_v2/discovered_peripheral_callback.h diff --git a/cpp/core/internal/mediums/BUILD b/cpp/core/internal/mediums/BUILD index 1cf244df..a8dff808 100644 --- a/cpp/core/internal/mediums/BUILD +++ b/cpp/core/internal/mediums/BUILD @@ -87,7 +87,6 @@ cc_test( deps = [ ":mediums", "//platform:utils", - "//platform/api", "//platform/impl/g3", "//testing/base/public:gunit_main", ], @@ -98,7 +97,6 @@ cc_test( srcs = ["ble_advertisement_test.cc"], deps = [ ":mediums", - "//platform/api", "//platform/impl/g3", "//testing/base/public:gunit_main", ], @@ -109,7 +107,6 @@ cc_test( srcs = ["ble_packet_test.cc"], deps = [ ":mediums", - "//platform/api", "//platform/impl/g3", "//testing/base/public:gunit_main", ], @@ -120,7 +117,6 @@ cc_test( srcs = ["bloom_filter_test.cc"], deps = [ ":mediums", - "//platform/api", "//platform/impl/g3", "//testing/base/public:gunit_main", ], diff --git a/cpp/core_v2/internal/BUILD b/cpp/core_v2/internal/BUILD index e68a6c28..7aea432f 100644 --- a/cpp/core_v2/internal/BUILD +++ b/cpp/core_v2/internal/BUILD @@ -61,6 +61,7 @@ cc_library( "//core/internal:message_lite", "//core_v2:core_types", "//core_v2/internal/mediums", + "//core_v2/internal/mediums:utils", "//core_v2/internal/mediums/webrtc", "//proto/connections:offline_wire_formats_portable_proto", "//platform_v2/base", diff --git a/cpp/core_v2/internal/mediums/BUILD b/cpp/core_v2/internal/mediums/BUILD index 02190bcc..b2125c5c 100644 --- a/cpp/core_v2/internal/mediums/BUILD +++ b/cpp/core_v2/internal/mediums/BUILD @@ -1,11 +1,7 @@ cc_library( name = "mediums", srcs = [ - "advertisement_read_result.cc", "ble.cc", - "ble_advertisement.cc", - "ble_advertisement_header.cc", - "ble_packet.cc", "bloom_filter.cc", "bluetooth_classic.cc", "bluetooth_radio.cc", @@ -15,12 +11,7 @@ cc_library( "wifi_lan.cc", ], hdrs = [ - "advertisement_read_result.h", "ble.h", - "ble_advertisement.h", - "ble_advertisement_header.h", - "ble_packet.h", - "ble_peripheral.h", "bloom_filter.h", "bluetooth_classic.h", "bluetooth_radio.h", @@ -37,7 +28,6 @@ cc_library( "//core_v2:core_types", "//core_v2/internal/mediums/webrtc", "//platform_v2/base", - "//platform_v2/base:util", "//platform_v2/public:comm", "//platform_v2/public:logging", "//platform_v2/public:types", @@ -59,11 +49,11 @@ cc_library( hdrs = ["utils.h"], visibility = [ "//core_v2/internal:__pkg__", + "//core_v2/internal/mediums/ble_v2:__pkg__", "//core_v2/internal/mediums/webrtc:__pkg__", ], deps = [ "//platform_v2/base", - "//platform_v2/public:comm", "//platform_v2/public:types", ], ) @@ -72,11 +62,6 @@ cc_test( name = "core_v2_internal_mediums_test", size = "small", srcs = [ - "advertisement_read_result_test.cc", - "ble_advertisement_header_test.cc", - "ble_advertisement_test.cc", - "ble_packet_test.cc", - "ble_peripheral_test.cc", "ble_test.cc", "bloom_filter_test.cc", "bluetooth_classic_test.cc", diff --git a/cpp/core_v2/internal/mediums/ble_advertisement.cc b/cpp/core_v2/internal/mediums/ble_advertisement.cc deleted file mode 100644 index c3772e4c..00000000 --- a/cpp/core_v2/internal/mediums/ble_advertisement.cc +++ /dev/null @@ -1,173 +0,0 @@ -#include "core_v2/internal/mediums/ble_advertisement.h" - -#include - -#include "platform_v2/base/base_input_stream.h" -#include "platform_v2/public/logging.h" -#include "absl/strings/str_cat.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { - -BleAdvertisement::BleAdvertisement(Version version, - SocketVersion socket_version, - const ByteArray &service_id_hash, - const ByteArray &data) { - // Check that the given input is valid. - if (!IsSupportedVersion(version) || - !IsSupportedSocketVersion(socket_version) || - service_id_hash.size() != kServiceIdHashLength || - data.size() > kMaxDataSize) { - return; - } - - version_ = version; - socket_version_ = socket_version; - service_id_hash_ = service_id_hash; - data_ = data; -} - -BleAdvertisement::BleAdvertisement(const ByteArray &ble_advertisement_bytes) { - if (ble_advertisement_bytes.Empty()) { - NEARBY_LOG(INFO, - "Cannot deserialize BleAdvertisement: null bytes passed in."); - return; - } - - if (ble_advertisement_bytes.size() < kMinAdvertisementLength) { - NEARBY_LOG(INFO, - "Cannot deserialize BleAdvertisement: expecting min %d raw " - "bytes, got %" PRIu64, - kMinAdvertisementLength, ble_advertisement_bytes.size()); - return; - } - - ByteArray advertisement_bytes{ble_advertisement_bytes}; - BaseInputStream base_input_stream{advertisement_bytes}; - // The first 1 byte is supposed to be the version and socket version. - auto version_and_socket_version_byte = - static_cast(base_input_stream.ReadUint8()); - - // Version. - version_ = static_cast( - (version_and_socket_version_byte & kVersionBitmask) >> 5); - if (!IsSupportedVersion(version_)) { - NEARBY_LOG(INFO, - "Cannot deserialize BleAdvertisement: unsupported Version %u", - version_); - return; - } - - // Socket version. - socket_version_ = static_cast( - (version_and_socket_version_byte & kSocketVersionBitmask) >> 2); - if (!IsSupportedSocketVersion(socket_version_)) { - NEARBY_LOG( - INFO, - "Cannot deserialize BleAdvertisement: unsupported SocketVersion %u", - socket_version_); - version_ = Version::kUndefined; - return; - } - - // The next 3 bytes are supposed to be the service_id_hash. - service_id_hash_ = base_input_stream.ReadBytes(kServiceIdHashLength); - - // The next 4 bytes are supposed to be the length of the data. - std::uint32_t expected_data_size = base_input_stream.ReadUint32(); - if (expected_data_size < 0) { - NEARBY_LOG(INFO, - "Cannot deserialize BleAdvertisement: negative data size %d", - expected_data_size); - version_ = Version::kUndefined; - return; - } - - // The rest bytes are supposed to be the data. - // Check that the stated data size is the same as what we received. - data_ = base_input_stream.ReadBytes(expected_data_size); - if (data_.size() != expected_data_size) { - NEARBY_LOG(INFO, - "Cannot deserialize BleAdvertisement: expected data to be %u " - "bytes, got %" PRIu64 " bytes ", - expected_data_size, data_.size()); - version_ = Version::kUndefined; - return; - } -} - -BleAdvertisement::operator ByteArray() const { - if (!IsValid()) { - return ByteArray{}; - } - - // The first 3 bits are the Version. - char version_and_socket_version_byte = - (static_cast(version_) << 5) & kVersionBitmask; - // The next 3 bits are the Socket version. 2 bits left are reserved. - version_and_socket_version_byte |= - (static_cast(socket_version_) << 2) & kSocketVersionBitmask; - // Serialize Data size bytes(4). - ByteArray data_size_bytes{kDataSizeLength}; - auto *data_size_bytes_write_ptr = data_size_bytes.data(); - SerializeDataSize(data_size_bytes_write_ptr, data_.size()); - - // clang-format off - std::string out = - absl::StrCat(std::string(1, version_and_socket_version_byte), - std::string(service_id_hash_), - std::string(data_size_bytes), - std::string(data_)); - // clang-format on - - return ByteArray{std::move(out)}; -} - -bool BleAdvertisement::operator==(const BleAdvertisement &rhs) const { - return this->GetVersion() == rhs.GetVersion() && - this->GetSocketVersion() == rhs.GetSocketVersion() && - this->GetServiceIdHash() == rhs.GetServiceIdHash() && - this->GetData() == rhs.GetData(); -} - -bool BleAdvertisement::operator<(const BleAdvertisement &rhs) const { - if (this->GetVersion() != rhs.GetVersion()) { - return this->GetVersion() < rhs.GetVersion(); - } - if (this->GetSocketVersion() != rhs.GetSocketVersion()) { - return this->GetSocketVersion() < rhs.GetSocketVersion(); - } - if (this->GetServiceIdHash() != rhs.GetServiceIdHash()) { - return this->GetServiceIdHash() < rhs.GetServiceIdHash(); - } - return this->GetData() < rhs.GetData(); -} - -bool BleAdvertisement::IsSupportedVersion(Version version) const { - return version >= Version::kV1 && version <= Version::kV2; -} - -bool BleAdvertisement::IsSupportedSocketVersion( - SocketVersion socket_version) const { - return socket_version >= SocketVersion::kV1 && - socket_version <= SocketVersion::kV2; -} - -void BleAdvertisement::SerializeDataSize(char *data_size_bytes_write_ptr, - size_t data_size) const { - // Get a raw representation of the data size bytes in memory. - char *data_size_bytes = reinterpret_cast(&data_size); - - // Append these raw bytes to advertisement bytes, keeping in mind that we need - // to convert from Little Endian to Big Endian in the process. - for (int i = 0; i < kDataSizeLength; ++i) { - data_size_bytes_write_ptr[i] = data_size_bytes[kDataSizeLength - i - 1]; - } -} - -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/cpp/core_v2/internal/mediums/ble_advertisement_test.cc b/cpp/core_v2/internal/mediums/ble_advertisement_test.cc deleted file mode 100644 index 68b80836..00000000 --- a/cpp/core_v2/internal/mediums/ble_advertisement_test.cc +++ /dev/null @@ -1,219 +0,0 @@ -#include "core_v2/internal/mediums/ble_advertisement.h" - -#include - -#include "gtest/gtest.h" - -namespace location { -namespace nearby { -namespace connections { -namespace mediums { -namespace { - -constexpr BleAdvertisement::Version kVersion = BleAdvertisement::Version::kV2; -constexpr BleAdvertisement::SocketVersion kSocketVersion = - BleAdvertisement::SocketVersion::kV2; -constexpr absl::string_view kServiceIDHashBytes{"\x0a\x0b\x0c"}; -constexpr absl::string_view kData{ - "How much wood can a woodchuck chuck if a wood chuck would chuck wood?"}; -// This corresponds to the length of a specific BleAdvertisement packed with the -// kData given above. Be sure to update this if kData ever changes. -constexpr size_t kAdvertisementLength = 77; -constexpr size_t kLongAdvertisementLength = kAdvertisementLength + 1000; - -TEST(BleAdvertisementTest, ConstructionWorksV1) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray data{std::string(kData)}; - - BleAdvertisement ble_advertisement{BleAdvertisement::Version::kV1, - BleAdvertisement::SocketVersion::kV1, - service_id_hash, data}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_EQ(BleAdvertisement::Version::kV1, ble_advertisement.GetVersion()); - EXPECT_EQ(BleAdvertisement::SocketVersion::kV1, - ble_advertisement.GetSocketVersion()); - EXPECT_EQ(service_id_hash, ble_advertisement.GetServiceIdHash()); - EXPECT_EQ(data.size(), ble_advertisement.GetData().size()); - EXPECT_EQ(data, ble_advertisement.GetData()); -} - -TEST(BleAdvertisementTest, ConstructionFailsWithBadVersion) { - BleAdvertisement::Version bad_version = - static_cast(666); - - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray data{std::string(kData)}; - - BleAdvertisement ble_advertisement{bad_version, kSocketVersion, - service_id_hash, data}; - - EXPECT_FALSE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionFailsWithBadSocketVersion) { - BleAdvertisement::SocketVersion bad_socket_version = - static_cast(666); - - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray data{std::string(kData)}; - - BleAdvertisement ble_advertisement{kVersion, bad_socket_version, - service_id_hash, data}; - - EXPECT_FALSE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionFailsWithShortServiceIdHash) { - char short_service_id_hash_bytes[] = "\x0a\x0b"; - - ByteArray bad_service_id_hash{short_service_id_hash_bytes}; - ByteArray data{std::string(kData)}; - - BleAdvertisement ble_advertisement{kVersion, kSocketVersion, - bad_service_id_hash, data}; - - EXPECT_FALSE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionFailsWithLongServiceIdHash) { - char long_service_id_hash_bytes[] = "\x0a\x0b\x0c\x0d"; - - ByteArray bad_service_id_hash{long_service_id_hash_bytes}; - ByteArray data{std::string(kData)}; - - BleAdvertisement ble_advertisement{kVersion, kSocketVersion, - bad_service_id_hash, data}; - - EXPECT_FALSE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionFailsWithLongData) { - // BleAdvertisement shouldn't be able to support data with the max GATT - // attribute length because it needs some room for the preceding fields. - char long_data[512]{}; - - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray bad_data{long_data, 512}; - - BleAdvertisement ble_advertisement{kVersion, kSocketVersion, service_id_hash, - bad_data}; - - EXPECT_FALSE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionFromSerializedBytesWorks) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray data{std::string(kData)}; - - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, - service_id_hash, data}; - ByteArray ble_advertisement_bytes{org_ble_advertisement}; - BleAdvertisement ble_advertisement{ble_advertisement_bytes}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); - EXPECT_EQ(kSocketVersion, ble_advertisement.GetSocketVersion()); - EXPECT_EQ(service_id_hash, ble_advertisement.GetServiceIdHash()); - EXPECT_EQ(data.size(), ble_advertisement.GetData().size()); - EXPECT_EQ(data, ble_advertisement.GetData()); -} - -TEST(BleAdvertisementTest, ConstructionFromSerializedBytesWithEmptyDataWorks) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, - service_id_hash, ByteArray()}; - ByteArray ble_advertisement_bytes{org_ble_advertisement}; - BleAdvertisement ble_advertisement{ble_advertisement_bytes}; - - EXPECT_TRUE(ble_advertisement.IsValid()); - EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); - EXPECT_EQ(kSocketVersion, ble_advertisement.GetSocketVersion()); - EXPECT_EQ(service_id_hash, ble_advertisement.GetServiceIdHash()); - EXPECT_TRUE(ble_advertisement.GetData().Empty()); -} - -TEST(BleAdvertisementTest, ConstructionFromExtraSerializedBytesWorks) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray data{std::string(kData)}; - - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, - service_id_hash, data}; - ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; - - // Copy the bytes into a new array with extra bytes. We must explicitly - // define how long our array is because we can't use variable length arrays. - char raw_ble_advertisement_bytes[kLongAdvertisementLength]{}; - memcpy(raw_ble_advertisement_bytes, org_ble_advertisement_bytes.data(), - std::min(sizeof(raw_ble_advertisement_bytes), - org_ble_advertisement_bytes.size())); - - // Re-parse the Ble advertisement using our extra long advertisement bytes. - ByteArray long_ble_advertisement_bytes{raw_ble_advertisement_bytes, - kLongAdvertisementLength}; - BleAdvertisement long_ble_advertisement{long_ble_advertisement_bytes}; - - EXPECT_TRUE(long_ble_advertisement.IsValid()); - EXPECT_EQ(kVersion, long_ble_advertisement.GetVersion()); - EXPECT_EQ(kSocketVersion, long_ble_advertisement.GetSocketVersion()); - EXPECT_EQ(service_id_hash, long_ble_advertisement.GetServiceIdHash()); - EXPECT_EQ(data.size(), long_ble_advertisement.GetData().size()); - EXPECT_EQ(data, long_ble_advertisement.GetData()); -} - -TEST(BleAdvertisementTest, ConstructionFromNullBytesFails) { - BleAdvertisement ble_advertisement{ByteArray{}}; - - EXPECT_FALSE(ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, ConstructionFromShortLengthSerializedBytesFails) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray data{std::string(kData)}; - - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, - service_id_hash, data}; - ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; - - // Cut off the advertisement so that it's too short. - ByteArray short_ble_advertisement_bytes{org_ble_advertisement_bytes.data(), - 7}; - BleAdvertisement short_ble_advertisement{short_ble_advertisement_bytes}; - - EXPECT_FALSE(short_ble_advertisement.IsValid()); -} - -TEST(BleAdvertisementTest, - ConstructionFromSerializedBytesWithInvalidDataLengthFails) { - ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; - ByteArray data{std::string(kData)}; - - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, - service_id_hash, data}; - ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; - - // Corrupt the DATA_SIZE bits. Start by making a raw copy of the Ble - // advertisement bytes so we can modify it. We must explicitly define how - // long our array is because we can't use variable length arrays. - char raw_ble_advertisement_bytes[kAdvertisementLength]; - memcpy(raw_ble_advertisement_bytes, org_ble_advertisement_bytes.data(), - kAdvertisementLength); - - // The data size field lives in indices 4-7. Corrupt it. - memset(raw_ble_advertisement_bytes + 4, 0xFF, 4); - - // Try to parse the Ble advertisement using our corrupted advertisement bytes. - ByteArray corrupted_ble_advertisement_bytes{raw_ble_advertisement_bytes, - kAdvertisementLength}; - BleAdvertisement corrupted_ble_advertisement{ - corrupted_ble_advertisement_bytes}; - - EXPECT_FALSE(corrupted_ble_advertisement.IsValid()); -} - -} // namespace -} // namespace mediums -} // namespace connections -} // namespace nearby -} // namespace location diff --git a/cpp/core_v2/internal/mediums/ble_test.cc b/cpp/core_v2/internal/mediums/ble_test.cc index 5ce85562..f1936af7 100644 --- a/cpp/core_v2/internal/mediums/ble_test.cc +++ b/cpp/core_v2/internal/mediums/ble_test.cc @@ -57,14 +57,14 @@ TEST_F(BleTest, CanStartAdvertising) { ByteArray advertisement_bytes{std::string(kAdvertisementString)}; CountDownLatch found_latch(1); - ble_b.StartScanning(service_id, - DiscoveredPeripheralCallback{ - .peripheral_discovered_cb = - [&found_latch](BlePeripheral& peripheral, - const std::string& service_id) { - found_latch.CountDown(); - }, - }); + ble_b.StartScanning( + service_id, + DiscoveredPeripheralCallback{ + .peripheral_discovered_cb = + [&found_latch]( + BlePeripheral& peripheral, const std::string& service_id, + bool fast_advertisement) { found_latch.CountDown(); }, + }); EXPECT_TRUE(ble_a.StartAdvertising(service_id, advertisement_bytes)); EXPECT_TRUE(found_latch.Await(kWaitDuration).result()); @@ -89,18 +89,18 @@ TEST_F(BleTest, CanStartDiscovery) { ble_b.StartAdvertising(service_id, advertisement_bytes); EXPECT_TRUE(ble_a.StartScanning( - service_id, DiscoveredPeripheralCallback{ - .peripheral_discovered_cb = - [&accept_latch](BlePeripheral& peripheral, - const std::string& service_id) { - accept_latch.CountDown(); - }, - .peripheral_lost_cb = - [&lost_latch](BlePeripheral& peripheral, - const std::string& service_id) { - lost_latch.CountDown(); - }, - })); + service_id, + DiscoveredPeripheralCallback{ + .peripheral_discovered_cb = + [&accept_latch]( + BlePeripheral& peripheral, const std::string& service_id, + bool fast_advertisement) { accept_latch.CountDown(); }, + .peripheral_lost_cb = + [&lost_latch](BlePeripheral& peripheral, + const std::string& service_id) { + lost_latch.CountDown(); + }, + })); EXPECT_TRUE(accept_latch.Await(kWaitDuration).result()); ble_b.StopAdvertising(service_id); EXPECT_TRUE(lost_latch.Await(kWaitDuration).result()); @@ -135,10 +135,13 @@ TEST_F(BleTest, CanStartAcceptingConnectionsAndConnect) { { .peripheral_discovered_cb = [&found_latch, &discovered_peripheral]( - BlePeripheral& peripheral, const std::string& service_id) { + BlePeripheral& peripheral, const std::string& service_id, + bool fast_advertisement) { discovered_peripheral = peripheral; - NEARBY_LOG(INFO, "Discovered peripheral=%p [impl=%p]", - &peripheral, &peripheral.GetImpl()); + NEARBY_LOG( + INFO, + "Discovered peripheral=%p [impl=%p], fast advertisement=%d", + &peripheral, &peripheral.GetImpl(), fast_advertisement); found_latch.CountDown(); }, }); diff --git a/cpp/core_v2/internal/mediums/ble_v2/BUILD b/cpp/core_v2/internal/mediums/ble_v2/BUILD new file mode 100644 index 00000000..85ba9fd9 --- /dev/null +++ b/cpp/core_v2/internal/mediums/ble_v2/BUILD @@ -0,0 +1,49 @@ +cc_library( + name = "ble_v2", + srcs = [ + "advertisement_read_result.cc", + "ble_advertisement.cc", + "ble_advertisement_header.cc", + "ble_packet.cc", + ], + hdrs = [ + "advertisement_read_result.h", + "ble_advertisement.h", + "ble_advertisement_header.h", + "ble_packet.h", + "ble_peripheral.h", + "discovered_peripheral_callback.h", + ], + visibility = [ + "//core_v2/internal:__subpackages__", + ], + deps = [ + "//core_v2:core_types", + "//platform_v2/base", + "//platform_v2/base:util", + "//platform_v2/public:logging", + "//platform_v2/public:types", + "//absl/container:flat_hash_map", + "//absl/container:flat_hash_set", + "//absl/strings", + "//absl/time", + ], +) + +cc_test( + name = "ble_v2_test", + srcs = [ + "advertisement_read_result_test.cc", + "ble_advertisement_header_test.cc", + "ble_advertisement_test.cc", + "ble_packet_test.cc", + "ble_peripheral_test.cc", + ], + deps = [ + ":ble_v2", + "//platform_v2/base", + "//platform_v2/impl/g3", # buildcleaner: keep + "//testing/base/public:gunit_main", + "//absl/time", + ], +) diff --git a/cpp/core_v2/internal/mediums/advertisement_read_result.cc b/cpp/core_v2/internal/mediums/ble_v2/advertisement_read_result.cc similarity index 98% rename from cpp/core_v2/internal/mediums/advertisement_read_result.cc rename to cpp/core_v2/internal/mediums/ble_v2/advertisement_read_result.cc index fbd97e34..63e43127 100644 --- a/cpp/core_v2/internal/mediums/advertisement_read_result.cc +++ b/cpp/core_v2/internal/mediums/ble_v2/advertisement_read_result.cc @@ -1,4 +1,4 @@ -#include "core_v2/internal/mediums/advertisement_read_result.h" +#include "core_v2/internal/mediums/ble_v2/advertisement_read_result.h" #include #include diff --git a/cpp/core_v2/internal/mediums/advertisement_read_result.h b/cpp/core_v2/internal/mediums/ble_v2/advertisement_read_result.h similarity index 93% rename from cpp/core_v2/internal/mediums/advertisement_read_result.h rename to cpp/core_v2/internal/mediums/ble_v2/advertisement_read_result.h index c4d2c566..ebf5b535 100644 --- a/cpp/core_v2/internal/mediums/advertisement_read_result.h +++ b/cpp/core_v2/internal/mediums/ble_v2/advertisement_read_result.h @@ -1,5 +1,5 @@ -#ifndef CORE_V2_INTERNAL_MEDIUMS_ADVERTISEMENT_READ_RESULT_H_ -#define CORE_V2_INTERNAL_MEDIUMS_ADVERTISEMENT_READ_RESULT_H_ +#ifndef CORE_V2_INTERNAL_MEDIUMS_BLE_V2_ADVERTISEMENT_READ_RESULT_H_ +#define CORE_V2_INTERNAL_MEDIUMS_BLE_V2_ADVERTISEMENT_READ_RESULT_H_ #include #include @@ -87,4 +87,4 @@ class AdvertisementReadResult { } // namespace nearby } // namespace location -#endif // CORE_V2_INTERNAL_MEDIUMS_ADVERTISEMENT_READ_RESULT_H_ +#endif // CORE_V2_INTERNAL_MEDIUMS_BLE_V2_ADVERTISEMENT_READ_RESULT_H_ diff --git a/cpp/core_v2/internal/mediums/advertisement_read_result_test.cc b/cpp/core_v2/internal/mediums/ble_v2/advertisement_read_result_test.cc similarity index 98% rename from cpp/core_v2/internal/mediums/advertisement_read_result_test.cc rename to cpp/core_v2/internal/mediums/ble_v2/advertisement_read_result_test.cc index 0d822274..7acfef4e 100644 --- a/cpp/core_v2/internal/mediums/advertisement_read_result_test.cc +++ b/cpp/core_v2/internal/mediums/ble_v2/advertisement_read_result_test.cc @@ -1,4 +1,4 @@ -#include "core_v2/internal/mediums/advertisement_read_result.h" +#include "core_v2/internal/mediums/ble_v2/advertisement_read_result.h" #include "gtest/gtest.h" #include "absl/time/clock.h" diff --git a/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement.cc b/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement.cc new file mode 100644 index 00000000..d988a869 --- /dev/null +++ b/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement.cc @@ -0,0 +1,244 @@ +#include "core_v2/internal/mediums/ble_v2/ble_advertisement.h" + +#include + +#include "platform_v2/base/base_input_stream.h" +#include "platform_v2/public/logging.h" +#include "absl/strings/str_cat.h" + +namespace location { +namespace nearby { +namespace connections { +namespace mediums { + +BleAdvertisement::BleAdvertisement(Version version, + SocketVersion socket_version, + const ByteArray &service_id_hash, + const ByteArray &data, + const ByteArray &device_token) { + DoInitialize(/*fast_advertisement=*/false, version, socket_version, + service_id_hash, data, device_token); +} + +BleAdvertisement::BleAdvertisement(Version version, + SocketVersion socket_version, + const ByteArray &data, + const ByteArray &device_token) { + DoInitialize(/*fast_advertisement=*/true, version, socket_version, + {}, data, device_token); +} + +void BleAdvertisement::DoInitialize(bool fast_advertisement, Version version, + SocketVersion socket_version, + const ByteArray &service_id_hash, + const ByteArray &data, + const ByteArray &device_token) { + // Check that the given input is valid. + fast_advertisement_ = fast_advertisement; + if (!fast_advertisement_) { + if (service_id_hash.size() != kServiceIdHashLength) return; + } + if (!IsSupportedVersion(version) || + !IsSupportedSocketVersion(socket_version) || + (!device_token.Empty() && device_token.size() != kDeviceTokenLength)) { + return; + } + + int advertisement_Length = ComputeAdvertisementLength( + data.size(), device_token.size(), fast_advertisement_); + int max_advertisement_length = fast_advertisement + ? kMaxFastAdvertisementLength + : kMaxAdvertisementLength; + if (advertisement_Length > max_advertisement_length) { + return; + } + + version_ = version; + socket_version_ = socket_version; + if (!fast_advertisement_) service_id_hash_ = service_id_hash; + data_ = data; + device_token_ = device_token; +} + +BleAdvertisement::BleAdvertisement(const ByteArray &ble_advertisement_bytes) { + if (ble_advertisement_bytes.Empty()) { + NEARBY_LOG(INFO, + "Cannot deserialize BleAdvertisement: null bytes passed in."); + return; + } + + if (ble_advertisement_bytes.size() < kVersionLength) { + NEARBY_LOG( + INFO, + "Cannot deserialize BleAdvertisement: expecting min %d raw bytes to " + "parse the version, got %" PRIu64, + kVersionLength, ble_advertisement_bytes.size()); + return; + } + + ByteArray advertisement_bytes{ble_advertisement_bytes}; + BaseInputStream base_input_stream{advertisement_bytes}; + // The first 1 byte is supposed to be the version, socket version and the fast + // advertisement flag. + auto version_byte = + static_cast(base_input_stream.ReadUint8()); + + // Version. + version_ = static_cast((version_byte & kVersionBitmask) >> 5); + if (!IsSupportedVersion(version_)) { + NEARBY_LOG(INFO, + "Cannot deserialize BleAdvertisement: unsupported Version %u", + version_); + return; + } + + // Socket version. + socket_version_ = + static_cast((version_byte & kSocketVersionBitmask) >> 2); + if (!IsSupportedSocketVersion(socket_version_)) { + NEARBY_LOG( + INFO, + "Cannot deserialize BleAdvertisement: unsupported SocketVersion %u", + socket_version_); + version_ = Version::kUndefined; + return; + } + + // Fast advertisement flag. + fast_advertisement_ = + static_cast((version_byte & kFastAdvertisementFlagBitmask) >> 1); + + // The next 3 bytes are supposed to be the service_id_hash if not fast + // advertisement. + if (!fast_advertisement_) { + service_id_hash_ = base_input_stream.ReadBytes(kServiceIdHashLength); + } + + // Data length. + int expected_data_size = + fast_advertisement_ + ? static_cast( + base_input_stream.ReadBytes(kFastDataSizeLength).data()[0]) + : static_cast(base_input_stream.ReadUint32()); + if (expected_data_size < 0) { + NEARBY_LOG(INFO, + "Cannot deserialize BleAdvertisement: negative data size %d", + expected_data_size); + version_ = Version::kUndefined; + return; + } + + // Data. + // Check that the stated data size is the same as what we received. + data_ = base_input_stream.ReadBytes(expected_data_size); + if (data_.size() != expected_data_size) { + NEARBY_LOG(INFO, + "Cannot deserialize BleAdvertisement: expected data to be %u " + "bytes, got %" PRIu64 " bytes ", + expected_data_size, data_.size()); + version_ = Version::kUndefined; + return; + } + + // Device token. If the number of remaining bytes are valid for device token, + // then read it. + if (base_input_stream.IsAvailable(kDeviceTokenLength)) { + device_token_ = base_input_stream.ReadBytes(kDeviceTokenLength); + } +} + +BleAdvertisement::operator ByteArray() const { + if (!IsValid()) { + return ByteArray{}; + } + + // The first 3 bits are the Version. + char version_byte = (static_cast(version_) << 5) & kVersionBitmask; + // The next 3 bits are the Socket version. 2 bits left are reserved. + version_byte |= + (static_cast(socket_version_) << 2) & kSocketVersionBitmask; + // The next 1 bit is the fast advertisement flag. 1 bit left is reserved. + version_byte |= (static_cast(fast_advertisement_ ? 1 : 0) << 1) & + kFastAdvertisementFlagBitmask; + + // Serialize Data size bytes + ByteArray data_size_bytes{static_cast( + fast_advertisement_ ? kFastDataSizeLength : kDataSizeLength)}; + auto *data_size_bytes_write_ptr = data_size_bytes.data(); + SerializeDataSize(fast_advertisement_, data_size_bytes_write_ptr, + data_.size()); + + // clang-format on + if (fast_advertisement_) { + std::string out = + absl::StrCat(std::string(1, version_byte), + std::string(data_size_bytes), + std::string(data_), + std::string(device_token_)); + return ByteArray{std::move(out)}; + } else { + std::string out = + absl::StrCat(std::string(1, version_byte), + std::string(service_id_hash_), + std::string(data_size_bytes), + std::string(data_), + std::string(device_token_)); + return ByteArray{std::move(out)}; + } + // clang-format on +} + +bool BleAdvertisement::operator==(const BleAdvertisement &rhs) const { + return this->GetVersion() == rhs.GetVersion() && + this->GetSocketVersion() == rhs.GetSocketVersion() && + this->GetServiceIdHash() == rhs.GetServiceIdHash() && + this->GetData() == rhs.GetData() && + this->GetDeviceToken() == rhs.GetDeviceToken(); +} + +bool BleAdvertisement::operator<(const BleAdvertisement &rhs) const { + if (this->GetVersion() != rhs.GetVersion()) { + return this->GetVersion() < rhs.GetVersion(); + } + if (this->GetSocketVersion() != rhs.GetSocketVersion()) { + return this->GetSocketVersion() < rhs.GetSocketVersion(); + } + if (this->GetServiceIdHash() != rhs.GetServiceIdHash()) { + return this->GetServiceIdHash() < rhs.GetServiceIdHash(); + } + if (this->GetDeviceToken() != rhs.GetDeviceToken()) { + return this->GetDeviceToken() < rhs.GetDeviceToken(); + } + return this->GetData() < rhs.GetData(); +} + +bool BleAdvertisement::IsSupportedVersion(Version version) const { + return version >= Version::kV1 && version <= Version::kV2; +} + +bool BleAdvertisement::IsSupportedSocketVersion( + SocketVersion socket_version) const { + return socket_version >= SocketVersion::kV1 && + socket_version <= SocketVersion::kV2; +} + +void BleAdvertisement::SerializeDataSize(bool fast_advertisement, + char *data_size_bytes_write_ptr, + size_t data_size) const { + // Get a raw representation of the data size bytes in memory. + char *data_size_bytes = reinterpret_cast(&data_size); + + const int data_size_length = + fast_advertisement ? kFastDataSizeLength : kDataSizeLength; + + // Append these raw bytes to advertisement bytes, keeping in mind that we need + // to convert from Little Endian to Big Endian in the process. + for (int i = 0; i < data_size_length; ++i) { + data_size_bytes_write_ptr[i] = data_size_bytes[data_size_length - i - 1]; + } +} + +} // namespace mediums +} // namespace connections +} // namespace nearby +} // namespace location diff --git a/cpp/core_v2/internal/mediums/ble_advertisement.h b/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement.h similarity index 52% rename from cpp/core_v2/internal/mediums/ble_advertisement.h rename to cpp/core_v2/internal/mediums/ble_v2/ble_advertisement.h index a1da4d4d..203b3614 100644 --- a/cpp/core_v2/internal/mediums/ble_advertisement.h +++ b/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement.h @@ -1,5 +1,5 @@ -#ifndef CORE_V2_INTERNAL_MEDIUMS_BLE_ADVERTISEMENT_H_ -#define CORE_V2_INTERNAL_MEDIUMS_BLE_ADVERTISEMENT_H_ +#ifndef CORE_V2_INTERNAL_MEDIUMS_BLE_V2_BLE_ADVERTISEMENT_H_ +#define CORE_V2_INTERNAL_MEDIUMS_BLE_V2_BLE_ADVERTISEMENT_H_ #include @@ -10,10 +10,14 @@ namespace nearby { namespace connections { namespace mediums { -// Represents the format of the Mediums Ble Advertisement used in advertising -// and discovery. +// Represents the format of the Mediums BLE Advertisement used in Advertising + +// Discovery. // -// [VERSION][SOCKET_VERSION][2_RESERVED_BITS][SERVICE_ID_HASH][DATA_SIZE][DATA] +// [VERSION][SOCKET_VERSION][FAST_ADVERTISEMENT_FLAG][1_RESERVED_BIT][SERVICE_ID_HASH][DATA_SIZE][DATA][DEVICE_TOKEN] +// +// For fast advertisement, we remove SERVICE_ID_HASH since we already have one +// copy in Nearby Connections(b/138447288) +// [VERSION][SOCKET_VERSION][FAST_ADVERTISEMENT_FLAG][1_RESERVED_BIT][DATA_SIZE][DATA][DEVICE_TOKEN] // // See go/nearby-ble-design for more information. class BleAdvertisement { @@ -37,10 +41,14 @@ class BleAdvertisement { }; static constexpr int kServiceIdHashLength = 3; + static constexpr int kDeviceTokenLength = 2; BleAdvertisement() = default; BleAdvertisement(Version version, SocketVersion socket_version, - const ByteArray &service_id_hash, const ByteArray &data); + const ByteArray &service_id_hash, const ByteArray &data, + const ByteArray &device_token); + BleAdvertisement(Version version, SocketVersion socket_version, + const ByteArray &data, const ByteArray &device_token); explicit BleAdvertisement(const ByteArray &ble_advertisement_bytes); BleAdvertisement(const BleAdvertisement &) = default; BleAdvertisement &operator=(const BleAdvertisement &) = default; @@ -56,37 +64,59 @@ class BleAdvertisement { bool IsValid() const { return IsSupportedVersion(version_); } Version GetVersion() const { return version_; } SocketVersion GetSocketVersion() const { return socket_version_; } + bool IsFastAdvertisement() const { return fast_advertisement_; } ByteArray GetServiceIdHash() const { return service_id_hash_; } ByteArray &GetData() & { return data_; } const ByteArray &GetData() const & { return data_; } ByteArray &&GetData() && { return std::move(data_); } const ByteArray &&GetData() const && { return std::move(data_); } + ByteArray GetDeviceToken() const { return device_token_; } private: + void DoInitialize(bool fast_advertisement, Version version, + SocketVersion socket_version, + const ByteArray &service_id_hash, const ByteArray &data, + const ByteArray &device_token); bool IsSupportedVersion(Version version) const; bool IsSupportedSocketVersion(SocketVersion socket_version) const; - void SerializeDataSize(char *data_size_bytes_write_ptr, + void SerializeDataSize(bool fast_advertisement, + char *data_size_bytes_write_ptr, size_t data_size) const; + int ComputeAdvertisementLength(int data_length, int total_optional_length, + bool fast_advertisement) const { + // The advertisement length is the minimum length + the length of the data + + // the length of in-use optional fields. + return fast_advertisement ? (kMinFastAdvertisementLegth + data_length + + total_optional_length) + : (kMinAdvertisementLength + data_length + + total_optional_length); + } static constexpr int kVersionLength = 1; - // Length of one int. Be sure to re-evaluate how we compute data size in this - // class if this constant ever changes! - static constexpr int kDataSizeLength = 4; + static constexpr int kVersionBitmask = 0x0E0; + static constexpr int kSocketVersionBitmask = 0x01C; + static constexpr int kFastAdvertisementFlagBitmask = 0x002; + static constexpr int kDataSizeLength = 4; // Length of one int. + static constexpr int kFastDataSizeLength = 1; // Length of one byte. static constexpr int kMinAdvertisementLength = kVersionLength + kServiceIdHashLength + kDataSizeLength; // The maximum length for a Gatt characteristic value is 512 bytes, so make // sure the entire advertisement is less than that. The data can take up // whatever space is remaining after the bytes preceding it. - static constexpr int kMaxGattCharacteristicValueSize = 512; - static constexpr int kMaxDataSize = - kMaxGattCharacteristicValueSize - kMinAdvertisementLength; - static constexpr int kVersionBitmask = 0x0E0; - static constexpr int kSocketVersionBitmask = 0x01C; + static constexpr int kMaxAdvertisementLength = 512; + static constexpr int kMinFastAdvertisementLegth = + kVersionLength + kFastDataSizeLength; + // The maximum length for the scan response is 31 bytes. However, with the + // required header that comes before the service data, this leaves the + // advertiser with 27 leftover bytes. + static constexpr int kMaxFastAdvertisementLength = 27; Version version_{Version::kUndefined}; SocketVersion socket_version_{SocketVersion::kUndefined}; + bool fast_advertisement_ = false; ByteArray service_id_hash_; ByteArray data_; + ByteArray device_token_; }; } // namespace mediums @@ -94,4 +124,4 @@ class BleAdvertisement { } // namespace nearby } // namespace location -#endif // CORE_V2_INTERNAL_MEDIUMS_BLE_ADVERTISEMENT_H_ +#endif // CORE_V2_INTERNAL_MEDIUMS_BLE_V2_BLE_ADVERTISEMENT_H_ diff --git a/cpp/core_v2/internal/mediums/ble_advertisement_header.cc b/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement_header.cc similarity index 98% rename from cpp/core_v2/internal/mediums/ble_advertisement_header.cc rename to cpp/core_v2/internal/mediums/ble_v2/ble_advertisement_header.cc index d1c55de5..5c35fafa 100644 --- a/cpp/core_v2/internal/mediums/ble_advertisement_header.cc +++ b/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement_header.cc @@ -1,4 +1,4 @@ -#include "core_v2/internal/mediums/ble_advertisement_header.h" +#include "core_v2/internal/mediums/ble_v2/ble_advertisement_header.h" #include diff --git a/cpp/core_v2/internal/mediums/ble_advertisement_header.h b/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement_header.h similarity index 93% rename from cpp/core_v2/internal/mediums/ble_advertisement_header.h rename to cpp/core_v2/internal/mediums/ble_v2/ble_advertisement_header.h index bcec8d55..b4c1289e 100644 --- a/cpp/core_v2/internal/mediums/ble_advertisement_header.h +++ b/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement_header.h @@ -1,5 +1,5 @@ -#ifndef CORE_V2_INTERNAL_MEDIUMS_BLE_ADVERTISEMENT_HEADER_H_ -#define CORE_V2_INTERNAL_MEDIUMS_BLE_ADVERTISEMENT_HEADER_H_ +#ifndef CORE_V2_INTERNAL_MEDIUMS_BLE_V2_BLE_ADVERTISEMENT_HEADER_H_ +#define CORE_V2_INTERNAL_MEDIUMS_BLE_V2_BLE_ADVERTISEMENT_HEADER_H_ #include @@ -80,4 +80,4 @@ class BleAdvertisementHeader { } // namespace nearby } // namespace location -#endif // CORE_V2_INTERNAL_MEDIUMS_BLE_ADVERTISEMENT_HEADER_H_ +#endif // CORE_V2_INTERNAL_MEDIUMS_BLE_V2_BLE_ADVERTISEMENT_HEADER_H_ diff --git a/cpp/core_v2/internal/mediums/ble_advertisement_header_test.cc b/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement_header_test.cc similarity index 99% rename from cpp/core_v2/internal/mediums/ble_advertisement_header_test.cc rename to cpp/core_v2/internal/mediums/ble_v2/ble_advertisement_header_test.cc index b4911c95..10aa62d0 100644 --- a/cpp/core_v2/internal/mediums/ble_advertisement_header_test.cc +++ b/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement_header_test.cc @@ -1,4 +1,4 @@ -#include "core_v2/internal/mediums/ble_advertisement_header.h" +#include "core_v2/internal/mediums/ble_v2/ble_advertisement_header.h" #include "platform_v2/base/base64_utils.h" #include "gtest/gtest.h" diff --git a/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement_test.cc b/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement_test.cc new file mode 100644 index 00000000..46a18850 --- /dev/null +++ b/cpp/core_v2/internal/mediums/ble_v2/ble_advertisement_test.cc @@ -0,0 +1,505 @@ +#include "core_v2/internal/mediums/ble_v2/ble_advertisement.h" + +#include + +#include "gtest/gtest.h" + +namespace location { +namespace nearby { +namespace connections { +namespace mediums { +namespace { + +constexpr BleAdvertisement::Version kVersion = BleAdvertisement::Version::kV2; +constexpr BleAdvertisement::SocketVersion kSocketVersion = + BleAdvertisement::SocketVersion::kV2; +constexpr absl::string_view kServiceIDHashBytes{"\x0a\x0b\x0c"}; +constexpr absl::string_view kData{ + "How much wood can a woodchuck chuck if a wood chuck would chuck wood?"}; +constexpr absl::string_view kFastData{"Fast Advertise"}; +constexpr absl::string_view kDeviceToken{"\x04\x20"}; +// kAdvertisementLength/kFastAdvertisementLength corresponds to the length of a +// specific BleAdvertisement packed with the kData/kFastData given above. Be +// sure to update this if kData/kFastData ever changes. +constexpr size_t kAdvertisementLength = 77; +constexpr size_t kFastAdvertisementLength = 16; +constexpr size_t kLongAdvertisementLength = kAdvertisementLength + 1000; + +TEST(BleAdvertisementTest, ConstructionWorksV1) { + ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; + ByteArray data{std::string(kData)}; + ByteArray device_token{std::string(kDeviceToken)}; + + BleAdvertisement ble_advertisement{BleAdvertisement::Version::kV1, + BleAdvertisement::SocketVersion::kV1, + service_id_hash, + data, + device_token}; + + EXPECT_TRUE(ble_advertisement.IsValid()); + EXPECT_FALSE(ble_advertisement.IsFastAdvertisement()); + EXPECT_EQ(BleAdvertisement::Version::kV1, ble_advertisement.GetVersion()); + EXPECT_EQ(BleAdvertisement::SocketVersion::kV1, + ble_advertisement.GetSocketVersion()); + EXPECT_EQ(service_id_hash, ble_advertisement.GetServiceIdHash()); + EXPECT_EQ(data.size(), ble_advertisement.GetData().size()); + EXPECT_EQ(data, ble_advertisement.GetData()); + EXPECT_EQ(device_token, ble_advertisement.GetDeviceToken()); +} + +TEST(BleAdvertisementTest, ConstructionWorksV1ForFastAdvertisement) { + ByteArray fast_data{std::string(kFastData)}; + ByteArray device_token{std::string(kDeviceToken)}; + + BleAdvertisement ble_advertisement{BleAdvertisement::Version::kV1, + BleAdvertisement::SocketVersion::kV1, + fast_data, + device_token}; + + EXPECT_TRUE(ble_advertisement.IsValid()); + EXPECT_TRUE(ble_advertisement.IsFastAdvertisement()); + EXPECT_EQ(BleAdvertisement::Version::kV1, ble_advertisement.GetVersion()); + EXPECT_EQ(BleAdvertisement::SocketVersion::kV1, + ble_advertisement.GetSocketVersion()); + EXPECT_EQ(fast_data.size(), ble_advertisement.GetData().size()); + EXPECT_EQ(fast_data, ble_advertisement.GetData()); + EXPECT_EQ(device_token, ble_advertisement.GetDeviceToken()); +} + +TEST(BleAdvertisementTest, ConstructionFailsWithBadVersion) { + BleAdvertisement::Version bad_version = + static_cast(666); + + ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; + ByteArray data{std::string(kData)}; + ByteArray device_token{std::string(kDeviceToken)}; + + BleAdvertisement ble_advertisement{bad_version, + kSocketVersion, + service_id_hash, + data, + device_token}; + EXPECT_FALSE(ble_advertisement.IsValid()); + + BleAdvertisement fast_ble_advertisement{bad_version, + kSocketVersion, + data, + device_token}; + EXPECT_FALSE(fast_ble_advertisement.IsValid()); +} + +TEST(BleAdvertisementTest, ConstructionFailsWithBadSocketVersion) { + BleAdvertisement::SocketVersion bad_socket_version = + static_cast(666); + + ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; + ByteArray data{std::string(kData)}; + ByteArray device_token{std::string(kDeviceToken)}; + + BleAdvertisement ble_advertisement{kVersion, + bad_socket_version, + service_id_hash, + data, + device_token}; + EXPECT_FALSE(ble_advertisement.IsValid()); + + BleAdvertisement fast_ble_advertisement{kVersion, + bad_socket_version, + data, + device_token}; + EXPECT_FALSE(fast_ble_advertisement.IsValid()); +} + +TEST(BleAdvertisementTest, ConstructionFailsWithShortServiceIdHash) { + char short_service_id_hash_bytes[] = "\x0a\x0b"; + + ByteArray bad_service_id_hash{short_service_id_hash_bytes}; + ByteArray data{std::string(kData)}; + ByteArray device_token{std::string(kDeviceToken)}; + + BleAdvertisement ble_advertisement{kVersion, + kSocketVersion, + bad_service_id_hash, + data, + device_token}; + + EXPECT_FALSE(ble_advertisement.IsValid()); +} + +TEST(BleAdvertisementTest, ConstructionFailsWithLongServiceIdHash) { + char long_service_id_hash_bytes[] = "\x0a\x0b\x0c\x0d"; + + ByteArray bad_service_id_hash{long_service_id_hash_bytes}; + ByteArray data{std::string(kData)}; + ByteArray device_token{std::string(kDeviceToken)}; + + BleAdvertisement ble_advertisement{kVersion, + kSocketVersion, + bad_service_id_hash, + data, + device_token}; + + EXPECT_FALSE(ble_advertisement.IsValid()); +} + +TEST(BleAdvertisementTest, ConstructionFailsWithLongData) { + // BleAdvertisement shouldn't be able to support data with the max GATT + // attribute length because it needs some room for the preceding fields. + char long_data[512]{}; + + ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; + ByteArray bad_data{long_data, 512}; + ByteArray device_token{std::string(kDeviceToken)}; + + BleAdvertisement ble_advertisement{kVersion, + kSocketVersion, + service_id_hash, + bad_data, + device_token}; + EXPECT_FALSE(ble_advertisement.IsValid()); + + BleAdvertisement fast_ble_advertisement{kVersion, + kSocketVersion, + bad_data, + device_token}; + EXPECT_FALSE(fast_ble_advertisement.IsValid()); +} + +TEST(BleAdvertisementTest, ConstructionWorksWithEmptyDeviceToken) { + ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; + ByteArray data{std::string(kData)}; + + BleAdvertisement ble_advertisement{kVersion, + kSocketVersion, + service_id_hash, + data, + ByteArray{}}; + + EXPECT_TRUE(ble_advertisement.IsValid()); + EXPECT_FALSE(ble_advertisement.IsFastAdvertisement()); + EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); + EXPECT_EQ(kSocketVersion, ble_advertisement.GetSocketVersion()); + EXPECT_EQ(service_id_hash, ble_advertisement.GetServiceIdHash()); + EXPECT_EQ(data.size(), ble_advertisement.GetData().size()); + EXPECT_EQ(data, ble_advertisement.GetData()); + EXPECT_TRUE(ble_advertisement.GetDeviceToken().Empty()); +} + +TEST(BleAdvertisementTest, + ConstructionWorksWithEmptyDeviceTokenForFastAdvertisement) { + ByteArray fast_data{std::string(kFastData)}; + + BleAdvertisement ble_advertisement{kVersion, + kSocketVersion, + fast_data, + ByteArray{}}; + + EXPECT_TRUE(ble_advertisement.IsValid()); + EXPECT_TRUE(ble_advertisement.IsFastAdvertisement()); + EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); + EXPECT_EQ(kSocketVersion, ble_advertisement.GetSocketVersion()); + EXPECT_EQ(fast_data.size(), ble_advertisement.GetData().size()); + EXPECT_EQ(fast_data, ble_advertisement.GetData()); + EXPECT_TRUE(ble_advertisement.GetDeviceToken().Empty()); +} + +TEST(BleAdvertisementTest, ConstructionFailsWithWrongSizeofDeviceToken) { + char wrong_device_token_bytes_1[] = "\x04\x2\x10"; // over 2 bytes + char wrong_device_token_bytes_2[] = "\x04"; // 1 byte + + ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; + ByteArray data{std::string(kData)}; + ByteArray bad_device_token_1{wrong_device_token_bytes_1}; + ByteArray bad_device_token_2{wrong_device_token_bytes_2}; + + BleAdvertisement ble_advertisement_1{kVersion, + kSocketVersion, + service_id_hash, + data, + bad_device_token_1}; + EXPECT_FALSE(ble_advertisement_1.IsValid()); + + BleAdvertisement ble_advertisement_2{kVersion, + kSocketVersion, + service_id_hash, + data, + bad_device_token_2}; + EXPECT_FALSE(ble_advertisement_2.IsValid()); + + BleAdvertisement fast_ble_advertisement_1{kVersion, + kSocketVersion, + data, + bad_device_token_1}; + EXPECT_FALSE(fast_ble_advertisement_1.IsValid()); + + BleAdvertisement fast_ble_advertisement_2{kVersion, + kSocketVersion, + data, + bad_device_token_2}; + EXPECT_FALSE(fast_ble_advertisement_2.IsValid()); +} + +TEST(BleAdvertisementTest, ConstructionFromSerializedBytesWorks) { + ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; + ByteArray data{std::string(kData)}; + ByteArray device_token{std::string(kDeviceToken)}; + + BleAdvertisement org_ble_advertisement{kVersion, + kSocketVersion, + service_id_hash, + data, + device_token}; + + ByteArray ble_advertisement_bytes{org_ble_advertisement}; + BleAdvertisement ble_advertisement{ble_advertisement_bytes}; + + EXPECT_TRUE(ble_advertisement.IsValid()); + EXPECT_FALSE(ble_advertisement.IsFastAdvertisement()); + EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); + EXPECT_EQ(kSocketVersion, ble_advertisement.GetSocketVersion()); + EXPECT_EQ(service_id_hash, ble_advertisement.GetServiceIdHash()); + EXPECT_EQ(data.size(), ble_advertisement.GetData().size()); + EXPECT_EQ(data, ble_advertisement.GetData()); + EXPECT_EQ(device_token, ble_advertisement.GetDeviceToken()); +} + +TEST(BleAdvertisementTest, + ConstructionFromSerializedBytesWorksForAdvertisement) { + ByteArray fast_data{std::string(kFastData)}; + ByteArray device_token{std::string(kDeviceToken)}; + + BleAdvertisement org_ble_advertisement{kVersion, + kSocketVersion, + fast_data, + device_token}; + + ByteArray ble_advertisement_bytes{org_ble_advertisement}; + BleAdvertisement ble_advertisement{ble_advertisement_bytes}; + + EXPECT_TRUE(ble_advertisement.IsValid()); + EXPECT_TRUE(ble_advertisement.IsFastAdvertisement()); + EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); + EXPECT_EQ(kSocketVersion, ble_advertisement.GetSocketVersion()); + EXPECT_EQ(fast_data.size(), ble_advertisement.GetData().size()); + EXPECT_EQ(fast_data, ble_advertisement.GetData()); + EXPECT_EQ(device_token, ble_advertisement.GetDeviceToken()); +} + +TEST(BleAdvertisementTest, ConstructionFromSerializedBytesWithEmptyDataWorks) { + ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; + ByteArray device_token{std::string(kDeviceToken)}; + + BleAdvertisement org_ble_advertisement{kVersion, + kSocketVersion, + service_id_hash, + ByteArray(), + device_token}; + ByteArray ble_advertisement_bytes{org_ble_advertisement}; + BleAdvertisement ble_advertisement{ble_advertisement_bytes}; + + EXPECT_TRUE(ble_advertisement.IsValid()); + EXPECT_FALSE(ble_advertisement.IsFastAdvertisement()); + EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); + EXPECT_EQ(kSocketVersion, ble_advertisement.GetSocketVersion()); + EXPECT_EQ(service_id_hash, ble_advertisement.GetServiceIdHash()); + EXPECT_TRUE(ble_advertisement.GetData().Empty()); + EXPECT_EQ(device_token, ble_advertisement.GetDeviceToken()); +} + +TEST(BleAdvertisementTest, + ConstructionFromSerializedBytesWithEmptyDataWorksForFastAdvertisement) { + ByteArray device_token{std::string(kDeviceToken)}; + + BleAdvertisement org_ble_advertisement{kVersion, + kSocketVersion, + ByteArray(), + device_token}; + ByteArray ble_advertisement_bytes{org_ble_advertisement}; + BleAdvertisement ble_advertisement{ble_advertisement_bytes}; + + EXPECT_TRUE(ble_advertisement.IsValid()); + EXPECT_TRUE(ble_advertisement.IsFastAdvertisement()); + EXPECT_EQ(kVersion, ble_advertisement.GetVersion()); + EXPECT_EQ(kSocketVersion, ble_advertisement.GetSocketVersion()); + EXPECT_TRUE(ble_advertisement.GetData().Empty()); + EXPECT_EQ(device_token, ble_advertisement.GetDeviceToken()); +} + +TEST(BleAdvertisementTest, ConstructionFromExtraSerializedBytesWorks) { + ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; + ByteArray data{std::string(kData)}; + ByteArray device_token{std::string(kDeviceToken)}; + + BleAdvertisement org_ble_advertisement{kVersion, + kSocketVersion, + service_id_hash, + data, + device_token}; + ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; + + // Copy the bytes into a new array with extra bytes. We must explicitly + // define how long our array is because we can't use variable length arrays. + char raw_ble_advertisement_bytes[kLongAdvertisementLength]{}; + memcpy(raw_ble_advertisement_bytes, org_ble_advertisement_bytes.data(), + std::min(sizeof(raw_ble_advertisement_bytes), + org_ble_advertisement_bytes.size())); + + // Re-parse the Ble advertisement using our extra long advertisement bytes. + ByteArray long_ble_advertisement_bytes{raw_ble_advertisement_bytes, + kLongAdvertisementLength}; + BleAdvertisement long_ble_advertisement{long_ble_advertisement_bytes}; + + EXPECT_TRUE(long_ble_advertisement.IsValid()); + EXPECT_FALSE(long_ble_advertisement.IsFastAdvertisement()); + EXPECT_EQ(kVersion, long_ble_advertisement.GetVersion()); + EXPECT_EQ(kSocketVersion, long_ble_advertisement.GetSocketVersion()); + EXPECT_EQ(service_id_hash, long_ble_advertisement.GetServiceIdHash()); + EXPECT_EQ(data.size(), long_ble_advertisement.GetData().size()); + EXPECT_EQ(data, long_ble_advertisement.GetData()); + EXPECT_EQ(device_token, long_ble_advertisement.GetDeviceToken()); +} + +TEST(BleAdvertisementTest, + ConstructionFromExtraSerializedBytesWorksForFastAdvertisement) { + ByteArray fast_data{std::string(kFastData)}; + ByteArray device_token{std::string(kDeviceToken)}; + + BleAdvertisement org_ble_advertisement{kVersion, + kSocketVersion, + fast_data, + device_token}; + ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; + + // Copy the bytes into a new array with extra bytes. We must explicitly + // define how long our array is because we can't use variable length arrays. + char raw_ble_advertisement_bytes[kLongAdvertisementLength]{}; + memcpy(raw_ble_advertisement_bytes, org_ble_advertisement_bytes.data(), + std::min(sizeof(raw_ble_advertisement_bytes), + org_ble_advertisement_bytes.size())); + + // Re-parse the Ble advertisement using our extra long advertisement bytes. + ByteArray long_ble_advertisement_bytes{raw_ble_advertisement_bytes, + kLongAdvertisementLength}; + BleAdvertisement long_ble_advertisement{long_ble_advertisement_bytes}; + + EXPECT_TRUE(long_ble_advertisement.IsValid()); + EXPECT_TRUE(long_ble_advertisement.IsFastAdvertisement()); + EXPECT_EQ(kVersion, long_ble_advertisement.GetVersion()); + EXPECT_EQ(kSocketVersion, long_ble_advertisement.GetSocketVersion()); + EXPECT_EQ(fast_data.size(), long_ble_advertisement.GetData().size()); + EXPECT_EQ(fast_data, long_ble_advertisement.GetData()); + EXPECT_EQ(device_token, long_ble_advertisement.GetDeviceToken()); +} + +TEST(BleAdvertisementTest, ConstructionFromNullBytesFails) { + BleAdvertisement ble_advertisement{ByteArray{}}; + + EXPECT_FALSE(ble_advertisement.IsValid()); +} + +TEST(BleAdvertisementTest, ConstructionFromShortLengthSerializedBytesFails) { + ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; + ByteArray data{std::string(kData)}; + ByteArray device_token{std::string(kDeviceToken)}; + + BleAdvertisement org_ble_advertisement{kVersion, + kSocketVersion, + service_id_hash, + data, + device_token}; + ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; + + // Cut off the advertisement so that it's too short. + ByteArray short_ble_advertisement_bytes{org_ble_advertisement_bytes.data(), + 7}; + BleAdvertisement short_ble_advertisement{short_ble_advertisement_bytes}; + + EXPECT_FALSE(short_ble_advertisement.IsValid()); +} + +TEST(BleAdvertisementTest, + ConstructionFromShortLengthSerializedBytesFailsForFastAdvertisement) { + ByteArray fast_data{std::string(kFastData)}; + ByteArray device_token{std::string(kDeviceToken)}; + + BleAdvertisement org_ble_advertisement{kVersion, + kSocketVersion, + fast_data, + device_token}; + ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; + + // Cut off the advertisement so that it's too short. + ByteArray short_ble_advertisement_bytes{org_ble_advertisement_bytes.data(), + 2}; + BleAdvertisement short_ble_advertisement{short_ble_advertisement_bytes}; + + EXPECT_FALSE(short_ble_advertisement.IsValid()); +} + +TEST(BleAdvertisementTest, + ConstructionFromSerializedBytesWithInvalidDataLengthFails) { + ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; + ByteArray data{std::string(kData)}; + ByteArray device_token{std::string(kDeviceToken)}; + + BleAdvertisement org_ble_advertisement{kVersion, + kSocketVersion, + service_id_hash, + data, + device_token}; + ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; + + // Corrupt the DATA_SIZE bits. Start by making a raw copy of the Ble + // advertisement bytes so we can modify it. We must explicitly define how + // long our array is because we can't use variable length arrays. + char raw_ble_advertisement_bytes[kAdvertisementLength]; + memcpy(raw_ble_advertisement_bytes, org_ble_advertisement_bytes.data(), + kAdvertisementLength); + + // The data size field lives in indices 4-7. Corrupt it. + memset(raw_ble_advertisement_bytes + 4, 0xFF, 4); + + // Try to parse the Ble advertisement using our corrupted advertisement bytes. + ByteArray corrupted_ble_advertisement_bytes{raw_ble_advertisement_bytes, + kAdvertisementLength}; + BleAdvertisement corrupted_ble_advertisement{ + corrupted_ble_advertisement_bytes}; + + EXPECT_FALSE(corrupted_ble_advertisement.IsValid()); +} + +TEST(BleAdvertisementTest, + ConstructionFromSerializedBytesWithInvalidDataLengthFails2) { + ByteArray fast_data{std::string(kFastData)}; + ByteArray device_token{std::string(kDeviceToken)}; + + BleAdvertisement org_ble_advertisement{kVersion, + kSocketVersion, + fast_data, + device_token}; + ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; + + // Corrupt the DATA_SIZE bits. Start by making a raw copy of the Ble + // advertisement bytes so we can modify it. We must explicitly define how + // long our array is because we can't use variable length arrays. + char raw_ble_advertisement_bytes[kFastAdvertisementLength]; + memcpy(raw_ble_advertisement_bytes, org_ble_advertisement_bytes.data(), + kFastAdvertisementLength); + + // The data size field lives in index 1. Corrupt it. + memset(raw_ble_advertisement_bytes + 1, 0xFF, 1); + + // Try to parse the Ble advertisement using our corrupted advertisement bytes. + ByteArray corrupted_ble_advertisement_bytes{raw_ble_advertisement_bytes, + kFastAdvertisementLength}; + BleAdvertisement corrupted_ble_advertisement{ + corrupted_ble_advertisement_bytes}; + + EXPECT_FALSE(corrupted_ble_advertisement.IsValid()); +} + +} // namespace +} // namespace mediums +} // namespace connections +} // namespace nearby +} // namespace location diff --git a/cpp/core_v2/internal/mediums/ble_packet.cc b/cpp/core_v2/internal/mediums/ble_v2/ble_packet.cc similarity index 96% rename from cpp/core_v2/internal/mediums/ble_packet.cc rename to cpp/core_v2/internal/mediums/ble_v2/ble_packet.cc index bd05ab8d..c98d7c38 100644 --- a/cpp/core_v2/internal/mediums/ble_packet.cc +++ b/cpp/core_v2/internal/mediums/ble_v2/ble_packet.cc @@ -1,4 +1,4 @@ -#include "core_v2/internal/mediums/ble_packet.h" +#include "core_v2/internal/mediums/ble_v2/ble_packet.h" #include "platform_v2/base/base_input_stream.h" #include "platform_v2/public/logging.h" diff --git a/cpp/core_v2/internal/mediums/ble_packet.h b/cpp/core_v2/internal/mediums/ble_v2/ble_packet.h similarity index 88% rename from cpp/core_v2/internal/mediums/ble_packet.h rename to cpp/core_v2/internal/mediums/ble_v2/ble_packet.h index bbdae131..1e7172ae 100644 --- a/cpp/core_v2/internal/mediums/ble_packet.h +++ b/cpp/core_v2/internal/mediums/ble_v2/ble_packet.h @@ -1,5 +1,5 @@ -#ifndef CORE_V2_INTERNAL_MEDIUMS_BLE_PACKET_H_ -#define CORE_V2_INTERNAL_MEDIUMS_BLE_PACKET_H_ +#ifndef CORE_V2_INTERNAL_MEDIUMS_BLE_V2_BLE_PACKET_H_ +#define CORE_V2_INTERNAL_MEDIUMS_BLE_V2_BLE_PACKET_H_ #include @@ -47,4 +47,4 @@ class BlePacket { } // namespace nearby } // namespace location -#endif // CORE_V2_INTERNAL_MEDIUMS_BLE_PACKET_H_ +#endif // CORE_V2_INTERNAL_MEDIUMS_BLE_V2_BLE_PACKET_H_ diff --git a/cpp/core_v2/internal/mediums/ble_packet_test.cc b/cpp/core_v2/internal/mediums/ble_v2/ble_packet_test.cc similarity index 97% rename from cpp/core_v2/internal/mediums/ble_packet_test.cc rename to cpp/core_v2/internal/mediums/ble_v2/ble_packet_test.cc index 6df5b07d..9b0f6a99 100644 --- a/cpp/core_v2/internal/mediums/ble_packet_test.cc +++ b/cpp/core_v2/internal/mediums/ble_v2/ble_packet_test.cc @@ -1,4 +1,4 @@ -#include "core_v2/internal/mediums/ble_packet.h" +#include "core_v2/internal/mediums/ble_v2/ble_packet.h" #include "gtest/gtest.h" diff --git a/cpp/core_v2/internal/mediums/ble_peripheral.h b/cpp/core_v2/internal/mediums/ble_v2/ble_peripheral.h similarity index 82% rename from cpp/core_v2/internal/mediums/ble_peripheral.h rename to cpp/core_v2/internal/mediums/ble_v2/ble_peripheral.h index 520b93ca..e144489f 100644 --- a/cpp/core_v2/internal/mediums/ble_peripheral.h +++ b/cpp/core_v2/internal/mediums/ble_v2/ble_peripheral.h @@ -1,5 +1,5 @@ -#ifndef CORE_V2_INTERNAL_MEDIUMS_BLE_PERIPHERAL_H_ -#define CORE_V2_INTERNAL_MEDIUMS_BLE_PERIPHERAL_H_ +#ifndef CORE_V2_INTERNAL_MEDIUMS_BLE_V2_BLE_PERIPHERAL_H_ +#define CORE_V2_INTERNAL_MEDIUMS_BLE_V2_BLE_PERIPHERAL_H_ #include "platform_v2/base/byte_array.h" @@ -32,4 +32,4 @@ class BlePeripheral { } // namespace nearby } // namespace location -#endif // CORE_V2_INTERNAL_MEDIUMS_BLE_PERIPHERAL_H_ +#endif // CORE_V2_INTERNAL_MEDIUMS_BLE_V2_BLE_PERIPHERAL_H_ diff --git a/cpp/core_v2/internal/mediums/ble_peripheral_test.cc b/cpp/core_v2/internal/mediums/ble_v2/ble_peripheral_test.cc similarity index 91% rename from cpp/core_v2/internal/mediums/ble_peripheral_test.cc rename to cpp/core_v2/internal/mediums/ble_v2/ble_peripheral_test.cc index b3aba76f..59a06260 100644 --- a/cpp/core_v2/internal/mediums/ble_peripheral_test.cc +++ b/cpp/core_v2/internal/mediums/ble_v2/ble_peripheral_test.cc @@ -1,4 +1,4 @@ -#include "core_v2/internal/mediums/ble_peripheral.h" +#include "core_v2/internal/mediums/ble_v2/ble_peripheral.h" #include "gtest/gtest.h" diff --git a/cpp/core_v2/internal/mediums/ble_v2/discovered_peripheral_callback.h b/cpp/core_v2/internal/mediums/ble_v2/discovered_peripheral_callback.h new file mode 100644 index 00000000..92b63adf --- /dev/null +++ b/cpp/core_v2/internal/mediums/ble_v2/discovered_peripheral_callback.h @@ -0,0 +1,31 @@ +#ifndef CORE_V2_INTERNAL_MEDIUMS_BLE_V2_DISCOVERED_PERIPHERAL_CALLBACK_H_ +#define CORE_V2_INTERNAL_MEDIUMS_BLE_V2_DISCOVERED_PERIPHERAL_CALLBACK_H_ + +#include "core_v2/internal/mediums/ble_v2/ble_peripheral.h" +#include "core_v2/listeners.h" +#include "platform_v2/base/byte_array.h" + +namespace location { +namespace nearby { +namespace connections { +namespace mediums { + +/** Callback that is invoked when a {@link BlePeripheral} is discovered. */ +struct DiscoveredPeripheralCallback { + std::function + peripheral_discovered_cb = + DefaultCallback(); + std::function + peripheral_lost_cb = + DefaultCallback(); +}; + +} // namespace mediums +} // namespace connections +} // namespace nearby +} // namespace location + +#endif // CORE_V2_INTERNAL_MEDIUMS_BLE_V2_DISCOVERED_PERIPHERAL_CALLBACK_H_ diff --git a/cpp/core_v2/internal/mediums/utils.cc b/cpp/core_v2/internal/mediums/utils.cc index 6785345a..33b141ac 100644 --- a/cpp/core_v2/internal/mediums/utils.cc +++ b/cpp/core_v2/internal/mediums/utils.cc @@ -31,8 +31,12 @@ ByteArray Utils::GenerateRandomBytes(size_t length) { } ByteArray Utils::Sha256Hash(const ByteArray& source, size_t length) { + return Utils::Sha256Hash(std::string(source), length); +} + +ByteArray Utils::Sha256Hash(const std::string& source, size_t length) { ByteArray full_hash(length); - full_hash.CopyAt(0, Crypto::Sha256(std::string(source))); + full_hash.CopyAt(0, Crypto::Sha256(source)); return full_hash; } diff --git a/cpp/core_v2/internal/mediums/utils.h b/cpp/core_v2/internal/mediums/utils.h index 7234a897..4804c31c 100644 --- a/cpp/core_v2/internal/mediums/utils.h +++ b/cpp/core_v2/internal/mediums/utils.h @@ -13,6 +13,7 @@ class Utils { public: static ByteArray GenerateRandomBytes(size_t length); static ByteArray Sha256Hash(const ByteArray& source, size_t length); + static ByteArray Sha256Hash(const std::string& source, size_t length); }; } // namespace connections diff --git a/cpp/core_v2/internal/mediums/webrtc.cc b/cpp/core_v2/internal/mediums/webrtc.cc index 4b9510c7..ba498346 100644 --- a/cpp/core_v2/internal/mediums/webrtc.cc +++ b/cpp/core_v2/internal/mediums/webrtc.cc @@ -248,6 +248,9 @@ bool WebRtc::InitWebRtcFlow(Role role, const PeerId& self_id) { connection_flow_ = ConnectionFlow::Create(GetLocalIceCandidateListener(), GetDataChannelListener(), medium_); + if (!connection_flow_) + return false; + return true; } diff --git a/cpp/core_v2/internal/mediums/webrtc.h b/cpp/core_v2/internal/mediums/webrtc.h index 1322b5bb..4c09e319 100644 --- a/cpp/core_v2/internal/mediums/webrtc.h +++ b/cpp/core_v2/internal/mediums/webrtc.h @@ -10,14 +10,14 @@ #include "core_v2/internal/mediums/webrtc/peer_id.h" #include "core_v2/internal/mediums/webrtc/webrtc_socket.h" #include "core_v2/internal/mediums/webrtc/webrtc_socket_wrapper.h" -#include "platform_v2/public/cancelable_alarm.h" -#include "platform_v2/public/scheduled_executor.h" #include "platform_v2/base/byte_array.h" #include "platform_v2/base/listeners.h" #include "platform_v2/base/runnable.h" #include "platform_v2/public/atomic_boolean.h" +#include "platform_v2/public/cancelable_alarm.h" #include "platform_v2/public/future.h" #include "platform_v2/public/mutex.h" +#include "platform_v2/public/scheduled_executor.h" #include "platform_v2/public/single_thread_executor.h" #include "platform_v2/public/webrtc.h" #include "location/nearby/mediums/proto/web_rtc_signaling_frames.pb.h" diff --git a/cpp/core_v2/internal/mediums/webrtc/connection_flow.cc b/cpp/core_v2/internal/mediums/webrtc/connection_flow.cc index 401cb0dc..3cb4e4ca 100644 --- a/cpp/core_v2/internal/mediums/webrtc/connection_flow.cc +++ b/cpp/core_v2/internal/mediums/webrtc/connection_flow.cc @@ -235,6 +235,11 @@ bool ConnectionFlow::InitPeerConnection(WebRtcMedium& webrtc_medium) { &peer_connection_observer_, [this, &success_future]( rtc::scoped_refptr peer_connection) { + if (!peer_connection) { + success_future.Set(false); + return; + } + peer_connection_ = peer_connection; success_future.Set(true); }); @@ -324,7 +329,9 @@ bool ConnectionFlow::CloseLocked() { state_ = State::kEnded; data_channel_future_.SetException({Exception::kInterrupted}); - peer_connection_->Close(); + if (peer_connection_) + peer_connection_->Close(); + data_channel_observer_.reset(); NEARBY_LOG(INFO, "Closed WebRTC connection."); return true; diff --git a/cpp/core_v2/internal/mediums/webrtc/connection_flow_test.cc b/cpp/core_v2/internal/mediums/webrtc/connection_flow_test.cc index 7a3a859c..c9767dff 100644 --- a/cpp/core_v2/internal/mediums/webrtc/connection_flow_test.cc +++ b/cpp/core_v2/internal/mediums/webrtc/connection_flow_test.cc @@ -184,6 +184,16 @@ TEST_F(ConnectionFlowTest, CannotReceiveOfferAfterClose) { EXPECT_FALSE(answerer->OnOfferReceived(offer)); } +TEST_F(ConnectionFlowTest, NullPeerConnection) { + MediumEnvironment::Instance().SetUseValidPeerConnection( + /*use_valid_peer_connection=*/false); + + WebRtcMedium medium; + std::unique_ptr answerer = ConnectionFlow::Create( + LocalIceCandidateListener(), DataChannelListener(), medium); + EXPECT_EQ(answerer, nullptr); +} + } // namespace } // namespace mediums } // namespace connections diff --git a/cpp/core_v2/internal/mediums/webrtc_test.cc b/cpp/core_v2/internal/mediums/webrtc_test.cc index 6e450e3d..749f21c1 100644 --- a/cpp/core_v2/internal/mediums/webrtc_test.cc +++ b/cpp/core_v2/internal/mediums/webrtc_test.cc @@ -233,6 +233,38 @@ TEST_F(WebRtcTest, ConnectBothDevices_ShutdownSignaling_SendData) { EXPECT_EQ(message, received_msg.result()); } +TEST_F(WebRtcTest, StartAcceptingConnections_NullPeerConnection) { + using MockAcceptedCallback = + testing::MockFunction; + testing::StrictMock mock_accepted_callback_; + + MediumEnvironment::Instance().SetUseValidPeerConnection( + /*use_valid_peer_connection=*/false); + + WebRtc webrtc; + PeerId self_id("peer_id"); + + ASSERT_TRUE(webrtc.IsAvailable()); + EXPECT_FALSE(webrtc.StartAcceptingConnections( + self_id, {mock_accepted_callback_.AsStdFunction()})); +} + +TEST_F(WebRtcTest, Connect_NullPeerConnection) { + using MockAcceptedCallback = + testing::MockFunction; + testing::StrictMock mock_accepted_callback_; + + MediumEnvironment::Instance().SetUseValidPeerConnection( + /*use_valid_peer_connection=*/false); + + WebRtc webrtc; + PeerId self_id("peer_id"); + + ASSERT_TRUE(webrtc.IsAvailable()); + WebRtcSocketWrapper wrapper = webrtc.Connect(PeerId("random_peer_id")); + EXPECT_FALSE(wrapper.IsValid()); +} + } // namespace } // namespace mediums diff --git a/cpp/core_v2/internal/p2p_cluster_pcp_handler.cc b/cpp/core_v2/internal/p2p_cluster_pcp_handler.cc index ad7c8bc3..d0154914 100644 --- a/cpp/core_v2/internal/p2p_cluster_pcp_handler.cc +++ b/cpp/core_v2/internal/p2p_cluster_pcp_handler.cc @@ -4,6 +4,7 @@ #include "core_v2/internal/ble_advertisement.h" #include "core_v2/internal/ble_endpoint_channel.h" #include "core_v2/internal/bluetooth_endpoint_channel.h" +#include "core_v2/internal/mediums/utils.h" #include "core_v2/internal/mediums/webrtc/webrtc_socket_wrapper.h" #include "core_v2/internal/webrtc_endpoint_channel.h" #include "core_v2/internal/wifi_lan_endpoint_channel.h" @@ -19,10 +20,7 @@ namespace connections { ByteArray P2pClusterPcpHandler::GenerateHash(const std::string& source, size_t size) { - ByteArray full_hash = Crypto::Sha256(source); - ByteArray result(size); - result.CopyAt(0, full_hash); - return result; + return Utils::Sha256Hash(source, size); } P2pClusterPcpHandler::P2pClusterPcpHandler( @@ -103,10 +101,8 @@ BasePcpHandler::StartOperationResult P2pClusterPcpHandler::StartAdvertisingImpl( } if (options.allowed.ble) { - const ByteArray ble_hash = - GenerateHash(service_id, BleAdvertisement::kServiceIdHashLength); proto::connections::Medium ble_medium = StartBleAdvertising( - client, service_id, ble_hash, local_endpoint_id, local_endpoint_info); + client, service_id, local_endpoint_id, local_endpoint_info, options); if (ble_medium != proto::connections::UNKNOWN_MEDIUM) { NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartAdvertisingImpl: Ble added"); mediums_started_successfully.push_back(ble_medium); @@ -264,12 +260,12 @@ bool P2pClusterPcpHandler::IsRecognizedBleEndpoint( return false; } - if (advertisement.GetVersion() != BleAdvertisement::Version::kV1) { + if (advertisement.GetVersion() != kBleAdvertisementVersion) { NEARBY_LOG( INFO, "P2pClusterPcpHandler::IsRecognizedBluetoothEndpoint: Version is " "not matched; advertisement.Version=%d, Version=%d", - advertisement.GetVersion(), BleAdvertisement::Version::kV1); + advertisement.GetVersion(), kBleAdvertisementVersion); return false; } @@ -281,17 +277,21 @@ bool P2pClusterPcpHandler::IsRecognizedBleEndpoint( return false; } - ByteArray expected_service_id_hash = - GenerateHash(service_id, BluetoothDeviceName::kServiceIdHashLength); + // Check ServiceId for normal advertisement. + // ServiceIdHash is empty for fast advertisement. + if (!advertisement.IsFastAdvertisement()) { + ByteArray expected_service_id_hash = + GenerateHash(service_id, BleAdvertisement::kServiceIdHashLength); - if (advertisement.GetServiceIdHash() != expected_service_id_hash) { - NEARBY_LOG(INFO, - "P2pClusterPcpHandler::IsRecognizedBleEndpoint: service " - "id hash is " - "not matched; advertisement.service_id_hash=%s, expected=%s", - advertisement.GetServiceIdHash().data(), - expected_service_id_hash.data()); - return false; + if (advertisement.GetServiceIdHash() != expected_service_id_hash) { + NEARBY_LOG(INFO, + "P2pClusterPcpHandler::IsRecognizedBleEndpoint: service " + "id hash is " + "not matched; advertisement.service_id_hash=%s, expected=%s", + advertisement.GetServiceIdHash().data(), + expected_service_id_hash.data()); + return false; + } } return true; @@ -299,8 +299,9 @@ bool P2pClusterPcpHandler::IsRecognizedBleEndpoint( void P2pClusterPcpHandler::BlePeripheralDiscoveredHandler( ClientProxy* client, BlePeripheral& peripheral, - const std::string& service_id) { - RunOnPcpHandlerThread([this, client, service_id, &peripheral]() { + const std::string& service_id, bool fast_advertisement) { + RunOnPcpHandlerThread([this, client, &peripheral, service_id, + fast_advertisement]() { // Make sure we are still discovering before proceeding. if (!client->IsDiscovering()) { NEARBY_LOG(INFO, @@ -312,7 +313,7 @@ void P2pClusterPcpHandler::BlePeripheralDiscoveredHandler( // Parse the Ble advertisement bytes. BleAdvertisement advertisement( - /*fast_advertisement=*/false, + fast_advertisement, peripheral.GetAdvertisementBytes(service_id)); // Make sure the Ble advertisement points to a valid @@ -341,6 +342,8 @@ void P2pClusterPcpHandler::BlePeripheralDiscoveredHandler( }, peripheral, })); + + // TODO(b/156632928): Check for Bluetooth device with remote mac address. }); } @@ -671,8 +674,8 @@ proto::connections::Medium P2pClusterPcpHandler::StartBluetoothAdvertising( absl::BytesToHexString(local_endpoint_info.data()).c_str()); // Generate a BluetoothDeviceName with which to become Bluetooth discoverable. std::string device_name(BluetoothDeviceName( - BluetoothDeviceName::Version::kV1, GetPcp(), local_endpoint_id, - service_id_hash, local_endpoint_info)); + kBluetoothDeviceNameVersion, GetPcp(), local_endpoint_id, service_id_hash, + local_endpoint_info)); if (device_name.empty()) { NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartBluetoothAdvertising: generate " @@ -747,8 +750,10 @@ BasePcpHandler::ConnectImplResult P2pClusterPcpHandler::BluetoothConnectImpl( proto::connections::Medium P2pClusterPcpHandler::StartBleAdvertising( ClientProxy* client, const std::string& service_id, - const ByteArray& service_id_hash, const std::string& local_endpoint_id, - const ByteArray& local_endpoint_info) { + const std::string& local_endpoint_id, const ByteArray& local_endpoint_info, + const ConnectionOptions& options) { + bool fast_advertisement = !options.fast_advertisement_service_uuid.empty(); + // Start listening for connections before advertising in case a connection // request comes in very quickly. NEARBY_LOGS(INFO) << "P2pClusterPcpHandler::StartBleAdvertising: service_id=" @@ -792,19 +797,30 @@ proto::connections::Medium P2pClusterPcpHandler::StartBleAdvertising( << service_id; return proto::connections::UNKNOWN_MEDIUM; } + // TODO(b/156632928): Should check for Bluetooth connection here NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartBleAdvertising: service=%s: " - "make advertisement; id=%s, hash=%s, name=%s", + "make advertisement; id=%s, name=%s", service_id.c_str(), local_endpoint_id.c_str(), - std::string(service_id_hash).c_str(), std::string(local_endpoint_info).c_str()); - // Generate a BleAdvertisement with which to become Ble discoverable. - // TODO(edwinwu): Add a bluetooth_adapter method to get the mac address. - std::string bluetooth_mac_address; - ByteArray advertisement_bytes(BleAdvertisement( - BleAdvertisement::Version::kV1, GetPcp(), service_id_hash, - local_endpoint_id, local_endpoint_info, bluetooth_mac_address)); + // Generate a BleAdvertisement. If a fast advertisement service UUID was + // provided, create a fast BleAdvertisement. + ByteArray advertisement_bytes; + if (fast_advertisement) { + advertisement_bytes = + ByteArray(BleAdvertisement(kBleAdvertisementVersion, GetPcp(), + local_endpoint_id, local_endpoint_info)); + } else { + const ByteArray service_id_hash = + GenerateHash(service_id, BleAdvertisement::kServiceIdHashLength); + // TODO(b/156632928): Should advertise Bluetooth MacAddress Over Ble + std::string bluetooth_mac_address; + + advertisement_bytes = ByteArray(BleAdvertisement( + kBleAdvertisementVersion, GetPcp(), service_id_hash, local_endpoint_id, + local_endpoint_info, bluetooth_mac_address)); + } if (advertisement_bytes.Empty()) { NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartBleAdvertising: generate " @@ -922,8 +938,8 @@ proto::connections::Medium P2pClusterPcpHandler::StartWifiLanAdvertising( absl::BytesToHexString(local_endpoint_info.data()).c_str()); // Generate a WifiLanServiceInfo with which to become WifiLan discoverable. std::string service_info_name(WifiLanServiceInfo( - WifiLanServiceInfo::Version::kV1, GetPcp(), local_endpoint_id, - service_id_hash, local_endpoint_info)); + kWifiLanServiceInfoVersion, GetPcp(), local_endpoint_id, service_id_hash, + local_endpoint_info)); if (service_info_name.empty()) { NEARBY_LOG(INFO, "P2pClusterPcpHandler::StartWifiLanAdvertising: generate " diff --git a/cpp/core_v2/internal/p2p_cluster_pcp_handler.h b/cpp/core_v2/internal/p2p_cluster_pcp_handler.h index a18be31f..b276a3f9 100644 --- a/cpp/core_v2/internal/p2p_cluster_pcp_handler.h +++ b/cpp/core_v2/internal/p2p_cluster_pcp_handler.h @@ -111,6 +111,8 @@ class P2pClusterPcpHandler : public BasePcpHandler { static constexpr BluetoothDeviceName::Version kBluetoothDeviceNameVersion = BluetoothDeviceName::Version::kV1; + static constexpr BleAdvertisement::Version kBleAdvertisementVersion = + BleAdvertisement::Version::kV1; static constexpr WifiLanServiceInfo::Version kWifiLanServiceInfoVersion = WifiLanServiceInfo::Version::kV1; @@ -143,13 +145,14 @@ class P2pClusterPcpHandler : public BasePcpHandler { const BleAdvertisement& advertisement) const; void BlePeripheralDiscoveredHandler(ClientProxy* client, BlePeripheral& peripheral, - const std::string& service_id); + const std::string& service_id, + bool fast_advertisement); void BlePeripheralLostHandler(ClientProxy* client, BlePeripheral& peripheral, const std::string& service_id); proto::connections::Medium StartBleAdvertising( ClientProxy* client, const std::string& service_id, - const ByteArray& service_id_hash, const std::string& local_endpoint_id, - const ByteArray& local_endpoint_info); + const std::string& local_endpoint_id, + const ByteArray& local_endpoint_info, const ConnectionOptions& options); proto::connections::Medium StartBleScanning( BleDiscoveredPeripheralCallback callback, ClientProxy* client, const std::string& service_id); diff --git a/cpp/core_v2/options.h b/cpp/core_v2/options.h index 9ee207ee..6e0b0a66 100644 --- a/cpp/core_v2/options.h +++ b/cpp/core_v2/options.h @@ -56,8 +56,8 @@ struct MediumSelector { // Mediums are sorted in order of decreasing preference. if (wifi_lan == value) mediums.push_back(Medium::WIFI_LAN); if (web_rtc == value) mediums.push_back(Medium::WEB_RTC); - if (ble == value) mediums.push_back(Medium::BLE); if (bluetooth == value) mediums.push_back(Medium::BLUETOOTH); + if (ble == value) mediums.push_back(Medium::BLE); return mediums; } }; @@ -73,6 +73,7 @@ struct ConnectionOptions { bool auto_upgrade_bandwidth; bool enforce_topology_constraints; ByteArray remote_bluetooth_mac_address; + std::string fast_advertisement_service_uuid; // Verify if ConnectionOptions is in a not-initialized (Empty) state. bool Empty() const { return strategy.IsNone(); } // Bring ConnectionOptions to a not-initialized (Empty) state. diff --git a/cpp/platform_v2/base/medium_environment.cc b/cpp/platform_v2/base/medium_environment.cc index 8687703e..3d8463be 100644 --- a/cpp/platform_v2/base/medium_environment.cc +++ b/cpp/platform_v2/base/medium_environment.cc @@ -160,7 +160,7 @@ api::BluetoothDevice* MediumEnvironment::FindBluetoothDevice( const std::string& mac_address) { api::BluetoothDevice* device = nullptr; CountDownLatch latch(1); - RunOnMediumEnvironmentThread([this, &device, &latch, &mac_address](){ + RunOnMediumEnvironmentThread([this, &device, &latch, &mac_address]() { for (auto& item : bluetooth_mediums_) { auto* adapter = item.second.adapter; if (!adapter) continue; @@ -306,85 +306,85 @@ void MediumEnvironment::UpdateBleMediumForAdvertising( api::BleMedium& medium, api::BlePeripheral& peripheral, const std::string& service_id, bool enabled) { if (!enabled_) return; - RunOnMediumEnvironmentThread([this, &medium, &peripheral, service_id, - enabled]() { - auto item = ble_mediums_.find(&medium); - if (item == ble_mediums_.end()) { - NEARBY_LOG(INFO, - "UpdateBleMediumForAdvertising failed. There is no medium " - "registered."); - return; - } - auto& context = item->second; - context.ble_peripheral = &peripheral; - context.advertising = enabled; - NEARBY_LOG(INFO, - "Update Ble medium for advertising: this=%p; medium=%p; " - "service_id=%s; name=%s; enabled=%d; ", - this, &medium, service_id.c_str(), peripheral.GetName().c_str(), - enabled); - for (auto& medium_info : ble_mediums_) { - auto& local_medium = medium_info.first; - auto& info = medium_info.second; - // Do not send notification to the same medium. - if (local_medium == &medium) continue; - OnBlePeripheralStateChanged(info, peripheral, service_id, enabled); - } - }); + RunOnMediumEnvironmentThread( + [this, &medium, &peripheral, service_id, enabled]() { + auto item = ble_mediums_.find(&medium); + if (item == ble_mediums_.end()) { + NEARBY_LOG(INFO, + "UpdateBleMediumForAdvertising failed. There is no medium " + "registered."); + return; + } + auto& context = item->second; + context.ble_peripheral = &peripheral; + context.advertising = enabled; + NEARBY_LOG(INFO, + "Update Ble medium for advertising: this=%p; medium=%p; " + "service_id=%s; name=%s; enabled=%d; ", + this, &medium, service_id.c_str(), + peripheral.GetName().c_str(), enabled); + for (auto& medium_info : ble_mediums_) { + auto& local_medium = medium_info.first; + auto& info = medium_info.second; + // Do not send notification to the same medium. + if (local_medium == &medium) continue; + OnBlePeripheralStateChanged(info, peripheral, service_id, enabled); + } + }); } void MediumEnvironment::UpdateBleMediumForScanning( api::BleMedium& medium, const std::string& service_id, BleDiscoveredPeripheralCallback callback, bool enabled) { if (!enabled_) return; - RunOnMediumEnvironmentThread([this, &medium, service_id, - callback = std::move(callback), enabled]() { - auto item = ble_mediums_.find(&medium); - if (item == ble_mediums_.end()) { - NEARBY_LOG(INFO, - "UpdateBleMediumFoScanning failed. There is no medium " - "registered."); - return; - } - auto& context = item->second; - context.discovery_callback = std::move(callback); - NEARBY_LOG(INFO, - "Update Ble medium for scanning: this=%p; medium=%p; " - "service_id=%s; enabled=%d ;", - this, &medium, service_id.c_str(), enabled); - for (auto& medium_info : ble_mediums_) { - auto& local_medium = medium_info.first; - auto& info = medium_info.second; - // Do not send notification to the same medium. - if (local_medium == &medium) continue; - // Search advertising mediums and send notification. - if (info.advertising && enabled) { - OnBlePeripheralStateChanged(context, *(info.ble_peripheral), service_id, - enabled); - } - } - }); + RunOnMediumEnvironmentThread( + [this, &medium, service_id, callback = std::move(callback), enabled]() { + auto item = ble_mediums_.find(&medium); + if (item == ble_mediums_.end()) { + NEARBY_LOG(INFO, + "UpdateBleMediumFoScanning failed. There is no medium " + "registered."); + return; + } + auto& context = item->second; + context.discovery_callback = std::move(callback); + NEARBY_LOG(INFO, + "Update Ble medium for scanning: this=%p; medium=%p; " + "service_id=%s; enabled=%d ;", + this, &medium, service_id.c_str(), enabled); + for (auto& medium_info : ble_mediums_) { + auto& local_medium = medium_info.first; + auto& info = medium_info.second; + // Do not send notification to the same medium. + if (local_medium == &medium) continue; + // Search advertising mediums and send notification. + if (info.advertising && enabled) { + OnBlePeripheralStateChanged(context, *(info.ble_peripheral), + service_id, enabled); + } + } + }); } void MediumEnvironment::UpdateBleMediumForAcceptedConnection( api::BleMedium& medium, const std::string& service_id, BleAcceptedConnectionCallback callback) { if (!enabled_) return; - RunOnMediumEnvironmentThread([this, &medium, service_id, - callback = std::move(callback)]() { - auto item = ble_mediums_.find(&medium); - if (item == ble_mediums_.end()) { - NEARBY_LOG( - INFO, "Update Ble medium failed. There is no medium registered."); - return; - } - auto& context = item->second; - context.accepted_connection_callback = std::move(callback); - NEARBY_LOG(INFO, - "Update Ble medium for accepted callback: this=%p; " - "medium=%p; service_id=%s; ", - this, &medium, service_id.c_str()); - }); + RunOnMediumEnvironmentThread( + [this, &medium, service_id, callback = std::move(callback)]() { + auto item = ble_mediums_.find(&medium); + if (item == ble_mediums_.end()) { + NEARBY_LOG( + INFO, "Update Ble medium failed. There is no medium registered."); + return; + } + auto& context = item->second; + context.accepted_connection_callback = std::move(callback); + NEARBY_LOG(INFO, + "Update Ble medium for accepted callback: this=%p; " + "medium=%p; service_id=%s; ", + this, &medium, service_id.c_str()); + }); } void MediumEnvironment::UnregisterBleMedium(api::BleMedium& medium) { @@ -451,6 +451,15 @@ void MediumEnvironment::SendWebRtcSignalingMessage(absl::string_view peer_id, }); } +void MediumEnvironment::SetUseValidPeerConnection( + bool use_valid_peer_connection) { + use_valid_peer_connection_ = use_valid_peer_connection; +} + +bool MediumEnvironment::GetUseValidPeerConnection() { + return use_valid_peer_connection_; +} + void MediumEnvironment::RegisterWifiLanMedium(api::WifiLanMedium& medium) { if (!enabled_) return; RunOnMediumEnvironmentThread([this, &medium]() { diff --git a/cpp/platform_v2/base/medium_environment.h b/cpp/platform_v2/base/medium_environment.h index a1a0f27e..f873d53d 100644 --- a/cpp/platform_v2/base/medium_environment.h +++ b/cpp/platform_v2/base/medium_environment.h @@ -124,6 +124,12 @@ class MediumEnvironment { void SendWebRtcSignalingMessage(absl::string_view peer_id, const ByteArray& message); + // Used to set if WebRtcMedium should use a valid peer connection or nullptr + // in tests. + void SetUseValidPeerConnection(bool use_valid_peer_connection); + + bool GetUseValidPeerConnection(); + // Adds medium-related info to allow for scanning/advertising to work. // This provides acccess to this medium from other mediums, when protocol // expects they should communicate. @@ -207,7 +213,7 @@ class MediumEnvironment { // Returns WiFi LAN service matching IP address and port, or nullptr. api::WifiLanService* FindWifiLanService(const std::string& ip_address, - int port); + int port); private: struct BluetoothMediumContext { @@ -280,6 +286,8 @@ class MediumEnvironment { absl::flat_hash_map wifi_lan_mediums_; + + bool use_valid_peer_connection_ = true; }; } // namespace nearby diff --git a/cpp/platform_v2/impl/g3/webrtc.cc b/cpp/platform_v2/impl/g3/webrtc.cc index 2d98544c..7dc16a2f 100644 --- a/cpp/platform_v2/impl/g3/webrtc.cc +++ b/cpp/platform_v2/impl/g3/webrtc.cc @@ -33,6 +33,12 @@ void WebRtcSignalingMessenger::StopReceivingMessages() { void WebRtcMedium::CreatePeerConnection( webrtc::PeerConnectionObserver* observer, PeerConnectionCallback callback) { + auto& env = MediumEnvironment::Instance(); + if (!env.GetUseValidPeerConnection()) { + callback(nullptr); + return; + } + webrtc::PeerConnectionInterface::RTCConfiguration rtc_config; webrtc::PeerConnectionDependencies dependencies(observer); diff --git a/cpp/platform_v2/public/ble.cc b/cpp/platform_v2/public/ble.cc index 7161eb7e..5c3207e5 100644 --- a/cpp/platform_v2/public/ble.cc +++ b/cpp/platform_v2/public/ble.cc @@ -46,7 +46,8 @@ bool BleMedium::StartScanning(const std::string& service_id, &context.peripheral, &peripheral, peripheral.GetName().c_str()); discovered_peripheral_callback_.peripheral_discovered_cb( - context.peripheral, service_id); + context.peripheral, service_id, + /*fast_advertisement=*/false); } }, .peripheral_lost_cb = diff --git a/cpp/platform_v2/public/ble.h b/cpp/platform_v2/public/ble.h index 5cb89f08..233b1abb 100644 --- a/cpp/platform_v2/public/ble.h +++ b/cpp/platform_v2/public/ble.h @@ -72,9 +72,10 @@ class BleMedium final { using Platform = api::ImplementationPlatform; struct DiscoveredPeripheralCallback { std::function + const std::string& service_id, + bool fast_advertisement)> peripheral_discovered_cb = - DefaultCallback(); + DefaultCallback(); std::function peripheral_lost_cb = diff --git a/cpp/platform_v2/public/ble_test.cc b/cpp/platform_v2/public/ble_test.cc index d1fcf653..0d4e2590 100644 --- a/cpp/platform_v2/public/ble_test.cc +++ b/cpp/platform_v2/public/ble_test.cc @@ -55,13 +55,13 @@ TEST_F(BleMediumTest, CanStartAdvertising) { ble_a.StartAdvertising(service_id, advertisement_bytes); EXPECT_TRUE(ble_b.StartScanning( - service_id, DiscoveredPeripheralCallback{ - .peripheral_discovered_cb = - [&found_latch](BlePeripheral& peripheral, - const std::string& service_id) { - found_latch.CountDown(); - }, - })); + service_id, + DiscoveredPeripheralCallback{ + .peripheral_discovered_cb = + [&found_latch]( + BlePeripheral& peripheral, const std::string& service_id, + bool fast_advertisement) { found_latch.CountDown(); }, + })); EXPECT_TRUE(found_latch.Await(kWaitDuration).result()); EXPECT_TRUE(ble_a.StopAdvertising(service_id)); EXPECT_TRUE(ble_b.StopScanning(service_id)); @@ -79,19 +79,19 @@ TEST_F(BleMediumTest, CanStartScanning) { CountDownLatch found_latch(1); CountDownLatch lost_latch(1); - ble_a.StartScanning(service_id, - DiscoveredPeripheralCallback{ - .peripheral_discovered_cb = - [&found_latch](BlePeripheral& peripheral, - const std::string& service_id) { - found_latch.CountDown(); - }, - .peripheral_lost_cb = - [&lost_latch](BlePeripheral& peripheral, - const std::string& service_id) { - lost_latch.CountDown(); - }, - }); + ble_a.StartScanning( + service_id, + DiscoveredPeripheralCallback{ + .peripheral_discovered_cb = + [&found_latch]( + BlePeripheral& peripheral, const std::string& service_id, + bool fast_advertisement) { found_latch.CountDown(); }, + .peripheral_lost_cb = + [&lost_latch](BlePeripheral& peripheral, + const std::string& service_id) { + lost_latch.CountDown(); + }, + }); EXPECT_TRUE(ble_b.StartAdvertising(service_id, advertisement_bytes)); EXPECT_TRUE(found_latch.Await(kWaitDuration).result()); EXPECT_TRUE(ble_b.StopAdvertising(service_id)); @@ -111,19 +111,19 @@ TEST_F(BleMediumTest, CanStopDiscovery) { CountDownLatch found_latch(1); CountDownLatch lost_latch(1); - ble_a.StartScanning(service_id, - DiscoveredPeripheralCallback{ - .peripheral_discovered_cb = - [&found_latch](BlePeripheral& peripheral, - const std::string& service_id) { - found_latch.CountDown(); - }, - .peripheral_lost_cb = - [&lost_latch](BlePeripheral& peripheral, - const std::string& service_id) { - lost_latch.CountDown(); - }, - }); + ble_a.StartScanning( + service_id, + DiscoveredPeripheralCallback{ + .peripheral_discovered_cb = + [&found_latch]( + BlePeripheral& peripheral, const std::string& service_id, + bool fast_advertisement) { found_latch.CountDown(); }, + .peripheral_lost_cb = + [&lost_latch](BlePeripheral& peripheral, + const std::string& service_id) { + lost_latch.CountDown(); + }, + }); EXPECT_TRUE(ble_b.StartAdvertising(service_id, advertisement_bytes)); EXPECT_TRUE(found_latch.Await(kWaitDuration).result()); EXPECT_TRUE(ble_a.StopScanning(service_id)); @@ -149,9 +149,13 @@ TEST_F(BleMediumTest, CanStartAcceptingConnectionsAndConnect) { DiscoveredPeripheralCallback{ .peripheral_discovered_cb = [&found_latch, &discovered_peripheral]( - BlePeripheral& peripheral, const std::string& service_id) { - NEARBY_LOG(INFO, "Peripheral discovered: %s, %p", - peripheral.GetName().c_str(), &peripheral); + BlePeripheral& peripheral, const std::string& service_id, + bool fast_advertisement) { + NEARBY_LOG( + INFO, + "Peripheral discovered: %s, %p, fast advertisement: %d", + peripheral.GetName().c_str(), &peripheral, + fast_advertisement); discovered_peripheral = &peripheral; found_latch.CountDown(); }, diff --git a/proto/error_code_enums.proto b/proto/error_code_enums.proto index 0eeb5080..1e94c48a 100644 --- a/proto/error_code_enums.proto +++ b/proto/error_code_enums.proto @@ -136,6 +136,20 @@ enum StartAdvertisingError { // Next ID :46 } +// The error for event START_ADVERTISING. The range between 31 and 99. +enum StopAdvertisingError { + // System error, failed to stop advertising. + STOP_ADVERTISING_FAILED = 31; + // System error, failed to modify the Bluetooth name. + RESTORE_BLUETOOTH_NAME_FAILED = 32; + // System error, failed to stop advertising for BLE legacy advertisements. + STOP_LEGACY_ADVERTISING_FAILED = 33; + // System error, failed to stop advertising for BLE extended advertisements. + STOP_EXTENDED_ADVERTISING_FAILED = 34; + + // Next ID :35 +} + // The error for event START_DISCOVERING. The range between 31 and 99. enum StartDiscoveringError { // Developing error, this service ID already requested, should not request it @@ -184,6 +198,11 @@ enum StartListeningIncomingConnectionError { // Network error, wait the GATT connection ready after the connection // established but never. CREATE_GATT_SERVER_SOCKET_NOT_READY = 35; + // System error, failed to accept the incoming connection + ACCEPT_CONNECTION_FAILED = 36; + // System error, failed to create a server socket for listening incoming + // connection. + CREATE_SERVER_SOCKET_FAILED = 37; // Next ID :36 } @@ -366,4 +385,15 @@ enum Description { WITHOUT_PSM_VALUE = 130; SOCKET_BIND_LISTEN_FAILED = 131; UNEXPECTED_PACKET_CONTENT = 132; + UNREGISTER_NSD_MANAGER_FAILED = 133; + PUBLISH_EMPTY_ADVERTISEMENT_FAILED = 134; + BLUETOOTH_SOCKET_NOT_IN_LISTENING_STATE = 135; + INVALID_BLUETOOTH_SOCKET_SIGNAL_SIZE = 136; + INVALID_BLUETOOTH_SOCKET_SIGNAL_STATUS = 137; + GET_ADDRESS_FAILED = 138; + NULL_LOCAL_ADDRESS = 139; + IS_LOOPBACK_ADDRESS = 140; + SOCKET_NOT_BOUND = 141; + INVALID_REMOTE_ADDRESS = 142; + SOCKET_ALREADY_BOUND = 143; }