blob: 3ee5c635e08bff5e281df3086f378a9ca5696ded [file] [log] [blame]
// 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
//
// http://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 "include/nearby_protocol.h"
#include "np_cpp_ffi_functions.h"
#ifdef __FILE_NAME__
#define __ASSERT_FILE_NAME __FILE_NAME__
#else /* __FILE_NAME__ */
#define __ASSERT_FILE_NAME __FILE__
#endif /* __FILE_NAME__ */
namespace nearby_protocol {
static void panic_handler(PanicReason reason);
struct PanicHandler {
void (*handler)(PanicReason);
bool set_by_client;
};
static PanicHandler gPanicHandler = PanicHandler{panic_handler, false};
// C++ layer internal panic handler
static void panic_handler(PanicReason reason) {
// Give clients a chance to use their own panic handler, but if they don't
// terminate the process we will make sure it happens.
if (gPanicHandler.set_by_client) {
gPanicHandler.handler(reason);
}
std::abort();
}
static void _assert_panic(bool condition, const char *func, const char *file,
int line) {
if (!condition) {
std::cout << "Assert failed: \n function: " << func << "\n file: " << file
<< "\n line: " << line << "\n";
panic_handler(PanicReason::AssertFailed);
}
}
#define assert_panic(e) _assert_panic(e, __func__, __ASSERT_FILE_NAME, __LINE__)
bool GlobalConfig::SetPanicHandler(void (*handler)(PanicReason)) {
if (!gPanicHandler.set_by_client) {
gPanicHandler.handler = handler;
gPanicHandler.set_by_client = true;
return np_ffi::internal::np_ffi_global_config_panic_handler(panic_handler);
}
return false;
}
void GlobalConfig::SetNumShards(uint8_t num_shards) {
np_ffi::internal::np_ffi_global_config_set_num_shards(num_shards);
}
void GlobalConfig::SetMaxNumCredentialBooks(uint32_t max_num_credential_books) {
np_ffi::internal::np_ffi_global_config_set_max_num_credential_books(
max_num_credential_books);
}
void GlobalConfig::SetMaxNumDeserializedV0Advertisements(
uint32_t max_num_deserialized_v0_advertisements) {
np_ffi::internal::
np_ffi_global_config_set_max_num_deserialized_v0_advertisements(
max_num_deserialized_v0_advertisements);
}
void GlobalConfig::SetMaxNumDeserializedV1Advertisements(
uint32_t max_num_deserialized_v1_advertisements) {
np_ffi::internal::
np_ffi_global_config_set_max_num_deserialized_v1_advertisements(
max_num_deserialized_v1_advertisements);
}
absl::StatusOr<CredentialBook> CredentialBook::TryCreate() {
auto result = np_ffi::internal::np_ffi_create_credential_book();
auto kind = np_ffi::internal::np_ffi_CreateCredentialBookResult_kind(result);
switch (kind) {
case CreateCredentialBookResultKind::Success: {
auto book = CredentialBook(
np_ffi::internal::np_ffi_CreateCredentialBookResult_into_SUCCESS(
result));
return book;
}
case CreateCredentialBookResultKind::NoSpaceLeft: {
return absl::ResourceExhaustedError(
"No space left to create credential book");
}
}
}
CredentialBook::~CredentialBook() {
if (!this->moved_) {
auto result =
np_ffi::internal::np_ffi_deallocate_credential_book(credential_book_);
assert_panic(result == np_ffi::internal::DeallocateResult::Success);
}
}
CredentialBook::CredentialBook(CredentialBook &&other) noexcept
: credential_book_(other.credential_book_), moved_(other.moved_) {
other.credential_book_ = {};
other.moved_ = true;
}
CredentialBook &CredentialBook::operator=(CredentialBook &&other) noexcept {
if (this != &other) {
if (!this->moved_) {
auto result = np_ffi::internal::np_ffi_deallocate_credential_book(
this->credential_book_);
assert_panic(result == np_ffi::internal::DeallocateResult::Success);
}
this->credential_book_ = other.credential_book_;
this->moved_ = other.moved_;
other.credential_book_ = {};
other.moved_ = true;
}
return *this;
}
DeserializeAdvertisementResult
Deserializer::DeserializeAdvertisement(RawAdvertisementPayload &payload,
const CredentialBook &credential_book) {
assert_panic(!credential_book.moved_);
auto result = np_ffi::internal::np_ffi_deserialize_advertisement(
{payload.buffer_.internal_}, credential_book.credential_book_);
return DeserializeAdvertisementResult(result);
}
DeserializeAdvertisementResultKind DeserializeAdvertisementResult::GetKind() {
assert_panic(!this->moved_);
return np_ffi::internal::np_ffi_DeserializeAdvertisementResult_kind(result_);
}
DeserializedV0Advertisement DeserializeAdvertisementResult::IntoV0() {
assert_panic(!this->moved_);
auto result =
np_ffi::internal::np_ffi_DeserializeAdvertisementResult_into_V0(result_);
this->moved_ = true;
return DeserializedV0Advertisement(result);
}
DeserializedV1Advertisement DeserializeAdvertisementResult::IntoV1() {
assert_panic(!this->moved_);
auto v1_adv =
np_ffi::internal::np_ffi_DeserializeAdvertisementResult_into_V1(result_);
this->moved_ = true;
return DeserializedV1Advertisement(v1_adv);
}
DeserializeAdvertisementResult::~DeserializeAdvertisementResult() {
if (!this->moved_) {
auto result =
np_ffi::internal::np_ffi_deallocate_deserialize_advertisement_result(
result_);
assert_panic(result == np_ffi::internal::DeallocateResult::Success);
}
}
DeserializeAdvertisementResult::DeserializeAdvertisementResult(
DeserializeAdvertisementResult &&other) noexcept
: result_(other.result_), moved_(other.moved_) {
other.result_ = {};
other.moved_ = true;
}
DeserializeAdvertisementResult &DeserializeAdvertisementResult::operator=(
DeserializeAdvertisementResult &&other) noexcept {
if (this != &other) {
if (!this->moved_) {
auto result =
np_ffi::internal::np_ffi_deallocate_deserialize_advertisement_result(
result_);
assert_panic(result == np_ffi::internal::DeallocateResult::Success);
}
this->result_ = other.result_;
this->moved_ = other.moved_;
other.result_ = {};
other.moved_ = true;
}
return *this;
}
// V0 Stuff
DeserializedV0Advertisement::DeserializedV0Advertisement(
DeserializedV0Advertisement &&other) noexcept
: v0_advertisement_(other.v0_advertisement_), moved_(other.moved_) {
other.v0_advertisement_ = {};
other.moved_ = true;
}
DeserializedV0Advertisement &DeserializedV0Advertisement::operator=(
DeserializedV0Advertisement &&other) noexcept {
if (this != &other) {
if (!this->moved_) {
auto result =
np_ffi::internal::np_ffi_deallocate_deserialized_V0_advertisement(
v0_advertisement_);
assert_panic(result == np_ffi::internal::DeallocateResult::Success);
}
this->v0_advertisement_ = other.v0_advertisement_;
this->moved_ = other.moved_;
other.v0_advertisement_ = {};
other.moved_ = true;
}
return *this;
}
DeserializedV0Advertisement::~DeserializedV0Advertisement() {
if (!this->moved_) {
auto result =
np_ffi::internal::np_ffi_deallocate_deserialized_V0_advertisement(
v0_advertisement_);
assert_panic(result == np_ffi::internal::DeallocateResult::Success);
}
}
np_ffi::internal::DeserializedV0AdvertisementKind
DeserializedV0Advertisement::GetKind() {
assert_panic(!this->moved_);
return np_ffi::internal::np_ffi_DeserializedV0Advertisement_kind(
v0_advertisement_);
}
LegibleDeserializedV0Advertisement DeserializedV0Advertisement::IntoLegible() {
assert_panic(!this->moved_);
auto result =
np_ffi::internal::np_ffi_DeserializedV0Advertisement_into_LEGIBLE(
v0_advertisement_);
this->moved_ = true;
this->v0_advertisement_ = {};
return LegibleDeserializedV0Advertisement(result);
}
LegibleDeserializedV0Advertisement::LegibleDeserializedV0Advertisement(
LegibleDeserializedV0Advertisement &&other) noexcept
: legible_v0_advertisement_(other.legible_v0_advertisement_),
moved_(other.moved_) {
other.moved_ = true;
other.legible_v0_advertisement_ = {};
}
LegibleDeserializedV0Advertisement &
LegibleDeserializedV0Advertisement::operator=(
LegibleDeserializedV0Advertisement &&other) noexcept {
if (this != &other) {
if (!this->moved_) {
auto result =
np_ffi::internal::np_ffi_deallocate_legible_v0_advertisement(
this->legible_v0_advertisement_);
assert_panic(result == np_ffi::internal::DeallocateResult::Success);
}
this->legible_v0_advertisement_ = other.legible_v0_advertisement_;
this->moved_ = other.moved_;
other.moved_ = true;
other.legible_v0_advertisement_ = {};
}
return *this;
}
LegibleDeserializedV0Advertisement::~LegibleDeserializedV0Advertisement() {
if (!this->moved_) {
auto result = np_ffi::internal::np_ffi_deallocate_legible_v0_advertisement(
this->legible_v0_advertisement_);
assert_panic(result == np_ffi::internal::DeallocateResult::Success);
}
}
DeserializedV0Identity LegibleDeserializedV0Advertisement::GetIdentity() {
assert_panic(!this->moved_);
auto result =
np_ffi::internal::np_ffi_LegibleDeserializedV0Advertisement_into_identity(
legible_v0_advertisement_);
return DeserializedV0Identity(result);
}
uint8_t LegibleDeserializedV0Advertisement::GetNumberOfDataElements() {
assert_panic(!this->moved_);
return np_ffi::internal::
np_ffi_LegibleDeserializedV0Advertisement_get_num_des(
legible_v0_advertisement_);
}
V0Payload LegibleDeserializedV0Advertisement::IntoPayload() {
assert_panic(!this->moved_);
auto result = np_ffi_LegibleDeserializedV0Advertisement_into_payload(
legible_v0_advertisement_);
this->moved_ = true;
return V0Payload(result);
}
np_ffi::internal::DeserializedV0IdentityKind DeserializedV0Identity::GetKind() {
return np_ffi::internal::np_ffi_DeserializedV0Identity_kind(v0_identity_);
}
V0Payload::V0Payload(V0Payload &&other) noexcept
: v0_payload_(other.v0_payload_), moved_(other.moved_) {
other.v0_payload_ = {};
other.moved_ = true;
}
V0Payload &V0Payload::operator=(V0Payload &&other) noexcept {
if (this != &other) {
if (!this->moved_) {
auto result =
np_ffi::internal::np_ffi_deallocate_v0_payload(this->v0_payload_);
assert_panic(result == np_ffi::internal::DeallocateResult::Success);
}
this->v0_payload_ = other.v0_payload_;
this->moved_ = other.moved_;
other.moved_ = true;
other.v0_payload_ = {};
}
return *this;
}
V0Payload::~V0Payload() {
if (!this->moved_) {
auto result =
np_ffi::internal::np_ffi_deallocate_v0_payload(this->v0_payload_);
assert_panic(result == np_ffi::internal::DeallocateResult::Success);
}
}
absl::StatusOr<V0DataElement> V0Payload::TryGetDataElement(uint8_t index) {
assert_panic(!this->moved_);
auto result = np_ffi::internal::np_ffi_V0Payload_get_de(v0_payload_, index);
auto kind = np_ffi::internal::np_ffi_GetV0DEResult_kind(result);
switch (kind) {
case GetV0DEResultKind::Success: {
auto de = np_ffi_GetV0DEResult_into_SUCCESS(result);
return V0DataElement(de);
}
case GetV0DEResultKind::Error: {
return absl::OutOfRangeError("Invalid Data Element index");
}
}
}
V0DataElementKind V0DataElement::GetKind() {
return np_ffi::internal::np_ffi_V0DataElement_kind(v0_data_element_);
}
TxPower V0DataElement::AsTxPower() {
return np_ffi::internal::np_ffi_V0DataElement_into_TX_POWER(v0_data_element_);
}
V0Actions V0DataElement::AsActions() {
auto internal =
np_ffi::internal::np_ffi_V0DataElement_into_ACTIONS(v0_data_element_);
return V0Actions(internal);
}
uint32_t V0Actions::GetAsU32() {
return np_ffi::internal::np_ffi_V0Actions_as_u32(actions_);
}
bool V0Actions::HasAction(BooleanActionType action) {
return np_ffi::internal::np_ffi_V0Actions_has_action(actions_, action);
}
uint8_t V0Actions::GetContextSyncSequenceNumber() {
return np_ffi::internal::np_ffi_V0Actions_get_context_sync_sequence_number(
actions_);
}
// This is called after all references to the shared_ptr have gone out of scope
auto DeallocateV1Adv(
np_ffi::internal::DeserializedV1Advertisement *v1_advertisement) {
auto result =
np_ffi::internal::np_ffi_deallocate_deserialized_V1_advertisement(
*v1_advertisement);
assert_panic(result == np_ffi::internal::DeallocateResult::Success);
delete v1_advertisement;
}
DeserializedV1Advertisement::DeserializedV1Advertisement(
np_ffi::internal::DeserializedV1Advertisement v1_advertisement) {
v1_advertisement_ =
std::shared_ptr<np_ffi::internal::DeserializedV1Advertisement>(
new np_ffi::internal::DeserializedV1Advertisement(v1_advertisement),
DeallocateV1Adv);
}
DeserializedV1Advertisement::DeserializedV1Advertisement(
DeserializedV1Advertisement &&other) noexcept
: v1_advertisement_(std::move(other.v1_advertisement_)) {}
DeserializedV1Advertisement &DeserializedV1Advertisement::operator=(
DeserializedV1Advertisement &&other) noexcept {
if (this != &other) {
this->v1_advertisement_ = std::move(other.v1_advertisement_);
}
return *this;
}
// V1 Stuff
uint8_t DeserializedV1Advertisement::GetNumLegibleSections() {
assert_panic(this->v1_advertisement_ != nullptr);
return np_ffi::internal::
np_ffi_DeserializedV1Advertisement_get_num_legible_sections(
*v1_advertisement_);
}
uint8_t DeserializedV1Advertisement::GetNumUndecryptableSections() {
assert_panic(this->v1_advertisement_ != nullptr);
return np_ffi::internal::
np_ffi_DeserializedV1Advertisement_get_num_undecryptable_sections(
*v1_advertisement_);
}
absl::StatusOr<DeserializedV1Section>
DeserializedV1Advertisement::TryGetSection(uint8_t section_index) {
assert_panic(this->v1_advertisement_ != nullptr);
auto result =
np_ffi::internal::np_ffi_DeserializedV1Advertisement_get_section(
*v1_advertisement_, section_index);
auto kind = np_ffi::internal::np_ffi_GetV1SectionResult_kind(result);
switch (kind) {
case np_ffi::internal::GetV1SectionResultKind::Error: {
return absl::OutOfRangeError("Invalid section index");
}
case np_ffi::internal::GetV1SectionResultKind::Success: {
auto section =
np_ffi::internal::np_ffi_GetV1SectionResult_into_SUCCESS(result);
return DeserializedV1Section(section, v1_advertisement_);
}
}
}
uint8_t DeserializedV1Section::NumberOfDataElements() {
return np_ffi::internal::np_ffi_DeserializedV1Section_get_num_des(section_);
}
DeserializedV1IdentityKind DeserializedV1Section::GetIdentityKind() {
return np_ffi::internal::np_ffi_DeserializedV1Section_get_identity_kind(
section_);
}
absl::StatusOr<V1DataElement>
DeserializedV1Section::TryGetDataElement(uint8_t index) {
auto result =
np_ffi::internal::np_ffi_DeserializedV1Section_get_de(section_, index);
auto kind = np_ffi::internal::np_ffi_GetV1DEResult_kind(result);
switch (kind) {
case np_ffi::internal::GetV1DEResultKind::Error: {
return absl::OutOfRangeError("Invalid data element index for this section");
}
case np_ffi::internal::GetV1DEResultKind::Success: {
return V1DataElement(
np_ffi::internal::np_ffi_GetV1DEResult_into_SUCCESS(result));
}
}
}
uint32_t V1DataElement::GetDataElementTypeCode() const {
return np_ffi::internal::np_ffi_V1DEType_to_uint32_t(
v1_data_element_.generic._0.de_type);
}
ByteBuffer<127> V1DataElement::GetPayload() const {
return ByteBuffer(v1_data_element_.generic._0.payload);
}
} // namespace nearby_protocol