Matter SDK Coverage Report
Current view: top level - transport - GroupPeerMessageCounter.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 92.4 % 145 134
Test Date: 2025-01-17 19:00:11 Functions: 100.0 % 10 10

            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
        

Generated by: LCOV version 2.0-1