mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 22:56:12 -04:00
Merge branch 'master' into release
Change-Id: I89401ad2264e728c6a9e5feadf00f92ce60c7248
This commit is contained in:
@@ -101,7 +101,6 @@ cc_test(
|
||||
deps = [
|
||||
":mediums",
|
||||
"//platform:utils",
|
||||
"//platform/api",
|
||||
"//platform/impl/g3",
|
||||
"//testing/base/public:gunit_main",
|
||||
],
|
||||
@@ -112,7 +111,6 @@ cc_test(
|
||||
srcs = ["ble_advertisement_test.cc"],
|
||||
deps = [
|
||||
":mediums",
|
||||
"//platform/api",
|
||||
"//platform/impl/g3",
|
||||
"//testing/base/public:gunit_main",
|
||||
],
|
||||
@@ -123,7 +121,6 @@ cc_test(
|
||||
srcs = ["ble_packet_test.cc"],
|
||||
deps = [
|
||||
":mediums",
|
||||
"//platform/api",
|
||||
"//platform/impl/g3",
|
||||
"//testing/base/public:gunit_main",
|
||||
],
|
||||
@@ -134,7 +131,6 @@ cc_test(
|
||||
srcs = ["bloom_filter_test.cc"],
|
||||
deps = [
|
||||
":mediums",
|
||||
"//platform/api",
|
||||
"//platform/impl/g3",
|
||||
"//testing/base/public:gunit_main",
|
||||
],
|
||||
|
||||
@@ -75,6 +75,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",
|
||||
|
||||
@@ -15,11 +15,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",
|
||||
@@ -29,12 +25,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",
|
||||
@@ -51,7 +42,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",
|
||||
@@ -73,11 +63,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",
|
||||
],
|
||||
)
|
||||
@@ -86,11 +76,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,187 +0,0 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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,233 +0,0 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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
|
||||
@@ -71,14 +71,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());
|
||||
@@ -103,18 +103,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());
|
||||
@@ -149,10 +149,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();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
# Copyright 2020 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
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
-1
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "core_v2/internal/mediums/advertisement_read_result.h"
|
||||
#include "core_v2/internal/mediums/ble_v2/advertisement_read_result.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
+3
-3
@@ -12,8 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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>
|
||||
@@ -101,4 +101,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
-1
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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,258 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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
|
||||
+46
-16
@@ -12,8 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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>
|
||||
|
||||
@@ -24,10 +24,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 {
|
||||
@@ -51,10 +55,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;
|
||||
@@ -70,37 +78,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
|
||||
@@ -108,4 +138,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
-1
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "core_v2/internal/mediums/ble_advertisement_header.h"
|
||||
#include "core_v2/internal/mediums/ble_v2/ble_advertisement_header.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
+3
-3
@@ -12,8 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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>
|
||||
|
||||
@@ -94,4 +94,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
-1
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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,519 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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
-1
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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"
|
||||
+3
-3
@@ -12,8 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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>
|
||||
|
||||
@@ -61,4 +61,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
-1
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "core_v2/internal/mediums/ble_packet.h"
|
||||
#include "core_v2/internal/mediums/ble_v2/ble_packet.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
+3
-3
@@ -12,8 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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"
|
||||
|
||||
@@ -46,4 +46,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
-1
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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,45 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#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_
|
||||
@@ -45,8 +45,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,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
|
||||
|
||||
@@ -262,6 +262,9 @@ bool WebRtc::InitWebRtcFlow(Role role, const PeerId& self_id) {
|
||||
|
||||
connection_flow_ = ConnectionFlow::Create(GetLocalIceCandidateListener(),
|
||||
GetDataChannelListener(), medium_);
|
||||
if (!connection_flow_)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,14 +24,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"
|
||||
|
||||
@@ -249,6 +249,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);
|
||||
});
|
||||
@@ -338,7 +343,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;
|
||||
|
||||
@@ -198,6 +198,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
|
||||
|
||||
@@ -247,6 +247,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
|
||||
|
||||
@@ -18,6 +18,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"
|
||||
@@ -33,10 +34,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(
|
||||
@@ -117,10 +115,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);
|
||||
@@ -278,12 +274,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;
|
||||
}
|
||||
|
||||
@@ -295,17 +291,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;
|
||||
@@ -313,8 +313,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,
|
||||
@@ -326,7 +327,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
|
||||
@@ -355,6 +356,8 @@ void P2pClusterPcpHandler::BlePeripheralDiscoveredHandler(
|
||||
},
|
||||
peripheral,
|
||||
}));
|
||||
|
||||
// TODO(b/156632928): Check for Bluetooth device with remote mac address.
|
||||
});
|
||||
}
|
||||
|
||||
@@ -685,8 +688,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 "
|
||||
@@ -761,8 +764,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="
|
||||
@@ -806,19 +811,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 "
|
||||
@@ -936,8 +952,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 "
|
||||
|
||||
@@ -125,6 +125,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;
|
||||
|
||||
@@ -157,13 +159,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);
|
||||
|
||||
@@ -70,8 +70,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;
|
||||
}
|
||||
};
|
||||
@@ -87,6 +87,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.
|
||||
|
||||
@@ -174,7 +174,7 @@ api::BluetoothDevice* MediumEnvironment::FindBluetoothDevice(
|
||||
const std::string& mac_address) {
|
||||
api::BluetoothDevice* device = nullptr;
|
||||
CountDownLatch latch(1);
|
||||
RunOnMediumEnvironmentThread([this, &device, &latch, &mac_address](){
|
||||
RunOnMediumEnvironmentThread([this, &device, &latch, &mac_address]() {
|
||||
for (auto& item : bluetooth_mediums_) {
|
||||
auto* adapter = item.second.adapter;
|
||||
if (!adapter) continue;
|
||||
@@ -320,85 +320,85 @@ void MediumEnvironment::UpdateBleMediumForAdvertising(
|
||||
api::BleMedium& medium, api::BlePeripheral& peripheral,
|
||||
const std::string& service_id, bool enabled) {
|
||||
if (!enabled_) return;
|
||||
RunOnMediumEnvironmentThread([this, &medium, &peripheral, service_id,
|
||||
enabled]() {
|
||||
auto item = ble_mediums_.find(&medium);
|
||||
if (item == ble_mediums_.end()) {
|
||||
NEARBY_LOG(INFO,
|
||||
"UpdateBleMediumForAdvertising failed. There is no medium "
|
||||
"registered.");
|
||||
return;
|
||||
}
|
||||
auto& context = item->second;
|
||||
context.ble_peripheral = &peripheral;
|
||||
context.advertising = enabled;
|
||||
NEARBY_LOG(INFO,
|
||||
"Update Ble medium for advertising: this=%p; medium=%p; "
|
||||
"service_id=%s; name=%s; enabled=%d; ",
|
||||
this, &medium, service_id.c_str(), peripheral.GetName().c_str(),
|
||||
enabled);
|
||||
for (auto& medium_info : ble_mediums_) {
|
||||
auto& local_medium = medium_info.first;
|
||||
auto& info = medium_info.second;
|
||||
// Do not send notification to the same medium.
|
||||
if (local_medium == &medium) continue;
|
||||
OnBlePeripheralStateChanged(info, peripheral, service_id, enabled);
|
||||
}
|
||||
});
|
||||
RunOnMediumEnvironmentThread(
|
||||
[this, &medium, &peripheral, service_id, enabled]() {
|
||||
auto item = ble_mediums_.find(&medium);
|
||||
if (item == ble_mediums_.end()) {
|
||||
NEARBY_LOG(INFO,
|
||||
"UpdateBleMediumForAdvertising failed. There is no medium "
|
||||
"registered.");
|
||||
return;
|
||||
}
|
||||
auto& context = item->second;
|
||||
context.ble_peripheral = &peripheral;
|
||||
context.advertising = enabled;
|
||||
NEARBY_LOG(INFO,
|
||||
"Update Ble medium for advertising: this=%p; medium=%p; "
|
||||
"service_id=%s; name=%s; enabled=%d; ",
|
||||
this, &medium, service_id.c_str(),
|
||||
peripheral.GetName().c_str(), enabled);
|
||||
for (auto& medium_info : ble_mediums_) {
|
||||
auto& local_medium = medium_info.first;
|
||||
auto& info = medium_info.second;
|
||||
// Do not send notification to the same medium.
|
||||
if (local_medium == &medium) continue;
|
||||
OnBlePeripheralStateChanged(info, peripheral, service_id, enabled);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void MediumEnvironment::UpdateBleMediumForScanning(
|
||||
api::BleMedium& medium, const std::string& service_id,
|
||||
BleDiscoveredPeripheralCallback callback, bool enabled) {
|
||||
if (!enabled_) return;
|
||||
RunOnMediumEnvironmentThread([this, &medium, service_id,
|
||||
callback = std::move(callback), enabled]() {
|
||||
auto item = ble_mediums_.find(&medium);
|
||||
if (item == ble_mediums_.end()) {
|
||||
NEARBY_LOG(INFO,
|
||||
"UpdateBleMediumFoScanning failed. There is no medium "
|
||||
"registered.");
|
||||
return;
|
||||
}
|
||||
auto& context = item->second;
|
||||
context.discovery_callback = std::move(callback);
|
||||
NEARBY_LOG(INFO,
|
||||
"Update Ble medium for scanning: this=%p; medium=%p; "
|
||||
"service_id=%s; enabled=%d ;",
|
||||
this, &medium, service_id.c_str(), enabled);
|
||||
for (auto& medium_info : ble_mediums_) {
|
||||
auto& local_medium = medium_info.first;
|
||||
auto& info = medium_info.second;
|
||||
// Do not send notification to the same medium.
|
||||
if (local_medium == &medium) continue;
|
||||
// Search advertising mediums and send notification.
|
||||
if (info.advertising && enabled) {
|
||||
OnBlePeripheralStateChanged(context, *(info.ble_peripheral), service_id,
|
||||
enabled);
|
||||
}
|
||||
}
|
||||
});
|
||||
RunOnMediumEnvironmentThread(
|
||||
[this, &medium, service_id, callback = std::move(callback), enabled]() {
|
||||
auto item = ble_mediums_.find(&medium);
|
||||
if (item == ble_mediums_.end()) {
|
||||
NEARBY_LOG(INFO,
|
||||
"UpdateBleMediumFoScanning failed. There is no medium "
|
||||
"registered.");
|
||||
return;
|
||||
}
|
||||
auto& context = item->second;
|
||||
context.discovery_callback = std::move(callback);
|
||||
NEARBY_LOG(INFO,
|
||||
"Update Ble medium for scanning: this=%p; medium=%p; "
|
||||
"service_id=%s; enabled=%d ;",
|
||||
this, &medium, service_id.c_str(), enabled);
|
||||
for (auto& medium_info : ble_mediums_) {
|
||||
auto& local_medium = medium_info.first;
|
||||
auto& info = medium_info.second;
|
||||
// Do not send notification to the same medium.
|
||||
if (local_medium == &medium) continue;
|
||||
// Search advertising mediums and send notification.
|
||||
if (info.advertising && enabled) {
|
||||
OnBlePeripheralStateChanged(context, *(info.ble_peripheral),
|
||||
service_id, enabled);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void MediumEnvironment::UpdateBleMediumForAcceptedConnection(
|
||||
api::BleMedium& medium, const std::string& service_id,
|
||||
BleAcceptedConnectionCallback callback) {
|
||||
if (!enabled_) return;
|
||||
RunOnMediumEnvironmentThread([this, &medium, service_id,
|
||||
callback = std::move(callback)]() {
|
||||
auto item = ble_mediums_.find(&medium);
|
||||
if (item == ble_mediums_.end()) {
|
||||
NEARBY_LOG(
|
||||
INFO, "Update Ble medium failed. There is no medium registered.");
|
||||
return;
|
||||
}
|
||||
auto& context = item->second;
|
||||
context.accepted_connection_callback = std::move(callback);
|
||||
NEARBY_LOG(INFO,
|
||||
"Update Ble medium for accepted callback: this=%p; "
|
||||
"medium=%p; service_id=%s; ",
|
||||
this, &medium, service_id.c_str());
|
||||
});
|
||||
RunOnMediumEnvironmentThread(
|
||||
[this, &medium, service_id, callback = std::move(callback)]() {
|
||||
auto item = ble_mediums_.find(&medium);
|
||||
if (item == ble_mediums_.end()) {
|
||||
NEARBY_LOG(
|
||||
INFO, "Update Ble medium failed. There is no medium registered.");
|
||||
return;
|
||||
}
|
||||
auto& context = item->second;
|
||||
context.accepted_connection_callback = std::move(callback);
|
||||
NEARBY_LOG(INFO,
|
||||
"Update Ble medium for accepted callback: this=%p; "
|
||||
"medium=%p; service_id=%s; ",
|
||||
this, &medium, service_id.c_str());
|
||||
});
|
||||
}
|
||||
|
||||
void MediumEnvironment::UnregisterBleMedium(api::BleMedium& medium) {
|
||||
@@ -465,6 +465,15 @@ void MediumEnvironment::SendWebRtcSignalingMessage(absl::string_view peer_id,
|
||||
});
|
||||
}
|
||||
|
||||
void MediumEnvironment::SetUseValidPeerConnection(
|
||||
bool use_valid_peer_connection) {
|
||||
use_valid_peer_connection_ = use_valid_peer_connection;
|
||||
}
|
||||
|
||||
bool MediumEnvironment::GetUseValidPeerConnection() {
|
||||
return use_valid_peer_connection_;
|
||||
}
|
||||
|
||||
void MediumEnvironment::RegisterWifiLanMedium(api::WifiLanMedium& medium) {
|
||||
if (!enabled_) return;
|
||||
RunOnMediumEnvironmentThread([this, &medium]() {
|
||||
|
||||
@@ -138,6 +138,12 @@ class MediumEnvironment {
|
||||
void SendWebRtcSignalingMessage(absl::string_view peer_id,
|
||||
const ByteArray& message);
|
||||
|
||||
// Used to set if WebRtcMedium should use a valid peer connection or nullptr
|
||||
// in tests.
|
||||
void SetUseValidPeerConnection(bool use_valid_peer_connection);
|
||||
|
||||
bool GetUseValidPeerConnection();
|
||||
|
||||
// Adds medium-related info to allow for scanning/advertising to work.
|
||||
// This provides acccess to this medium from other mediums, when protocol
|
||||
// expects they should communicate.
|
||||
@@ -221,7 +227,7 @@ class MediumEnvironment {
|
||||
|
||||
// Returns WiFi LAN service matching IP address and port, or nullptr.
|
||||
api::WifiLanService* FindWifiLanService(const std::string& ip_address,
|
||||
int port);
|
||||
int port);
|
||||
|
||||
private:
|
||||
struct BluetoothMediumContext {
|
||||
@@ -294,6 +300,8 @@ class MediumEnvironment {
|
||||
|
||||
absl::flat_hash_map<api::WifiLanMedium*, WifiLanMediumContext>
|
||||
wifi_lan_mediums_;
|
||||
|
||||
bool use_valid_peer_connection_ = true;
|
||||
};
|
||||
|
||||
} // namespace nearby
|
||||
|
||||
@@ -47,6 +47,12 @@ void WebRtcSignalingMessenger::StopReceivingMessages() {
|
||||
|
||||
void WebRtcMedium::CreatePeerConnection(
|
||||
webrtc::PeerConnectionObserver* observer, PeerConnectionCallback callback) {
|
||||
auto& env = MediumEnvironment::Instance();
|
||||
if (!env.GetUseValidPeerConnection()) {
|
||||
callback(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
webrtc::PeerConnectionInterface::RTCConfiguration rtc_config;
|
||||
webrtc::PeerConnectionDependencies dependencies(observer);
|
||||
|
||||
|
||||
@@ -60,7 +60,8 @@ bool BleMedium::StartScanning(const std::string& service_id,
|
||||
&context.peripheral, &peripheral,
|
||||
peripheral.GetName().c_str());
|
||||
discovered_peripheral_callback_.peripheral_discovered_cb(
|
||||
context.peripheral, service_id);
|
||||
context.peripheral, service_id,
|
||||
/*fast_advertisement=*/false);
|
||||
}
|
||||
},
|
||||
.peripheral_lost_cb =
|
||||
|
||||
@@ -86,9 +86,10 @@ class BleMedium final {
|
||||
using Platform = api::ImplementationPlatform;
|
||||
struct DiscoveredPeripheralCallback {
|
||||
std::function<void(BlePeripheral& peripheral,
|
||||
const std::string& service_id)>
|
||||
const std::string& service_id,
|
||||
bool fast_advertisement)>
|
||||
peripheral_discovered_cb =
|
||||
DefaultCallback<BlePeripheral&, const std::string&>();
|
||||
DefaultCallback<BlePeripheral&, const std::string&, bool>();
|
||||
std::function<void(BlePeripheral& peripheral,
|
||||
const std::string& service_id)>
|
||||
peripheral_lost_cb =
|
||||
|
||||
@@ -69,13 +69,13 @@ TEST_F(BleMediumTest, CanStartAdvertising) {
|
||||
ble_a.StartAdvertising(service_id, advertisement_bytes);
|
||||
|
||||
EXPECT_TRUE(ble_b.StartScanning(
|
||||
service_id, DiscoveredPeripheralCallback{
|
||||
.peripheral_discovered_cb =
|
||||
[&found_latch](BlePeripheral& peripheral,
|
||||
const std::string& service_id) {
|
||||
found_latch.CountDown();
|
||||
},
|
||||
}));
|
||||
service_id,
|
||||
DiscoveredPeripheralCallback{
|
||||
.peripheral_discovered_cb =
|
||||
[&found_latch](
|
||||
BlePeripheral& peripheral, const std::string& service_id,
|
||||
bool fast_advertisement) { found_latch.CountDown(); },
|
||||
}));
|
||||
EXPECT_TRUE(found_latch.Await(kWaitDuration).result());
|
||||
EXPECT_TRUE(ble_a.StopAdvertising(service_id));
|
||||
EXPECT_TRUE(ble_b.StopScanning(service_id));
|
||||
@@ -93,19 +93,19 @@ TEST_F(BleMediumTest, CanStartScanning) {
|
||||
CountDownLatch found_latch(1);
|
||||
CountDownLatch lost_latch(1);
|
||||
|
||||
ble_a.StartScanning(service_id,
|
||||
DiscoveredPeripheralCallback{
|
||||
.peripheral_discovered_cb =
|
||||
[&found_latch](BlePeripheral& peripheral,
|
||||
const std::string& service_id) {
|
||||
found_latch.CountDown();
|
||||
},
|
||||
.peripheral_lost_cb =
|
||||
[&lost_latch](BlePeripheral& peripheral,
|
||||
const std::string& service_id) {
|
||||
lost_latch.CountDown();
|
||||
},
|
||||
});
|
||||
ble_a.StartScanning(
|
||||
service_id,
|
||||
DiscoveredPeripheralCallback{
|
||||
.peripheral_discovered_cb =
|
||||
[&found_latch](
|
||||
BlePeripheral& peripheral, const std::string& service_id,
|
||||
bool fast_advertisement) { found_latch.CountDown(); },
|
||||
.peripheral_lost_cb =
|
||||
[&lost_latch](BlePeripheral& peripheral,
|
||||
const std::string& service_id) {
|
||||
lost_latch.CountDown();
|
||||
},
|
||||
});
|
||||
EXPECT_TRUE(ble_b.StartAdvertising(service_id, advertisement_bytes));
|
||||
EXPECT_TRUE(found_latch.Await(kWaitDuration).result());
|
||||
EXPECT_TRUE(ble_b.StopAdvertising(service_id));
|
||||
@@ -125,19 +125,19 @@ TEST_F(BleMediumTest, CanStopDiscovery) {
|
||||
CountDownLatch found_latch(1);
|
||||
CountDownLatch lost_latch(1);
|
||||
|
||||
ble_a.StartScanning(service_id,
|
||||
DiscoveredPeripheralCallback{
|
||||
.peripheral_discovered_cb =
|
||||
[&found_latch](BlePeripheral& peripheral,
|
||||
const std::string& service_id) {
|
||||
found_latch.CountDown();
|
||||
},
|
||||
.peripheral_lost_cb =
|
||||
[&lost_latch](BlePeripheral& peripheral,
|
||||
const std::string& service_id) {
|
||||
lost_latch.CountDown();
|
||||
},
|
||||
});
|
||||
ble_a.StartScanning(
|
||||
service_id,
|
||||
DiscoveredPeripheralCallback{
|
||||
.peripheral_discovered_cb =
|
||||
[&found_latch](
|
||||
BlePeripheral& peripheral, const std::string& service_id,
|
||||
bool fast_advertisement) { found_latch.CountDown(); },
|
||||
.peripheral_lost_cb =
|
||||
[&lost_latch](BlePeripheral& peripheral,
|
||||
const std::string& service_id) {
|
||||
lost_latch.CountDown();
|
||||
},
|
||||
});
|
||||
EXPECT_TRUE(ble_b.StartAdvertising(service_id, advertisement_bytes));
|
||||
EXPECT_TRUE(found_latch.Await(kWaitDuration).result());
|
||||
EXPECT_TRUE(ble_a.StopScanning(service_id));
|
||||
@@ -163,9 +163,13 @@ TEST_F(BleMediumTest, CanStartAcceptingConnectionsAndConnect) {
|
||||
DiscoveredPeripheralCallback{
|
||||
.peripheral_discovered_cb =
|
||||
[&found_latch, &discovered_peripheral](
|
||||
BlePeripheral& peripheral, const std::string& service_id) {
|
||||
NEARBY_LOG(INFO, "Peripheral discovered: %s, %p",
|
||||
peripheral.GetName().c_str(), &peripheral);
|
||||
BlePeripheral& peripheral, const std::string& service_id,
|
||||
bool fast_advertisement) {
|
||||
NEARBY_LOG(
|
||||
INFO,
|
||||
"Peripheral discovered: %s, %p, fast advertisement: %d",
|
||||
peripheral.GetName().c_str(), &peripheral,
|
||||
fast_advertisement);
|
||||
discovered_peripheral = &peripheral;
|
||||
found_latch.CountDown();
|
||||
},
|
||||
|
||||
@@ -150,6 +150,20 @@ enum StartAdvertisingError {
|
||||
// Next ID :46
|
||||
}
|
||||
|
||||
// The error for event START_ADVERTISING. The range between 31 and 99.
|
||||
enum StopAdvertisingError {
|
||||
// System error, failed to stop advertising.
|
||||
STOP_ADVERTISING_FAILED = 31;
|
||||
// System error, failed to modify the Bluetooth name.
|
||||
RESTORE_BLUETOOTH_NAME_FAILED = 32;
|
||||
// System error, failed to stop advertising for BLE legacy advertisements.
|
||||
STOP_LEGACY_ADVERTISING_FAILED = 33;
|
||||
// System error, failed to stop advertising for BLE extended advertisements.
|
||||
STOP_EXTENDED_ADVERTISING_FAILED = 34;
|
||||
|
||||
// Next ID :35
|
||||
}
|
||||
|
||||
// The error for event START_DISCOVERING. The range between 31 and 99.
|
||||
enum StartDiscoveringError {
|
||||
// Developing error, this service ID already requested, should not request it
|
||||
@@ -198,6 +212,11 @@ enum StartListeningIncomingConnectionError {
|
||||
// Network error, wait the GATT connection ready after the connection
|
||||
// established but never.
|
||||
CREATE_GATT_SERVER_SOCKET_NOT_READY = 35;
|
||||
// System error, failed to accept the incoming connection
|
||||
ACCEPT_CONNECTION_FAILED = 36;
|
||||
// System error, failed to create a server socket for listening incoming
|
||||
// connection.
|
||||
CREATE_SERVER_SOCKET_FAILED = 37;
|
||||
|
||||
// Next ID :36
|
||||
}
|
||||
@@ -380,4 +399,15 @@ enum Description {
|
||||
WITHOUT_PSM_VALUE = 130;
|
||||
SOCKET_BIND_LISTEN_FAILED = 131;
|
||||
UNEXPECTED_PACKET_CONTENT = 132;
|
||||
UNREGISTER_NSD_MANAGER_FAILED = 133;
|
||||
PUBLISH_EMPTY_ADVERTISEMENT_FAILED = 134;
|
||||
BLUETOOTH_SOCKET_NOT_IN_LISTENING_STATE = 135;
|
||||
INVALID_BLUETOOTH_SOCKET_SIGNAL_SIZE = 136;
|
||||
INVALID_BLUETOOTH_SOCKET_SIGNAL_STATUS = 137;
|
||||
GET_ADDRESS_FAILED = 138;
|
||||
NULL_LOCAL_ADDRESS = 139;
|
||||
IS_LOOPBACK_ADDRESS = 140;
|
||||
SOCKET_NOT_BOUND = 141;
|
||||
INVALID_REMOTE_ADDRESS = 142;
|
||||
SOCKET_ALREADY_BOUND = 143;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user