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 27603 : ~StorageKeyName() { memset(mKeyNameBuffer, 0, sizeof(mKeyNameBuffer)); }
40 :
41 21755 : const char * KeyName() const { return mKeyNameBuffer; }
42 :
43 2 : bool IsInitialized() const { return mKeyNameBuffer[0] != 0; }
44 4571 : bool IsUninitialized() const { return mKeyNameBuffer[0] == 0; }
45 4571 : bool operator!() const { return IsUninitialized(); }
46 :
47 7377 : static StorageKeyName FromConst(const char * value)
48 : {
49 7377 : StorageKeyName result;
50 7377 : Platform::CopyString(result.mKeyNameBuffer, value);
51 7377 : return result;
52 : }
53 :
54 16421 : static StorageKeyName ENFORCE_FORMAT(1, 2) Formatted(const char * format, ...)
55 : {
56 16421 : StorageKeyName result;
57 :
58 : va_list args;
59 16421 : va_start(args, format);
60 16421 : vsnprintf(result.mKeyNameBuffer, sizeof(result.mKeyNameBuffer), format, args);
61 16421 : va_end(args);
62 :
63 16421 : return result;
64 : }
65 :
66 : // Explicit 0-filled key. MUST be initialized later
67 2836 : static StorageKeyName Uninitialized()
68 : {
69 2836 : StorageKeyName result;
70 2836 : return result;
71 : }
72 :
73 : private:
74 : // May only be created by the underlying constructor methods
75 29648 : 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 1125 : static StorageKeyName FabricIndexInfo() { return StorageKeyName::FromConst("g/fidx"); }
99 1493 : static StorageKeyName FabricNOC(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/n", fabric); }
100 1473 : static StorageKeyName FabricICAC(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/i", fabric); }
101 1497 : static StorageKeyName FabricRCAC(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/r", fabric); }
102 736 : static StorageKeyName FabricMetadata(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/m", fabric); }
103 756 : static StorageKeyName FabricOpKey(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/o", fabric); }
104 :
105 : // Fail-safe handling
106 1817 : static StorageKeyName FailSafeCommitMarkerKey() { return StorageKeyName::FromConst("g/fs/c"); }
107 : static StorageKeyName FailSafeNetworkConfig() { return StorageKeyName::FromConst("g/fs/n"); }
108 :
109 : // LastKnownGoodTime
110 1931 : static StorageKeyName LastKnownGoodTimeKey() { return StorageKeyName::FromConst("g/lkgt"); }
111 :
112 : // Session resumption
113 879 : static StorageKeyName FabricSession(FabricIndex fabric, NodeId nodeId)
114 : {
115 879 : return StorageKeyName::Formatted("f/%x/s/%08" PRIX32 "%08" PRIX32, fabric, static_cast<uint32_t>(nodeId >> 32),
116 879 : static_cast<uint32_t>(nodeId));
117 : }
118 :
119 496 : 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 741 : static StorageKeyName GroupDataCounter() { return StorageKeyName::FromConst("g/gdc"); }
135 740 : 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 0 : 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 0 : 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 44 : static StorageKeyName ICDManagementTableEntry(chip::FabricIndex fabric, uint16_t index)
192 : {
193 44 : return StorageKeyName::Formatted("f/%x/icd/%x", fabric, index);
194 : }
195 :
196 : // Thread Network Directory
197 :
198 : static StorageKeyName ThreadNetworkDirectoryIndex() { return StorageKeyName::FromConst("g/tnd/i"); }
199 : static StorageKeyName ThreadNetworkDirectoryDataset(uint64_t extendedPanId)
200 : {
201 : return StorageKeyName::Formatted("g/tnd/n/%08" PRIx32 "%08" PRIx32, // some platforms can't format uint64
202 : static_cast<uint32_t>(extendedPanId >> 32), static_cast<uint32_t>(extendedPanId));
203 : }
204 :
205 : // OTA
206 :
207 : static StorageKeyName OTADefaultProviders() { return StorageKeyName::FromConst("g/o/dp"); }
208 : static StorageKeyName OTACurrentProvider() { return StorageKeyName::FromConst("g/o/cp"); }
209 : static StorageKeyName OTAUpdateToken() { return StorageKeyName::FromConst("g/o/ut"); }
210 : static StorageKeyName OTACurrentUpdateState() { return StorageKeyName::FromConst("g/o/us"); }
211 : static StorageKeyName OTATargetVersion() { return StorageKeyName::FromConst("g/o/tv"); }
212 :
213 : // Event number counter.
214 1 : static StorageKeyName IMEventNumber() { return StorageKeyName::FromConst("g/im/ec"); }
215 :
216 : // Subscription resumption
217 440 : static StorageKeyName SubscriptionResumption(size_t index)
218 : {
219 440 : return StorageKeyName::Formatted("g/su/%x", static_cast<unsigned>(index));
220 : }
221 5 : static StorageKeyName SubscriptionResumptionMaxCount() { return StorageKeyName::Formatted("g/sum"); }
222 :
223 : // Number of scenes stored in a given endpoint's scene table, across all fabrics.
224 : static StorageKeyName EndpointSceneCountKey(EndpointId endpoint) { return StorageKeyName::Formatted("g/scc/e/%x", endpoint); }
225 :
226 : // Stores the scene count for a fabric for the given endpoint and a map between scene storage ids (<sceneId, groupId>) and
227 : // sceneIndex for a specific Fabric and endpoint.
228 : static StorageKeyName FabricSceneDataKey(FabricIndex fabric, EndpointId endpoint)
229 : {
230 : return StorageKeyName::Formatted("f/%x/e/%x/sc", fabric, endpoint);
231 : }
232 :
233 : // Stores the actual scene data for a given scene on a given endpoint for a particular fabric.
234 : // idx corresponds to the indices read from FabricSceneDataKey.
235 : // SceneIndex
236 : static StorageKeyName FabricSceneKey(FabricIndex fabric, EndpointId endpoint, uint16_t idx)
237 : {
238 : return StorageKeyName::Formatted("f/%x/e/%x/sc/%x", fabric, endpoint, idx);
239 : }
240 :
241 : // Time synchronization cluster
242 : static StorageKeyName TSTrustedTimeSource() { return StorageKeyName::FromConst("g/ts/tts"); }
243 : static StorageKeyName TSDefaultNTP() { return StorageKeyName::FromConst("g/ts/dntp"); }
244 : static StorageKeyName TSTimeZone() { return StorageKeyName::FromConst("g/ts/tz"); }
245 : static StorageKeyName TSDSTOffset() { return StorageKeyName::FromConst("g/ts/dsto"); }
246 :
247 : // FabricICDClientInfoCounter is only used by DefaultICDClientStorage
248 : // Records the number of ClientInfos for a particular fabric
249 144 : static StorageKeyName FabricICDClientInfoCounter(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/icdc", fabric); }
250 :
251 : // ICDClientInfoKey is only used by DefaultICDClientStorage
252 : // Stores/Loads all ICD clientInfos for a particular fabric
253 84 : static StorageKeyName ICDClientInfoKey(FabricIndex fabric) { return StorageKeyName::Formatted("f/%x/icdk", fabric); }
254 :
255 : // ICDFabricList is only used by DefaultICDClientStorage
256 : // when new fabric is created, this list needs to be updated,
257 : // when client init DefaultICDClientStorage, this table needs to be loaded.
258 31 : static StorageKeyName ICDFabricList() { return StorageKeyName::FromConst("g/icdfl"); }
259 : };
260 :
261 : } // namespace chip
|