Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/common storage class #23409

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 6 additions & 33 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/CommonIterator.h>

namespace chip {
namespace Credentials {
Expand Down Expand Up @@ -186,39 +187,11 @@ class GroupDataProvider
virtual void OnGroupRemoved(FabricIndex fabric_index, const GroupInfo & old_group) = 0;
};

/**
* Template used to iterate the stored group data
*/
template <typename T>
class Iterator
{
public:
virtual ~Iterator() = default;
/**
* @retval The number of entries in total that will be iterated.
*/
virtual size_t Count() = 0;
/**
* @param[out] item Value associated with the next element in the iteration.
* @retval true if the next entry is successfully retrieved.
* @retval false if no more entries can be found.
*/
virtual bool Next(T & item) = 0;
/**
* Release the memory allocated by this iterator.
* Must be called before the pointer goes out of scope.
*/
virtual void Release() = 0;

protected:
Iterator() = default;
};

using GroupInfoIterator = Iterator<GroupInfo>;
using GroupKeyIterator = Iterator<GroupKey>;
using EndpointIterator = Iterator<GroupEndpoint>;
using KeySetIterator = Iterator<KeySet>;
using GroupSessionIterator = Iterator<GroupSession>;
using GroupInfoIterator = CommonIterator<GroupInfo>;
using GroupKeyIterator = CommonIterator<GroupKey>;
using EndpointIterator = CommonIterator<GroupEndpoint>;
using KeySetIterator = CommonIterator<KeySet>;
using GroupSessionIterator = CommonIterator<GroupSession>;

GroupDataProvider(uint16_t maxGroupsPerFabric = CHIP_CONFIG_MAX_GROUPS_PER_FABRIC,
uint16_t maxGroupKeysPerFabric = CHIP_CONFIG_MAX_GROUP_KEYS_PER_FABRIC) :
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
55 changes: 55 additions & 0 deletions src/lib/support/CommonIterator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
*
* 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 standard iterator class.
*/

#pragma once

namespace chip {

/**
* Template used to generate a custom iterator
*/
template <typename T>
class CommonIterator
{
public:
virtual ~CommonIterator() = default;
/**
* @retval The number of entries in total that will be iterated.
*/
virtual size_t Count() = 0;
/**
* @param[out] item Value associated with the next element in the iteration.
* @retval true if the next entry is successfully retrieved.
* @retval false if no more entries can be found.
*/
virtual bool Next(T & item) = 0;
/**
* Release the memory allocated by this iterator.
* Must be called before the iterator goes out of scope in the iterator was dynamically allocated.
*/
virtual void Release() = 0;

protected:
CommonIterator() = default;
};

} // namespace chip
Loading