mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Add TLV parsing and vendor ID tlv to C++ advertisement.
PiperOrigin-RevId: 635936457
This commit is contained in:
committed by
Copybara-Service
parent
0e85eb6a58
commit
ffda9da870
+88
-20
@@ -49,9 +49,36 @@ constexpr uint8_t kVisibilityBitmask = 0b1;
|
||||
// The bit mask for parsing and writing Device Type.
|
||||
constexpr uint8_t kDeviceTypeBitmask = 0b111;
|
||||
|
||||
// The minimum length of a TLV element.
|
||||
// 1 byte for type and 1 byte for length, which can be 0.
|
||||
constexpr uint8_t kTlvMinimumLength = 2;
|
||||
// LINT.IfChange()
|
||||
enum class TlvTypes : uint8_t {
|
||||
kUnknown = 0,
|
||||
kQrCode = 1,
|
||||
kVendorId = 2,
|
||||
};
|
||||
|
||||
enum class VendorId : uint8_t {
|
||||
kNone = 0,
|
||||
kSamsung = 1,
|
||||
};
|
||||
// The length in bytes of the vendor ID in the TLV advertisement.
|
||||
constexpr uint8_t kVendorIdLength = 1;
|
||||
|
||||
// Turns |vendor_id| into a supported vendor ID.
|
||||
uint8_t ConvertVendorId(uint8_t vendor_id) {
|
||||
switch (vendor_id) {
|
||||
case 1:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// LINT.ThenChange(//depot/google3/java/com/google/android/gmscore/integ/modules/nearby/src/com/google/android/gms/nearby/sharing/provider/connections/certificatemanager/Advertisement.java)
|
||||
|
||||
const uint8_t kMinimumSize =
|
||||
/* Version(3 bits)|Visibility(1 bit)|Device Type(3 bits)|Reserved(1 bits)=
|
||||
*/
|
||||
/* Version(3 bits)|Visibility(1 bit)|Device Type(3 bits)|Reserved(1 bits) */
|
||||
1 + sharing::Advertisement::kSaltSize +
|
||||
sharing::Advertisement::kMetadataEncryptionKeyHashByteSize;
|
||||
|
||||
@@ -94,14 +121,13 @@ ShareTargetType ParseDeviceType(uint8_t b) {
|
||||
bool ParseHasDeviceName(uint8_t b) {
|
||||
return ((b >> 4) & kVisibilityBitmask) == 0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
std::unique_ptr<Advertisement> Advertisement::NewInstance(
|
||||
std::vector<uint8_t> salt, std::vector<uint8_t> encrypted_metadata_key,
|
||||
ShareTargetType device_type, std::optional<std::string> device_name,
|
||||
int32_t vendor_id) {
|
||||
uint8_t vendor_id) {
|
||||
if (salt.size() != Advertisement::kSaltSize) {
|
||||
NL_LOG(ERROR) << "Failed to create advertisement because the salt did "
|
||||
"not match the expected length "
|
||||
@@ -132,8 +158,13 @@ std::unique_ptr<Advertisement> Advertisement::NewInstance(
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Advertisement::ToEndpointInfo() {
|
||||
// We add 3 bytes for vendor ID because of type (1 byte), len (1 byte), and
|
||||
// the ID itself (1 byte).
|
||||
int size = kMinimumSize + (device_name_.has_value() ? 1 : 0) +
|
||||
(device_name_.has_value() ? device_name_->size() : 0);
|
||||
(device_name_.has_value() ? device_name_->size() : 0) +
|
||||
(vendor_id_ != static_cast<uint8_t>(VendorId::kNone)
|
||||
? (kTlvMinimumLength + kVendorIdLength)
|
||||
: 0);
|
||||
|
||||
std::vector<uint8_t> endpoint_info;
|
||||
endpoint_info.reserve(size);
|
||||
@@ -151,6 +182,16 @@ std::vector<uint8_t> Advertisement::ToEndpointInfo() {
|
||||
device_name_->end());
|
||||
}
|
||||
|
||||
// Add vendor ID if it is not the default |VendorId::kNone|.
|
||||
if (vendor_id_ != static_cast<uint8_t>(VendorId::kNone)) {
|
||||
// Add vendor ID in TLV format.
|
||||
endpoint_info.push_back(static_cast<uint8_t>(TlvTypes::kVendorId));
|
||||
// Length is 1 byte.
|
||||
endpoint_info.push_back(kVendorIdLength);
|
||||
// The vendor ID itself.
|
||||
endpoint_info.push_back(vendor_id_);
|
||||
}
|
||||
|
||||
return endpoint_info;
|
||||
}
|
||||
|
||||
@@ -182,27 +223,54 @@ std::unique_ptr<Advertisement> Advertisement::FromEndpointInfo(
|
||||
iter, iter + Advertisement::kMetadataEncryptionKeyHashByteSize);
|
||||
iter += Advertisement::kMetadataEncryptionKeyHashByteSize;
|
||||
|
||||
int device_name_length = 0;
|
||||
if (iter != endpoint_info.end()) device_name_length = *iter++ & 0xff;
|
||||
|
||||
if (endpoint_info.end() - iter < device_name_length ||
|
||||
(device_name_length == 0 && has_device_name)) {
|
||||
NL_LOG(ERROR)
|
||||
<< "Failed to parse advertisement because the device name did "
|
||||
"not match the expected length "
|
||||
<< device_name_length;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::optional<std::string> optional_device_name;
|
||||
if (device_name_length > 0) {
|
||||
if (has_device_name) {
|
||||
int device_name_length = 0;
|
||||
if (iter != endpoint_info.end()) device_name_length = *iter++ & 0xff;
|
||||
|
||||
if (device_name_length == 0 ||
|
||||
(endpoint_info.end() - iter < device_name_length)) {
|
||||
NL_LOG(ERROR)
|
||||
<< "Failed to parse advertisement because the device name did "
|
||||
"not match the expected length "
|
||||
<< device_name_length;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
optional_device_name = std::string(iter, iter + device_name_length);
|
||||
iter += device_name_length;
|
||||
}
|
||||
|
||||
uint8_t vendor_id = static_cast<uint8_t>(VendorId::kNone);
|
||||
while (endpoint_info.end() - iter >= kTlvMinimumLength) {
|
||||
// We will parse a TLV element now.
|
||||
TlvTypes type = static_cast<TlvTypes>(*iter++);
|
||||
uint8_t value_len = *iter++;
|
||||
if (endpoint_info.end() - iter < value_len) {
|
||||
NL_LOG(ERROR) << "Invalid length when parsing TLV element: " << value_len;
|
||||
return nullptr;
|
||||
}
|
||||
switch (type) {
|
||||
case TlvTypes::kVendorId:
|
||||
if (value_len != kVendorIdLength) {
|
||||
NL_LOG(ERROR) << "Invalid vendor_id_len: " << value_len;
|
||||
return nullptr;
|
||||
}
|
||||
vendor_id = ConvertVendorId(*iter++);
|
||||
break;
|
||||
case TlvTypes::kQrCode:
|
||||
// TODO: b/341984671 - Implement handling for this TLV type.
|
||||
break;
|
||||
default:
|
||||
NL_LOG(ERROR) << "Unknown TLV type: " << static_cast<uint8_t>(type);
|
||||
break;
|
||||
}
|
||||
iter += value_len;
|
||||
}
|
||||
|
||||
return Advertisement::NewInstance(
|
||||
std::move(salt), std::move(encrypted_metadata_key), device_type,
|
||||
std::move(optional_device_name), /*vendor_id=*/0);
|
||||
std::move(optional_device_name), vendor_id);
|
||||
}
|
||||
|
||||
bool Advertisement::operator==(const Advertisement& other) const {
|
||||
@@ -217,7 +285,7 @@ Advertisement::Advertisement(int version, std::vector<uint8_t> salt,
|
||||
std::vector<uint8_t> encrypted_metadata_key,
|
||||
ShareTargetType device_type,
|
||||
std::optional<std::string> device_name,
|
||||
int32_t vendor_id)
|
||||
uint8_t vendor_id)
|
||||
: version_(version),
|
||||
salt_(std::move(salt)),
|
||||
encrypted_metadata_key_(std::move(encrypted_metadata_key)),
|
||||
|
||||
@@ -40,12 +40,14 @@ class Advertisement {
|
||||
static std::unique_ptr<Advertisement> NewInstance(
|
||||
std::vector<uint8_t> salt, std::vector<uint8_t> encrypted_metadata_key,
|
||||
ShareTargetType device_type, std::optional<std::string> device_name,
|
||||
int32_t vendor_id);
|
||||
uint8_t vendor_id);
|
||||
|
||||
// TODO: b/341967036 - Remove uses of std::optional for device name. Empty
|
||||
// string should be enough.
|
||||
Advertisement(int version, std::vector<uint8_t> salt,
|
||||
std::vector<uint8_t> encrypted_metadata_key,
|
||||
ShareTargetType device_type,
|
||||
std::optional<std::string> device_name, int32_t vendor_id);
|
||||
std::optional<std::string> device_name, uint8_t vendor_id);
|
||||
~Advertisement() = default;
|
||||
Advertisement(const Advertisement&) = default;
|
||||
Advertisement& operator=(const Advertisement&) = default;
|
||||
@@ -63,7 +65,7 @@ class Advertisement {
|
||||
ShareTargetType device_type() const { return device_type_; }
|
||||
const std::optional<std::string>& device_name() const { return device_name_; }
|
||||
bool HasDeviceName() const { return device_name_.has_value(); }
|
||||
int32_t vendor_id() const { return vendor_id_; }
|
||||
uint8_t vendor_id() const { return vendor_id_; }
|
||||
|
||||
static std::unique_ptr<Advertisement> FromEndpointInfo(
|
||||
absl::Span<const uint8_t> endpoint_info);
|
||||
@@ -91,7 +93,7 @@ class Advertisement {
|
||||
|
||||
// The vendor identifier of the remote device. Reference for vendor ID:
|
||||
// google3/java/com/google/android/gmscore/integ/client/nearby/src/com/google/android/gms/nearby/sharing/SharingOptions.java
|
||||
const int32_t vendor_id_;
|
||||
const uint8_t vendor_id_;
|
||||
};
|
||||
|
||||
} // namespace sharing
|
||||
|
||||
@@ -67,6 +67,21 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
.target_type = ShareTargetType::kTablet,
|
||||
.target_name = std::nullopt,
|
||||
.vendor_id = 0}));
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
VendorIds, AdvertisementTest,
|
||||
testing::Values(
|
||||
TestParameters{.salt = std::vector<uint8_t>(Advertisement::kSaltSize),
|
||||
.encrypted_metadata_key = std::vector<uint8_t>(
|
||||
Advertisement::kMetadataEncryptionKeyHashByteSize),
|
||||
.target_type = ShareTargetType::kPhone,
|
||||
.target_name = std::nullopt,
|
||||
.vendor_id = 0},
|
||||
TestParameters{.salt = std::vector<uint8_t>(Advertisement::kSaltSize),
|
||||
.encrypted_metadata_key = std::vector<uint8_t>(
|
||||
Advertisement::kMetadataEncryptionKeyHashByteSize),
|
||||
.target_type = ShareTargetType::kPhone,
|
||||
.target_name = std::nullopt,
|
||||
.vendor_id = 1}));
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
TargetNames, AdvertisementTest,
|
||||
testing::Values(
|
||||
|
||||
Reference in New Issue
Block a user