LCOV - code coverage report
Current view: top level - transport - GroupPeerMessageCounter.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 134 145 92.4 %
Date: 2024-02-15 08:20:41 Functions: 10 10 100.0 %

          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

Generated by: LCOV version 1.14