Merge branch 'google3'

Change-Id: I019ed6ec4eb0539d364af44dcc27587914131b47
This commit is contained in:
Alexey Polyudov
2020-09-03 02:11:01 -07:00
39 changed files with 1210 additions and 622 deletions
+1
View File
@@ -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",
+1 -16
View File
@@ -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",
@@ -1,173 +0,0 @@
#include "core_v2/internal/mediums/ble_advertisement.h"
#include <inttypes.h>
#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<char>(base_input_stream.ReadUint8());
// Version.
version_ = static_cast<Version>(
(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<SocketVersion>(
(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<char>(version_) << 5) & kVersionBitmask;
// The next 3 bits are the Socket version. 2 bits left are reserved.
version_and_socket_version_byte |=
(static_cast<char>(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<char *>(&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
@@ -1,219 +0,0 @@
#include "core_v2/internal/mediums/ble_advertisement.h"
#include <algorithm>
#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<BleAdvertisement::Version>(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<BleAdvertisement::SocketVersion>(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
+26 -23
View File
@@ -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();
},
});
+49
View File
@@ -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",
],
)
@@ -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 <algorithm>
#include <vector>
@@ -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 <cstdint>
#include <vector>
@@ -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_
@@ -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"
@@ -0,0 +1,244 @@
#include "core_v2/internal/mediums/ble_v2/ble_advertisement.h"
#include <inttypes.h>
#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<char>(base_input_stream.ReadUint8());
// Version.
version_ = static_cast<Version>((version_byte & kVersionBitmask) >> 5);
if (!IsSupportedVersion(version_)) {
NEARBY_LOG(INFO,
"Cannot deserialize BleAdvertisement: unsupported Version %u",
version_);
return;
}
// Socket version.
socket_version_ =
static_cast<SocketVersion>((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<bool>((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<int>(
base_input_stream.ReadBytes(kFastDataSizeLength).data()[0])
: static_cast<int>(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<char>(version_) << 5) & kVersionBitmask;
// The next 3 bits are the Socket version. 2 bits left are reserved.
version_byte |=
(static_cast<char>(socket_version_) << 2) & kSocketVersionBitmask;
// The next 1 bit is the fast advertisement flag. 1 bit left is reserved.
version_byte |= (static_cast<char>(fast_advertisement_ ? 1 : 0) << 1) &
kFastAdvertisementFlagBitmask;
// Serialize Data size bytes
ByteArray data_size_bytes{static_cast<size_t>(
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<char *>(&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
@@ -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 <utility>
@@ -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_
@@ -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 <inttypes.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 <string>
@@ -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_
@@ -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"
@@ -0,0 +1,505 @@
#include "core_v2/internal/mediums/ble_v2/ble_advertisement.h"
#include <algorithm>
#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<BleAdvertisement::Version>(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<BleAdvertisement::SocketVersion>(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
@@ -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"
@@ -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 <limits>
@@ -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_
@@ -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"
@@ -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_
@@ -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"
@@ -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<void(BlePeripheral& peripheral, const std::string& service_id,
const ByteArray& advertisement_byts,
bool fast_advertisement)>
peripheral_discovered_cb =
DefaultCallback<BlePeripheral&, const std::string&, const ByteArray&,
bool>();
std::function<void(BlePeripheral& peripheral, const std::string& service_id)>
peripheral_lost_cb =
DefaultCallback<BlePeripheral&, const std::string&>();
};
} // namespace mediums
} // namespace connections
} // namespace nearby
} // namespace location
#endif // CORE_V2_INTERNAL_MEDIUMS_BLE_V2_DISCOVERED_PERIPHERAL_CALLBACK_H_
+5 -1
View File
@@ -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;
}
+1
View File
@@ -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
+3
View File
@@ -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;
}
+2 -2
View File
@@ -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"
@@ -235,6 +235,11 @@ bool ConnectionFlow::InitPeerConnection(WebRtcMedium& webrtc_medium) {
&peer_connection_observer_,
[this, &success_future](
rtc::scoped_refptr<webrtc::PeerConnectionInterface> 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;
@@ -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<ConnectionFlow> answerer = ConnectionFlow::Create(
LocalIceCandidateListener(), DataChannelListener(), medium);
EXPECT_EQ(answerer, nullptr);
}
} // namespace
} // namespace mediums
} // namespace connections
@@ -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<void(WebRtcSocketWrapper socket)>;
testing::StrictMock<MockAcceptedCallback> 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<void(WebRtcSocketWrapper socket)>;
testing::StrictMock<MockAcceptedCallback> 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
+52 -36
View File
@@ -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 "
@@ -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);
+2 -1
View File
@@ -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.