blob: dd7098ecf607f9db824f4270b6791c9495f01700 [file] [log] [blame]
/*
*
* Copyright (c) 2021 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.
*/
#pragma once
#include <lib/core/CHIPPersistentStorageDelegate.h>
#include <lib/core/DataModelTypes.h>
#include <lib/support/CHIPMemString.h>
#include <stdio.h>
namespace chip {
/**
* Represents a key used for addressing a specific storage element.
*
* May contain generic fixed keys (e.g. "g/fidx") or formatted fabric-specific
* keys ("f/%x/..." where %x is the fabric index).
*/
class StorageKeyName
{
public:
StorageKeyName(const StorageKeyName & other) = default;
StorageKeyName & operator=(const StorageKeyName & other) = default;
~StorageKeyName() { memset(mKeyNameBuffer, 0, sizeof(mKeyNameBuffer)); }
const char * KeyName() const { return mKeyNameBuffer; }
bool IsInitialized() const { return mKeyNameBuffer[0] != 0; }
bool IsUninitialized() const { return mKeyNameBuffer[0] == 0; }
bool operator!() const { return IsUninitialized(); }
static StorageKeyName FromConst(const char * value)
{
StorageKeyName result;
Platform::CopyString(result.mKeyNameBuffer, value);
return result;
}
static StorageKeyName ENFORCE_FORMAT(1, 2) Formatted(const char * format, ...)
{
StorageKeyName result;
va_list args;
va_start(args, format);
vsnprintf(result.mKeyNameBuffer, sizeof(result.mKeyNameBuffer), format, args);
va_end(args);
return result;
}
// Explicit 0-filled key. MUST be initialized later
static StorageKeyName Uninitialized()
{
StorageKeyName result;
return result;
}
private:
// May only be created by the underlying constructor methods
StorageKeyName() {}
// Contains the storage for the key name because some strings may be formatted.
char mKeyNameBuffer[PersistentStorageDelegate::kKeyLengthMax + 1] = { 0 };
};
/**
* This is the common key allocation policy for all classes using
* PersistentStorageDelegate storage.
*
* Keys should have the following formats:
*
* * Keys that are not tied to a specific fabric: "g/....".
* * Keys that are tied to a specific fabric: "f/%x/...." where the %x gets
* replaced by the fabric index.
*/
class DefaultStorageKeyAllocator
{
private:
DefaultStorageKeyAllocator() = default;
public:
// Fabric Table
static StorageKeyName FabricIndexInfo() { return StorageKeyName::FromConst("g/fidx"); }
static StorageKeyName FabricNOC(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/n", fabric); }
static StorageKeyName FabricICAC(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/i", fabric); }
static StorageKeyName FabricRCAC(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/r", fabric); }
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"); }
// LastKnownGoodTime
static StorageKeyName LastKnownGoodTimeKey() { return StorageKeyName::FromConst("g/lkgt"); }
// Session resumption
static StorageKeyName FabricSession(FabricIndex fabric, NodeId nodeId)
{
return StorageKeyName::Formatted("f/%x/s/%08" PRIX32 "%08" PRIX32, fabric, static_cast<uint32_t>(nodeId >> 32),
static_cast<uint32_t>(nodeId));
}
static StorageKeyName SessionResumptionIndex() { return StorageKeyName::FromConst("g/sri"); }
static StorageKeyName SessionResumption(const char * resumptionIdBase64)
{
return StorageKeyName::Formatted("g/s/%s", resumptionIdBase64);
}
// Access Control
static StorageKeyName AccessControlAclEntry(FabricIndex fabric, size_t index)
{
return StorageKeyName::Formatted("f/%x/ac/0/%x", fabric, static_cast<unsigned>(index));
}
static StorageKeyName AccessControlExtensionEntry(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/ac/1", fabric); }
// Group Message Counters
static StorageKeyName GroupDataCounter() { return StorageKeyName::FromConst("g/gdc"); }
static StorageKeyName GroupControlCounter() { return StorageKeyName::FromConst("g/gcc"); }
// Device Information Provider
static StorageKeyName UserLabelLengthKey(EndpointId endpoint) { return StorageKeyName::Formatted("g/userlbl/%x", endpoint); }
static StorageKeyName UserLabelIndexKey(EndpointId endpoint, uint32_t index)
{
return StorageKeyName::Formatted("g/userlbl/%x/%" PRIx32, endpoint, index);
}
// Group Data Provider
// List of fabric indices that have endpoint-to-group associations defined.
static StorageKeyName FabricGroups(chip::FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/g", fabric); }
static StorageKeyName FabricGroup(chip::FabricIndex fabric, chip::GroupId group)
{
return StorageKeyName::Formatted("f/%x/g/%x", fabric, group);
}
static StorageKeyName FabricGroupKey(chip::FabricIndex fabric, uint16_t index)
{
return StorageKeyName::Formatted("f/%x/gk/%x", fabric, index);
}
static StorageKeyName FabricGroupEndpoint(chip::FabricIndex fabric, chip::GroupId group, chip::EndpointId endpoint)
{
return StorageKeyName::Formatted("f/%x/g/%x/e/%x", fabric, group, endpoint);
}
static StorageKeyName FabricKeyset(chip::FabricIndex fabric, uint16_t keyset)
{
return StorageKeyName::Formatted("f/%x/k/%x", fabric, keyset);
}
static StorageKeyName AttributeValue(EndpointId endpointId, ClusterId clusterId, AttributeId attributeId)
{
// Needs at most 26 chars: 6 for "g/a///", 4 for the endpoint id, 8 each
// for the cluster and attribute ids.
return StorageKeyName::Formatted("g/a/%x/%" PRIx32 "/%" PRIx32, endpointId, clusterId, attributeId);
}
// TODO: Should store fabric-specific parts of the binding list under keys
// starting with "f/%x/".
static StorageKeyName BindingTable() { return StorageKeyName::FromConst("g/bt"); }
static StorageKeyName BindingTableEntry(uint8_t index) { return StorageKeyName::Formatted("g/bt/%x", index); }
static StorageKeyName OTADefaultProviders() { return StorageKeyName::FromConst("g/o/dp"); }
static StorageKeyName OTACurrentProvider() { return StorageKeyName::FromConst("g/o/cp"); }
static StorageKeyName OTAUpdateToken() { return StorageKeyName::FromConst("g/o/ut"); }
static StorageKeyName OTACurrentUpdateState() { return StorageKeyName::FromConst("g/o/us"); }
static StorageKeyName OTATargetVersion() { return StorageKeyName::FromConst("g/o/tv"); }
// Event number counter.
static StorageKeyName IMEventNumber() { return StorageKeyName::FromConst("g/im/ec"); }
};
} // namespace chip