mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Add BleL2capPacket
PiperOrigin-RevId: 736771387
This commit is contained in:
committed by
Copybara-Service
parent
f168d0c91b
commit
2ea692213d
@@ -460,6 +460,7 @@ let package = Package(
|
||||
"connections/implementation/mediums/advertisements/advertisement_util_test.cc",
|
||||
"connections/implementation/mediums/ble_v2_test.cc",
|
||||
"connections/implementation/mediums/ble_v2/bloom_filter_test.cc",
|
||||
"connections/implementation/mediums/ble_v2/ble_l2cap_packet_test.cc",
|
||||
"connections/implementation/mediums/ble_v2/ble_packet_test.cc",
|
||||
"connections/implementation/mediums/ble_v2/ble_advertisement_test.cc",
|
||||
"connections/implementation/mediums/ble_v2/advertisement_read_result_test.cc",
|
||||
|
||||
@@ -54,6 +54,7 @@ cc_library(
|
||||
srcs = [
|
||||
"advertisement_read_result.cc",
|
||||
"ble_advertisement.cc",
|
||||
"ble_l2cap_packet.cc",
|
||||
"ble_packet.cc",
|
||||
"ble_utils.cc",
|
||||
"discovered_peripheral_tracker.cc",
|
||||
@@ -63,6 +64,7 @@ cc_library(
|
||||
hdrs = [
|
||||
"advertisement_read_result.h",
|
||||
"ble_advertisement.h",
|
||||
"ble_l2cap_packet.h",
|
||||
"ble_packet.h",
|
||||
"ble_utils.h",
|
||||
"discovered_peripheral_callback.h",
|
||||
@@ -111,6 +113,7 @@ cc_test(
|
||||
"advertisement_read_result_test.cc",
|
||||
"ble_advertisement_header_test.cc",
|
||||
"ble_advertisement_test.cc",
|
||||
"ble_l2cap_packet_test.cc",
|
||||
"ble_packet_test.cc",
|
||||
"ble_utils_test.cc",
|
||||
"bloom_filter_test.cc",
|
||||
|
||||
@@ -62,7 +62,25 @@ class BleAdvertisement {
|
||||
|
||||
static constexpr int kServiceIdHashLength = 3;
|
||||
static constexpr int kDeviceTokenLength = 2;
|
||||
|
||||
static constexpr int kVersionLength = 1;
|
||||
static constexpr int kVersionBitmask = 0x0E0;
|
||||
static constexpr int kSocketVersionBitmask = 0x01C;
|
||||
static constexpr int kFastAdvertisementFlagBitmask = 0x002;
|
||||
static constexpr int kDataSizeLength = 4; // Length of one int.
|
||||
static constexpr int kFastDataSizeLength = 1; // Length of one byte.
|
||||
static constexpr int kMinAdvertisementLength =
|
||||
kVersionLength + kServiceIdHashLength + kDataSizeLength;
|
||||
// The maximum length for a Gatt characteristic value is 512 bytes, so make
|
||||
// sure the entire advertisement is less than that. The data can take up
|
||||
// whatever space is remaining after the bytes preceding it.
|
||||
static constexpr int kMaxAdvertisementLength = 512;
|
||||
static constexpr int kMinFastAdvertisementLegth =
|
||||
kVersionLength + kFastDataSizeLength;
|
||||
// The maximum length for the scan response is 31 bytes. However, with the
|
||||
// required header that comes before the service data, this leaves the
|
||||
// advertiser with 27 leftover bytes.
|
||||
static constexpr int kMaxFastAdvertisementLength = 27;
|
||||
static constexpr int kExtraFieldsMaskLength = 1;
|
||||
// Hashable
|
||||
bool operator==(const BleAdvertisement &rhs) const;
|
||||
template <typename H>
|
||||
@@ -160,26 +178,6 @@ class BleAdvertisement {
|
||||
total_optional_length);
|
||||
}
|
||||
|
||||
static constexpr int kVersionLength = 1;
|
||||
static constexpr int kVersionBitmask = 0x0E0;
|
||||
static constexpr int kSocketVersionBitmask = 0x01C;
|
||||
static constexpr int kFastAdvertisementFlagBitmask = 0x002;
|
||||
static constexpr int kDataSizeLength = 4; // Length of one int.
|
||||
static constexpr int kFastDataSizeLength = 1; // Length of one byte.
|
||||
static constexpr int kMinAdvertisementLength =
|
||||
kVersionLength + kServiceIdHashLength + kDataSizeLength;
|
||||
// The maximum length for a Gatt characteristic value is 512 bytes, so make
|
||||
// sure the entire advertisement is less than that. The data can take up
|
||||
// whatever space is remaining after the bytes preceding it.
|
||||
static constexpr int kMaxAdvertisementLength = 512;
|
||||
static constexpr int kMinFastAdvertisementLegth =
|
||||
kVersionLength + kFastDataSizeLength;
|
||||
// The maximum length for the scan response is 31 bytes. However, with the
|
||||
// required header that comes before the service data, this leaves the
|
||||
// advertiser with 27 leftover bytes.
|
||||
static constexpr int kMaxFastAdvertisementLength = 27;
|
||||
static constexpr int kExtraFieldsMaskLength = 1;
|
||||
|
||||
Version version_{Version::kUndefined};
|
||||
SocketVersion socket_version_{SocketVersion::kUndefined};
|
||||
bool fast_advertisement_ = false;
|
||||
|
||||
@@ -146,7 +146,7 @@ BleAdvertisementHeader::operator ByteArray() const {
|
||||
// Convert psm_ value to 2-bytes.
|
||||
ByteArray psm_bytes{kPsmValueByteLength};
|
||||
char *data = psm_bytes.data();
|
||||
data[0] = psm_ & 0xFF00;
|
||||
data[0] = (psm_ & 0xFF00) >> 8;
|
||||
data[1] = psm_ & 0x00FF;
|
||||
|
||||
// clang-format off
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
// Copyright 2025 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 "connections/implementation/mediums/ble_v2/ble_l2cap_packet.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "connections/implementation/mediums/ble_v2/ble_advertisement.h"
|
||||
#include "connections/implementation/mediums/utils.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/stream_reader.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace mediums {
|
||||
|
||||
BleL2capPacket::BleL2capPacket(Command command,
|
||||
const ByteArray* service_id_hash,
|
||||
const ByteArray* data)
|
||||
: command_(command) {
|
||||
if (service_id_hash) {
|
||||
service_id_hash_ = *service_id_hash;
|
||||
}
|
||||
if (data) {
|
||||
advertisement_ = *data;
|
||||
}
|
||||
}
|
||||
|
||||
absl::StatusOr<BleL2capPacket> BleL2capPacket::CreateFromBytes(
|
||||
const ByteArray& bytes) {
|
||||
if (bytes.size() < kCommandLength) {
|
||||
LOG(INFO) << "Cannot deserialize BleL2capPacket: expecting min "
|
||||
<< kCommandLength << " bytes, got " << bytes.size();
|
||||
return absl::InvalidArgumentError(
|
||||
"Cannot deserialize BleL2capPacket: input bytes too short.");
|
||||
}
|
||||
|
||||
StreamReader stream_reader(bytes);
|
||||
// The first 1 byte is the command.
|
||||
auto command_byte = stream_reader.ReadUint8();
|
||||
if (!command_byte.has_value()) {
|
||||
LOG(INFO)
|
||||
<< "Cannot deserialize BleL2capPacket: command byte not available.";
|
||||
return absl::InvalidArgumentError(
|
||||
"Cannot deserialize BleL2capPacket: command byte not available.");
|
||||
}
|
||||
Command command_data = static_cast<Command>(*command_byte);
|
||||
|
||||
if (command_data == Command::kRequestAdvertisementFinish ||
|
||||
command_data == Command::kRequestDataConnection ||
|
||||
command_data == Command::kResponseServiceIdNotFound ||
|
||||
command_data == Command::kResponseDataConnectionReady ||
|
||||
command_data == Command::kResponseDataConnectionFailure) {
|
||||
return BleL2capPacket(command_data, nullptr, nullptr);
|
||||
}
|
||||
|
||||
if (!stream_reader.IsAvailable(kDataLength)) {
|
||||
LOG(INFO) << "Cannot deserialize BleL2capPacket: data length bytes not "
|
||||
"available.";
|
||||
return absl::InvalidArgumentError(
|
||||
"Cannot deserialize BleL2capPacket: data length bytes not available.");
|
||||
}
|
||||
|
||||
int data_length = stream_reader.ReadUint16().value_or(0);
|
||||
if (data_length == 0) {
|
||||
LOG(INFO) << "Cannot deserialize BleL2capPacket: data length incorrect.";
|
||||
return absl::InvalidArgumentError(
|
||||
"Cannot deserialize BleL2capPacket: data length incorrect.");
|
||||
}
|
||||
|
||||
if (command_data == Command::kRequestAdvertisement) {
|
||||
if (data_length < BleAdvertisement::kServiceIdHashLength) {
|
||||
LOG(INFO)
|
||||
<< "Cannot deserialize BleL2capPacket: service id hash length, got "
|
||||
<< data_length;
|
||||
return absl::InvalidArgumentError(
|
||||
"Cannot deserialize BleL2capPacket: service id hash length "
|
||||
"incorrect.");
|
||||
}
|
||||
auto service_id_hash_data = stream_reader.ReadBytes(data_length);
|
||||
if (!service_id_hash_data.has_value()) {
|
||||
LOG(INFO) << "Cannot deserialize BleL2capPacket: service id hash not "
|
||||
"available.";
|
||||
return absl::InvalidArgumentError(
|
||||
"Cannot deserialize BleL2capPacket: service id hash not available.");
|
||||
}
|
||||
return BleL2capPacket(command_data, &service_id_hash_data.value(), nullptr);
|
||||
} else if (command_data == Command::kResponseAdvertisement) {
|
||||
if (data_length > BleAdvertisement::kMaxAdvertisementLength) {
|
||||
LOG(INFO) << "Cannot deserialize BleL2capPacket: advertisement length, "
|
||||
"got "
|
||||
<< data_length;
|
||||
return absl::InvalidArgumentError(
|
||||
"Cannot deserialize BleL2capPacket: advertisement length incorrect.");
|
||||
}
|
||||
auto advertisement_data = stream_reader.ReadBytes(data_length);
|
||||
if (!advertisement_data.has_value()) {
|
||||
LOG(INFO)
|
||||
<< "Cannot deserialize BleL2capPacket: advertisement not available.";
|
||||
return absl::InvalidArgumentError(
|
||||
"Cannot deserialize BleL2capPacket: advertisement not available.");
|
||||
}
|
||||
return BleL2capPacket(command_data, nullptr, &advertisement_data.value());
|
||||
} else {
|
||||
LOG(INFO) << "Cannot deserialize BleL2capPacket: unsupported command "
|
||||
<< static_cast<int>(command_data);
|
||||
return absl::InvalidArgumentError(
|
||||
"Cannot deserialize BleL2capPacket: unsupported command.");
|
||||
}
|
||||
}
|
||||
|
||||
absl::StatusOr<ByteArray> BleL2capPacket::ByteArrayForRequestAdvertisement(
|
||||
const std::string& service_id) {
|
||||
if (service_id.empty()) {
|
||||
return absl::InvalidArgumentError(
|
||||
"Cannot deserialize BleL2capPacket: service id is empty.");
|
||||
}
|
||||
ByteArray service_id_hash = GenerateServiceIdHash(service_id);
|
||||
return ByteArrayForCommand(BleL2capPacket::Command::kRequestAdvertisement,
|
||||
&service_id_hash);
|
||||
}
|
||||
|
||||
absl::StatusOr<ByteArray> BleL2capPacket::ByteArrayForResponseAdvertisement(
|
||||
const ByteArray& advertisement) {
|
||||
if (advertisement.size() < BleAdvertisement::kMinAdvertisementLength) {
|
||||
return absl::InvalidArgumentError(
|
||||
"Cannot deserialize BleL2capPacket: advertisement size is too small.");
|
||||
}
|
||||
return ByteArrayForCommand(BleL2capPacket::Command::kResponseAdvertisement,
|
||||
&advertisement);
|
||||
}
|
||||
|
||||
ByteArray BleL2capPacket::ByteArrayForRequestAdvertisementFinish() {
|
||||
return ByteArrayForCommand(
|
||||
BleL2capPacket::Command::kRequestAdvertisementFinish, {});
|
||||
}
|
||||
|
||||
ByteArray BleL2capPacket::ByteArrayForServiceIdNotFound() {
|
||||
return ByteArrayForCommand(Command::kResponseServiceIdNotFound, {});
|
||||
}
|
||||
|
||||
ByteArray BleL2capPacket::ByteArrayForRequestDataConnection() {
|
||||
return ByteArrayForCommand(Command::kRequestDataConnection, {});
|
||||
}
|
||||
|
||||
ByteArray BleL2capPacket::ByteArrayForDataConnectionReady() {
|
||||
return ByteArrayForCommand(Command::kResponseDataConnectionReady, {});
|
||||
}
|
||||
|
||||
ByteArray BleL2capPacket::ByteArrayForDataConnectionFailure() {
|
||||
return ByteArrayForCommand(Command::kResponseDataConnectionFailure, {});
|
||||
}
|
||||
|
||||
ByteArray BleL2capPacket::GenerateServiceIdHash(const std::string& service_id) {
|
||||
return Utils::Sha256Hash(service_id, BleAdvertisement::kServiceIdHashLength);
|
||||
}
|
||||
|
||||
ByteArray BleL2capPacket::ByteArrayForCommand(BleL2capPacket::Command command,
|
||||
const ByteArray* data) {
|
||||
std::string out;
|
||||
if (data) {
|
||||
ByteArray length_bytes{kDataLength};
|
||||
char* length_bytes_data = length_bytes.data();
|
||||
length_bytes_data[0] = (data->size() & 0xFF00) >> 8;
|
||||
length_bytes_data[1] = data->size() & 0x00FF;
|
||||
out = absl::StrCat(std::string(1, static_cast<char>(command)),
|
||||
std::string(length_bytes), std::string(*data));
|
||||
} else {
|
||||
out = static_cast<char>(command);
|
||||
}
|
||||
return ByteArray{std::move(out)};
|
||||
}
|
||||
|
||||
} // namespace mediums
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,135 @@
|
||||
// Copyright 2025 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef CORE_INTERNAL_MEDIUMS_BLE_V2_BLE_L2CAP_PACKET_H_
|
||||
#define CORE_INTERNAL_MEDIUMS_BLE_V2_BLE_L2CAP_PACKET_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/status/statusor.h"
|
||||
#include "connections/implementation/mediums/ble_v2/ble_advertisement.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace mediums {
|
||||
|
||||
// Represents the format of the BLE L2CAP packet used in L2CAP socket for
|
||||
// requesting/responsing.
|
||||
//
|
||||
// [COMMAND] or [COMMAND][LENGTH][DATA]
|
||||
//
|
||||
class BleL2capPacket {
|
||||
public:
|
||||
enum class Command {
|
||||
// Use to fetch advertisement from server with serviceId.
|
||||
kRequestAdvertisement = 1,
|
||||
// Use to notify the server have fetched all advertisements completely.
|
||||
kRequestAdvertisementFinish = 2,
|
||||
// Use to notify the server current L2CAP socket use for file transferring.
|
||||
kRequestDataConnection = 3,
|
||||
// 11-20 reserved
|
||||
// Use to response the advertisement raw data to the client.
|
||||
kResponseAdvertisement = 21,
|
||||
// Use to response the queried service ID not exist in server side.
|
||||
kResponseServiceIdNotFound = 22,
|
||||
// Use to notify the data connection ready
|
||||
kResponseDataConnectionReady = 23,
|
||||
// Use to notify failure for requesting the data connection.
|
||||
kResponseDataConnectionFailure = 24,
|
||||
};
|
||||
|
||||
static constexpr int kCommandLength = 1;
|
||||
static constexpr int kDataLength = 2;
|
||||
// The maximum length of a BleL2capPacket is the length when carry the
|
||||
// advertisement raw data.
|
||||
static constexpr int kMaxLength =
|
||||
kCommandLength + kDataLength + BleAdvertisement::kMaxAdvertisementLength;
|
||||
|
||||
// Creates a BleL2capPacket from the raw bytes.
|
||||
static absl::StatusOr<BleL2capPacket> CreateFromBytes(const ByteArray& bytes);
|
||||
// Creates a BleL2capPacket for requesting advertisement with service ID.
|
||||
static absl::StatusOr<ByteArray> ByteArrayForRequestAdvertisement(
|
||||
const std::string& service_id);
|
||||
// Creates a BleL2capPacket for responding advertisement with raw data.
|
||||
static absl::StatusOr<ByteArray> ByteArrayForResponseAdvertisement(
|
||||
const ByteArray& advertisement);
|
||||
// Creates a BleL2capPacket for requesting advertisement finish.
|
||||
static ByteArray ByteArrayForRequestAdvertisementFinish();
|
||||
// Creates a BleL2capPacket for responding service ID not found.
|
||||
static ByteArray ByteArrayForServiceIdNotFound();
|
||||
// Creates a BleL2capPacket for requesting data connection.
|
||||
static ByteArray ByteArrayForRequestDataConnection();
|
||||
// Creates a BleL2capPacket for responding data connection ready.
|
||||
static ByteArray ByteArrayForDataConnectionReady();
|
||||
// Creates a BleL2capPacket for responding data connection failure.
|
||||
static ByteArray ByteArrayForDataConnectionFailure();
|
||||
// Generates the service ID hash bytes from the service ID string.
|
||||
static ByteArray GenerateServiceIdHash(const std::string& service_id);
|
||||
// Checks if the length of the BleL2capPacket is valid.
|
||||
static bool IsValidLength(int length) {
|
||||
return length > 0 && length <= kMaxLength;
|
||||
}
|
||||
|
||||
BleL2capPacket(Command command, const ByteArray* service_id_hash,
|
||||
const ByteArray* data);
|
||||
BleL2capPacket(const BleL2capPacket&) = default;
|
||||
BleL2capPacket& operator=(const BleL2capPacket&) = default;
|
||||
BleL2capPacket(BleL2capPacket&&) = default;
|
||||
BleL2capPacket& operator=(BleL2capPacket&&) = default;
|
||||
~BleL2capPacket() = default;
|
||||
|
||||
explicit operator ByteArray() const;
|
||||
|
||||
// The service ID hash bytes, only exist for command REQUEST_ADVERTISEMENT and
|
||||
// Command.REQUEST_DATA_CONNECTION.
|
||||
ByteArray GetServiceIdHash() const { return service_id_hash_; }
|
||||
// The advertisement raw bytes, only exist for command RESPONSE_ADVERTISEMENT.
|
||||
ByteArray GetAdvertisement() const { return advertisement_; }
|
||||
bool IsErrorServiceIdNotFound() const {
|
||||
return command_ == Command::kResponseServiceIdNotFound;
|
||||
}
|
||||
bool IsAdvertisementResponse() const {
|
||||
return command_ == Command::kResponseAdvertisement;
|
||||
}
|
||||
bool IsFetchAdvertisementRequest() const {
|
||||
return command_ == Command::kRequestAdvertisement;
|
||||
}
|
||||
bool IsFetchAdvertisementFinished() const {
|
||||
return command_ == Command::kRequestAdvertisementFinish;
|
||||
}
|
||||
bool IsDataConnectionRequest() const {
|
||||
return command_ == Command::kRequestDataConnection;
|
||||
}
|
||||
bool IsDataConnectionReadyResponse() const {
|
||||
return command_ == Command::kResponseDataConnectionReady;
|
||||
}
|
||||
bool IsDataConnectionFailureResponse() const {
|
||||
return command_ == Command::kResponseDataConnectionFailure;
|
||||
}
|
||||
|
||||
private:
|
||||
BleL2capPacket() = default;
|
||||
static ByteArray ByteArrayForCommand(Command command, const ByteArray* data);
|
||||
|
||||
Command command_;
|
||||
ByteArray service_id_hash_;
|
||||
ByteArray advertisement_;
|
||||
};
|
||||
|
||||
} // namespace mediums
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
|
||||
#endif // CORE_INTERNAL_MEDIUMS_BLE_V2_BLE_L2CAP_PACKET_H_
|
||||
@@ -0,0 +1,203 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "connections/implementation/mediums/ble_v2/ble_l2cap_packet.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace mediums {
|
||||
namespace {
|
||||
|
||||
constexpr absl::string_view kInCorrectData = {"\x01\x02\x03\x04\x05"};
|
||||
constexpr absl::string_view kServiceID = "1test_service_id";
|
||||
constexpr absl::string_view kCorrectData = {
|
||||
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x00"};
|
||||
|
||||
TEST(BleL2capPacketTest, ByteArrayForRequestAdvertisementWithCorrectServiceID) {
|
||||
auto byte_array =
|
||||
BleL2capPacket::ByteArrayForRequestAdvertisement(std::string(kServiceID));
|
||||
|
||||
ASSERT_TRUE(byte_array.ok());
|
||||
|
||||
auto result = BleL2capPacket::CreateFromBytes(*byte_array);
|
||||
ASSERT_TRUE(result.ok());
|
||||
ASSERT_TRUE(result.value().IsFetchAdvertisementRequest());
|
||||
ASSERT_EQ(result.value().GetServiceIdHash(),
|
||||
BleL2capPacket::GenerateServiceIdHash(std::string(kServiceID)));
|
||||
}
|
||||
|
||||
TEST(BleL2capPacketTest, ByteArrayForRequestAdvertisementWithEmptyServiceID) {
|
||||
auto byte_array = BleL2capPacket::ByteArrayForRequestAdvertisement("");
|
||||
|
||||
ASSERT_FALSE(byte_array.ok());
|
||||
}
|
||||
|
||||
TEST(BleL2capPacketTest,
|
||||
ByteArrayForResponseAdvertisementWithCorrectAdvertisement) {
|
||||
ByteArray advertisement(kCorrectData.data(), kCorrectData.size());
|
||||
auto byte_array =
|
||||
BleL2capPacket::ByteArrayForResponseAdvertisement(advertisement);
|
||||
|
||||
ASSERT_TRUE(byte_array.ok());
|
||||
|
||||
auto result = BleL2capPacket::CreateFromBytes(*byte_array);
|
||||
ASSERT_TRUE(result.ok());
|
||||
ASSERT_TRUE(result.value().IsAdvertisementResponse());
|
||||
ASSERT_EQ(result.value().GetAdvertisement(), advertisement);
|
||||
}
|
||||
|
||||
TEST(BleL2capPacketTest,
|
||||
ByteArrayForResponseAdvertisementWithInCorrectAdvertisement) {
|
||||
ByteArray advertisement(kInCorrectData.data(), kInCorrectData.size());
|
||||
auto byte_array =
|
||||
BleL2capPacket::ByteArrayForResponseAdvertisement(advertisement);
|
||||
|
||||
ASSERT_FALSE(byte_array.ok());
|
||||
}
|
||||
|
||||
TEST(BleL2capPacketTest,
|
||||
ByteArrayForResponseAdvertisementWithLargeAdvertisement) {
|
||||
auto byte_array =
|
||||
BleL2capPacket::ByteArrayForResponseAdvertisement(ByteArray(300));
|
||||
|
||||
ASSERT_TRUE(byte_array.ok());
|
||||
|
||||
auto result = BleL2capPacket::CreateFromBytes(byte_array.value());
|
||||
ASSERT_TRUE(result.ok());
|
||||
ASSERT_TRUE(result.value().IsAdvertisementResponse());
|
||||
ASSERT_EQ(result.value().GetAdvertisement().size(), 300);
|
||||
}
|
||||
|
||||
TEST(BleL2capPacketTest, ByteArrayForRequestAdvertisementFinish) {
|
||||
ByteArray byte_array =
|
||||
BleL2capPacket::ByteArrayForRequestAdvertisementFinish();
|
||||
|
||||
auto result = BleL2capPacket::CreateFromBytes(byte_array);
|
||||
ASSERT_TRUE(result.ok());
|
||||
ASSERT_TRUE(result.value().IsFetchAdvertisementFinished());
|
||||
}
|
||||
|
||||
TEST(BleL2capPacketTest, ByteArrayForServiceIdNotFound) {
|
||||
ByteArray byte_array = BleL2capPacket::ByteArrayForServiceIdNotFound();
|
||||
|
||||
auto result = BleL2capPacket::CreateFromBytes(byte_array);
|
||||
ASSERT_TRUE(result.value().IsErrorServiceIdNotFound());
|
||||
}
|
||||
|
||||
TEST(BleL2capPacketTest, ByteArrayForRequestDataConnection) {
|
||||
ByteArray byte_array = BleL2capPacket::ByteArrayForRequestDataConnection();
|
||||
|
||||
auto result = BleL2capPacket::CreateFromBytes(byte_array);
|
||||
ASSERT_TRUE(result.ok());
|
||||
ASSERT_TRUE(result.value().IsDataConnectionRequest());
|
||||
}
|
||||
|
||||
TEST(BleL2capPacketTest, ByteArrayForDataConnectionReady) {
|
||||
ByteArray byte_array = BleL2capPacket::ByteArrayForDataConnectionReady();
|
||||
|
||||
auto result = BleL2capPacket::CreateFromBytes(byte_array);
|
||||
ASSERT_TRUE(result.ok());
|
||||
ASSERT_TRUE(result.value().IsDataConnectionReadyResponse());
|
||||
}
|
||||
|
||||
TEST(BleL2capPacketTest, ByteArrayForDataConnectionFailure) {
|
||||
ByteArray byte_array = BleL2capPacket::ByteArrayForDataConnectionFailure();
|
||||
|
||||
auto result = BleL2capPacket::CreateFromBytes(byte_array);
|
||||
ASSERT_TRUE(result.ok());
|
||||
ASSERT_TRUE(result.value().IsDataConnectionFailureResponse());
|
||||
}
|
||||
|
||||
TEST(BleL2capPacketTest, CreateFromBytesWithEmptyData) {
|
||||
auto byte_array = BleL2capPacket::CreateFromBytes(ByteArray());
|
||||
|
||||
ASSERT_FALSE(byte_array.ok());
|
||||
}
|
||||
|
||||
TEST(BleL2capPacketTest, CreateFromBytesWithInvalidCommand) {
|
||||
ByteArray byte_array(nullptr, 1);
|
||||
|
||||
auto result = BleL2capPacket::CreateFromBytes(byte_array);
|
||||
ASSERT_FALSE(result.ok());
|
||||
}
|
||||
|
||||
TEST(BleL2capPacketTest, CreateFromBytesWithoutDataLength) {
|
||||
ByteArray byte_array{1};
|
||||
char *byte_array_data = byte_array.data();
|
||||
byte_array_data[0] =
|
||||
static_cast<char>(BleL2capPacket::Command::kRequestAdvertisement);
|
||||
|
||||
auto result = BleL2capPacket::CreateFromBytes(byte_array);
|
||||
ASSERT_FALSE(result.ok());
|
||||
}
|
||||
|
||||
TEST(BleL2capPacketTest, CreateFromBytesWithEmptyDataLength) {
|
||||
ByteArray byte_array{3};
|
||||
char *byte_array_data = byte_array.data();
|
||||
byte_array_data[0] =
|
||||
static_cast<char>(BleL2capPacket::Command::kRequestAdvertisement);
|
||||
byte_array_data[1] = 0x00;
|
||||
byte_array_data[2] = 0x00;
|
||||
|
||||
auto result = BleL2capPacket::CreateFromBytes(byte_array);
|
||||
ASSERT_FALSE(result.ok());
|
||||
}
|
||||
|
||||
TEST(BleL2capPacketTest, CreateFromBytesWithInvalidServiceIdHashLength) {
|
||||
ByteArray byte_array{3};
|
||||
char *byte_array_data = byte_array.data();
|
||||
byte_array_data[0] =
|
||||
static_cast<char>(BleL2capPacket::Command::kRequestAdvertisement);
|
||||
byte_array_data[1] = 0x00;
|
||||
byte_array_data[2] = 0x01;
|
||||
|
||||
auto result = BleL2capPacket::CreateFromBytes(byte_array);
|
||||
ASSERT_FALSE(result.ok());
|
||||
}
|
||||
|
||||
TEST(BleL2capPacketTest, CreateFromBytesWithTooLongAdvertisementLength) {
|
||||
ByteArray byte_array{3};
|
||||
char *byte_array_data = byte_array.data();
|
||||
byte_array_data[0] =
|
||||
static_cast<char>(BleL2capPacket::Command::kResponseAdvertisement);
|
||||
byte_array_data[1] = 0xFF;
|
||||
byte_array_data[2] = 0xFF;
|
||||
|
||||
auto result = BleL2capPacket::CreateFromBytes(byte_array);
|
||||
ASSERT_FALSE(result.ok());
|
||||
}
|
||||
|
||||
TEST(BleL2capPacketTest, CreateFromBytesWithInvalidLengthAdvertisement) {
|
||||
ByteArray byte_array{4};
|
||||
char *byte_array_data = byte_array.data();
|
||||
byte_array_data[0] =
|
||||
static_cast<char>(BleL2capPacket::Command::kResponseAdvertisement);
|
||||
byte_array_data[1] = 0x00;
|
||||
byte_array_data[2] = 0x03;
|
||||
byte_array_data[3] = 0x01;
|
||||
|
||||
auto result = BleL2capPacket::CreateFromBytes(byte_array);
|
||||
ASSERT_FALSE(result.ok());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mediums
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
Reference in New Issue
Block a user