Implement connection info DE format

PiperOrigin-RevId: 522678942
This commit is contained in:
Anay Wadhera
2023-04-07 14:02:40 -07:00
committed by Copybara-Service
parent c8ea42dbc6
commit a1868432b9
18 changed files with 1202 additions and 289 deletions
+1
View File
@@ -507,6 +507,7 @@ let package = Package(
"internal/platform/wifi_lan_test.cc",
"internal/platform/wifi_test.cc",
"internal/platform/wifi_utils_test.cc",
"internal/platform/connection_info_test.cc",
"internal/platform/condition_variable_test.cc",
"internal/platform/thread_check_nocompile_test.py",
"internal/platform/bluetooth_classic_test.cc",
+4 -3
View File
@@ -26,8 +26,10 @@
namespace nearby {
// We need absl::monostate here to represent the case that we get an invalid
// connection info data element.
using ConnectionInfoVariant =
absl::variant<BleConnectionInfo, BluetoothConnectionInfo,
absl::variant<absl::monostate, BleConnectionInfo, BluetoothConnectionInfo,
WifiLanConnectionInfo>;
class NearbyDevice {
@@ -43,8 +45,7 @@ class NearbyDevice {
NearbyDevice& operator=(NearbyDevice&&) = default;
NearbyDevice(const NearbyDevice&) = delete;
NearbyDevice& operator=(const NearbyDevice&) = delete;
virtual absl::string_view GetEndpointId() const = 0;
virtual absl::string_view GetEndpointInfo() const = 0;
virtual std::string GetEndpointId() const = 0;
// We will be adding more ConnectionInfo types to this variant as they are
// implemented.
virtual std::vector<ConnectionInfoVariant> GetConnectionInfos() const = 0;
+7 -1
View File
@@ -139,6 +139,7 @@ cc_library(
srcs = [
"ble_connection_info.cc",
"bluetooth_connection_info.cc",
"connection_info.cc",
"wifi_lan_connection_info.cc",
],
hdrs = [
@@ -152,11 +153,13 @@ cc_library(
"//presence:__subpackages__",
],
deps = [
":base",
":logging",
"//proto:connections_enums_cc_proto",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
"@com_google_absl//absl/types:variant",
],
)
@@ -442,6 +445,7 @@ cc_test(
"borrowable_test.cc",
"cancelable_alarm_test.cc",
"condition_variable_test.cc",
"connection_info_test.cc",
"count_down_latch_test.cc",
"credential_storage_impl_test.cc",
"crypto_test.cc",
@@ -476,11 +480,13 @@ cc_test(
"//internal/platform/implementation:comm",
"//internal/platform/implementation/g3", # build_cleaner: keep
"//internal/proto:credential_cc_proto",
"//proto:connections_enums_cc_proto",
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/synchronization",
"@com_google_absl//absl/time",
"@com_google_absl//absl/types:variant",
"@com_google_googletest//:gtest_main",
],
)
+99 -5
View File
@@ -14,15 +14,109 @@
#include "internal/platform/ble_connection_info.h"
#include <algorithm>
#include <string>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "internal/platform/connection_info.h"
namespace nearby {
namespace {
constexpr int kBleMacAddressMask = 0b01000000;
constexpr int kGattCharacteristicMask = 0b00100000;
constexpr int kPsmMask = 0b00010000;
constexpr int kPsmSize = 2;
} // namespace
ByteArray BleConnectionInfo::ToBytes() const { return ByteArray(mac_address_); }
std::string BleConnectionInfo::ToDataElementBytes() const {
std::string payload_data;
payload_data.push_back(kBleGattMediumType);
bool has_mac = mac_address_.size() == kMacAddressLength;
bool has_gatt = !gatt_characteristic_.empty();
bool has_psm = psm_.size() == kPsmSize;
char mask = has_mac ? kBleMacAddressMask : 0;
mask |= has_gatt ? kGattCharacteristicMask : 0;
mask |= has_psm ? kPsmMask : 0;
payload_data.push_back(mask);
if (has_mac) {
payload_data.insert(payload_data.end(), mac_address_.begin(),
mac_address_.end());
}
if (has_gatt) {
payload_data.push_back(gatt_characteristic_.length());
payload_data.insert(payload_data.end(), gatt_characteristic_.begin(),
gatt_characteristic_.end());
}
if (has_psm) {
payload_data.insert(payload_data.end(), psm_.begin(), psm_.end());
}
payload_data.push_back(actions_);
std::string ret;
ret.push_back(kDataElementFieldType);
ret.push_back(payload_data.size());
ret.insert(ret.end(), payload_data.begin(), payload_data.end());
return ret;
}
BleConnectionInfo BleConnectionInfo::FromBytes(ByteArray bytes) {
std::string serial(bytes.AsStringView());
return BleConnectionInfo(serial.substr(0, kMacAddressLength));
absl::StatusOr<BleConnectionInfo> BleConnectionInfo::FromDataElementBytes(
absl::string_view bytes) {
if (bytes.size() < kConnectionInfoMinimumLength) {
return absl::InvalidArgumentError("Insufficient length of data element");
}
if (bytes[0] != kDataElementFieldType) {
return absl::InvalidArgumentError("Not a data element type");
}
int position = 1;
int length = static_cast<int>(bytes[position]);
if (length != bytes.size() - 2) {
return absl::InvalidArgumentError("Bad data element length");
}
if (bytes[++position] != kBleGattMediumType) {
return absl::InvalidArgumentError("Not a BLE data element");
}
char mask = bytes[++position];
std::string address;
++position;
if ((mask & kBleMacAddressMask) == kBleMacAddressMask) {
if (bytes.size() - position < kMacAddressLength) {
return absl::InvalidArgumentError(
"Insufficient remaining bytes to read MAC address.");
}
address = std::string(bytes.substr(position, kMacAddressLength));
position += kMacAddressLength;
}
std::string characteristic;
if ((mask & kGattCharacteristicMask) == kGattCharacteristicMask) {
char characteristic_length = bytes[position];
if (bytes.size() - (position + 1) < characteristic_length) {
return absl::InvalidArgumentError(
"Insufficient remaining bytes to read GATT characteristic.");
}
characteristic =
std::string(bytes.substr(position + 1, characteristic_length));
position += characteristic_length + 1;
}
std::string psm;
if ((mask & kPsmMask) == kPsmMask) {
if (bytes.size() - position < kPsmSize) {
return absl::InvalidArgumentError(
"Insufficient remaining bytes to read PSM.");
}
psm = std::string(bytes.substr(position, kPsmSize));
position += kPsmSize;
}
if (bytes.size() == position) {
return absl::InvalidArgumentError(
"Insufficient remaining bytes to read action.");
}
char action = bytes[position];
// Check that we don't have any remaining bytes.
if (bytes.size() != ++position) {
return absl::InvalidArgumentError(absl::StrFormat(
"Nonzero remaining bytes: %d.", bytes.size() - position));
}
return BleConnectionInfo(address, characteristic, psm, action);
}
} // namespace nearby
+26 -21
View File
@@ -17,42 +17,47 @@
#include <string>
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/connection_info.h"
#include "internal/platform/logging.h"
#include "proto/connections_enums.pb.h"
namespace nearby {
// 6 bytes that spell "BADMAC"
constexpr absl::string_view kDefunctMacAddr = "\x42\x41\x44\x4D\x41\x43";
class BleConnectionInfo : public ConnectionInfo {
public:
explicit BleConnectionInfo(absl::string_view mac_address)
: mac_address_(std::string(mac_address)) {
if (mac_address_.size() != kMacAddressLength) {
NEARBY_LOGS(WARNING)
<< "MAC address is not of the expected length! Trying to "
"connect to this MAC address will not work!";
mac_address_ = std::string(kDefunctMacAddr);
}
}
static absl::StatusOr<BleConnectionInfo> FromDataElementBytes(
absl::string_view bytes);
BleConnectionInfo(BleConnectionInfo const& info) {
mac_address_ = info.mac_address_;
BleConnectionInfo(absl::string_view mac_address,
absl::string_view gatt_characteristic,
absl::string_view psm, char actions)
: mac_address_(std::string(mac_address)),
gatt_characteristic_(std::string(gatt_characteristic)),
psm_(std::string(psm)),
actions_(actions) {}
::location::nearby::proto::connections::Medium GetMediumType()
const override {
return ::location::nearby::proto::connections::Medium::BLE;
}
MediumType GetMediumType() const override { return MediumType::kBle; }
ByteArray ToBytes() const override;
static BleConnectionInfo FromBytes(ByteArray bytes);
ByteArray GetMacAddress() const { return ByteArray(mac_address_); }
std::string ToDataElementBytes() const override;
std::string GetMacAddress() const { return mac_address_; }
std::string GetGattCharacteristic() const { return gatt_characteristic_; }
std::string GetPsm() const { return psm_; }
char GetActions() const override { return actions_; }
private:
std::string mac_address_;
std::string gatt_characteristic_;
std::string psm_;
char actions_ = 0;
};
inline bool operator==(const BleConnectionInfo& a, const BleConnectionInfo& b) {
return a.GetMacAddress() == b.GetMacAddress();
return a.GetMacAddress() == b.GetMacAddress() &&
a.GetActions() == b.GetActions() &&
a.GetGattCharacteristic() == b.GetGattCharacteristic();
}
inline bool operator!=(const BleConnectionInfo& a, const BleConnectionInfo& b) {
+282 -34
View File
@@ -1,4 +1,4 @@
// Copyright 2022 Google LLC
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -19,64 +19,312 @@
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/connection_info.h"
#include "proto/connections_enums.pb.h"
namespace nearby {
namespace {
using Medium = ::location::nearby::proto::connections::Medium;
using ::testing::status::StatusIs;
constexpr absl::string_view kMacAddr = "\x4C\x8B\x1D\xCE\xBA\xD1";
constexpr absl::string_view kGattCharacteristic =
"\x03\x0a\x13\x56\x67\x21\x12\x45";
constexpr absl::string_view kPsm = "\x45\x56";
constexpr char kAction = 0x0F;
TEST(BleConnectionInfoTest, TestMediumType) {
BleConnectionInfo info(kMacAddr);
EXPECT_EQ(info.GetMediumType(), BleConnectionInfo::MediumType::kBle);
TEST(BleConnectionInfoTest, TestGetFields) {
BleConnectionInfo info(kMacAddr, kGattCharacteristic, kPsm, kAction);
EXPECT_EQ(info.GetMediumType(), Medium::BLE);
EXPECT_EQ(info.GetGattCharacteristic(), kGattCharacteristic);
EXPECT_EQ(info.GetActions(), kAction);
EXPECT_EQ(info.GetMacAddress(), kMacAddr);
EXPECT_EQ(info.GetPsm(), kPsm);
}
TEST(BleConnectionInfoTest, TestToBytes) {
ByteArray mac_addr_bytes = ByteArray(std::string(kMacAddr));
BleConnectionInfo info(kMacAddr);
EXPECT_EQ(info.ToBytes(), mac_addr_bytes);
TEST(BleConnectionInfoTest, TestFromEmptyBytes) {
auto result = BleConnectionInfo::FromDataElementBytes("");
EXPECT_THAT(result, StatusIs(absl::StatusCode::kInvalidArgument));
}
TEST(BleConnectionInfoTest, TestFromBytes) {
ByteArray mac_addr_bytes = ByteArray(std::string(kMacAddr));
BleConnectionInfo info = BleConnectionInfo::FromBytes(mac_addr_bytes);
EXPECT_EQ(info.GetMacAddress(), mac_addr_bytes);
TEST(BleConnectionInfoTest, TestFromInvalidBytes) {
auto result = BleConnectionInfo::FromDataElementBytes(kMacAddr);
EXPECT_THAT(result, StatusIs(absl::StatusCode::kInvalidArgument));
}
TEST(BleConnectionInfoTest, TestGetMacAddress) {
ByteArray mac_addr_bytes = ByteArray(std::string(kMacAddr));
BleConnectionInfo info(kMacAddr);
EXPECT_EQ(info.GetMacAddress(), mac_addr_bytes);
}
TEST(BleConnectionInfoTest, TestGetLongMacAddr) {
BleConnectionInfo info(absl::StrCat(kMacAddr, "\x56\x70\x89"));
EXPECT_EQ(info.GetMacAddress().AsStringView(), kDefunctMacAddr);
}
TEST(BleConnectionInfoTest, TestGetShortMacAddr) {
BleConnectionInfo info("\x56\x70\x89");
EXPECT_EQ(info.GetMacAddress().AsStringView(), kDefunctMacAddr);
TEST(BleConnectionInfoTest, TestFromNoAction) {
BleConnectionInfo info(kMacAddr, kGattCharacteristic, kPsm, kAction);
std::string serialized = info.ToDataElementBytes();
serialized[1] -= 1;
auto result = BleConnectionInfo::FromDataElementBytes(
serialized.substr(0, serialized.length() - 1));
EXPECT_THAT(result, StatusIs(absl::StatusCode::kInvalidArgument));
}
TEST(BleConnectionInfoTest, TestToFromBytes) {
BleConnectionInfo info(kMacAddr);
ByteArray serialized = info.ToBytes();
BleConnectionInfo result = BleConnectionInfo::FromBytes(serialized);
EXPECT_EQ(result, info);
BleConnectionInfo info(kMacAddr, kGattCharacteristic, kPsm, kAction);
std::string serialized = info.ToDataElementBytes();
auto result = BleConnectionInfo::FromDataElementBytes(serialized);
ASSERT_OK(result);
auto info2 = result.value();
EXPECT_EQ(info2.GetMacAddress(), info.GetMacAddress());
EXPECT_EQ(info2.GetGattCharacteristic(), info.GetGattCharacteristic());
EXPECT_EQ(info2.GetActions(), info.GetActions());
EXPECT_EQ(info2.GetPsm(), info.GetPsm());
}
TEST(BleConnectionInfoTest, TestToFromBytesNoGattCharacteristic) {
BleConnectionInfo info(kMacAddr, "", kPsm, kAction);
std::string serialized = info.ToDataElementBytes();
auto result = BleConnectionInfo::FromDataElementBytes(serialized);
ASSERT_OK(result);
auto info2 = result.value();
EXPECT_EQ(info2.GetMacAddress(), info.GetMacAddress());
EXPECT_EQ(info2.GetGattCharacteristic(), "");
EXPECT_EQ(info2.GetActions(), info.GetActions());
EXPECT_EQ(info2.GetPsm(), info.GetPsm());
}
TEST(BleConnectionInfoTest, TestToFromBytesNoMac) {
BleConnectionInfo info("", kGattCharacteristic, kPsm, kAction);
std::string serialized = info.ToDataElementBytes();
auto result = BleConnectionInfo::FromDataElementBytes(serialized);
ASSERT_OK(result);
auto info2 = result.value();
EXPECT_EQ(info2.GetMacAddress(), "");
EXPECT_EQ(info2.GetGattCharacteristic(), info.GetGattCharacteristic());
EXPECT_EQ(info2.GetActions(), info.GetActions());
EXPECT_EQ(info2.GetPsm(), info.GetPsm());
}
TEST(BleConnectionInfoTest, TestToFromBytesLongMac) {
BleConnectionInfo info(absl::StrCat(kMacAddr, kMacAddr), kGattCharacteristic,
kPsm, kAction);
std::string serialized = info.ToDataElementBytes();
auto result = BleConnectionInfo::FromDataElementBytes(serialized);
ASSERT_OK(result);
auto info2 = result.value();
EXPECT_EQ(info2.GetMacAddress(), "");
EXPECT_EQ(info2.GetGattCharacteristic(), info.GetGattCharacteristic());
EXPECT_EQ(info2.GetActions(), info.GetActions());
EXPECT_EQ(info2.GetPsm(), info.GetPsm());
}
TEST(BleConnectionInfoTest, TestToFromBytesNoPsm) {
BleConnectionInfo info(kMacAddr, kGattCharacteristic, "", kAction);
std::string serialized = info.ToDataElementBytes();
auto result = BleConnectionInfo::FromDataElementBytes(serialized);
ASSERT_OK(result);
auto info2 = result.value();
EXPECT_EQ(info2.GetMacAddress(), info.GetMacAddress());
EXPECT_EQ(info2.GetGattCharacteristic(), info.GetGattCharacteristic());
EXPECT_EQ(info2.GetActions(), info.GetActions());
EXPECT_EQ(info2.GetPsm(), "");
}
TEST(BleConnectionInfoTest, TestToFromBytesLongPsm) {
BleConnectionInfo info(kMacAddr, kGattCharacteristic,
absl::StrCat(kPsm, kPsm), kAction);
std::string serialized = info.ToDataElementBytes();
auto result = BleConnectionInfo::FromDataElementBytes(serialized);
ASSERT_OK(result);
auto info2 = result.value();
EXPECT_EQ(info2.GetMacAddress(), info.GetMacAddress());
EXPECT_EQ(info2.GetGattCharacteristic(), info.GetGattCharacteristic());
EXPECT_EQ(info2.GetActions(), info.GetActions());
EXPECT_EQ(info2.GetPsm(), "");
}
TEST(BleConnectionInfoTest, TestFromEmpty) {
auto result = BleConnectionInfo::FromDataElementBytes("");
EXPECT_THAT(result, StatusIs(absl::StatusCode::kInvalidArgument));
}
TEST(BleConnectionInfoTest, TestFromBadElementType) {
BleConnectionInfo info(kMacAddr, kGattCharacteristic, kPsm, kAction);
std::string serialized = info.ToDataElementBytes();
serialized[0] = 0x56;
auto result = BleConnectionInfo::FromDataElementBytes(serialized);
EXPECT_THAT(result, StatusIs(absl::StatusCode::kInvalidArgument));
}
TEST(BleConnectionInfoTest, TestFromBadMask) {
BleConnectionInfo info(kMacAddr, kGattCharacteristic, kPsm, kAction);
std::string serialized = info.ToDataElementBytes();
// Set mask for MAC address only.
serialized[3] = 0x40;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for GATT characteristic only.
serialized[3] = 0x20;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for PSM only.
serialized[3] = 0x10;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Remove all masks.
serialized[3] = 0x00;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for MAC address + GATT characteristic.
serialized[3] = 0x60;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for GATT characteristic + PSM.
serialized[3] = 0x30;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for MAC address and PSM.
serialized[3] = 0x50;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Verify OK with the correct mask.
serialized[3] = 0x70;
EXPECT_OK(BleConnectionInfo::FromDataElementBytes(serialized));
}
TEST(BleConnectionInfoTest, TestFromBadMaskNoMac) {
BleConnectionInfo info("", kGattCharacteristic, kPsm, kAction);
std::string serialized = info.ToDataElementBytes();
// Set mask for MAC address only.
serialized[3] = 0x40;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for GATT characteristic only.
serialized[3] = 0x20;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for PSM only.
serialized[3] = 0x10;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for MAC address + GATT characteristic.
serialized[3] = 0x60;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for MAC address + PSM.
serialized[3] = 0x50;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Remove all masks.
serialized[3] = 0x00;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Verify OK with the correct mask.
serialized[3] = 0x30;
EXPECT_OK(BleConnectionInfo::FromDataElementBytes(serialized));
}
TEST(BleConnectionInfoTest, TestFromBadMaskNoGattCharacteristic) {
BleConnectionInfo info(kMacAddr, "", kPsm, kAction);
std::string serialized = info.ToDataElementBytes();
// Set mask for MAC address only.
serialized[3] = 0x40;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for GATT characteristic only.
serialized[3] = 0x20;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for PSM only.
serialized[3] = 0x10;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for all fields.
serialized[3] = 0x70;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for MAC address + GATT characteristic.
serialized[3] = 0x60;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for GATT characteristic + PSM.
serialized[3] = 0x30;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Remove all masks.
serialized[3] = 0x00;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Verify OK with the correct mask.
serialized[3] = 0x50;
EXPECT_OK(BleConnectionInfo::FromDataElementBytes(serialized));
}
TEST(BleConnectionInfoTest, TestFromBadMaskNoPsm) {
BleConnectionInfo info(kMacAddr, kGattCharacteristic, "", kAction);
std::string serialized = info.ToDataElementBytes();
// Set mask for MAC address only.
serialized[3] = 0x40;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for GATT characteristic only.
serialized[3] = 0x20;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for PSM only.
serialized[3] = 0x10;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Remove all masks.
serialized[3] = 0x00;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for all fields.
serialized[3] = 0x70;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for GATT characteristic + PSM.
serialized[3] = 0x30;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for MAC address + PSM.
serialized[3] = 0x50;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Verify OK with the correct mask.
serialized[3] = 0x60;
EXPECT_OK(BleConnectionInfo::FromDataElementBytes(serialized));
}
TEST(BleConnectionInfoTest, TestFromBadMaskEmpty) {
BleConnectionInfo info("", "", "", kAction);
std::string serialized = info.ToDataElementBytes();
// Set mask for MAC address only.
serialized[3] = 0x40;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for GATT characteristic only.
serialized[3] = 0x20;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for PSM only.
serialized[3] = 0x10;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for all fields.
serialized[3] = 0x70;
EXPECT_THAT(BleConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Verify OK with correct mask.
serialized[3] = 0x00;
EXPECT_OK(BleConnectionInfo::FromDataElementBytes(serialized));
}
TEST(BleConnectionInfoTest, TestCopy) {
BleConnectionInfo info(kMacAddr);
BleConnectionInfo info(kMacAddr, kGattCharacteristic, kPsm, kAction);
BleConnectionInfo copy(info);
EXPECT_EQ(info, copy);
}
TEST(BleConnectionInfoTest, TestEquals) {
BleConnectionInfo info(kMacAddr);
BleConnectionInfo info2(kMacAddr);
BleConnectionInfo info(kMacAddr, kGattCharacteristic, kPsm, kAction);
BleConnectionInfo info2(kMacAddr, kGattCharacteristic, kPsm, kAction);
EXPECT_EQ(info, info2);
}
+81 -10
View File
@@ -1,4 +1,4 @@
// Copyright 2022 Google LLC
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -14,19 +14,90 @@
#include "internal/platform/bluetooth_connection_info.h"
#include <algorithm>
#include <string>
namespace nearby {
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "internal/platform/connection_info.h"
ByteArray BluetoothConnectionInfo::ToBytes() const {
return ByteArray(absl::StrCat(mac_address_, service_id_));
namespace nearby {
namespace {
constexpr int kMacAddressMask = 0b01000000;
constexpr int kBluetoothUuidMask = 0b00100000;
} // namespace
std::string BluetoothConnectionInfo::ToDataElementBytes() const {
std::string payload_data;
payload_data.push_back(kBluetoothMediumType);
bool has_mac = mac_address_.size() == kMacAddressLength;
bool has_bluetooth_uuid = !bluetooth_uuid_.empty();
char mask = has_mac ? kMacAddressMask : 0;
mask |= has_bluetooth_uuid ? kBluetoothUuidMask : 0;
payload_data.push_back(mask);
if (has_mac) {
payload_data.insert(payload_data.end(), mac_address_.begin(),
mac_address_.end());
}
if (has_bluetooth_uuid) {
payload_data.insert(payload_data.end(), bluetooth_uuid_.begin(),
bluetooth_uuid_.end());
}
payload_data.push_back(actions_);
std::string ret;
ret.push_back(kDataElementFieldType);
ret.push_back(payload_data.size());
ret.insert(ret.end(), payload_data.begin(), payload_data.end());
return std::string(ret.data(), ret.size());
}
BluetoothConnectionInfo BluetoothConnectionInfo::FromBytes(ByteArray bytes) {
std::string serial(bytes.AsStringView());
ByteArray mac_address = ByteArray(serial.substr(0, kMacAddressLength));
std::string service_id = serial.substr(kMacAddressLength);
return BluetoothConnectionInfo(mac_address, service_id);
absl::StatusOr<BluetoothConnectionInfo>
BluetoothConnectionInfo::FromDataElementBytes(absl::string_view bytes) {
if (bytes.size() < kConnectionInfoMinimumLength) {
return absl::InvalidArgumentError("Insufficient length of data element");
}
if (bytes[0] != kDataElementFieldType) {
return absl::InvalidArgumentError("Not a data element type");
}
int position = 1;
char length = bytes[position];
if (length != bytes.size() - 2) {
return absl::InvalidArgumentError("Bad data element length");
}
if (bytes[++position] != kBluetoothMediumType) {
return absl::InvalidArgumentError("Not a Bluetooth data element");
}
char mask = bytes[++position];
std::string address = "";
++position;
if ((mask & kMacAddressMask) == kMacAddressMask) {
if (bytes.size() - position < kMacAddressLength) {
return absl::InvalidArgumentError(
"Insufficient remaining bytes to read MAC address.");
}
address = std::string(bytes.substr(position, kMacAddressLength));
position += kMacAddressLength;
}
std::string uuid = "";
if ((mask & kBluetoothUuidMask) == kBluetoothUuidMask) {
if (bytes.size() - position < 4) {
return absl::InvalidArgumentError(
"Insufficient remaining bytes to read bluetooth UUID.");
}
uuid = std::string(bytes.substr(position, 4));
position += 4;
}
if (bytes.size() == position) {
return absl::InvalidArgumentError(
"Insufficient remaining bytes to read action.");
}
char action = bytes[position];
// Check that we don't have any remaining bytes.
if (bytes.size() != ++position) {
return absl::InvalidArgumentError(absl::StrFormat(
"Nonzero remaining bytes: %d.", bytes.size() - position));
}
return BluetoothConnectionInfo(address, uuid, action);
}
} // namespace nearby
+22 -18
View File
@@ -1,4 +1,4 @@
// Copyright 2022 Google LLC
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -17,40 +17,44 @@
#include <string>
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/connection_info.h"
#include "proto/connections_enums.pb.h"
namespace nearby {
class BluetoothConnectionInfo : public ConnectionInfo {
public:
MediumType GetMediumType() const override { return MediumType::kBluetooth; }
ByteArray ToBytes() const override;
BluetoothConnectionInfo() = delete;
explicit BluetoothConnectionInfo(const ByteArray& mac_address,
absl::string_view service_id)
: mac_address_(mac_address.data()), service_id_(std::string(service_id)) {
mac_address_.resize(kMacAddressLength);
}
static absl::StatusOr<BluetoothConnectionInfo> FromDataElementBytes(
absl::string_view bytes);
BluetoothConnectionInfo(BluetoothConnectionInfo const& info) {
mac_address_ = info.mac_address_;
service_id_ = info.service_id_;
BluetoothConnectionInfo(absl::string_view mac_address,
absl::string_view bluetooth_uuid, char actions)
: mac_address_(std::string(mac_address)),
bluetooth_uuid_(std::string(bluetooth_uuid)),
actions_(actions) {}
::location::nearby::proto::connections::Medium GetMediumType()
const override {
return ::location::nearby::proto::connections::Medium::BLUETOOTH;
}
static BluetoothConnectionInfo FromBytes(ByteArray bytes);
ByteArray GetMacAddress() const { return ByteArray(mac_address_); }
absl::string_view GetServiceId() const { return service_id_; }
std::string ToDataElementBytes() const override;
std::string GetMacAddress() const { return mac_address_; }
std::string GetBluetoothUuid() const { return bluetooth_uuid_; }
char GetActions() const override { return actions_; }
private:
std::string mac_address_;
std::string service_id_;
std::string bluetooth_uuid_;
char actions_;
};
inline bool operator==(const BluetoothConnectionInfo& a,
const BluetoothConnectionInfo& b) {
return a.GetMacAddress() == b.GetMacAddress() &&
a.GetServiceId() == b.GetServiceId();
a.GetBluetoothUuid() == b.GetBluetoothUuid() &&
a.GetActions() == b.GetActions();
}
inline bool operator!=(const BluetoothConnectionInfo& a,
@@ -1,4 +1,4 @@
// Copyright 2022 Google LLC
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -19,77 +19,190 @@
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "proto/connections_enums.pb.h"
namespace nearby {
namespace {
using Medium = ::location::nearby::proto::connections::Medium;
using ::testing::status::StatusIs;
constexpr absl::string_view kMacAddr = "\x4C\x8B\x1D\xCE\xBA\xD1";
constexpr absl::string_view kServiceId{"test"};
constexpr absl::string_view kBluetoothUuid{"test"};
constexpr char kAction = 0x0F;
TEST(BluetoothConnectionInfoTest, TestMediumType) {
std::string macAddr(kMacAddr);
BluetoothConnectionInfo info(ByteArray(macAddr), kServiceId);
EXPECT_EQ(info.GetMediumType(),
BluetoothConnectionInfo::MediumType::kBluetooth);
}
TEST(BluetoothConnectionInfoTest, TestToBytes) {
std::string macAddr(kMacAddr);
BluetoothConnectionInfo info(ByteArray(macAddr), kServiceId);
ByteArray serialized_expected =
ByteArray(absl::StrCat(kMacAddr, kServiceId));
EXPECT_EQ(info.ToBytes(), serialized_expected);
}
TEST(BluetoothConnectionInfoTest, TestFromBytes) {
std::string macAddr(kMacAddr);
ByteArray serialized =
ByteArray(absl::StrCat(macAddr, kServiceId));
BluetoothConnectionInfo info = BluetoothConnectionInfo::FromBytes(serialized);
EXPECT_EQ(info.GetMacAddress(), ByteArray(macAddr));
EXPECT_EQ(info.GetServiceId(), kServiceId);
}
TEST(BluetoothConnectionInfoTest, TestGetMacAddress) {
std::string macAddr(kMacAddr);
BluetoothConnectionInfo info(ByteArray(macAddr), kServiceId);
EXPECT_EQ(info.GetMacAddress(), ByteArray(macAddr));
TEST(BluetoothConnectionInfoTest, TestGetFields) {
BluetoothConnectionInfo info(kMacAddr, kBluetoothUuid, kAction);
EXPECT_EQ(info.GetMediumType(), Medium::BLUETOOTH);
EXPECT_EQ(info.GetMacAddress(), kMacAddr);
EXPECT_EQ(info.GetActions(), kAction);
EXPECT_EQ(info.GetBluetoothUuid(), kBluetoothUuid);
}
TEST(BluetoothConnectionInfoTest, TestGetLongMacAddr) {
std::string macAddr(kMacAddr);
BluetoothConnectionInfo info(ByteArray(macAddr + "\x56\x70\x89"), kServiceId);
EXPECT_EQ(info.GetMacAddress().AsStringView(), kMacAddr);
}
TEST(BluetoothConnectionInfoTest, TestGetServiceId) {
std::string macAddr(kMacAddr);
BluetoothConnectionInfo info(ByteArray(macAddr), kServiceId);
EXPECT_EQ(info.GetServiceId(), kServiceId);
BluetoothConnectionInfo info(absl::StrCat(kMacAddr, "\x56\x70\x89"),
kBluetoothUuid, kAction);
EXPECT_NE(info.GetMacAddress(), kMacAddr);
}
TEST(BluetoothConnectionInfoTest, TestToFromBytes) {
std::string macAddr(kMacAddr);
BluetoothConnectionInfo info(ByteArray(macAddr), kServiceId);
ByteArray serialized = info.ToBytes();
BluetoothConnectionInfo result =
BluetoothConnectionInfo::FromBytes(serialized);
EXPECT_EQ(result, info);
BluetoothConnectionInfo info(kMacAddr, kBluetoothUuid, kAction);
std::string serialized = info.ToDataElementBytes();
auto result = BluetoothConnectionInfo::FromDataElementBytes(serialized);
ASSERT_OK(result);
EXPECT_EQ(result.value(), info);
}
TEST(BluetoothConnectionInfoTest, TestToFromNoMacAddress) {
BluetoothConnectionInfo info("", kBluetoothUuid, kAction);
std::string serialized = info.ToDataElementBytes();
auto result = BluetoothConnectionInfo::FromDataElementBytes(serialized);
ASSERT_OK(result);
info = result.value();
EXPECT_EQ(info.GetMacAddress(), "");
EXPECT_EQ(info.GetBluetoothUuid(), kBluetoothUuid);
EXPECT_EQ(info.GetActions(), kAction);
}
TEST(BluetoothConnectionInfoTest, TestToFromWrongLength) {
BluetoothConnectionInfo info(kMacAddr, kBluetoothUuid, kAction);
std::string serialized = info.ToDataElementBytes();
++serialized[1];
auto result = BluetoothConnectionInfo::FromDataElementBytes(serialized);
EXPECT_THAT(result, StatusIs(absl::StatusCode::kInvalidArgument));
}
TEST(BluetoothConnectionInfoTest, TestToFromNoBluetoothUuid) {
BluetoothConnectionInfo info(kMacAddr, "", kAction);
std::string serialized = info.ToDataElementBytes();
auto result = BluetoothConnectionInfo::FromDataElementBytes(serialized);
ASSERT_OK(result);
EXPECT_EQ(result.value(), info);
}
TEST(BluetoothConnectionInfoTest, TestFromEmptyBytes) {
auto result = BluetoothConnectionInfo::FromDataElementBytes("");
EXPECT_THAT(result, StatusIs(absl::StatusCode::kInvalidArgument));
}
TEST(BluetoothConnectionInfoTest, TestFromNoAction) {
BluetoothConnectionInfo info("", "", kAction);
std::string serialized = info.ToDataElementBytes();
serialized[1] -= 1;
auto result = BluetoothConnectionInfo::FromDataElementBytes(
serialized.substr(0, serialized.length() - 1));
EXPECT_THAT(result, StatusIs(absl::StatusCode::kInvalidArgument));
}
TEST(BluetoothConnectionInfoTest, TestFromInvalidBytes) {
auto result = BluetoothConnectionInfo::FromDataElementBytes(kMacAddr);
EXPECT_THAT(result, StatusIs(absl::StatusCode::kInvalidArgument));
}
TEST(BluetoothConnectionInfoTest, TestFromBadElementType) {
BluetoothConnectionInfo info(kMacAddr, kBluetoothUuid, kAction);
std::string serialized = info.ToDataElementBytes();
serialized[0] = 0x56;
auto result = BluetoothConnectionInfo::FromDataElementBytes(serialized);
EXPECT_THAT(result, StatusIs(absl::StatusCode::kInvalidArgument));
}
TEST(BluetoothConnectionInfoTest, TestFromBadMask) {
BluetoothConnectionInfo info(kMacAddr, kBluetoothUuid, kAction);
std::string serialized = info.ToDataElementBytes();
// Remove the mask for UUID.
serialized[3] = 0x40;
EXPECT_THAT(BluetoothConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Remove the mask for MAC address and add back UUID.
serialized[3] = 0x20;
EXPECT_THAT(BluetoothConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Remove all masks.
serialized[3] = 0x00;
EXPECT_THAT(BluetoothConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set empty mask.
serialized[3] = 0x00;
EXPECT_THAT(BluetoothConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Verify OK with the correct mask.
serialized[3] = 0x60;
EXPECT_OK(BluetoothConnectionInfo::FromDataElementBytes(serialized));
}
TEST(BluetoothConnectionInfoTest, TestFromBadMaskNoUuid) {
BluetoothConnectionInfo info(kMacAddr, "", kAction);
std::string serialized = info.ToDataElementBytes();
// Set the mask for UUID and MAC address.
serialized[3] = 0x60;
EXPECT_THAT(BluetoothConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set the mask for only UUID.
serialized[3] = 0x20;
EXPECT_THAT(BluetoothConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set empty mask.
serialized[3] = 0x00;
EXPECT_THAT(BluetoothConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Verify OK with the correct mask.
serialized[3] = 0x40;
EXPECT_OK(BluetoothConnectionInfo::FromDataElementBytes(serialized));
}
TEST(BluetoothConnectionInfoTest, TestFromBadMaskNoMac) {
BluetoothConnectionInfo info("", kBluetoothUuid, kAction);
std::string serialized = info.ToDataElementBytes();
// Set the mask for UUID and MAC address.
serialized[3] = 0x60;
EXPECT_THAT(BluetoothConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set the mask for only MAC address.
serialized[3] = 0x40;
EXPECT_THAT(BluetoothConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set empty mask.
serialized[3] = 0x00;
EXPECT_THAT(BluetoothConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Verify OK with the correct mask.
serialized[3] = 0x20;
EXPECT_OK(BluetoothConnectionInfo::FromDataElementBytes(serialized));
}
TEST(BluetoothConnectionInfoTest, TestFromBadMaskEmpty) {
BluetoothConnectionInfo info("", "", kAction);
std::string serialized = info.ToDataElementBytes();
// Set mask for UUID and MAC address.
serialized[3] = 0x60;
EXPECT_THAT(BluetoothConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for only UUID.
serialized[3] = 0x20;
EXPECT_THAT(BluetoothConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for only MAC address.
serialized[3] = 0x40;
EXPECT_THAT(BluetoothConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Verify OK with correct mask.
serialized[3] = 0x00;
EXPECT_OK(BluetoothConnectionInfo::FromDataElementBytes(serialized));
}
TEST(BluetoothConnectionInfoTest, TestCopy) {
std::string macAddr(kMacAddr);
BluetoothConnectionInfo info(ByteArray(macAddr), kServiceId);
BluetoothConnectionInfo info(kMacAddr, kBluetoothUuid, kAction);
BluetoothConnectionInfo copy(info);
EXPECT_EQ(info, copy);
}
TEST(BluetoothConnectionInfoTest, TestEquals) {
std::string macAddr(kMacAddr);
BluetoothConnectionInfo info(ByteArray(macAddr), kServiceId);
BluetoothConnectionInfo info2(ByteArray(macAddr), kServiceId);
BluetoothConnectionInfo info(kMacAddr, kBluetoothUuid, kAction);
BluetoothConnectionInfo info2(kMacAddr, kBluetoothUuid, kAction);
EXPECT_EQ(info, info2);
}
+47
View File
@@ -0,0 +1,47 @@
// Copyright 2023 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 "internal/platform/connection_info.h"
#include "absl/strings/string_view.h"
#include "absl/types/variant.h"
#include "internal/platform/ble_connection_info.h"
#include "internal/platform/bluetooth_connection_info.h"
#include "internal/platform/wifi_lan_connection_info.h"
namespace nearby {
ConnectionInfoVariant ConnectionInfo::FromDataElementBytes(
absl::string_view data_element_bytes) {
uint8_t type = data_element_bytes[2];
if (type == kBluetoothMediumType) {
auto result =
BluetoothConnectionInfo::FromDataElementBytes(data_element_bytes);
if (result.ok()) {
return result.value();
}
} else if (type == kBleGattMediumType) {
auto result = BleConnectionInfo::FromDataElementBytes(data_element_bytes);
if (result.ok()) {
return result.value();
}
} else if (type == kWifiLanMediumType) {
auto result =
WifiLanConnectionInfo::FromDataElementBytes(data_element_bytes);
if (result.ok()) {
return result.value();
}
}
return absl::monostate();
}
} // namespace nearby
+25 -11
View File
@@ -1,4 +1,4 @@
// Copyright 2022 Google LLC
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -15,23 +15,37 @@
#ifndef THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_CONNECTION_INFO_H_
#define THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_CONNECTION_INFO_H_
#include "internal/platform/byte_array.h"
#include <string>
#include "absl/strings/string_view.h"
#include "absl/types/variant.h"
#include "proto/connections_enums.pb.h"
namespace nearby {
inline constexpr uint8_t kDataElementFieldType = 0x14;
inline constexpr uint8_t kBluetoothMediumType = 0x00;
inline constexpr uint8_t kBleGattMediumType = 0x01;
inline constexpr uint8_t kWifiLanMediumType = 0x03;
inline constexpr int kMacAddressLength = 6;
inline constexpr int kConnectionInfoMinimumLength = 2;
constexpr int kMacAddressLength = 6;
class BleConnectionInfo;
class BluetoothConnectionInfo;
class WifiLanConnectionInfo;
using ConnectionInfoVariant =
absl::variant<absl::monostate, BleConnectionInfo, BluetoothConnectionInfo,
WifiLanConnectionInfo>;
class ConnectionInfo {
public:
enum class MediumType {
kUnknown = 0,
kBluetooth = 1,
kWifiLan = 2,
kBle = 3,
};
virtual ~ConnectionInfo() = default;
virtual MediumType GetMediumType() const = 0;
virtual ByteArray ToBytes() const = 0;
virtual ::location::nearby::proto::connections::Medium GetMediumType()
const = 0;
virtual std::string ToDataElementBytes() const = 0;
virtual char GetActions() const = 0;
static ConnectionInfoVariant FromDataElementBytes(
absl::string_view data_element_bytes);
};
} // namespace nearby
+108
View File
@@ -0,0 +1,108 @@
// Copyright 2023 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 "internal/platform/connection_info.h"
#include <vector>
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "internal/platform/ble_connection_info.h"
#include "internal/platform/bluetooth_connection_info.h"
#include "internal/platform/wifi_lan_connection_info.h"
namespace nearby {
namespace {
// BLE
constexpr absl::string_view kMacAddr = "\x4C\x8B\x1D\xCE\xBA\xD1";
constexpr absl::string_view kGattCharacteristic =
"\x03\x0a\x13\x56\x67\x21\x12\x45";
constexpr absl::string_view kPsm = "\x45\x56";
constexpr char kAction = 0x0F;
// Bluetooth
constexpr absl::string_view kBluetoothUuid{"test"};
// WLAN
constexpr absl::string_view kIpv4Addr = "\x4C\x8B\x1D\xCE";
constexpr absl::string_view kPort = "\x12\x34\x56\x78";
constexpr absl::string_view kBssid = "\x0A\x1B\x2C\x34\x58\x7E";
TEST(ConnectionInfoTest, TestRestoreBle) {
BleConnectionInfo info(kMacAddr, kGattCharacteristic, kPsm, kAction);
auto serialized = info.ToDataElementBytes();
auto connection_info = ConnectionInfo::FromDataElementBytes(serialized);
ASSERT_TRUE(absl::holds_alternative<BleConnectionInfo>(connection_info));
auto ble_connection_info = absl::get<BleConnectionInfo>(connection_info);
EXPECT_EQ(ble_connection_info, info);
}
TEST(ConnectionInfoTest, TestRestoreBluetooth) {
BluetoothConnectionInfo info(kMacAddr, kBluetoothUuid, kAction);
auto serialized = info.ToDataElementBytes();
auto connection_info = ConnectionInfo::FromDataElementBytes(serialized);
ASSERT_TRUE(
absl::holds_alternative<BluetoothConnectionInfo>(connection_info));
auto bt_connection_info = absl::get<BluetoothConnectionInfo>(connection_info);
EXPECT_EQ(bt_connection_info, info);
}
TEST(ConnectionInfoTest, TestRestoreMdns) {
WifiLanConnectionInfo info(kIpv4Addr, kPort, kBssid, kAction);
auto serialized = info.ToDataElementBytes();
auto connection_info = ConnectionInfo::FromDataElementBytes(serialized);
ASSERT_TRUE(absl::holds_alternative<WifiLanConnectionInfo>(connection_info));
auto wlan_connection_info = absl::get<WifiLanConnectionInfo>(connection_info);
EXPECT_EQ(wlan_connection_info, info);
}
TEST(ConnectionInfoTest, TestMonostate) {
WifiLanConnectionInfo wifi_info(kIpv4Addr, kPort, kBssid, kAction);
BluetoothConnectionInfo bt_info(kMacAddr, kBluetoothUuid, kAction);
BleConnectionInfo ble_info(kMacAddr, kGattCharacteristic, kPsm, kAction);
std::vector<ConnectionInfo*> infos = {&bt_info, &ble_info, &wifi_info};
for (auto info : infos) {
auto serialized = info->ToDataElementBytes();
auto connection_info =
ConnectionInfo::FromDataElementBytes(serialized.substr(0, 10));
EXPECT_TRUE(absl::holds_alternative<absl::monostate>(connection_info));
}
}
TEST(ConnectionInfoTest, TestCannotRestoreAsOtherInfos) {
WifiLanConnectionInfo wifi_info(kIpv4Addr, kPort, kBssid, kAction);
BluetoothConnectionInfo bt_info(kMacAddr, kBluetoothUuid, kAction);
BleConnectionInfo ble_info(kMacAddr, kGattCharacteristic, kPsm, kAction);
EXPECT_THAT(
BleConnectionInfo::FromDataElementBytes(wifi_info.ToDataElementBytes()),
testing::status::StatusIs(absl::StatusCode::kInvalidArgument));
EXPECT_THAT(
BleConnectionInfo::FromDataElementBytes(bt_info.ToDataElementBytes()),
testing::status::StatusIs(absl::StatusCode::kInvalidArgument));
EXPECT_THAT(BluetoothConnectionInfo::FromDataElementBytes(
ble_info.ToDataElementBytes()),
testing::status::StatusIs(absl::StatusCode::kInvalidArgument));
EXPECT_THAT(BluetoothConnectionInfo::FromDataElementBytes(
wifi_info.ToDataElementBytes()),
testing::status::StatusIs(absl::StatusCode::kInvalidArgument));
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(
ble_info.ToDataElementBytes()),
testing::status::StatusIs(absl::StatusCode::kInvalidArgument));
EXPECT_THAT(
WifiLanConnectionInfo::FromDataElementBytes(bt_info.ToDataElementBytes()),
testing::status::StatusIs(absl::StatusCode::kInvalidArgument));
}
} // namespace
} // namespace nearby
+103 -23
View File
@@ -1,4 +1,4 @@
// Copyright 2022 Google LLC
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -18,36 +18,116 @@
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "internal/platform/connection_info.h"
namespace nearby {
namespace {
constexpr char kIpv4Mask = 0b01000000;
constexpr char kIpv6Mask = 0b00100000;
constexpr char kPortMask = 0b00010000;
constexpr char kBssidMask = 0b00001000;
} // namespace
ByteArray WifiLanConnectionInfo::ToBytes() const {
return ByteArray(absl::StrCat(std::to_string(GetWifiLanConnectionInfoType()),
ip_address_, port_, bssid_));
std::string WifiLanConnectionInfo::ToDataElementBytes() const {
std::string payload_data;
payload_data.push_back(kWifiLanMediumType);
bool has_ipv4 = ip_address_.size() == kIpv4AddressLength;
bool has_ipv6 = ip_address_.size() == kIpv6AddressLength;
bool has_bssid = bssid_.size() == kBssidLength;
char mask = kPortMask;
mask |= has_ipv4 ? kIpv4Mask : 0;
mask |= has_ipv6 ? kIpv6Mask : 0;
mask |= has_bssid ? kBssidMask : 0;
payload_data.push_back(mask);
if (has_ipv4 || has_ipv6) {
payload_data.insert(payload_data.end(), ip_address_.begin(),
ip_address_.end());
}
payload_data.insert(payload_data.end(), port_.begin(), port_.end());
if (has_bssid) {
payload_data.insert(payload_data.end(), bssid_.begin(), bssid_.end());
}
payload_data.push_back(actions_);
std::string ret;
ret.push_back(kDataElementFieldType);
ret.push_back(payload_data.size());
ret.insert(ret.end(), payload_data.begin(), payload_data.end());
return std::string(ret.data(), ret.size());
}
absl::StatusOr<WifiLanConnectionInfo> WifiLanConnectionInfo::FromBytes(
ByteArray bytes) {
// IPV4/IPV6 indicator size are both 1
int ip_size = 1;
absl::string_view serial = bytes.AsStringView();
if (serial.length() !=
ip_size + kIpv4AddressLength + kPortLength + kBssidLength &&
serial.length() !=
ip_size + kIpv6AddressLength + kPortLength + kBssidLength) {
return absl::InvalidArgumentError("Bad byte array length");
absl::StatusOr<WifiLanConnectionInfo>
WifiLanConnectionInfo::FromDataElementBytes(absl::string_view bytes) {
if (bytes.size() < kConnectionInfoMinimumLength) {
return absl::InvalidArgumentError("Insufficient length of data element");
}
size_t proc;
int type = std::stoi(std::string(serial.substr(0, ip_size)), &proc);
if (proc != ip_size) {
return absl::InvalidArgumentError("Could not determine IPV4 or IPV6");
if (bytes[0] != kDataElementFieldType) {
return absl::InvalidArgumentError("Not a data element type");
}
int ip_length = type == kIpv4 ? kIpv4AddressLength : kIpv6AddressLength;
absl::string_view ip = serial.substr(ip_size, ip_length);
absl::string_view port = serial.substr(ip_size + ip_length, kPortLength);
absl::string_view bssid = serial.substr(ip_size + ip_length + kPortLength);
return WifiLanConnectionInfo(ip, port, bssid);
int position = 1;
char length = bytes[position];
if (length != bytes.size() - 2) {
return absl::InvalidArgumentError("Bad data element length");
}
if (bytes[++position] != kWifiLanMediumType) {
return absl::InvalidArgumentError("Not a WiFi LAN data element");
}
char mask = bytes[++position];
std::string address;
++position;
// Sanity check to make sure that both are not present.
if ((mask & kIpv4Mask) == kIpv4Mask && (mask & kIpv6Mask) == kIpv6Mask) {
return absl::InvalidArgumentError(
"Both IPV4 and IPV6 addresses cannot be present.");
}
if ((mask & kIpv4Mask) == kIpv4Mask) {
if (bytes.size() - position < kIpv4AddressLength) {
return absl::InvalidArgumentError(
"Insufficient remaining bytes to read IPV4 address.");
}
address = std::string(bytes.substr(position, kIpv4AddressLength));
position += kIpv4AddressLength;
} else if ((mask & kIpv6Mask) == kIpv6Mask) {
if (bytes.size() - position < kIpv6AddressLength) {
return absl::InvalidArgumentError(
"Insufficient remaining bytes to read IPV6 address.");
}
address = std::string(bytes.substr(position, kIpv6AddressLength));
position += kIpv6AddressLength;
}
std::string port;
if ((mask & kPortMask) == kPortMask) {
if (bytes.size() - position < kPortLength) {
return absl::InvalidArgumentError(
"Insufficient remaining bytes to read port.");
}
port = std::string(bytes.substr(position, kPortLength));
position += kPortLength;
}
std::string bssid;
if ((mask & kBssidMask) == kBssidMask) {
if (bytes.size() - position < kBssidLength) {
return absl::InvalidArgumentError(
"Insufficient remaining bytes to read port.");
}
bssid = std::string(bytes.substr(position, kBssidLength));
position += kBssidLength;
}
if (bytes.size() == position) {
return absl::InvalidArgumentError(
"Insufficient remaining bytes to read action.");
}
char action = bytes[position];
// Check that we don't have any remaining bytes.
if (bytes.size() != ++position) {
return absl::InvalidArgumentError(absl::StrFormat(
"Nonzero remaining bytes: %d.", bytes.size() - position));
}
return WifiLanConnectionInfo(address, port, bssid, action);
}
} // namespace nearby
+24 -31
View File
@@ -1,4 +1,4 @@
// Copyright 2022 Google LLC
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -20,53 +20,46 @@
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/connection_info.h"
#include "proto/connections_enums.pb.h"
namespace nearby {
constexpr int kIpv4AddressLength = 4;
constexpr int kIpv6AddressLength = 16;
constexpr int kPortLength = 2;
constexpr int kPortLength = 4;
constexpr int kBssidLength = 6;
class WifiLanConnectionInfo : public ConnectionInfo {
public:
enum WifiLanConnectionInfoType {
kUnknown = 0,
kIpv4 = 1,
kIpv6 = 2,
};
WifiLanConnectionInfo(absl::string_view ip_address, absl::string_view port)
: ip_address_(ip_address), port_(port), bssid_("") {
port_.resize(kPortLength);
bssid_.resize(kBssidLength);
}
static absl::StatusOr<WifiLanConnectionInfo> FromDataElementBytes(
absl::string_view bytes);
WifiLanConnectionInfo(absl::string_view ip_address, absl::string_view port,
absl::string_view bssid)
: ip_address_(ip_address), port_(port), bssid_(std::string(bssid)) {
port_.resize(kPortLength);
bssid_.resize(kBssidLength);
}
static absl::StatusOr<WifiLanConnectionInfo> FromBytes(ByteArray bytes);
MediumType GetMediumType() const override { return MediumType::kWifiLan; }
ByteArray ToBytes() const override;
ByteArray GetIpAddress() const { return ByteArray(ip_address_); }
ByteArray GetPort() const { return ByteArray(port_); }
ByteArray GetBssid() const { return ByteArray(bssid_); }
WifiLanConnectionInfoType GetWifiLanConnectionInfoType() const {
if (ip_address_.size() == kIpv6AddressLength) {
return kIpv6;
} else if (ip_address_.size() == kIpv4AddressLength) {
return kIpv4;
}
return kUnknown;
char actions)
: ip_address_(ip_address), port_(port), bssid_(""), actions_(actions) {}
WifiLanConnectionInfo(absl::string_view ip_address, absl::string_view port,
absl::string_view bssid, char actions)
: ip_address_(ip_address),
port_(port),
bssid_(std::string(bssid)),
actions_(actions) {}
::location::nearby::proto::connections::Medium GetMediumType()
const override {
return ::location::nearby::proto::connections::Medium::WIFI_LAN;
}
std::string ToDataElementBytes() const override;
std::string GetIpAddress() const { return ip_address_; }
std::string GetPort() const { return port_; }
std::string GetBssid() const { return bssid_; }
char GetActions() const override { return actions_; }
private:
std::string ip_address_;
std::string port_;
std::string bssid_;
char actions_;
};
inline bool operator==(const WifiLanConnectionInfo& a,
@@ -1,4 +1,4 @@
// Copyright 2022 Google LLC
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "proto/connections_enums.pb.h"
namespace nearby {
namespace {
@@ -29,110 +30,242 @@ namespace {
constexpr absl::string_view kIpv4Addr = "\x4C\x8B\x1D\xCE";
constexpr absl::string_view kIpv6Addr =
"\x4C\x8B\x1D\xCE\x4C\x8B\x1D\xCE\x4C\x8B\x1D\xCE\x4C\x8B\x1D\xCE";
constexpr absl::string_view kPort = "\x56\x78";
constexpr absl::string_view kPort = "\x12\x34\x56\x78";
constexpr absl::string_view kBssid = "\x0A\x1B\x2C\x34\x58\x7E";
constexpr char kAction = 0x0F;
using ::testing::status::StatusIs;
using Medium = ::location::nearby::proto::connections::Medium;
TEST(WifiLanConnectionInfoTest, TestMediumType) {
WifiLanConnectionInfo info(kIpv4Addr, kPort);
EXPECT_EQ(info.GetMediumType(), WifiLanConnectionInfo::MediumType::kWifiLan);
WifiLanConnectionInfo info(kIpv4Addr, kPort, kAction);
EXPECT_EQ(info.GetMediumType(), Medium::WIFI_LAN);
}
TEST(WifiLanConnectionInfoTest, TestGetMembers) {
WifiLanConnectionInfo info(kIpv4Addr, kPort, kBssid);
EXPECT_EQ(info.GetIpAddress().AsStringView(), kIpv4Addr);
EXPECT_EQ(info.GetPort().AsStringView(), kPort);
EXPECT_EQ(info.GetBssid().AsStringView(), kBssid);
}
TEST(WifiLanConnectionInfoTest, TestIpv4ToBytes) {
WifiLanConnectionInfo info(kIpv4Addr, kPort, kBssid);
ByteArray expected(
absl::StrCat(std::to_string(info.GetWifiLanConnectionInfoType()),
kIpv4Addr, kPort, kBssid));
EXPECT_EQ(info.ToBytes(), expected);
}
TEST(WifiLanConnectionInfoTest, TestFromBytesIpv4) {
ByteArray expected = ByteArray(absl::StrCat(
std::to_string(WifiLanConnectionInfo::kIpv4), kIpv4Addr, kPort, kBssid));
ASSERT_OK(WifiLanConnectionInfo::FromBytes(expected));
WifiLanConnectionInfo info =
WifiLanConnectionInfo::FromBytes(expected).value();
EXPECT_EQ(info.GetIpAddress().AsStringView(), kIpv4Addr);
EXPECT_EQ(info.GetPort().AsStringView(), kPort);
EXPECT_EQ(info.GetBssid().AsStringView(), kBssid);
}
TEST(WifiLanConnectionInfoTest, TestFromBytesIpv6) {
ByteArray expected = ByteArray(absl::StrCat(
std::to_string(WifiLanConnectionInfo::kIpv6), kIpv6Addr, kPort, kBssid));
ASSERT_OK(WifiLanConnectionInfo::FromBytes(expected));
WifiLanConnectionInfo info =
WifiLanConnectionInfo::FromBytes(expected).value();
EXPECT_EQ(info.GetIpAddress().AsStringView(), kIpv6Addr);
EXPECT_EQ(info.GetPort().AsStringView(), kPort);
EXPECT_EQ(info.GetBssid().AsStringView(), kBssid);
WifiLanConnectionInfo info(kIpv4Addr, kPort, kBssid, kAction);
EXPECT_EQ(info.GetIpAddress(), kIpv4Addr);
EXPECT_EQ(info.GetPort(), kPort);
EXPECT_EQ(info.GetBssid(), kBssid);
EXPECT_EQ(info.GetActions(), kAction);
}
TEST(WifiLanConnectionInfoTest, TestToFromBytesIpv4) {
WifiLanConnectionInfo info(kIpv4Addr, kPort, kBssid);
ByteArray serialized = info.ToBytes();
WifiLanConnectionInfo result =
WifiLanConnectionInfo::FromBytes(serialized).value();
EXPECT_EQ(result, info);
WifiLanConnectionInfo info(kIpv4Addr, kPort, kBssid, kAction);
std::string serialized = info.ToDataElementBytes();
auto result = WifiLanConnectionInfo::FromDataElementBytes(serialized);
ASSERT_OK(result);
EXPECT_EQ(result.value(), info);
}
TEST(WifiLanConnectionInfoTest, TestToFromBytesIpv6) {
WifiLanConnectionInfo info(kIpv6Addr, kPort, kBssid);
ByteArray serialized = info.ToBytes();
WifiLanConnectionInfo result =
WifiLanConnectionInfo::FromBytes(serialized).value();
EXPECT_EQ(result, info);
WifiLanConnectionInfo info(kIpv6Addr, kPort, kBssid, kAction);
std::string serialized = info.ToDataElementBytes();
auto result = WifiLanConnectionInfo::FromDataElementBytes(serialized);
ASSERT_OK(result);
EXPECT_EQ(result.value(), info);
}
TEST(WifiLanConnectionInfoTest, TestCopy) {
WifiLanConnectionInfo info(kIpv4Addr, kPort, kBssid);
WifiLanConnectionInfo info(kIpv4Addr, kPort, kBssid, kAction);
WifiLanConnectionInfo copy(info);
EXPECT_EQ(info, copy);
}
TEST(WifiLanConnectionInfoTest, TestEquals) {
WifiLanConnectionInfo info(kIpv4Addr, kPort, kBssid);
WifiLanConnectionInfo info2(kIpv4Addr, kPort, kBssid);
WifiLanConnectionInfo info(kIpv4Addr, kPort, kBssid, kAction);
WifiLanConnectionInfo info2(kIpv4Addr, kPort, kBssid, kAction);
EXPECT_EQ(info, info2);
}
TEST(WifiLanConnectionInfoTest, TestShortBssid) {
std::string shortBssid = "\x0A\x1B\x2C";
std::string extended("\x0A\x1B\x2C\0\0\0", kBssidLength);
WifiLanConnectionInfo info(kIpv4Addr, kPort, shortBssid);
EXPECT_EQ(info.GetBssid().size(), kBssidLength);
// Value-initialized so there will be 3 0x0 characters
EXPECT_EQ(info.GetBssid().AsStringView(), extended);
TEST(WifiLanConnectionInfoTest, TestFromNoAction) {
WifiLanConnectionInfo info(kIpv4Addr, kPort, kBssid, kAction);
std::string serialized = info.ToDataElementBytes();
serialized[1] -= 1;
auto result = WifiLanConnectionInfo::FromDataElementBytes(
serialized.substr(0, serialized.length() - 1));
EXPECT_THAT(result, StatusIs(absl::StatusCode::kInvalidArgument));
}
TEST(WifiLanConnectionInfoTest, TestLongBssid) {
std::string longBssid = absl::StrCat(kBssid, "\x68\x42\x35");
WifiLanConnectionInfo info(kIpv4Addr, kPort, longBssid);
EXPECT_EQ(info.GetBssid().size(), kBssidLength);
EXPECT_EQ(info.GetBssid().AsStringView(), kBssid);
TEST(WifiLanConnectionInfoTest, TestToFromShortBssid) {
std::string shortBssid = "\x0A\x1B\x2C";
WifiLanConnectionInfo info(kIpv4Addr, kPort, shortBssid, kAction);
auto bytes = info.ToDataElementBytes();
auto result = WifiLanConnectionInfo::FromDataElementBytes(bytes);
ASSERT_OK(result);
EXPECT_EQ(result->GetIpAddress(), kIpv4Addr);
EXPECT_EQ(result->GetPort(), kPort);
EXPECT_TRUE(result->GetBssid().empty());
EXPECT_EQ(result->GetActions(), kAction);
}
TEST(WifiLanConnectionInfoTest, TestToFromNoIp) {
WifiLanConnectionInfo info("", kPort, kBssid, kAction);
auto bytes = info.ToDataElementBytes();
auto result = WifiLanConnectionInfo::FromDataElementBytes(bytes);
ASSERT_OK(result);
EXPECT_TRUE(result->GetIpAddress().empty());
EXPECT_EQ(result->GetPort(), kPort);
EXPECT_EQ(result->GetBssid(), kBssid);
EXPECT_EQ(result->GetActions(), kAction);
}
TEST(WifiLanConnectionInfoTest, TestToFromLongIp) {
WifiLanConnectionInfo info(absl::StrCat(kIpv4Addr, kIpv6Addr), kPort, kBssid,
kAction);
auto bytes = info.ToDataElementBytes();
auto result = WifiLanConnectionInfo::FromDataElementBytes(bytes);
ASSERT_OK(result);
EXPECT_TRUE(result->GetIpAddress().empty());
EXPECT_EQ(result->GetPort(), kPort);
EXPECT_EQ(result->GetBssid(), kBssid);
EXPECT_EQ(result->GetActions(), kAction);
}
TEST(WifiLanConnectionInfoTest, TestFromIp) {
auto result = WifiLanConnectionInfo::FromDataElementBytes(kIpv4Addr);
EXPECT_THAT(result, StatusIs(absl::StatusCode::kInvalidArgument));
result = WifiLanConnectionInfo::FromDataElementBytes(kIpv6Addr);
EXPECT_THAT(result, StatusIs(absl::StatusCode::kInvalidArgument));
}
TEST(WifiLanConnectionInfoTest, TestBadBytesLength) {
WifiLanConnectionInfo info(kIpv4Addr, kPort);
ByteArray serialized = info.ToBytes();
ByteArray modified_short(std::string(
serialized.AsStringView().substr(0, kIpv4AddressLength + kPortLength)));
ByteArray modified_long(absl::StrCat(serialized.AsStringView(), kPort));
EXPECT_THAT(WifiLanConnectionInfo::FromBytes(modified_short),
WifiLanConnectionInfo info(kIpv4Addr, kPort, kBssid, kAction);
std::string serialized = info.ToDataElementBytes();
std::string modified_short(
serialized.substr(0, kIpv4AddressLength + kPortLength));
std::string modified_long(absl::StrCat(serialized, kPort));
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(modified_short),
StatusIs(absl::StatusCode::kInvalidArgument));
EXPECT_THAT(WifiLanConnectionInfo::FromBytes(ByteArray()),
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(""),
StatusIs(absl::StatusCode::kInvalidArgument));
EXPECT_THAT(WifiLanConnectionInfo::FromBytes(modified_long),
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(modified_long),
StatusIs(absl::StatusCode::kInvalidArgument));
}
TEST(WifiLanConnectionInfoTest, TestFromBadElementType) {
WifiLanConnectionInfo info(kIpv4Addr, kPort, kBssid, kAction);
std::string serialized = info.ToDataElementBytes();
serialized[0] = 0x56;
auto result = WifiLanConnectionInfo::FromDataElementBytes(serialized);
EXPECT_THAT(result, StatusIs(absl::StatusCode::kInvalidArgument));
}
TEST(WifiLanConnectionInfoTest, TestFromBadMaskIpv4) {
WifiLanConnectionInfo info(kIpv4Addr, kPort, kBssid, kAction);
std::string serialized = info.ToDataElementBytes();
// Set mask for IPV4 address only.
serialized[3] = 0x40;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for IPV6 address only.
serialized[3] = 0x20;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for port only.
serialized[3] = 0x10;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for BSSID only.
serialized[3] = 0x08;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Remove all masks.
serialized[3] = 0x00;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for IPV4 + IPV6 addresses.
serialized[3] = 0x60;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for IPV4 + port.
serialized[3] = 0x50;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for IPV4 + BSSID.
serialized[3] = 0x48;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for all fields present.
serialized[3] = 0x78;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Verify OK with the correct mask.
serialized[3] = 0x58;
EXPECT_OK(WifiLanConnectionInfo::FromDataElementBytes(serialized));
}
TEST(WifiLanConnectionInfoTest, TestFromBadMaskIpv6) {
WifiLanConnectionInfo info(kIpv6Addr, kPort, kBssid, kAction);
std::string serialized = info.ToDataElementBytes();
// Set mask for IPV4 address only.
serialized[3] = 0x40;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for IPV6 address only.
serialized[3] = 0x20;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for port only.
serialized[3] = 0x10;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for BSSID only.
serialized[3] = 0x08;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Remove all masks.
serialized[3] = 0x00;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for IPV4 + IPV6 addresses.
serialized[3] = 0x60;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for IPV6 + port.
serialized[3] = 0x30;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for IPV6 + BSSID.
serialized[3] = 0x28;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for all fields present.
serialized[3] = 0x78;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Verify OK with the correct mask.
serialized[3] = 0x38;
EXPECT_OK(WifiLanConnectionInfo::FromDataElementBytes(serialized));
}
TEST(WifiLanConnectionInfoTest, TestFromBadMaskEmpty) {
WifiLanConnectionInfo info("", "", "", kAction);
std::string serialized = info.ToDataElementBytes();
// Set mask for IPV4 address only.
serialized[3] = 0x40;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for IPV6 address only.
serialized[3] = 0x20;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for port only.
serialized[3] = 0x10;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for BSSID only.
serialized[3] = 0x08;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Set mask for all fields.
serialized[3] = 0x78;
EXPECT_THAT(WifiLanConnectionInfo::FromDataElementBytes(serialized),
StatusIs(absl::StatusCode::kInvalidArgument));
// Verify OK with correct mask.
serialized[3] = 0x00;
EXPECT_OK(WifiLanConnectionInfo::FromDataElementBytes(serialized));
}
} // namespace
} // namespace nearby
+3 -1
View File
@@ -18,6 +18,7 @@
#include <vector>
#include "internal/crypto/random.h"
#include "internal/device.h"
#include "internal/platform/ble_connection_info.h"
#include "internal/platform/implementation/system_clock.h"
#include "presence/device_motion.h"
@@ -47,7 +48,8 @@ PresenceDevice::PresenceDevice(DeviceMotion device_motion,
std::vector<nearby::ConnectionInfoVariant> PresenceDevice::GetConnectionInfos()
const {
return {nearby::BleConnectionInfo(metadata_.bluetooth_mac_address())};
return {nearby::BleConnectionInfo(metadata_.bluetooth_mac_address(),
/*gatt_characteristic=*/"", /*psm=*/"", 0)};
}
} // namespace presence
} // namespace nearby
+1 -6
View File
@@ -39,10 +39,7 @@ class PresenceDevice : public nearby::NearbyDevice {
explicit PresenceDevice(Metadata metadata) noexcept;
explicit PresenceDevice(DeviceMotion device_motion,
Metadata metadata) noexcept;
absl::string_view GetEndpointId() const override { return endpoint_id_; }
void SetEndpointInfo(absl::string_view endpoint_info) {
endpoint_info_ = std::string(endpoint_info);
}
std::string GetEndpointId() const override { return endpoint_id_; }
void AddExtendedProperty(const DataElement& data_element) {
extended_properties_.push_back(data_element);
}
@@ -55,7 +52,6 @@ class PresenceDevice : public nearby::NearbyDevice {
}
void AddAction(const PresenceAction& action) { actions_.push_back(action); }
std::vector<PresenceAction> GetActions() const { return actions_; }
absl::string_view GetEndpointInfo() const override { return endpoint_info_; }
NearbyDevice::Type GetType() const override {
return NearbyDevice::Type::kPresenceDevice;
}
@@ -73,7 +69,6 @@ class PresenceDevice : public nearby::NearbyDevice {
std::vector<DataElement> extended_properties_;
std::vector<PresenceAction> actions_;
std::string endpoint_id_;
std::string endpoint_info_;
};
// Timestamp is not used for equality since if the same device is discovered
+2 -4
View File
@@ -21,7 +21,6 @@
#include "gtest/gtest.h"
#include "absl/types/variant.h"
#include "internal/platform/ble_connection_info.h"
#include "internal/platform/logging.h"
#include "presence/data_element.h"
#include "presence/presence_action.h"
@@ -78,9 +77,8 @@ TEST(PresenceDeviceTest, TestGetBluetoothAddress) {
PresenceDevice device = PresenceDevice({kDefaultMotionType}, metadata);
auto info = (device.GetConnectionInfos().at(0));
ASSERT_TRUE(absl::holds_alternative<nearby::BleConnectionInfo>(info));
EXPECT_EQ(
absl::get<nearby::BleConnectionInfo>(info).GetMacAddress().AsStringView(),
kMacAddr);
EXPECT_EQ(absl::get<nearby::BleConnectionInfo>(info).GetMacAddress(),
kMacAddr);
}
TEST(PresenceDevicetest, TestGetAddExtendedProperties) {