Migrate bluetooth_address from location/nearby to third_party/nearby

PiperOrigin-RevId: 500784376
This commit is contained in:
Qin Wang
2023-01-09 12:49:52 -08:00
committed by Copybara-Service
parent 6ac239688f
commit e90fd77e47
5 changed files with 278 additions and 0 deletions
+1
View File
@@ -467,6 +467,7 @@ let package = Package(
"connections/core_test.cc",
"connections/status_test.cc",
"connections/payload_test.cc",
"internal/base/bluetooth_address_test.cc",
"internal/crypto/aead_unittest.cc",
"internal/crypto/ec_private_key_unittest.cc",
"internal/crypto/ec_signature_creator_unittest.cc",
+43
View File
@@ -18,3 +18,46 @@ cc_library(
"@com_google_absl//absl/container:flat_hash_set",
],
)
cc_library(
name = "bluetooth_address",
srcs = [
"bluetooth_address.cc",
],
hdrs = [
"bluetooth_address.h",
],
copts = [
"-Ithird_party",
],
visibility = [
"//fastpair:__subpackages__",
"//location/nearby/cpp/fastpair:__subpackages__",
],
deps = [
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
"@com_google_absl//absl/types:optional",
"@com_google_absl//absl/types:span",
],
)
cc_test(
name = "base_test",
size = "small",
timeout = "short",
srcs = [
"bluetooth_address_test.cc",
],
copts = [
"-Ithird_party",
],
shard_count = 8,
deps = [
":bluetooth_address",
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_absl//absl/time",
"@com_google_absl//absl/types:span",
"@com_google_googletest//:gtest_main",
],
)
+124
View File
@@ -0,0 +1,124 @@
// Copyright 2021 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/base/bluetooth_address.h"
#include <algorithm>
#include <array>
#include <string>
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
namespace nearby {
namespace device {
namespace {
template <int BASE, typename CHAR>
// Note that some of the methods return absl::optional instead
// of std::optional, because iOS platform is still in C++14.
absl::optional<uint8_t> CharToDigit(CHAR c) {
static_assert(1 <= BASE && BASE <= 36, "BASE needs to be in [1, 36]");
if (c >= '0' && c < '0' + std::min(BASE, 10)) return c - '0';
if (c >= 'a' && c < 'a' + BASE - 10) return c - 'a' + 10;
if (c >= 'A' && c < 'A' + BASE - 10) return c - 'A' + 10;
return absl::nullopt;
}
template <typename OutIter>
static bool HexStringToByteContainer(absl::string_view input, OutIter output) {
size_t count = input.size();
if (count == 0 || (count % 2) != 0) return false;
for (uintptr_t i = 0; i < count / 2; ++i) {
// most significant 4 bits
absl::optional<uint8_t> msb = CharToDigit<16>(input[i * 2]);
// least significant 4 bits
absl::optional<uint8_t> lsb = CharToDigit<16>(input[i * 2 + 1]);
if (!msb.has_value() || !lsb.has_value()) {
return false;
}
*(output++) = (*msb << 4) | *lsb;
}
return true;
}
bool HexStringToSpan(absl::string_view input, absl::Span<uint8_t> output) {
if (input.size() / 2 != output.size()) return false;
return HexStringToByteContainer(input, output.begin());
}
} // namespace
bool ParseBluetoothAddress(absl::string_view input,
absl::Span<uint8_t> output) {
if (output.size() != 6) return false;
// Try parsing addresses that lack separators, like "1A2B3C4D5E6F".
if (input.size() == 12) return HexStringToSpan(input, output);
// Try parsing MAC address with separators like: "00:11:22:33:44:55" or
// "00-11-22-33-44-55". Separator can be either '-' or ':', but must use the
// same style throughout.
if (input.size() == 17) {
const char separator = input[2];
if (separator != '-' && separator != ':') return false;
return (input[2] == separator) && (input[5] == separator) &&
(input[8] == separator) && (input[11] == separator) &&
(input[14] == separator) &&
HexStringToSpan(input.substr(0, 2), output.subspan(0, 1)) &&
HexStringToSpan(input.substr(3, 2), output.subspan(1, 1)) &&
HexStringToSpan(input.substr(6, 2), output.subspan(2, 1)) &&
HexStringToSpan(input.substr(9, 2), output.subspan(3, 1)) &&
HexStringToSpan(input.substr(12, 2), output.subspan(4, 1)) &&
HexStringToSpan(input.substr(15, 2), output.subspan(5, 1));
}
return false;
}
std::string ConvertBluetoothAddressUIntToString(uint64_t address) {
std::string mac_address = absl::StrFormat(
"%02llX:%02llX:%02llX:%02llX:%02llX:%02llX", address >> 40,
(address >> 32) & 0xff, (address >> 24) & 0xff, (address >> 16) & 0xff,
(address >> 8) & 0xff, address & 0xff);
return CanonicalizeBluetoothAddress(mac_address);
}
std::string CanonicalizeBluetoothAddress(absl::string_view address) {
std::array<uint8_t, 6> bytes;
if (!ParseBluetoothAddress(address, absl::MakeSpan(bytes.data(), 6)))
return std::string();
return CanonicalizeBluetoothAddress(bytes);
}
std::string CanonicalizeBluetoothAddress(
const std::array<uint8_t, 6>& address_bytes) {
return absl::StrFormat("%02X:%02X:%02X:%02X:%02X:%02X", address_bytes[0],
address_bytes[1], address_bytes[2], address_bytes[3],
address_bytes[4], address_bytes[5]);
}
std::string CanonicalizeBluetoothAddress(uint64_t address) {
return ConvertBluetoothAddressUIntToString(address);
}
} // namespace device
} // namespace nearby
+51
View File
@@ -0,0 +1,51 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef THIRD_PARTY_NEARBY_INTERNAL_BASE_BLUETOOTH_ADDRESS_H_
#define THIRD_PARTY_NEARBY_INTERNAL_BASE_BLUETOOTH_ADDRESS_H_
#include <stddef.h>
#include <stdint.h>
#include <array>
#include <string>
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
namespace nearby {
namespace device {
// Parses a Bluetooth address to an output buffer. The output buffer must be
// exactly 6 bytes in size. The address can be formatted in one of three ways:
//
// 1A:2B:3C:4D:5E:6F
// 1A-2B-3C-4D-5E-6F
// 1A2B3C4D5E6F
bool ParseBluetoothAddress(absl::string_view input, absl::Span<uint8_t> output);
// Converts a uint64_t Bluetooth address to string.
std::string ConvertBluetoothAddressUIntToString(uint64_t address);
// Returns |address| in the canonical format: XX:XX:XX:XX:XX:XX, where each 'X'
// is a hex digit. If the input |address| is invalid, returns an empty string.
std::string CanonicalizeBluetoothAddress(absl::string_view address);
std::string CanonicalizeBluetoothAddress(
const std::array<uint8_t, 6>& address_bytes);
std::string CanonicalizeBluetoothAddress(uint64_t address);
} // namespace device
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_INTERNAL_BASE_BLUETOOTH_ADDRESS_H_
+59
View File
@@ -0,0 +1,59 @@
// Copyright 2021 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/base/bluetooth_address.h"
#include <array>
#include <string>
#include "absl/types/span.h"
#include "gtest/gtest.h"
namespace nearby {
namespace device {
namespace {
TEST(BluetoothUtil, ParseBluetoothAddress) {
std::array<uint8_t, 6> output;
std::array<uint8_t, 6> expected_output{{26, 43, 60, 77, 94, 111}};
EXPECT_TRUE(ParseBluetoothAddress(
"1A:2B:3C:4D:5E:6F", absl::MakeSpan(output.data(), output.size())));
EXPECT_EQ(output, expected_output);
}
TEST(BluetoothUtil, ConvertBluetoothAddressUIntToString) {
const uint64_t input = 0x00001A2B3C4D5E6F;
std::string expected_output = "1A:2B:3C:4D:5E:6F";
std::string output = ConvertBluetoothAddressUIntToString(input);
EXPECT_EQ(output, expected_output);
}
TEST(BluetoothUtil, CanonicalizeBluetoothAddress) {
std::array<uint8_t, 6> address{{26, 43, 60, 77, 94, 111}};
EXPECT_EQ(CanonicalizeBluetoothAddress(address), "1A:2B:3C:4D:5E:6F");
EXPECT_EQ(CanonicalizeBluetoothAddress("1A-2B-3C-4D-5E-6F"),
"1A:2B:3C:4D:5E:6F");
EXPECT_EQ(CanonicalizeBluetoothAddress(0x00001A2B3C4D5E6F),
"1A:2B:3C:4D:5E:6F");
// Canonicalizes invalid address
EXPECT_EQ(CanonicalizeBluetoothAddress("1A-2B-3C-4D-5E-6F-89"), "");
EXPECT_EQ(CanonicalizeBluetoothAddress("nearby"), "");
EXPECT_EQ(CanonicalizeBluetoothAddress("MA-2M-3C-4D-5E-6F"), "");
EXPECT_EQ(CanonicalizeBluetoothAddress(0x001A2B3C4D5E6F89), "");
}
} // namespace
} // namespace device
} // namespace nearby