Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2025 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 :
18 : #pragma once
19 :
20 : #include <app-common/zap-generated/cluster-objects.h>
21 : #include <app/data-model-provider/MetadataTypes.h>
22 : #include <credentials/CHIPCert.h>
23 : #include <functional>
24 : #include <lib/core/CHIPPersistentStorageDelegate.h>
25 : #include <lib/core/CHIPVendorIdentifiers.hpp>
26 : #include <lib/core/NodeId.h>
27 : #include <lib/support/ReadOnlyBuffer.h>
28 : #include <unordered_map>
29 : #include <vector>
30 :
31 : namespace chip {
32 :
33 : // Forward declaration for friend class
34 : class JFAManager;
35 :
36 : namespace app {
37 :
38 : namespace datastore {
39 :
40 : struct AccessControlEntryStruct
41 : {
42 : Clusters::JointFabricDatastore::DatastoreAccessControlEntryPrivilegeEnum privilege =
43 : static_cast<Clusters::JointFabricDatastore::DatastoreAccessControlEntryPrivilegeEnum>(0);
44 : Clusters::JointFabricDatastore::DatastoreAccessControlEntryAuthModeEnum authMode =
45 : static_cast<Clusters::JointFabricDatastore::DatastoreAccessControlEntryAuthModeEnum>(0);
46 : std::vector<uint64_t> subjects;
47 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreAccessControlTargetStruct::Type> targets;
48 : };
49 :
50 : struct ACLEntryStruct
51 : {
52 : chip::NodeId nodeID = static_cast<chip::NodeId>(0);
53 : uint16_t listID = static_cast<uint16_t>(0);
54 : AccessControlEntryStruct ACLEntry;
55 : Clusters::JointFabricDatastore::Structs::DatastoreStatusEntryStruct::Type statusEntry;
56 : };
57 :
58 : } // namespace datastore
59 :
60 : enum RefreshState
61 : {
62 : kIdle,
63 : kRefreshingEndpoints,
64 : kRefreshingGroups,
65 : kRefreshingBindings,
66 : kFetchingGroupKeySets,
67 : kRefreshingGroupKeySets,
68 : kRefreshingACLs,
69 : };
70 :
71 : /**
72 : * A struct which extends the DatastoreNodeInformationEntry type with FriendlyName buffer reservation.
73 : */
74 : struct GenericDatastoreNodeInformationEntry
75 : : public Clusters::JointFabricDatastore::Structs::DatastoreNodeInformationEntryStruct::Type
76 : {
77 11 : GenericDatastoreNodeInformationEntry(NodeId nodeId = 0,
78 : Clusters::JointFabricDatastore::DatastoreStateEnum state =
79 : Clusters::JointFabricDatastore::DatastoreStateEnum::kUnknownEnumValue,
80 : Optional<CharSpan> label = NullOptional)
81 11 : {
82 11 : Set(nodeId, state, label);
83 11 : }
84 :
85 11 : GenericDatastoreNodeInformationEntry(const GenericDatastoreNodeInformationEntry & op) { *this = op; }
86 :
87 11 : GenericDatastoreNodeInformationEntry & operator=(const GenericDatastoreNodeInformationEntry & op)
88 : {
89 11 : Set(op.nodeID, op.commissioningStatusEntry.state, MakeOptional(op.friendlyName));
90 11 : return *this;
91 : }
92 :
93 22 : void Set(NodeId nodeId, Clusters::JointFabricDatastore::DatastoreStateEnum state, Optional<CharSpan> label = NullOptional)
94 : {
95 22 : this->nodeID = nodeId;
96 22 : this->commissioningStatusEntry.state = state;
97 22 : Set(label);
98 22 : }
99 :
100 23 : void Set(Optional<CharSpan> label = NullOptional)
101 : {
102 23 : if (label.HasValue())
103 : {
104 23 : memset(mFriendlyNameBuffer, 0, sizeof(mFriendlyNameBuffer));
105 23 : if (label.Value().size() > sizeof(mFriendlyNameBuffer))
106 : {
107 0 : memcpy(mFriendlyNameBuffer, label.Value().data(), sizeof(mFriendlyNameBuffer));
108 0 : this->friendlyName = CharSpan(mFriendlyNameBuffer, sizeof(mFriendlyNameBuffer));
109 : }
110 : else
111 : {
112 23 : memcpy(mFriendlyNameBuffer, label.Value().data(), label.Value().size());
113 23 : this->friendlyName = CharSpan(mFriendlyNameBuffer, label.Value().size());
114 : }
115 : }
116 : else
117 : {
118 0 : this->friendlyName = CharSpan();
119 : }
120 23 : }
121 :
122 : private:
123 : static constexpr size_t kFriendlyNameMaxSize = 32u;
124 :
125 : char mFriendlyNameBuffer[kFriendlyNameMaxSize];
126 : };
127 :
128 : class JointFabricDatastore
129 : {
130 : public:
131 : static JointFabricDatastore & GetInstance()
132 : {
133 : static JointFabricDatastore sInstance;
134 : return sInstance;
135 : }
136 :
137 : class Delegate
138 : {
139 : public:
140 22 : Delegate() {}
141 22 : virtual ~Delegate() {}
142 :
143 : virtual CHIP_ERROR
144 0 : SyncNode(NodeId nodeId,
145 : const Clusters::JointFabricDatastore::Structs::DatastoreEndpointGroupIDEntryStruct::Type & endpointGroupIDEntry,
146 : std::function<void()> onSuccess)
147 : {
148 0 : return CHIP_ERROR_NOT_IMPLEMENTED;
149 : }
150 :
151 : virtual CHIP_ERROR
152 0 : SyncNode(NodeId nodeId,
153 : const Clusters::JointFabricDatastore::Structs::DatastoreNodeKeySetEntryStruct::Type & nodeKeySetEntry,
154 : std::function<void()> onSuccess)
155 : {
156 0 : return CHIP_ERROR_NOT_IMPLEMENTED;
157 : }
158 :
159 : virtual CHIP_ERROR
160 0 : SyncNode(NodeId nodeId,
161 : const Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type & bindingEntry,
162 : std::function<void()> onSuccess)
163 : {
164 0 : return CHIP_ERROR_NOT_IMPLEMENTED;
165 : }
166 :
167 : virtual CHIP_ERROR
168 0 : SyncNode(NodeId nodeId,
169 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type> & bindingEntries,
170 : std::function<void()> onSuccess)
171 : {
172 0 : return CHIP_ERROR_NOT_IMPLEMENTED;
173 : }
174 :
175 0 : virtual CHIP_ERROR SyncNode(NodeId nodeId,
176 : const Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type & aclEntry,
177 : std::function<void()> onSuccess)
178 : {
179 0 : return CHIP_ERROR_NOT_IMPLEMENTED;
180 : }
181 :
182 : virtual CHIP_ERROR
183 0 : SyncNode(NodeId nodeId,
184 : const std::vector<app::Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type> & aclEntries,
185 : std::function<void()> onSuccess)
186 : {
187 0 : return CHIP_ERROR_NOT_IMPLEMENTED;
188 : }
189 :
190 0 : virtual CHIP_ERROR SyncNode(NodeId nodeId,
191 : const Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type & groupKeySet,
192 : std::function<void()> onSuccess)
193 : {
194 0 : return CHIP_ERROR_NOT_IMPLEMENTED;
195 : }
196 :
197 0 : virtual CHIP_ERROR FetchEndpointList(
198 : NodeId nodeId,
199 : std::function<void(CHIP_ERROR,
200 : const std::vector<Clusters::JointFabricDatastore::Structs::DatastoreEndpointEntryStruct::Type> &)>
201 : onSuccess)
202 : {
203 0 : return CHIP_ERROR_NOT_IMPLEMENTED;
204 : }
205 :
206 0 : virtual CHIP_ERROR FetchEndpointGroupList(
207 : NodeId nodeId, EndpointId endpointId,
208 : std::function<
209 : void(CHIP_ERROR,
210 : const std::vector<Clusters::JointFabricDatastore::Structs::DatastoreGroupInformationEntryStruct::Type> &)>
211 : onSuccess)
212 : {
213 0 : return CHIP_ERROR_NOT_IMPLEMENTED;
214 : }
215 :
216 0 : virtual CHIP_ERROR FetchEndpointBindingList(
217 : NodeId nodeId, EndpointId endpointId,
218 : std::function<
219 : void(CHIP_ERROR,
220 : const std::vector<Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type> &)>
221 : onSuccess)
222 : {
223 0 : return CHIP_ERROR_NOT_IMPLEMENTED;
224 : }
225 :
226 0 : virtual CHIP_ERROR FetchGroupKeySetList(
227 : NodeId nodeId,
228 : std::function<void(CHIP_ERROR,
229 : const std::vector<Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type> &)>
230 : onSuccess)
231 : {
232 0 : return CHIP_ERROR_NOT_IMPLEMENTED;
233 : }
234 :
235 0 : virtual CHIP_ERROR FetchACLList(
236 : NodeId nodeId,
237 : std::function<void(CHIP_ERROR,
238 : const std::vector<Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type> &)>
239 : onSuccess)
240 : {
241 0 : return CHIP_ERROR_NOT_IMPLEMENTED;
242 : }
243 : };
244 :
245 : CHIP_ERROR SetAnchorRootCA(const ByteSpan & anchorRootCA)
246 : {
247 : if (anchorRootCA.size() >= sizeof(mAnchorRootCA))
248 : {
249 : return CHIP_ERROR_INVALID_ARGUMENT;
250 : }
251 : mAnchorRootCALength = anchorRootCA.size();
252 : memcpy(mAnchorRootCA, anchorRootCA.data(), mAnchorRootCALength);
253 : return CHIP_NO_ERROR;
254 : }
255 : ByteSpan GetAnchorRootCA() const { return ByteSpan(mAnchorRootCA, mAnchorRootCALength); }
256 :
257 : CHIP_ERROR SetAnchorNodeId(NodeId anchorNodeId)
258 : {
259 : mAnchorNodeId = anchorNodeId;
260 : return CHIP_NO_ERROR;
261 : }
262 : NodeId GetAnchorNodeId() { return mAnchorNodeId; }
263 :
264 : CHIP_ERROR SetAnchorVendorId(VendorId anchorVendorId)
265 : {
266 : mAnchorVendorId = anchorVendorId;
267 : return CHIP_NO_ERROR;
268 : }
269 : VendorId GetAnchorVendorId() { return mAnchorVendorId; }
270 :
271 : CHIP_ERROR SetFriendlyName(const CharSpan & friendlyName)
272 : {
273 : if (friendlyName.size() >= sizeof(mFriendlyNameBuffer))
274 : {
275 : return CHIP_ERROR_INVALID_ARGUMENT;
276 : }
277 : mFriendlyNameBufferLength = friendlyName.size();
278 : memcpy(mFriendlyNameBuffer, friendlyName.data(), mFriendlyNameBufferLength);
279 : mFriendlyNameBuffer[mFriendlyNameBufferLength] = '\0'; // Ensure null-termination
280 : return CHIP_NO_ERROR;
281 : }
282 : CharSpan GetFriendlyName() const { return CharSpan(mFriendlyNameBuffer, mFriendlyNameBufferLength); }
283 :
284 : const std::vector<Clusters::JointFabricDatastore::Structs::DatastoreGroupInformationEntryStruct::Type> & GetGroupEntries()
285 : {
286 : return mGroupInformationEntries;
287 : }
288 :
289 : void SetStatus(Clusters::JointFabricDatastore::DatastoreStateEnum state, uint32_t updateTimestamp, uint8_t failureCode)
290 : {
291 : mDatastoreStatusEntry.state = state;
292 : mDatastoreStatusEntry.updateTimestamp = updateTimestamp;
293 : mDatastoreStatusEntry.failureCode = failureCode;
294 : }
295 : Clusters::JointFabricDatastore::Structs::DatastoreStatusEntryStruct::Type & GetStatus() { return mDatastoreStatusEntry; }
296 :
297 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreEndpointGroupIDEntryStruct::Type> & GetEndpointGroupIDList()
298 : {
299 : return mEndpointGroupIDEntries;
300 : }
301 :
302 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type> & GetEndpointBindingList()
303 : {
304 : return mEndpointBindingEntries;
305 : }
306 :
307 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreNodeKeySetEntryStruct::Type> & GetNodeKeySetList()
308 : {
309 : return mNodeKeySetEntries;
310 : }
311 :
312 : std::vector<datastore::ACLEntryStruct> & GetNodeACLList() { return mACLEntries; }
313 :
314 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreEndpointEntryStruct::Type> & GetNodeEndpointList()
315 : {
316 : return mEndpointEntries;
317 : }
318 :
319 : CHIP_ERROR AddPendingNode(NodeId nodeId, const CharSpan & friendlyName);
320 : CHIP_ERROR UpdateNode(NodeId nodeId, const CharSpan & friendlyName);
321 : CHIP_ERROR RemoveNode(NodeId nodeId);
322 : CHIP_ERROR RefreshNode(NodeId nodeId);
323 : CHIP_ERROR ContinueRefresh();
324 :
325 : CHIP_ERROR SetNode(NodeId nodeId, Clusters::JointFabricDatastore::DatastoreStateEnum state);
326 :
327 : CHIP_ERROR AddGroupKeySetEntry(const Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type & groupKeySet);
328 : bool IsGroupKeySetEntryPresent(uint16_t groupKeySetId);
329 : CHIP_ERROR RemoveGroupKeySetEntry(uint16_t groupKeySetId);
330 : CHIP_ERROR UpdateGroupKeySetEntry(Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type & groupKeySet);
331 :
332 : CHIP_ERROR
333 : AddAdmin(const Clusters::JointFabricDatastore::Structs::DatastoreAdministratorInformationEntryStruct::Type & adminId);
334 : bool IsAdminEntryPresent(NodeId nodeId);
335 : CHIP_ERROR UpdateAdmin(NodeId nodeId, CharSpan friendlyName, ByteSpan icac);
336 : CHIP_ERROR RemoveAdmin(NodeId nodeId);
337 :
338 : CHIP_ERROR AddGroup(const Clusters::JointFabricDatastore::Commands::AddGroup::DecodableType & commandData);
339 : CHIP_ERROR UpdateGroup(const Clusters::JointFabricDatastore::Commands::UpdateGroup::DecodableType & commandData);
340 : CHIP_ERROR RemoveGroup(const Clusters::JointFabricDatastore::Commands::RemoveGroup::DecodableType & commandData);
341 :
342 : CHIP_ERROR UpdateEndpointForNode(NodeId nodeId, EndpointId endpointId, CharSpan friendlyName);
343 :
344 : CHIP_ERROR AddGroupIDToEndpointForNode(NodeId nodeId, EndpointId endpointId, GroupId groupId);
345 : CHIP_ERROR RemoveGroupIDFromEndpointForNode(NodeId nodeId, EndpointId endpointId, GroupId groupId);
346 :
347 : CHIP_ERROR
348 : AddBindingToEndpointForNode(NodeId nodeId, EndpointId endpointId,
349 : const Clusters::JointFabricDatastore::Structs::DatastoreBindingTargetStruct::Type & binding);
350 : CHIP_ERROR
351 : RemoveBindingFromEndpointForNode(uint16_t listId, NodeId nodeId, EndpointId endpointId);
352 :
353 : CHIP_ERROR
354 : AddACLToNode(NodeId nodeId,
355 : const Clusters::JointFabricDatastore::Structs::DatastoreAccessControlEntryStruct::DecodableType & aclEntry);
356 : CHIP_ERROR RemoveACLFromNode(uint16_t listId, NodeId nodeId);
357 :
358 : CHIP_ERROR TestAddNodeKeySetEntry(GroupId groupId, uint16_t groupKeySetId, NodeId nodeId);
359 : CHIP_ERROR TestAddEndpointEntry(EndpointId endpointId, NodeId nodeId, CharSpan friendlyName);
360 :
361 : CHIP_ERROR ForceAddNodeKeySetEntry(uint16_t groupKeySetId, NodeId nodeId);
362 :
363 : const std::vector<Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type> & GetGroupKeySetList()
364 : {
365 : return mGroupKeySetList;
366 : }
367 : const std::vector<GenericDatastoreNodeInformationEntry> & GetNodeInformationEntries() { return mNodeInformationEntries; }
368 : const std::vector<Clusters::JointFabricDatastore::Structs::DatastoreAdministratorInformationEntryStruct::Type> &
369 : GetAdminEntries()
370 : {
371 : return mAdminEntries;
372 : }
373 :
374 : /**
375 : * Used to notify of changes in the node list and more TODO.
376 : */
377 : class Listener
378 : {
379 : public:
380 6 : virtual ~Listener() = default;
381 :
382 : /**
383 : * Notifies of a change in the node list.
384 : */
385 : virtual void MarkNodeListChanged() = 0;
386 :
387 : private:
388 : Listener * mNext = nullptr;
389 :
390 : friend class JointFabricDatastore;
391 : };
392 :
393 : /**
394 : * Add a listener to be notified of changes in the Joint Fabric Datastore.
395 : *
396 : * @param [in] listener The listener to add.
397 : */
398 : void AddListener(Listener & listener);
399 :
400 : /**
401 : * Remove a listener from being notified of changes in the Joint Fabric Datastore.
402 : *
403 : * @param [in] listener The listener to remove.
404 : */
405 : void RemoveListener(Listener & listener);
406 :
407 22 : CHIP_ERROR SetDelegate(Delegate * delegate)
408 : {
409 22 : VerifyOrReturnError(delegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
410 22 : mDelegate = delegate;
411 :
412 22 : return CHIP_NO_ERROR;
413 : }
414 :
415 : private:
416 : struct GroupKeySetStorage
417 : {
418 : std::vector<uint8_t> epochKey0;
419 : std::vector<uint8_t> epochKey1;
420 : std::vector<uint8_t> epochKey2;
421 : };
422 :
423 : struct GroupInformationStorage
424 : {
425 : // Friendly names are surfaced as CharSpan and may come from non-null-terminated buffers.
426 : // Keep raw owned bytes in vector<char> to preserve exact length semantics for Span use.
427 : std::vector<char> friendlyName;
428 : };
429 :
430 : struct AdminEntryStorage
431 : {
432 : // Friendly names are stored as owned raw bytes for CharSpan (not C-string) semantics.
433 : std::vector<char> friendlyName;
434 : std::vector<uint8_t> icac;
435 : };
436 :
437 : static constexpr size_t kMaxNodes = 256;
438 : static constexpr size_t kMaxAdminNodes = 32;
439 : static constexpr size_t kMaxGroups = kMaxNodes / 16;
440 : static constexpr size_t kMaxGroupKeySet = kMaxGroups * 16;
441 : static constexpr size_t kMaxFriendlyNameSize = 32;
442 : static constexpr size_t kMaxACLs = 64;
443 :
444 : uint8_t mAnchorRootCA[Credentials::kMaxDERCertLength] = { 0 };
445 : size_t mAnchorRootCALength = 0;
446 : char mFriendlyNameBuffer[kMaxFriendlyNameSize] = { 0 };
447 : size_t mFriendlyNameBufferLength = 0;
448 : NodeId mAnchorNodeId = kUndefinedNodeId;
449 : VendorId mAnchorVendorId = VendorId::NotSpecified;
450 : Clusters::JointFabricDatastore::Structs::DatastoreStatusEntryStruct::Type mDatastoreStatusEntry;
451 :
452 : // TODO: Persist these members to local storage
453 : std::vector<GenericDatastoreNodeInformationEntry> mNodeInformationEntries;
454 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type> mGroupKeySetList;
455 : std::unordered_map<uint16_t, GroupKeySetStorage> mGroupKeySetStorage;
456 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreAdministratorInformationEntryStruct::Type> mAdminEntries;
457 : std::unordered_map<NodeId, AdminEntryStorage> mAdminEntryStorage;
458 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreGroupInformationEntryStruct::Type> mGroupInformationEntries;
459 : std::unordered_map<GroupId, GroupInformationStorage> mGroupInformationStorage;
460 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreEndpointGroupIDEntryStruct::Type> mEndpointGroupIDEntries;
461 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type> mEndpointBindingEntries;
462 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreNodeKeySetEntryStruct::Type> mNodeKeySetEntries;
463 : std::vector<datastore::ACLEntryStruct> mACLEntries;
464 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreEndpointEntryStruct::Type> mEndpointEntries;
465 :
466 : Listener * mListeners = nullptr;
467 :
468 : friend class chip::JFAManager;
469 :
470 : CHIP_ERROR
471 : ForceAddGroup(const Clusters::JointFabricDatastore::Commands::AddGroup::DecodableType & commandData);
472 :
473 : CHIP_ERROR IsNodeIDInDatastore(NodeId nodeId, size_t & index);
474 :
475 : CHIP_ERROR UpdateNodeKeySetList(Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type & groupKeySet);
476 : CHIP_ERROR RemoveKeySet(uint16_t groupKeySetId);
477 :
478 : CHIP_ERROR IsGroupIDInDatastore(GroupId groupId, size_t & index);
479 : CHIP_ERROR IsNodeIdInNodeInformationEntries(NodeId nodeId, size_t & index);
480 : CHIP_ERROR IsNodeIdAndEndpointInEndpointInformationEntries(NodeId nodeId, EndpointId endpointId, size_t & index);
481 :
482 : CHIP_ERROR GenerateAndAssignAUniqueListID(uint16_t & listId);
483 : bool BindingMatches(const Clusters::JointFabricDatastore::Structs::DatastoreBindingTargetStruct::Type & binding1,
484 : const Clusters::JointFabricDatastore::Structs::DatastoreBindingTargetStruct::Type & binding2);
485 : bool ACLMatches(const datastore::AccessControlEntryStruct & acl1,
486 : const Clusters::JointFabricDatastore::Structs::DatastoreAccessControlEntryStruct::DecodableType & acl2);
487 : bool ACLTargetMatches(const Clusters::JointFabricDatastore::Structs::DatastoreAccessControlTargetStruct::Type & target1,
488 : const Clusters::JointFabricDatastore::Structs::DatastoreAccessControlTargetStruct::Type & target2);
489 :
490 : CHIP_ERROR AddNodeKeySetEntry(GroupId groupId, uint16_t groupKeySetId);
491 : CHIP_ERROR RemoveNodeKeySetEntry(GroupId groupId, uint16_t groupKeySetId);
492 :
493 : void CopyGroupKeySetWithOwnedSpans(const Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type & source,
494 : Clusters::JointFabricDatastore::Structs::DatastoreGroupKeySetStruct::Type & destination);
495 : void RemoveGroupKeySetStorage(uint16_t groupKeySetId);
496 :
497 : void SetGroupInformationFriendlyNameWithOwnedStorage(
498 : GroupId groupId, const CharSpan & friendlyName,
499 : Clusters::JointFabricDatastore::Structs::DatastoreGroupInformationEntryStruct::Type & destination);
500 : void RemoveGroupInformationStorage(GroupId groupId);
501 :
502 : CHIP_ERROR SetAdminEntryWithOwnedStorage(
503 : NodeId nodeId, const CharSpan & friendlyName, const ByteSpan & icac,
504 : Clusters::JointFabricDatastore::Structs::DatastoreAdministratorInformationEntryStruct::Type & destination);
505 : void RemoveAdminEntryStorage(NodeId nodeId);
506 :
507 : // Helper methods for copying optional ByteSpan and simple nullable values
508 : void CopyByteSpanWithOwnedStorage(const DataModel::Nullable<ByteSpan> & source, std::vector<uint8_t> & storage,
509 : DataModel::Nullable<ByteSpan> & destination);
510 :
511 : template <typename T>
512 12 : void CopyNullableValue(const DataModel::Nullable<T> & source, DataModel::Nullable<T> & destination)
513 : {
514 : // Only update destination if source has a value; leave destination unchanged if source is null.
515 12 : if (!source.IsNull())
516 : {
517 0 : static_cast<void>(destination.Update(source));
518 : }
519 12 : }
520 :
521 : Delegate * mDelegate = nullptr;
522 :
523 : NodeId mRefreshingNodeId = kUndefinedNodeId;
524 : RefreshState mRefreshState = kIdle;
525 : size_t mRefreshingEndpointIndex = 0;
526 :
527 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreEndpointEntryStruct::Type> mRefreshingEndpointsList;
528 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreEndpointBindingEntryStruct::Type> mRefreshingBindingEntries;
529 : std::vector<Clusters::JointFabricDatastore::Structs::DatastoreACLEntryStruct::Type> mRefreshingACLEntries;
530 : };
531 :
532 : } // namespace app
533 : } // namespace chip
|