Line data Source code
1 : /*
2 : * Copyright (c) 2021 Project CHIP Authors
3 : *
4 : * Licensed under the Apache License, Version 2.0 (the "License");
5 : * you may not use this file except in compliance with the License.
6 : * You may obtain a copy of the License at
7 : *
8 : * http://www.apache.org/licenses/LICENSE-2.0
9 : *
10 : * Unless required by applicable law or agreed to in writing, software
11 : * distributed under the License is distributed on an "AS IS" BASIS,
12 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : * See the License for the specific language governing permissions and
14 : * limitations under the License.
15 : */
16 :
17 : /**
18 : * @file
19 : * This file defines the Matter Group message counters of remote nodes for groups.
20 : *
21 : */
22 :
23 : #include <lib/support/DefaultStorageKeyAllocator.h>
24 : #include <transport/GroupPeerMessageCounter.h>
25 :
26 : #include <crypto/RandUtils.h>
27 :
28 : namespace chip {
29 : namespace Transport {
30 :
31 109 : CHIP_ERROR GroupPeerTable::FindOrAddPeer(FabricIndex fabricIndex, NodeId nodeId, bool isControl,
32 : chip::Transport::PeerMessageCounter *& counter)
33 : {
34 109 : if (fabricIndex == kUndefinedFabricIndex || nodeId == kUndefinedNodeId)
35 : {
36 0 : return CHIP_ERROR_INVALID_ARGUMENT;
37 : }
38 :
39 655 : for (auto & groupFabric : mGroupFabrics)
40 : {
41 653 : if (groupFabric.mFabricIndex == kUndefinedFabricIndex)
42 : {
43 : // Already iterated through all known fabricIndex
44 : // Add the new peer to save some processing time
45 62 : groupFabric.mFabricIndex = fabricIndex;
46 62 : if (isControl)
47 : {
48 26 : groupFabric.mControlGroupSenders[0].mNodeId = nodeId;
49 26 : counter = &(groupFabric.mControlGroupSenders[0].msgCounter);
50 26 : groupFabric.mControlPeerCount++;
51 : }
52 : else
53 : {
54 36 : groupFabric.mDataGroupSenders[0].mNodeId = nodeId;
55 36 : counter = &(groupFabric.mDataGroupSenders[0].msgCounter);
56 36 : groupFabric.mDataPeerCount++;
57 : }
58 62 : return CHIP_NO_ERROR;
59 : }
60 :
61 591 : if (fabricIndex == groupFabric.mFabricIndex)
62 : {
63 45 : if (isControl)
64 : {
65 35 : for (auto & node : groupFabric.mControlGroupSenders)
66 : {
67 35 : if (node.mNodeId == kUndefinedNodeId)
68 : {
69 : // Already iterated through all known NodeIds
70 : // Add the new peer to save some processing time
71 17 : node.mNodeId = nodeId;
72 17 : counter = &(node.msgCounter);
73 17 : groupFabric.mControlPeerCount++;
74 17 : return CHIP_NO_ERROR;
75 : }
76 :
77 18 : if (node.mNodeId == nodeId)
78 : {
79 1 : counter = &(node.msgCounter);
80 1 : return CHIP_NO_ERROR;
81 : }
82 : }
83 : }
84 : else
85 : {
86 183 : for (auto & node : groupFabric.mDataGroupSenders)
87 : {
88 182 : if (node.mNodeId == kUndefinedNodeId)
89 : {
90 : // Already iterated through all known NodeIds
91 : // Add the new peer to save some processing time
92 22 : node.mNodeId = nodeId;
93 22 : counter = &(node.msgCounter);
94 22 : groupFabric.mDataPeerCount++;
95 22 : return CHIP_NO_ERROR;
96 : }
97 :
98 160 : if (node.mNodeId == nodeId)
99 : {
100 4 : counter = &(node.msgCounter);
101 4 : return CHIP_NO_ERROR;
102 : }
103 : }
104 : }
105 : // Exceeded the Max number of Group peers
106 1 : return CHIP_ERROR_TOO_MANY_PEER_NODES;
107 : }
108 : }
109 :
110 : // Exceeded the Max number of Group peers
111 2 : return CHIP_ERROR_TOO_MANY_PEER_NODES;
112 : }
113 :
114 : // Used in case of MCSP failure
115 38 : CHIP_ERROR GroupPeerTable::RemovePeer(FabricIndex fabricIndex, NodeId nodeId, bool isControl)
116 : {
117 38 : CHIP_ERROR err = CHIP_ERROR_NOT_FOUND;
118 38 : uint32_t fabricIt = CHIP_CONFIG_MAX_FABRICS;
119 :
120 38 : if (fabricIndex == kUndefinedFabricIndex || nodeId == kUndefinedNodeId)
121 : {
122 0 : return CHIP_ERROR_INVALID_ARGUMENT;
123 : }
124 :
125 156 : for (uint32_t it = 0; it < CHIP_CONFIG_MAX_FABRICS; it++)
126 : {
127 156 : if (fabricIndex == mGroupFabrics[it].mFabricIndex)
128 : {
129 38 : if (isControl)
130 : {
131 33 : if (RemoveSpecificPeer(mGroupFabrics[it].mControlGroupSenders, nodeId, CHIP_CONFIG_MAX_GROUP_CONTROL_PEERS))
132 : {
133 33 : fabricIt = it;
134 33 : mGroupFabrics[it].mControlPeerCount--;
135 33 : err = CHIP_NO_ERROR;
136 : }
137 : }
138 : else
139 : {
140 5 : if (RemoveSpecificPeer(mGroupFabrics[it].mDataGroupSenders, nodeId, CHIP_CONFIG_MAX_GROUP_DATA_PEERS))
141 : {
142 5 : fabricIt = it;
143 5 : mGroupFabrics[it].mDataPeerCount--;
144 5 : err = CHIP_NO_ERROR;
145 : }
146 : }
147 38 : break;
148 : }
149 : }
150 :
151 : // Remove Fabric entry from PeerTable if empty
152 38 : if (fabricIt < CHIP_CONFIG_MAX_FABRICS)
153 : {
154 38 : if (mGroupFabrics[fabricIt].mDataPeerCount == 0 && mGroupFabrics[fabricIt].mControlPeerCount == 0)
155 : {
156 18 : RemoveAndCompactFabric(fabricIt);
157 : }
158 : }
159 :
160 : // Cannot find Peer to remove
161 38 : return err;
162 : }
163 :
164 9 : CHIP_ERROR GroupPeerTable::FabricRemoved(FabricIndex fabricIndex)
165 : {
166 9 : CHIP_ERROR err = CHIP_ERROR_NOT_FOUND;
167 :
168 9 : if (fabricIndex == kUndefinedFabricIndex)
169 : {
170 0 : return CHIP_ERROR_INVALID_ARGUMENT;
171 : }
172 :
173 136 : for (uint32_t it = 0; it < CHIP_CONFIG_MAX_FABRICS; it++)
174 : {
175 129 : if (fabricIndex == mGroupFabrics[it].mFabricIndex)
176 : {
177 2 : RemoveAndCompactFabric(it);
178 2 : return CHIP_NO_ERROR;
179 : }
180 : }
181 :
182 : // Cannot find Fabric to remove
183 7 : return err;
184 : }
185 :
186 38 : bool GroupPeerTable::RemoveSpecificPeer(GroupSender * list, NodeId nodeId, uint32_t size)
187 : {
188 38 : bool removed = false;
189 47 : for (uint32_t nodeIt = 0; nodeIt < size; nodeIt++)
190 : {
191 47 : if (list[nodeIt].mNodeId == nodeId)
192 : {
193 38 : list[nodeIt].mNodeId = kUndefinedNodeId;
194 38 : list[nodeIt].msgCounter.Reset();
195 38 : removed = true;
196 38 : break;
197 : }
198 : }
199 :
200 38 : if (removed)
201 : {
202 38 : CompactPeers(list, size);
203 : }
204 :
205 38 : return removed;
206 : }
207 :
208 38 : void GroupPeerTable::CompactPeers(GroupSender * list, uint32_t size)
209 : {
210 38 : if (list == nullptr || size == 0)
211 : {
212 0 : return;
213 : }
214 :
215 179 : for (uint32_t peerIndex = 0; peerIndex < size; peerIndex++)
216 : {
217 141 : if (list[peerIndex].mNodeId != kUndefinedNodeId)
218 : {
219 18 : continue;
220 : }
221 :
222 455 : for (uint32_t i = (size - 1); i > peerIndex; i--)
223 : {
224 352 : if (list[i].mNodeId != kUndefinedNodeId)
225 : {
226 : // Logic works since all buffer are static
227 : // move it up front
228 20 : new (&list[peerIndex]) GroupSender(list[i]);
229 20 : new (&list[i]) GroupSender();
230 20 : break;
231 : }
232 : }
233 : }
234 : }
235 :
236 20 : void GroupPeerTable::RemoveAndCompactFabric(uint32_t tableIndex)
237 : {
238 20 : if (tableIndex >= CHIP_CONFIG_MAX_FABRICS)
239 : {
240 0 : return;
241 : }
242 20 : mGroupFabrics[tableIndex].mFabricIndex = kUndefinedFabricIndex;
243 20 : new (&mGroupFabrics[tableIndex]) GroupFabric();
244 :
245 : // To maintain logic integrity Fabric array cannot have empty slot in between data
246 : // Find the last non empty element
247 153 : for (uint32_t i = CHIP_CONFIG_MAX_FABRICS - 1; i > tableIndex; i--)
248 : {
249 144 : if (mGroupFabrics[i].mFabricIndex != kUndefinedFabricIndex)
250 : {
251 : // Logic works since all buffer are static
252 : // move it up front
253 11 : new (&mGroupFabrics[tableIndex]) GroupFabric(mGroupFabrics[i]);
254 11 : new (&mGroupFabrics[i]) GroupFabric();
255 11 : break;
256 : }
257 : }
258 : }
259 :
260 4 : GroupOutgoingCounters::GroupOutgoingCounters(chip::PersistentStorageDelegate * storage_delegate)
261 : {
262 4 : Init(storage_delegate);
263 4 : }
264 :
265 375 : CHIP_ERROR GroupOutgoingCounters::Init(chip::PersistentStorageDelegate * storage_delegate)
266 : {
267 :
268 375 : if (storage_delegate == nullptr)
269 : {
270 0 : return CHIP_ERROR_INVALID_ARGUMENT;
271 : }
272 :
273 : // Spec 4.5.1.3
274 375 : mStorage = storage_delegate;
275 375 : uint16_t size = static_cast<uint16_t>(sizeof(uint32_t));
276 : uint32_t temp;
277 : CHIP_ERROR err;
278 375 : err = mStorage->SyncGetKeyValue(DefaultStorageKeyAllocator::GroupControlCounter().KeyName(), &temp, size);
279 375 : if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
280 : {
281 : // First time retrieving the counter
282 371 : mGroupControlCounter = (chip::Crypto::GetRandU32() & kMessageCounterRandomInitMask) + 1;
283 : }
284 4 : else if (err != CHIP_NO_ERROR)
285 : {
286 0 : return err;
287 : }
288 : else
289 : {
290 4 : mGroupControlCounter = temp;
291 : }
292 :
293 375 : err = mStorage->SyncGetKeyValue(DefaultStorageKeyAllocator::GroupDataCounter().KeyName(), &temp, size);
294 375 : if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
295 : {
296 : // First time retrieving the counter
297 371 : mGroupDataCounter = (chip::Crypto::GetRandU32() & kMessageCounterRandomInitMask) + 1;
298 : }
299 4 : else if (err != CHIP_NO_ERROR)
300 : {
301 0 : return err;
302 : }
303 : else
304 : {
305 4 : mGroupDataCounter = temp;
306 : }
307 :
308 375 : temp = mGroupControlCounter + GROUP_MSG_COUNTER_MIN_INCREMENT;
309 375 : size = static_cast<uint16_t>(sizeof(temp));
310 375 : ReturnErrorOnFailure(mStorage->SyncSetKeyValue(DefaultStorageKeyAllocator::GroupControlCounter().KeyName(), &temp, size));
311 :
312 375 : temp = mGroupDataCounter + GROUP_MSG_COUNTER_MIN_INCREMENT;
313 :
314 375 : return mStorage->SyncSetKeyValue(DefaultStorageKeyAllocator::GroupDataCounter().KeyName(), &temp, size);
315 : }
316 :
317 15 : uint32_t GroupOutgoingCounters::GetCounter(bool isControl)
318 : {
319 15 : return (isControl) ? mGroupControlCounter : mGroupDataCounter;
320 : }
321 :
322 5 : CHIP_ERROR GroupOutgoingCounters::IncrementCounter(bool isControl)
323 : {
324 5 : uint32_t temp = 0;
325 5 : uint16_t size = static_cast<uint16_t>(sizeof(uint32_t));
326 5 : uint32_t value = 0;
327 :
328 5 : StorageKeyName key = StorageKeyName::Uninitialized();
329 :
330 5 : if (isControl)
331 : {
332 2 : mGroupControlCounter++;
333 2 : key = DefaultStorageKeyAllocator::GroupControlCounter();
334 2 : value = mGroupControlCounter;
335 : }
336 : else
337 : {
338 3 : mGroupDataCounter++;
339 3 : key = DefaultStorageKeyAllocator::GroupDataCounter();
340 3 : value = mGroupDataCounter;
341 : }
342 :
343 5 : if (mStorage == nullptr)
344 : {
345 0 : return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
346 : }
347 :
348 5 : ReturnErrorOnFailure(mStorage->SyncGetKeyValue(key.KeyName(), &temp, size));
349 5 : if (temp == value)
350 : {
351 0 : temp = value + GROUP_MSG_COUNTER_MIN_INCREMENT;
352 0 : return mStorage->SyncSetKeyValue(key.KeyName(), &temp, sizeof(uint32_t));
353 : }
354 5 : return CHIP_NO_ERROR;
355 5 : }
356 :
357 : } // namespace Transport
358 : } // namespace chip
|