mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-15 07:06:11 -04:00
Implement connection info DE format
PiperOrigin-RevId: 522678942
This commit is contained in:
committed by
Copybara-Service
parent
c8ea42dbc6
commit
a1868432b9
@@ -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
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user