diff --git a/connections/implementation/mediums/ble_v2.cc b/connections/implementation/mediums/ble_v2.cc index b6cef336..7893d6d6 100644 --- a/connections/implementation/mediums/ble_v2.cc +++ b/connections/implementation/mediums/ble_v2.cc @@ -100,9 +100,9 @@ bool BleV2::StartAdvertising( ByteArray medium_advertisement_bytes{mediums::BleAdvertisement{ mediums::BleAdvertisement::Version::kV2, mediums::BleAdvertisement::SocketVersion::kV2, - /* service_id_hash= */ - is_fast_advertisement ? ByteArray{} : service_id_hash, - advertisement_bytes, mediums::bleutils::GenerateDeviceToken()}}; + /*service_id_hash=*/is_fast_advertisement ? ByteArray{} : service_id_hash, + advertisement_bytes, mediums::bleutils::GenerateDeviceToken(), + mediums::BleAdvertisementHeader::kDefaultPsmValue}}; if (medium_advertisement_bytes.Empty()) { NEARBY_LOGS(INFO) << "Failed to BLE advertise because we could not wrap a " "connection advertisement to medium advertisement."; @@ -443,7 +443,7 @@ ByteArray BleV2::CreateAdvertisementHeader() { mediums::BloomFilter bloom_filter( std::make_unique>()); + mediums::BleAdvertisementHeader::kServiceIdBloomFilterByteLength>>()); bloom_filter.Add(dummy_service_id); ByteArray advertisement_hash = diff --git a/connections/implementation/mediums/ble_v2/ble_advertisement.cc b/connections/implementation/mediums/ble_v2/ble_advertisement.cc index 50608b14..885b7713 100644 --- a/connections/implementation/mediums/ble_v2/ble_advertisement.cc +++ b/connections/implementation/mediums/ble_v2/ble_advertisement.cc @@ -16,7 +16,11 @@ #include +#include +#include + #include "absl/strings/str_cat.h" +#include "connections/implementation/mediums/ble_v2/ble_advertisement_header.h" #include "internal/platform/base_input_stream.h" #include "internal/platform/logging.h" @@ -29,16 +33,16 @@ BleAdvertisement::BleAdvertisement(Version version, SocketVersion socket_version, const ByteArray &service_id_hash, const ByteArray &data, - const ByteArray &device_token) { + const ByteArray &device_token, int psm) { DoInitialize(/*fast_advertisement=*/service_id_hash.Empty(), version, - socket_version, service_id_hash, data, device_token); + socket_version, service_id_hash, data, device_token, psm); } void BleAdvertisement::DoInitialize(bool fast_advertisement, Version version, SocketVersion socket_version, const ByteArray &service_id_hash, const ByteArray &data, - const ByteArray &device_token) { + const ByteArray &device_token, int psm) { // Check that the given input is valid. fast_advertisement_ = fast_advertisement; if (!fast_advertisement_) { @@ -64,6 +68,7 @@ void BleAdvertisement::DoInitialize(bool fast_advertisement, Version version, if (!fast_advertisement_) service_id_hash_ = service_id_hash; data_ = data; device_token_ = device_token; + psm_ = psm; } BleAdvertisement::BleAdvertisement(const ByteArray &ble_advertisement_bytes) { @@ -149,6 +154,20 @@ BleAdvertisement::BleAdvertisement(const ByteArray &ble_advertisement_bytes) { // then read it. if (base_input_stream.IsAvailable(kDeviceTokenLength)) { device_token_ = base_input_stream.ReadBytes(kDeviceTokenLength); + } else { + // No device token no more optional field. + return; + } + + // Extra fields, for backward compatible reason, put this field in the end of + // this advertisement. That means it must support device token if there's any + // extra field. E.g. If iOS or other platform wants to use extra fields, need + // to put a random or empty device token in the advertisement. + // TODO(b/219939733): Implement BleExtraField to read the PSM value. We fake + // this extra field as uint16, 2 bytes. + if (base_input_stream.IsAvailable( + BleAdvertisementHeader::kPsmValueByteLength)) { + psm_ = static_cast(base_input_stream.ReadUint16()); } } @@ -173,6 +192,10 @@ BleAdvertisement::operator ByteArray() const { SerializeDataSize(fast_advertisement_, data_size_bytes_write_ptr, data_.size()); + // For Extra fields, there's no space for legacy fast advertisement, use + // ByteArrayWithExtraField() to get the new advertisement bytes for extended + // advertising. + // clang-format on if (fast_advertisement_) { std::string out = @@ -189,13 +212,27 @@ BleAdvertisement::operator ByteArray() const { // clang-format on } +ByteArray BleAdvertisement::ByteArrayWithExtraField() const { + ByteArray advertisement_bytes = ByteArray(*this); + // TODO(b/219939733): Implement BleExtraField for PSM value. + ByteArray psm_byte{BleAdvertisementHeader::kPsmValueByteLength}; + char *data = psm_byte.data(); + data[0] = psm_ & 0xFF00; + data[1] = psm_ & 0x00FF; + std::string advertisement_with_extra_bytes = + absl::StrCat(std::string(advertisement_bytes), std::string(psm_byte)); + + return ByteArray(std::move(advertisement_with_extra_bytes)); +} + bool BleAdvertisement::operator==(const BleAdvertisement &rhs) const { return this->GetVersion() == rhs.GetVersion() && this->GetSocketVersion() == rhs.GetSocketVersion() && this->IsFastAdvertisement() == rhs.IsFastAdvertisement() && this->GetServiceIdHash() == rhs.GetServiceIdHash() && this->GetData() == rhs.GetData() && - this->GetDeviceToken() == rhs.GetDeviceToken(); + this->GetDeviceToken() == rhs.GetDeviceToken() && + this->GetPsm() == rhs.GetPsm(); } bool BleAdvertisement::IsSupportedVersion(Version version) const { diff --git a/connections/implementation/mediums/ble_v2/ble_advertisement.h b/connections/implementation/mediums/ble_v2/ble_advertisement.h index 92c04a2e..6a4b4b39 100644 --- a/connections/implementation/mediums/ble_v2/ble_advertisement.h +++ b/connections/implementation/mediums/ble_v2/ble_advertisement.h @@ -17,6 +17,7 @@ #include +#include "connections/implementation/mediums/ble_v2/ble_advertisement_header.h" #include "internal/platform/byte_array.h" namespace location { @@ -27,11 +28,13 @@ namespace mediums { // Represents the format of the Mediums BLE Advertisement used in Advertising + // Discovery. // -// [VERSION][SOCKET_VERSION][FAST_ADVERTISEMENT_FLAG][1_RESERVED_BIT][SERVICE_ID_HASH][DATA_SIZE][DATA][DEVICE_TOKEN] +// [VERSION][SOCKET_VERSION][FAST_ADVERTISEMENT_FLAG][1_RESERVED_BIT] +// [SERVICE_ID_HASH][DATA_SIZE][DATA][DEVICE_TOKEN][EXTRA_FIELD] // // 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] +// [VERSION][SOCKET_VERSION][FAST_ADVERTISEMENT_FLAG][1_RESERVED_BIT][DATA_SIZE] +// [DATA][DEVICE_TOKEN][EXTRA_FIELD] // // See go/nearby-ble-design for more information. class BleAdvertisement { @@ -63,13 +66,14 @@ class BleAdvertisement { friend H AbslHashValue(H h, const BleAdvertisement &b) { return H::combine(std::move(h), b.version_, b.socket_version_, b.fast_advertisement_, b.service_id_hash_, b.data_, - b.device_token_); + b.device_token_, b.psm_); } BleAdvertisement() = default; BleAdvertisement(Version version, SocketVersion socket_version, const ByteArray &service_id_hash, const ByteArray &data, - const ByteArray &device_token); + const ByteArray &device_token, + int psm = BleAdvertisementHeader::kDefaultPsmValue); explicit BleAdvertisement(const ByteArray &ble_advertisement_bytes); BleAdvertisement(const BleAdvertisement &) = default; BleAdvertisement &operator=(const BleAdvertisement &) = default; @@ -77,8 +81,12 @@ class BleAdvertisement { BleAdvertisement &operator=(BleAdvertisement &&) = default; ~BleAdvertisement() = default; + // Returns ByteArray for legacy advertisement. explicit operator ByteArray() const; + // Returns ByteArray for extended advertisement, which included extra field. + ByteArray ByteArrayWithExtraField() const; + bool IsValid() const { return IsSupportedVersion(version_); } Version GetVersion() const { return version_; } SocketVersion GetSocketVersion() const { return socket_version_; } @@ -89,12 +97,13 @@ class BleAdvertisement { ByteArray &&GetData() && { return std::move(data_); } const ByteArray &&GetData() const && { return std::move(data_); } ByteArray GetDeviceToken() const { return device_token_; } + int GetPsm() const { return psm_; } private: void DoInitialize(bool fast_advertisement, Version version, SocketVersion socket_version, const ByteArray &service_id_hash, const ByteArray &data, - const ByteArray &device_token); + const ByteArray &device_token, int psm); bool IsSupportedVersion(Version version) const; bool IsSupportedSocketVersion(SocketVersion socket_version) const; void SerializeDataSize(bool fast_advertisement, @@ -135,6 +144,7 @@ class BleAdvertisement { ByteArray service_id_hash_; ByteArray data_; ByteArray device_token_; + int psm_ = BleAdvertisementHeader::kDefaultPsmValue; }; } // namespace mediums diff --git a/connections/implementation/mediums/ble_v2/ble_advertisement_header.cc b/connections/implementation/mediums/ble_v2/ble_advertisement_header.cc index 23ea7ab1..674bbd39 100644 --- a/connections/implementation/mediums/ble_v2/ble_advertisement_header.cc +++ b/connections/implementation/mediums/ble_v2/ble_advertisement_header.cc @@ -16,6 +16,9 @@ #include +#include +#include + #include "absl/strings/str_cat.h" #include "internal/platform/base64_utils.h" #include "internal/platform/base_input_stream.h" @@ -27,16 +30,18 @@ namespace connections { namespace mediums { // These definitions are necessary before C++17. -constexpr int BleAdvertisementHeader::kAdvertisementHashLength; -constexpr int BleAdvertisementHeader::kServiceIdBloomFilterLength; +constexpr int BleAdvertisementHeader::kAdvertisementHashByteLength; +constexpr int BleAdvertisementHeader::kServiceIdBloomFilterByteLength; +constexpr int BleAdvertisementHeader::kDefaultPsmValue; +constexpr int BleAdvertisementHeader::kPsmValueByteLength; BleAdvertisementHeader::BleAdvertisementHeader( Version version, bool extended_advertisement, int num_slots, const ByteArray &service_id_bloom_filter, const ByteArray &advertisement_hash, int psm) { if (version != Version::kV2 || num_slots < 0 || - service_id_bloom_filter.size() != kServiceIdBloomFilterLength || - advertisement_hash.size() != kAdvertisementHashLength) { + service_id_bloom_filter.size() != kServiceIdBloomFilterByteLength || + advertisement_hash.size() != kAdvertisementHashByteLength) { return; } @@ -93,13 +98,14 @@ BleAdvertisementHeader::BleAdvertisementHeader( // The next 10 bytes are supposed to be the service_id_bloom_filter. service_id_bloom_filter_ = - base_input_stream.ReadBytes(kServiceIdBloomFilterLength); + base_input_stream.ReadBytes(kServiceIdBloomFilterByteLength); // The next 4 bytes are supposed to be the advertisement_hash. - advertisement_hash_ = base_input_stream.ReadBytes(kAdvertisementHashLength); + advertisement_hash_ = + base_input_stream.ReadBytes(kAdvertisementHashByteLength); // The next 2 bytes are PSM value. - if (base_input_stream.IsAvailable(sizeof(std::uint16_t))) { + if (base_input_stream.IsAvailable(kPsmValueByteLength)) { psm_ = static_cast(base_input_stream.ReadUint16()); } } @@ -121,8 +127,8 @@ BleAdvertisementHeader::operator ByteArray() const { static_cast(num_slots_) & kNumSlotsBitmask; // Convert psm_ value to 2-bytes. - ByteArray psm_byte{sizeof(std::uint16_t)}; - char *data = psm_byte.data(); + ByteArray psm_bytes{kPsmValueByteLength}; + char *data = psm_bytes.data(); data[0] = psm_ & 0xFF00; data[1] = psm_ & 0x00FF; @@ -130,7 +136,7 @@ BleAdvertisementHeader::operator ByteArray() const { std::string out = absl::StrCat(std::string(1, version_and_num_slots_byte), std::string(service_id_bloom_filter_), std::string(advertisement_hash_), - std::string(psm_byte)); + std::string(psm_bytes)); // clang-format on return ByteArray(std::move(out)); @@ -143,7 +149,7 @@ bool BleAdvertisementHeader::operator==( GetNumSlots() == rhs.GetNumSlots() && GetServiceIdBloomFilter() == rhs.GetServiceIdBloomFilter() && GetAdvertisementHash() == rhs.GetAdvertisementHash() && - GetPsmValue() == rhs.GetPsmValue(); + GetPsm() == rhs.GetPsm(); } } // namespace mediums diff --git a/connections/implementation/mediums/ble_v2/ble_advertisement_header.h b/connections/implementation/mediums/ble_v2/ble_advertisement_header.h index 532042a2..9d37d8b3 100644 --- a/connections/implementation/mediums/ble_v2/ble_advertisement_header.h +++ b/connections/implementation/mediums/ble_v2/ble_advertisement_header.h @@ -51,8 +51,10 @@ class BleAdvertisementHeader { // characteristic so the two are not compatible. }; - static constexpr int kAdvertisementHashLength = 4; - static constexpr int kServiceIdBloomFilterLength = 10; + static constexpr int kAdvertisementHashByteLength = 4; + static constexpr int kServiceIdBloomFilterByteLength = 10; + static constexpr int kDefaultPsmValue = 0; + static constexpr int kPsmValueByteLength = 2; // Hashable bool operator==(const BleAdvertisementHeader &rhs) const; @@ -84,13 +86,14 @@ class BleAdvertisementHeader { int GetNumSlots() const { return num_slots_; } ByteArray GetServiceIdBloomFilter() const { return service_id_bloom_filter_; } ByteArray GetAdvertisementHash() const { return advertisement_hash_; } - int GetPsmValue() const { return psm_; } + int GetPsm() const { return psm_; } + void SetPsm(int psm) { psm_ = psm; } private: static constexpr int kVersionAndNumSlotsLength = 1; static constexpr int kMinAdvertisementHeaderLength = - kVersionAndNumSlotsLength + kServiceIdBloomFilterLength + - kAdvertisementHashLength; + kVersionAndNumSlotsLength + kServiceIdBloomFilterByteLength + + kAdvertisementHashByteLength; static constexpr int kVersionBitmask = 0x0E0; static constexpr int kExtendedAdvertismentBitMask = 0x010; static constexpr int kNumSlotsBitmask = 0x00F; @@ -100,7 +103,7 @@ class BleAdvertisementHeader { int num_slots_ = 0; ByteArray service_id_bloom_filter_; ByteArray advertisement_hash_; - int psm_ = 0; + int psm_ = kDefaultPsmValue; }; } // namespace mediums diff --git a/connections/implementation/mediums/ble_v2/ble_advertisement_header_test.cc b/connections/implementation/mediums/ble_v2/ble_advertisement_header_test.cc index bac9c92a..0c712df2 100644 --- a/connections/implementation/mediums/ble_v2/ble_advertisement_header_test.cc +++ b/connections/implementation/mediums/ble_v2/ble_advertisement_header_test.cc @@ -14,6 +14,8 @@ #include "connections/implementation/mediums/ble_v2/ble_advertisement_header.h" +#include + #include "gtest/gtest.h" #include "absl/hash/hash_testing.h" #include "internal/platform/base64_utils.h" @@ -27,7 +29,7 @@ namespace { constexpr BleAdvertisementHeader::Version kVersion = BleAdvertisementHeader::Version::kV2; constexpr int kNumSlots = 2; -constexpr std::int16_t kPsmValue = 1; +constexpr int kPsmValue = 127; constexpr absl::string_view kServiceIDBloomFilter{ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a"}; constexpr absl::string_view kAdvertisementHash{"\x0a\x0b\x0c\x0d"}; @@ -48,7 +50,7 @@ TEST(BleAdvertisementHeaderTest, ConstructionWorks) { ble_advertisement_header.GetServiceIdBloomFilter()); EXPECT_EQ(advertisement_hash, ble_advertisement_header.GetAdvertisementHash()); - EXPECT_EQ(kPsmValue, ble_advertisement_header.GetPsmValue()); + EXPECT_EQ(kPsmValue, ble_advertisement_header.GetPsm()); } TEST(BleAdvertisementHeaderTest, ConstructionFailsWithBadVersion) { @@ -165,7 +167,7 @@ TEST(BleAdvertisementHeaderTest, ConstructionFromSerializedStringWorks) { ble_advertisement_header.GetServiceIdBloomFilter()); EXPECT_EQ(advertisement_hash, ble_advertisement_header.GetAdvertisementHash()); - EXPECT_EQ(kPsmValue, ble_advertisement_header.GetPsmValue()); + EXPECT_EQ(kPsmValue, ble_advertisement_header.GetPsm()); } TEST(BleAdvertisementHeaderTest, ConstructionFromExtraBytesWorks) { @@ -192,7 +194,7 @@ TEST(BleAdvertisementHeaderTest, ConstructionFromExtraBytesWorks) { long_ble_advertisement_header.GetServiceIdBloomFilter()); EXPECT_EQ(advertisement_hash, long_ble_advertisement_header.GetAdvertisementHash()); - EXPECT_EQ(kPsmValue, long_ble_advertisement_header.GetPsmValue()); + EXPECT_EQ(kPsmValue, long_ble_advertisement_header.GetPsm()); } TEST(BleAdvertisementHeaderTest, ConstructionFromShortLengthFails) { diff --git a/connections/implementation/mediums/ble_v2/ble_advertisement_test.cc b/connections/implementation/mediums/ble_v2/ble_advertisement_test.cc index 632e5280..71ebde6a 100644 --- a/connections/implementation/mediums/ble_v2/ble_advertisement_test.cc +++ b/connections/implementation/mediums/ble_v2/ble_advertisement_test.cc @@ -15,6 +15,7 @@ #include "connections/implementation/mediums/ble_v2/ble_advertisement.h" #include +#include #include "gtest/gtest.h" #include "absl/hash/hash_testing.h" @@ -220,10 +221,10 @@ TEST(BleAdvertisementTest, ConstructionFromSerializedBytesWorks) { ByteArray data{std::string(kData)}; ByteArray device_token{std::string(kDeviceToken)}; - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, - service_id_hash, data, device_token}; + BleAdvertisement original_ble_advertisement{ + kVersion, kSocketVersion, service_id_hash, data, device_token}; - ByteArray ble_advertisement_bytes{org_ble_advertisement}; + ByteArray ble_advertisement_bytes{original_ble_advertisement}; BleAdvertisement ble_advertisement{ble_advertisement_bytes}; EXPECT_TRUE(ble_advertisement.IsValid()); @@ -241,10 +242,10 @@ TEST(BleAdvertisementTest, ByteArray fast_data{std::string(kFastData)}; ByteArray device_token{std::string(kDeviceToken)}; - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, ByteArray{}, - fast_data, device_token}; + BleAdvertisement original_ble_advertisement{ + kVersion, kSocketVersion, ByteArray{}, fast_data, device_token}; - ByteArray ble_advertisement_bytes{org_ble_advertisement}; + ByteArray ble_advertisement_bytes{original_ble_advertisement}; BleAdvertisement ble_advertisement{ble_advertisement_bytes}; EXPECT_TRUE(ble_advertisement.IsValid()); @@ -260,9 +261,9 @@ TEST(BleAdvertisementTest, ConstructionFromSerializedBytesWithEmptyDataWorks) { ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; ByteArray device_token{std::string(kDeviceToken)}; - BleAdvertisement org_ble_advertisement{ + BleAdvertisement original_ble_advertisement{ kVersion, kSocketVersion, service_id_hash, ByteArray(), device_token}; - ByteArray ble_advertisement_bytes{org_ble_advertisement}; + ByteArray ble_advertisement_bytes{original_ble_advertisement}; BleAdvertisement ble_advertisement{ble_advertisement_bytes}; EXPECT_TRUE(ble_advertisement.IsValid()); @@ -278,9 +279,9 @@ TEST(BleAdvertisementTest, ConstructionFromSerializedBytesWithEmptyDataWorksForFastAdvertisement) { ByteArray device_token{std::string(kDeviceToken)}; - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, ByteArray{}, - ByteArray(), device_token}; - ByteArray ble_advertisement_bytes{org_ble_advertisement}; + BleAdvertisement original_ble_advertisement{ + kVersion, kSocketVersion, ByteArray{}, ByteArray(), device_token}; + ByteArray ble_advertisement_bytes{original_ble_advertisement}; BleAdvertisement ble_advertisement{ble_advertisement_bytes}; EXPECT_TRUE(ble_advertisement.IsValid()); @@ -296,16 +297,16 @@ TEST(BleAdvertisementTest, ConstructionFromExtraSerializedBytesWorks) { 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}; + BleAdvertisement original_ble_advertisement{ + kVersion, kSocketVersion, service_id_hash, data, device_token}; + ByteArray original_ble_advertisement_bytes{original_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(), + memcpy(raw_ble_advertisement_bytes, original_ble_advertisement_bytes.data(), std::min(sizeof(raw_ble_advertisement_bytes), - org_ble_advertisement_bytes.size())); + original_ble_advertisement_bytes.size())); // Re-parse the Ble advertisement using our extra long advertisement bytes. ByteArray long_ble_advertisement_bytes{raw_ble_advertisement_bytes, @@ -327,16 +328,16 @@ TEST(BleAdvertisementTest, ByteArray fast_data{std::string(kFastData)}; ByteArray device_token{std::string(kDeviceToken)}; - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, ByteArray{}, - fast_data, device_token}; - ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; + BleAdvertisement original_ble_advertisement{ + kVersion, kSocketVersion, ByteArray{}, fast_data, device_token}; + ByteArray original_ble_advertisement_bytes{original_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(), + memcpy(raw_ble_advertisement_bytes, original_ble_advertisement_bytes.data(), std::min(sizeof(raw_ble_advertisement_bytes), - org_ble_advertisement_bytes.size())); + original_ble_advertisement_bytes.size())); // Re-parse the Ble advertisement using our extra long advertisement bytes. ByteArray long_ble_advertisement_bytes{raw_ble_advertisement_bytes, @@ -363,13 +364,13 @@ TEST(BleAdvertisementTest, ConstructionFromShortLengthSerializedBytesFails) { 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}; + BleAdvertisement original_ble_advertisement{ + kVersion, kSocketVersion, service_id_hash, data, device_token}; + ByteArray original_ble_advertisement_bytes{original_ble_advertisement}; // Cut off the advertisement so that it's too short. - ByteArray short_ble_advertisement_bytes{org_ble_advertisement_bytes.data(), - 7}; + ByteArray short_ble_advertisement_bytes{ + original_ble_advertisement_bytes.data(), 7}; BleAdvertisement short_ble_advertisement{short_ble_advertisement_bytes}; EXPECT_FALSE(short_ble_advertisement.IsValid()); @@ -380,13 +381,13 @@ TEST(BleAdvertisementTest, ByteArray fast_data{std::string(kFastData)}; ByteArray device_token{std::string(kDeviceToken)}; - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, ByteArray{}, - fast_data, device_token}; - ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; + BleAdvertisement original_ble_advertisement{ + kVersion, kSocketVersion, ByteArray{}, fast_data, device_token}; + ByteArray original_ble_advertisement_bytes{original_ble_advertisement}; // Cut off the advertisement so that it's too short. - ByteArray short_ble_advertisement_bytes{org_ble_advertisement_bytes.data(), - 2}; + ByteArray short_ble_advertisement_bytes{ + original_ble_advertisement_bytes.data(), 2}; BleAdvertisement short_ble_advertisement{short_ble_advertisement_bytes}; EXPECT_FALSE(short_ble_advertisement.IsValid()); @@ -398,15 +399,15 @@ TEST(BleAdvertisementTest, 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}; + BleAdvertisement original_ble_advertisement{ + kVersion, kSocketVersion, service_id_hash, data, device_token}; + ByteArray original_ble_advertisement_bytes{original_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(), + memcpy(raw_ble_advertisement_bytes, original_ble_advertisement_bytes.data(), kAdvertisementLength); // The data size field lives in indices 4-7. Corrupt it. @@ -426,15 +427,15 @@ TEST(BleAdvertisementTest, ByteArray fast_data{std::string(kFastData)}; ByteArray device_token{std::string(kDeviceToken)}; - BleAdvertisement org_ble_advertisement{kVersion, kSocketVersion, ByteArray{}, - fast_data, device_token}; - ByteArray org_ble_advertisement_bytes{org_ble_advertisement}; + BleAdvertisement original_ble_advertisement{ + kVersion, kSocketVersion, ByteArray{}, fast_data, device_token}; + ByteArray original_ble_advertisement_bytes{original_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(), + memcpy(raw_ble_advertisement_bytes, original_ble_advertisement_bytes.data(), kFastAdvertisementLength); // The data size field lives in index 1. Corrupt it. @@ -449,6 +450,49 @@ TEST(BleAdvertisementTest, EXPECT_FALSE(corrupted_ble_advertisement.IsValid()); } +TEST(BleAdvertisementTest, ConstructionWorksWithPsmValue) { + ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; + ByteArray data{std::string(kData)}; + ByteArray device_token{std::string(kDeviceToken)}; + int psm = 127; + + BleAdvertisement ble_advertisement(kVersion, kSocketVersion, service_id_hash, + data, device_token, psm); + + ASSERT_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()); + EXPECT_EQ(psm, ble_advertisement.GetPsm()); +} + +TEST(BleAdvertisementTest, ConstructionFromSerializedBytesWithPsmValueWorks) { + ByteArray service_id_hash{std::string(kServiceIDHashBytes)}; + ByteArray data{std::string(kData)}; + ByteArray device_token{std::string(kDeviceToken)}; + int psm = 127; + + BleAdvertisement original_ble_advertisement( + kVersion, kSocketVersion, service_id_hash, data, device_token, psm); + ByteArray ble_advertisement_bytes = + original_ble_advertisement.ByteArrayWithExtraField(); + BleAdvertisement ble_advertisement(ble_advertisement_bytes); + + ASSERT_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()); + EXPECT_EQ(psm, ble_advertisement.GetPsm()); +} + TEST(BleAdvertisementTest, Hash) { EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({ BleAdvertisement(), diff --git a/connections/implementation/mediums/ble_v2/ble_peripheral.h b/connections/implementation/mediums/ble_v2/ble_peripheral.h index cd9ba571..1b61093b 100644 --- a/connections/implementation/mediums/ble_v2/ble_peripheral.h +++ b/connections/implementation/mediums/ble_v2/ble_peripheral.h @@ -15,6 +15,7 @@ #ifndef CORE_INTERNAL_MEDIUMS_BLE_V2_BLE_PERIPHERAL_H_ #define CORE_INTERNAL_MEDIUMS_BLE_V2_BLE_PERIPHERAL_H_ +#include "connections/implementation/mediums/ble_v2/ble_advertisement_header.h" #include "internal/platform/byte_array.h" namespace location { @@ -30,7 +31,8 @@ namespace mediums { class BlePeripheral { public: BlePeripheral() = default; - explicit BlePeripheral(const ByteArray& id) : BlePeripheral(id, 0) {} + explicit BlePeripheral(const ByteArray& id) + : BlePeripheral(id, BleAdvertisementHeader::kDefaultPsmValue) {} BlePeripheral(const ByteArray& id, int psm) : id_(id), psm_(psm) {} BlePeripheral(const BlePeripheral&) = default; BlePeripheral& operator=(const BlePeripheral&) = default; diff --git a/connections/implementation/mediums/ble_v2/ble_utils.cc b/connections/implementation/mediums/ble_v2/ble_utils.cc index 55a08823..4d6bb366 100644 --- a/connections/implementation/mediums/ble_v2/ble_utils.cc +++ b/connections/implementation/mediums/ble_v2/ble_utils.cc @@ -53,8 +53,9 @@ ByteArray GenerateDeviceToken() { } ByteArray GenerateAdvertisementHash(const ByteArray& advertisement_bytes) { - return Utils::Sha256Hash(advertisement_bytes, - BleAdvertisementHeader::kAdvertisementHashLength); + return Utils::Sha256Hash( + advertisement_bytes, + BleAdvertisementHeader::kAdvertisementHashByteLength); } std::string GenerateAdvertisementUuid(int slot) {