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 339 : CHIP_ERROR GroupOutgoingCounters::Init(chip::PersistentStorageDelegate * storage_delegate) 266 : { 267 : 268 339 : if (storage_delegate == nullptr) 269 : { 270 0 : return CHIP_ERROR_INVALID_ARGUMENT; 271 : } 272 : 273 : // Spec 4.5.1.3 274 339 : mStorage = storage_delegate; 275 339 : uint16_t size = static_cast<uint16_t>(sizeof(uint32_t)); 276 : uint32_t temp; 277 : CHIP_ERROR err; 278 339 : err = mStorage->SyncGetKeyValue(DefaultStorageKeyAllocator::GroupControlCounter().KeyName(), &temp, size); 279 339 : if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) 280 : { 281 : // First time retrieving the counter 282 335 : 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 339 : err = mStorage->SyncGetKeyValue(DefaultStorageKeyAllocator::GroupDataCounter().KeyName(), &temp, size); 294 339 : if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) 295 : { 296 : // First time retrieving the counter 297 335 : 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 339 : temp = mGroupControlCounter + GROUP_MSG_COUNTER_MIN_INCREMENT; 309 339 : size = static_cast<uint16_t>(sizeof(temp)); 310 339 : ReturnErrorOnFailure(mStorage->SyncSetKeyValue(DefaultStorageKeyAllocator::GroupControlCounter().KeyName(), &temp, size)); 311 : 312 339 : temp = mGroupDataCounter + GROUP_MSG_COUNTER_MIN_INCREMENT; 313 : 314 339 : 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