Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2021 Project CHIP Authors
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 : #pragma once
18 :
19 : #include <lib/core/CHIPPersistentStorageDelegate.h>
20 : #include <lib/core/DataModelTypes.h>
21 : #include <lib/support/CHIPMemString.h>
22 :
23 : #include <stdio.h>
24 :
25 : namespace chip {
26 :
27 : /**
28 : * Represents a key used for addressing a specific storage element.
29 : *
30 : * May contain generic fixed keys (e.g. "g/fidx") or formatted fabric-specific
31 : * keys ("f/%x/..." where %x is the fabric index).
32 : */
33 : class StorageKeyName
34 : {
35 : public:
36 : StorageKeyName(const StorageKeyName & other) = default;
37 : StorageKeyName & operator=(const StorageKeyName & other) = default;
38 :
39 25496 : ~StorageKeyName() { memset(mKeyNameBuffer, 0, sizeof(mKeyNameBuffer)); }
40 :
41 19782 : const char * KeyName() const { return mKeyNameBuffer; }
42 :
43 2 : bool IsInitialized() const { return mKeyNameBuffer[0] != 0; }
44 4120 : bool IsUninitialized() const { return mKeyNameBuffer[0] == 0; }
45 4120 : bool operator!() const { return IsUninitialized(); }
46 :
47 6655 : static StorageKeyName FromConst(const char * value)
48 : {
49 6655 : StorageKeyName result;
50 6655 : Platform::CopyString(result.mKeyNameBuffer, value);
51 6655 : return result;
52 : }
53 :
54 15171 : static StorageKeyName ENFORCE_FORMAT(1, 2) Formatted(const char * format, ...)
55 : {
56 15171 : StorageKeyName result;
57 :
58 : va_list args;
59 15171 : va_start(args, format);
60 15171 : vsnprintf(result.mKeyNameBuffer, sizeof(result.mKeyNameBuffer), format, args);
61 15171 : va_end(args);
62 :
63 15171 : return result;
64 : }
65 :
66 : // Explicit 0-filled key. MUST be initialized later
67 2766 : static StorageKeyName Uninitialized()
68 : {
69 2766 : StorageKeyName result;
70 2766 : return result;
71 : }
72 :
73 : private:
74 : // May only be created by the underlying constructor methods
75 27541 : StorageKeyName() {}
76 :
77 : // Contains the storage for the key name because some strings may be formatted.
78 : char mKeyNameBuffer[PersistentStorageDelegate::kKeyLengthMax + 1] = { 0 };
79 : };
80 :
81 : /**
82 : * This is the common key allocation policy for all classes using
83 : * PersistentStorageDelegate storage.
84 : *
85 : * Keys should have the following formats:
86 : *
87 : * * Keys that are not tied to a specific fabric: "g/....".
88 : * * Keys that are tied to a specific fabric: "f/%x/...." where the %x gets
89 : * replaced by the fabric index.
90 : */
91 : class DefaultStorageKeyAllocator
92 : {
93 : private:
94 : DefaultStorageKeyAllocator() = default;
95 :
96 : public:
97 : // Fabric Table
98 1010 : static StorageKeyName FabricIndexInfo() { return StorageKeyName::FromConst("g/fidx"); }
99 1343 : static StorageKeyName FabricNOC(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/n", fabric); }
100 1323 : static StorageKeyName FabricICAC(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/i", fabric); }
101 1346 : static StorageKeyName FabricRCAC(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/r", fabric); }
102 661 : static StorageKeyName FabricMetadata(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/m", fabric); }
103 681 : static StorageKeyName FabricOpKey(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/o", fabric); }
104 :
105 : // Fail-safe handling
106 1627 : static StorageKeyName FailSafeCommitMarkerKey() { return StorageKeyName::FromConst("g/fs/c"); }
107 : static StorageKeyName FailSafeNetworkConfig() { return StorageKeyName::FromConst("g/fs/n"); }
108 :
109 : // LastKnownGoodTime
110 1736 : static StorageKeyName LastKnownGoodTimeKey() { return StorageKeyName::FromConst("g/lkgt"); }
111 :
112 : // Session resumption
113 883 : static StorageKeyName FabricSession(FabricIndex fabric, NodeId nodeId)
114 : {
115 883 : return StorageKeyName::Formatted("f/%x/s/%08" PRIX32 "%08" PRIX32, fabric, static_cast<uint32_t>(nodeId >> 32),
116 883 : static_cast<uint32_t>(nodeId));
117 : }
118 :
119 491 : static StorageKeyName SessionResumptionIndex() { return StorageKeyName::FromConst("g/sri"); }
120 683 : static StorageKeyName SessionResumption(const char * resumptionIdBase64)
121 : {
122 683 : return StorageKeyName::Formatted("g/s/%s", resumptionIdBase64);
123 : }
124 :
125 : // Access Control
126 0 : static StorageKeyName AccessControlAclEntry(FabricIndex fabric, size_t index)
127 : {
128 0 : return StorageKeyName::Formatted("f/%x/ac/0/%x", fabric, static_cast<unsigned>(index));
129 : }
130 :
131 0 : static StorageKeyName AccessControlExtensionEntry(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/ac/1", fabric); }
132 :
133 : // Group Message Counters
134 669 : static StorageKeyName GroupDataCounter() { return StorageKeyName::FromConst("g/gdc"); }
135 668 : static StorageKeyName GroupControlCounter() { return StorageKeyName::FromConst("g/gcc"); }
136 :
137 : // ICD Check-In Counter
138 : static StorageKeyName ICDCheckInCounter() { return StorageKeyName::FromConst("g/icd/cic"); }
139 :
140 : // Device Information Provider
141 : static StorageKeyName UserLabelLengthKey(EndpointId endpoint) { return StorageKeyName::Formatted("g/userlbl/%x", endpoint); }
142 : static StorageKeyName UserLabelIndexKey(EndpointId endpoint, uint32_t index)
143 : {
144 : return StorageKeyName::Formatted("g/userlbl/%x/%" PRIx32, endpoint, index);
145 : }
146 :
147 : // Group Data Provider
148 :
149 : // List of fabric indices that have endpoint-to-group associations defined.
150 376 : static StorageKeyName GroupFabricList() { return StorageKeyName::FromConst("g/gfl"); }
151 1332 : static StorageKeyName FabricGroups(chip::FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/g", fabric); }
152 884 : static StorageKeyName FabricGroup(chip::FabricIndex fabric, chip::GroupId group)
153 : {
154 884 : return StorageKeyName::Formatted("f/%x/g/%x", fabric, group);
155 : }
156 513 : static StorageKeyName FabricGroupKey(chip::FabricIndex fabric, uint16_t index)
157 : {
158 513 : return StorageKeyName::Formatted("f/%x/gk/%x", fabric, index);
159 : }
160 412 : static StorageKeyName FabricGroupEndpoint(chip::FabricIndex fabric, chip::GroupId group, chip::EndpointId endpoint)
161 : {
162 412 : return StorageKeyName::Formatted("f/%x/g/%x/e/%x", fabric, group, endpoint);
163 : }
164 381 : static StorageKeyName FabricKeyset(chip::FabricIndex fabric, uint16_t keyset)
165 : {
166 381 : return StorageKeyName::Formatted("f/%x/k/%x", fabric, keyset);
167 : }
168 :
169 0 : static StorageKeyName AttributeValue(EndpointId endpointId, ClusterId clusterId, AttributeId attributeId)
170 : {
171 : // Needs at most 26 chars: 6 for "g/a///", 4 for the endpoint id, 8 each
172 : // for the cluster and attribute ids.
173 0 : return StorageKeyName::Formatted("g/a/%x/%" PRIx32 "/%" PRIx32, endpointId, clusterId, attributeId);
174 : }
175 :
176 : // Returns the key for Safely stored attributes.
177 136 : static StorageKeyName SafeAttributeValue(EndpointId endpointId, ClusterId clusterId, AttributeId attributeId)
178 : {
179 : // Needs at most 26 chars: 6 for "s/a///", 4 for the endpoint id, 8 each
180 : // for the cluster and attribute ids.
181 136 : return StorageKeyName::Formatted("g/sa/%x/%" PRIx32 "/%" PRIx32, endpointId, clusterId, attributeId);
182 : }
183 :
184 : // TODO: Should store fabric-specific parts of the binding list under keys
185 : // starting with "f/%x/".
186 37 : static StorageKeyName BindingTable() { return StorageKeyName::FromConst("g/bt"); }
187 218 : static StorageKeyName BindingTableEntry(uint8_t index) { return StorageKeyName::Formatted("g/bt/%x", index); }
188 :
189 : // ICD Management
190 :
191 : static StorageKeyName ICDManagementTableEntry(chip::FabricIndex fabric, uint16_t index)
192 : {
193 : return StorageKeyName::Formatted("f/%x/icd/%x", fabric, index);
194 : }
195 :
196 : static StorageKeyName OTADefaultProviders() { return StorageKeyName::FromConst("g/o/dp"); }
197 : static StorageKeyName OTACurrentProvider() { return StorageKeyName::FromConst("g/o/cp"); }
198 : static StorageKeyName OTAUpdateToken() { return StorageKeyName::FromConst("g/o/ut"); }
199 : static StorageKeyName OTACurrentUpdateState() { return StorageKeyName::FromConst("g/o/us"); }
200 : static StorageKeyName OTATargetVersion() { return StorageKeyName::FromConst("g/o/tv"); }
201 :
202 : // Event number counter.
203 1 : static StorageKeyName IMEventNumber() { return StorageKeyName::FromConst("g/im/ec"); }
204 :
205 : // Subscription resumption
206 48 : static StorageKeyName SubscriptionResumption(size_t index)
207 : {
208 48 : return StorageKeyName::Formatted("g/su/%x", static_cast<unsigned>(index));
209 : }
210 2 : static StorageKeyName SubscriptionResumptionMaxCount() { return StorageKeyName::Formatted("g/sum"); }
211 :
212 : // Number of scenes stored in a given endpoint's scene table, across all fabrics.
213 : static StorageKeyName EndpointSceneCountKey(EndpointId endpoint) { return StorageKeyName::Formatted("g/scc/e/%x", endpoint); }
214 :
215 : // Stores the scene count for a fabric for the given endpoint and a map between scene storage ids (<sceneId, groupId>) and
216 : // sceneIndex for a specific Fabric and endpoint.
217 : static StorageKeyName FabricSceneDataKey(FabricIndex fabric, EndpointId endpoint)
218 : {
219 : return StorageKeyName::Formatted("f/%x/e/%x/sc", fabric, endpoint);
220 : }
221 :
222 : // Stores the actual scene data for a given scene on a given endpoint for a particular fabric.
223 : // idx corresponds to the indices read from FabricSceneDataKey.
224 : // SceneIndex
225 : static StorageKeyName FabricSceneKey(FabricIndex fabric, EndpointId endpoint, uint16_t idx)
226 : {
227 : return StorageKeyName::Formatted("f/%x/e/%x/sc/%x", fabric, endpoint, idx);
228 : }
229 :
230 : // Time synchronization cluster
231 : static StorageKeyName TSTrustedTimeSource() { return StorageKeyName::FromConst("g/ts/tts"); }
232 : static StorageKeyName TSDefaultNTP() { return StorageKeyName::FromConst("g/ts/dntp"); }
233 : static StorageKeyName TSTimeZone() { return StorageKeyName::FromConst("g/ts/tz"); }
234 : static StorageKeyName TSDSTOffset() { return StorageKeyName::FromConst("g/ts/dsto"); }
235 :
236 : // FabricICDClientInfoCounter is only used by DefaultICDClientStorage
237 : // Records the number of ClientInfos for a particular fabric
238 50 : static StorageKeyName FabricICDClientInfoCounter(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/icdc", fabric); }
239 :
240 : // ICDClientInfoKey is only used by DefaultICDClientStorage
241 : // Stores/Loads all ICD clientInfos for a particular fabric
242 31 : static StorageKeyName ICDClientInfoKey(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/icdk", fabric); }
243 :
244 : // ICDFabricList is only used by DefaultICDClientStorage
245 : // when new fabric is created, this list needs to be updated,
246 : // when client init DefaultICDClientStorage, this table needs to be loaded.
247 8 : static StorageKeyName ICDFabricList() { return StorageKeyName::FromConst("g/icdfl"); }
248 : };
249 :
250 : } // namespace chip
|