Skip to content

Commit

Permalink
Moved structures from group data that could be re-used in scenes in a…
Browse files Browse the repository at this point in the history
… comon location: PersistentData.h
  • Loading branch information
lpbeliveau-silabs committed Nov 11, 2022
1 parent 008df4d commit 7f2e12a
Show file tree
Hide file tree
Showing 6 changed files with 263 additions and 134 deletions.
1 change: 1 addition & 0 deletions src/credentials/GroupDataProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <crypto/CHIPCryptoPAL.h>
#include <lib/core/CHIPError.h>
#include <lib/support/CHIPMemString.h>
#include <lib/support/Iterator.h>

namespace chip {
namespace Credentials {
Expand Down
154 changes: 21 additions & 133 deletions src/credentials/GroupDataProviderImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
#include <crypto/CHIPCryptoPAL.h>
#include <lib/core/CHIPTLV.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/CommonPersistentData.h>
#include <lib/support/DefaultStorageKeyAllocator.h>
#include <lib/support/PersistentData.h>
#include <lib/support/Pool.h>
#include <stdlib.h>
#include <string.h>

namespace chip {
namespace Credentials {
Expand All @@ -32,69 +33,9 @@ using GroupEndpoint = GroupDataProvider::GroupEndpoint;
using EpochKey = GroupDataProvider::EpochKey;
using KeySet = GroupDataProvider::KeySet;
using GroupSession = GroupDataProvider::GroupSession;
using FabricList = CommonPersistentData::FabricList;

static constexpr size_t kPersistentBufferMax = 128;

template <size_t kMaxSerializedSize>
struct PersistentData
{
virtual ~PersistentData() = default;

virtual CHIP_ERROR UpdateKey(StorageKeyName & key) = 0;
virtual CHIP_ERROR Serialize(TLV::TLVWriter & writer) const = 0;
virtual CHIP_ERROR Deserialize(TLV::TLVReader & reader) = 0;
virtual void Clear() = 0;

virtual CHIP_ERROR Save(PersistentStorageDelegate * storage)
{
VerifyOrReturnError(nullptr != storage, CHIP_ERROR_INVALID_ARGUMENT);

uint8_t buffer[kMaxSerializedSize] = { 0 };
StorageKeyName key = StorageKeyName::Uninitialized();
ReturnErrorOnFailure(UpdateKey(key));

// Serialize the data
TLV::TLVWriter writer;
writer.Init(buffer, sizeof(buffer));
ReturnErrorOnFailure(Serialize(writer));

// Save serialized data
return storage->SyncSetKeyValue(key.KeyName(), buffer, static_cast<uint16_t>(writer.GetLengthWritten()));
}

CHIP_ERROR Load(PersistentStorageDelegate * storage)
{
VerifyOrReturnError(nullptr != storage, CHIP_ERROR_INVALID_ARGUMENT);

uint8_t buffer[kMaxSerializedSize] = { 0 };
StorageKeyName key = StorageKeyName::Uninitialized();

// Set data to defaults
Clear();
ReturnErrorOnFailure(UpdateKey(key));

// Load the serialized data
uint16_t size = static_cast<uint16_t>(sizeof(buffer));
CHIP_ERROR err = storage->SyncGetKeyValue(key.KeyName(), buffer, size);
VerifyOrReturnError(CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND != err, CHIP_ERROR_NOT_FOUND);
ReturnErrorOnFailure(err);

// Decode serialized data
TLV::TLVReader reader;
reader.Init(buffer, size);
return Deserialize(reader);
}

virtual CHIP_ERROR Delete(PersistentStorageDelegate * storage)
{
VerifyOrReturnError(nullptr != storage, CHIP_ERROR_INVALID_ARGUMENT);

StorageKeyName key = StorageKeyName::Uninitialized();
ReturnErrorOnFailure(UpdateKey(key));

return storage->SyncDeleteKeyValue(key.KeyName());
}
};
constexpr size_t kPersistentBufferMax = 128;

struct LinkedData : public PersistentData<kPersistentBufferMax>
{
Expand All @@ -110,59 +51,6 @@ struct LinkedData : public PersistentData<kPersistentBufferMax>
bool first = true;
};

struct FabricList : public PersistentData<kPersistentBufferMax>
{
static constexpr TLV::Tag TagFirstFabric() { return TLV::ContextTag(1); }
static constexpr TLV::Tag TagFabricCount() { return TLV::ContextTag(2); }

chip::FabricIndex first_fabric = kUndefinedFabricIndex;
uint8_t fabric_count = 0;

FabricList() = default;
FabricList(chip::FabricIndex first) : first_fabric(first), fabric_count(1) {}

CHIP_ERROR UpdateKey(StorageKeyName & key) override
{
key = DefaultStorageKeyAllocator::GroupFabricList();
return CHIP_NO_ERROR;
}

void Clear() override
{
first_fabric = kUndefinedFabricIndex;
fabric_count = 0;
}

CHIP_ERROR Serialize(TLV::TLVWriter & writer) const override
{
TLV::TLVType container;
ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, container));

ReturnErrorOnFailure(writer.Put(TagFirstFabric(), static_cast<uint16_t>(first_fabric)));
ReturnErrorOnFailure(writer.Put(TagFabricCount(), static_cast<uint16_t>(fabric_count)));

return writer.EndContainer(container);
}

CHIP_ERROR Deserialize(TLV::TLVReader & reader) override
{
ReturnErrorOnFailure(reader.Next(TLV::AnonymousTag()));
VerifyOrReturnError(TLV::kTLVType_Structure == reader.GetType(), CHIP_ERROR_INTERNAL);

TLV::TLVType container;
ReturnErrorOnFailure(reader.EnterContainer(container));

// first_fabric
ReturnErrorOnFailure(reader.Next(TagFirstFabric()));
ReturnErrorOnFailure(reader.Get(first_fabric));
// fabric_count
ReturnErrorOnFailure(reader.Next(TagFabricCount()));
ReturnErrorOnFailure(reader.Get(fabric_count));

return reader.ExitContainer(container);
}
};

struct FabricData : public PersistentData<kPersistentBufferMax>
{
static constexpr TLV::Tag TagFirstGroup() { return TLV::ContextTag(1); }
Expand Down Expand Up @@ -257,15 +145,15 @@ struct FabricData : public PersistentData<kPersistentBufferMax>
if (CHIP_ERROR_NOT_FOUND == err)
{
// New fabric list
fabric_list.first_fabric = fabric_index;
fabric_list.fabric_count = 1;
fabric_list.first_entry = fabric_index;
fabric_list.entry_count = 1;
return fabric_list.Save(storage);
}
ReturnErrorOnFailure(err);

// Existing fabric list, search for existing entry
FabricData fabric(fabric_list.first_fabric);
for (size_t i = 0; i < fabric_list.fabric_count; i++)
FabricData fabric(fabric_list.first_entry);
for (size_t i = 0; i < fabric_list.entry_count; i++)
{
err = fabric.Load(storage);
if (CHIP_NO_ERROR != err)
Expand All @@ -280,9 +168,9 @@ struct FabricData : public PersistentData<kPersistentBufferMax>
fabric.fabric_index = fabric.next;
}
// Add this fabric to the fabric list
this->next = fabric_list.first_fabric;
fabric_list.first_fabric = this->fabric_index;
fabric_list.fabric_count++;
this->next = fabric_list.first_entry;
fabric_list.first_entry = this->fabric_index;
fabric_list.entry_count++;
return fabric_list.Save(storage);
}

Expand All @@ -294,10 +182,10 @@ struct FabricData : public PersistentData<kPersistentBufferMax>
VerifyOrReturnError(CHIP_NO_ERROR == err || CHIP_ERROR_NOT_FOUND == err, err);

// Existing fabric list, search for existing entry
FabricData fabric(fabric_list.first_fabric);
FabricData fabric(fabric_list.first_entry);
FabricData prev;

for (size_t i = 0; i < fabric_list.fabric_count; i++)
for (size_t i = 0; i < fabric_list.entry_count; i++)
{
err = fabric.Load(storage);
if (CHIP_NO_ERROR != err)
Expand All @@ -310,16 +198,16 @@ struct FabricData : public PersistentData<kPersistentBufferMax>
if (i == 0)
{
// Remove first fabric
fabric_list.first_fabric = this->next;
fabric_list.first_entry = this->next;
}
else
{
// Remove intermediate fabric
prev.next = this->next;
ReturnErrorOnFailure(prev.Save(storage));
}
VerifyOrReturnError(fabric_list.fabric_count > 0, CHIP_ERROR_INTERNAL);
fabric_list.fabric_count--;
VerifyOrReturnError(fabric_list.entry_count > 0, CHIP_ERROR_INTERNAL);
fabric_list.entry_count--;
return fabric_list.Save(storage);
}
prev = fabric;
Expand All @@ -336,9 +224,9 @@ struct FabricData : public PersistentData<kPersistentBufferMax>
ReturnErrorOnFailure(fabric_list.Load(storage));

// Existing fabric list, search for existing entry
FabricData fabric(fabric_list.first_fabric);
FabricData fabric(fabric_list.first_entry);

for (size_t i = 0; i < fabric_list.fabric_count; i++)
for (size_t i = 0; i < fabric_list.entry_count; i++)
{
ReturnErrorOnFailure(fabric.Load(storage));
if (fabric.fabric_index == this->fabric_index)
Expand Down Expand Up @@ -1892,10 +1780,10 @@ GroupDataProviderImpl::GroupSessionIteratorImpl::GroupSessionIteratorImpl(GroupD
{
FabricList fabric_list;
ReturnOnFailure(fabric_list.Load(provider.mStorage));
mFirstFabric = fabric_list.first_fabric;
mFabric = fabric_list.first_fabric;
mFirstFabric = fabric_list.first_entry;
mFabric = fabric_list.first_entry;
mFabricCount = 0;
mFabricTotal = fabric_list.fabric_count;
mFabricTotal = fabric_list.entry_count;
mMapCount = 0;
mFirstMap = true;
}
Expand Down
92 changes: 92 additions & 0 deletions src/lib/support/CommonPersistentData.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
*
* Copyright (c) 2022 Project CHIP Authors
*
* 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.
*/

/**
* @file
* Contains a class handling creation of linked list of stored persistent data.
*/

#include <lib/core/DataModelTypes.h>
#include <lib/support/PersistentData.h>

namespace chip {
namespace CommonPersistentData {

constexpr uint8_t kdefaultUndefinedEntry = 0;

/// @brief Generic class to implement storage of a list persistently
/// @tparam EntryType : Type of entry depends on the stored data
/// @tparam kMaxSerializedSize : inherited from PersistentData class
template <typename EntryType, size_t kMaxSerializedSize>
struct StoredDataList : public PersistentData<kMaxSerializedSize>
{
static constexpr TLV::Tag TagFirstEntry() { return TLV::ContextTag(1); }
static constexpr TLV::Tag TagEntryCount() { return TLV::ContextTag(2); }

EntryType first_entry = kdefaultUndefinedEntry;
uint16_t entry_count = 0;

StoredDataList() = default;
StoredDataList(EntryType first) : first_entry(first), entry_count(1) {}

CHIP_ERROR Serialize(TLV::TLVWriter & writer) const override
{
TLV::TLVType container;
ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, container));

ReturnErrorOnFailure(writer.Put(TagFirstEntry(), static_cast<uint16_t>(first_entry)));
ReturnErrorOnFailure(writer.Put(TagEntryCount(), static_cast<uint16_t>(entry_count)));

return writer.EndContainer(container);
}

CHIP_ERROR Deserialize(TLV::TLVReader & reader) override
{
ReturnErrorOnFailure(reader.Next(TLV::AnonymousTag()));
VerifyOrReturnError(TLV::kTLVType_Structure == reader.GetType(), CHIP_ERROR_INTERNAL);

TLV::TLVType container;
ReturnErrorOnFailure(reader.EnterContainer(container));

// first_entry
ReturnErrorOnFailure(reader.Next(TagFirstEntry()));
ReturnErrorOnFailure(reader.Get(first_entry));
// entry_count
ReturnErrorOnFailure(reader.Next(TagEntryCount()));
ReturnErrorOnFailure(reader.Get(entry_count));

return reader.ExitContainer(container);
}
};

constexpr size_t kPersistentFabricBufferMax = 32;
struct FabricList : StoredDataList<FabricIndex, kPersistentFabricBufferMax>
{
CHIP_ERROR UpdateKey(StorageKeyName & key) override
{
key = DefaultStorageKeyAllocator::FabricList();
return CHIP_NO_ERROR;
}

void Clear() override
{
first_entry = kUndefinedFabricIndex;
entry_count = 0;
}
};
} // namespace CommonPersistentData
} // namespace chip
4 changes: 3 additions & 1 deletion src/lib/support/DefaultStorageKeyAllocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ class DefaultStorageKeyAllocator
static StorageKeyName FabricMetadata(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/m", fabric); }
static StorageKeyName FabricOpKey(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/o", fabric); }

// Fabric List
static StorageKeyName FabricList() { return StorageKeyName::FromConst("g/fl"); }

// Fail-safe handling
static StorageKeyName FailSafeCommitMarkerKey() { return StorageKeyName::FromConst("g/fs/c"); }
static StorageKeyName FailSafeNetworkConfig() { return StorageKeyName::FromConst("g/fs/n"); }
Expand Down Expand Up @@ -144,7 +147,6 @@ class DefaultStorageKeyAllocator
// Group Data Provider

// List of fabric indices that have endpoint-to-group associations defined.
static StorageKeyName GroupFabricList() { return StorageKeyName::FromConst("g/gfl"); }
static StorageKeyName FabricGroups(chip::FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/g", fabric); }
static StorageKeyName FabricGroup(chip::FabricIndex fabric, chip::GroupId group)
{
Expand Down
Loading

0 comments on commit 7f2e12a

Please sign in to comment.