Matter SDK Coverage Report
Current view: top level - app/icd/client - CheckInHandler.cpp (source / functions) Coverage Total Hit
Test: SHA:704d97f9c619242ad76fcf75aeabc67802fa72d4 Lines: 88.1 % 59 52
Test Date: 2026-05-18 07:37:39 Functions: 66.7 % 6 4

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2023 Project CHIP Authors
       4              :  *    All rights reserved.
       5              :  *
       6              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7              :  *    you may not use this file except in compliance with the License.
       8              :  *    You may obtain a copy of the License at
       9              :  *
      10              :  *        http://www.apache.org/licenses/LICENSE-2.0
      11              :  *
      12              :  *    Unless required by applicable law or agreed to in writing, software
      13              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15              :  *    See the License for the specific language governing permissions and
      16              :  *    limitations under the License.
      17              :  */
      18              : 
      19              : /**
      20              :  *    @file
      21              :  *      This file defines objects for a CHIP ICD handler which handles unsolicited check-in messages.
      22              :  *
      23              :  */
      24              : 
      25              : #include <app/AppConfig.h>
      26              : #include <app/InteractionModelEngine.h>
      27              : #include <app/InteractionModelTimeout.h>
      28              : #include <app/icd/client/CheckInHandler.h>
      29              : #include <app/icd/client/RefreshKeySender.h>
      30              : 
      31              : #include <cinttypes>
      32              : 
      33              : #include <lib/core/Global.h>
      34              : #include <lib/support/CodeUtils.h>
      35              : #include <messaging/Flags.h>
      36              : #include <protocols/Protocols.h>
      37              : 
      38              : #include <protocols/secure_channel/Constants.h>
      39              : 
      40              : using namespace chip::Protocols::SecureChannel;
      41              : 
      42              : namespace chip {
      43              : namespace app {
      44              : 
      45              : inline constexpr uint64_t kCheckInCounterMax = (1ULL << 32);
      46              : inline constexpr uint32_t kKeyRefreshLimit   = (1U << 31);
      47              : 
      48            1 : CheckInHandler::CheckInHandler() {}
      49              : 
      50            1 : CHIP_ERROR CheckInHandler::Init(Messaging::ExchangeManager * exchangeManager, ICDClientStorage * clientStorage,
      51              :                                 CheckInDelegate * delegate, InteractionModelEngine * engine)
      52              : {
      53            1 :     VerifyOrReturnError(exchangeManager != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
      54            1 :     VerifyOrReturnError(clientStorage != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
      55            1 :     VerifyOrReturnError(delegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
      56            1 :     VerifyOrReturnError(engine != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
      57            1 :     VerifyOrReturnError(mpExchangeManager == nullptr, CHIP_ERROR_INCORRECT_STATE);
      58            1 :     VerifyOrReturnError(mpICDClientStorage == nullptr, CHIP_ERROR_INCORRECT_STATE);
      59            1 :     VerifyOrReturnError(mpCheckInDelegate == nullptr, CHIP_ERROR_INCORRECT_STATE);
      60            1 :     VerifyOrReturnError(mpImEngine == nullptr, CHIP_ERROR_INCORRECT_STATE);
      61              : 
      62            1 :     mpExchangeManager  = exchangeManager;
      63            1 :     mpICDClientStorage = clientStorage;
      64            1 :     mpCheckInDelegate  = delegate;
      65            1 :     mpImEngine         = engine;
      66            1 :     return mpExchangeManager->RegisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::MsgType::ICD_CheckIn, this);
      67              : }
      68              : 
      69            1 : void CheckInHandler::Shutdown()
      70              : {
      71            1 :     mpICDClientStorage = nullptr;
      72            1 :     mpCheckInDelegate  = nullptr;
      73            1 :     mpImEngine         = nullptr;
      74            1 :     if (mpExchangeManager)
      75              :     {
      76            1 :         TEMPORARY_RETURN_IGNORED mpExchangeManager->UnregisterUnsolicitedMessageHandlerForType(
      77              :             Protocols::SecureChannel::MsgType::ICD_CheckIn);
      78            1 :         mpExchangeManager = nullptr;
      79              :     }
      80            1 : }
      81              : 
      82            0 : CHIP_ERROR CheckInHandler::OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, ExchangeDelegate *& newDelegate)
      83              : {
      84              :     // Return error for wrong message type
      85            0 :     VerifyOrReturnError(payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::ICD_CheckIn),
      86              :                         CHIP_ERROR_INVALID_MESSAGE_TYPE);
      87              : 
      88            0 :     newDelegate = this;
      89            0 :     return CHIP_NO_ERROR;
      90              : }
      91              : 
      92            8 : CHIP_ERROR CheckInHandler::OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader,
      93              :                                              System::PacketBufferHandle && payload)
      94              : {
      95              :     // If the message type is not ICD_CheckIn, return CHIP_NO_ERROR and exit
      96            8 :     VerifyOrReturnError(payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::ICD_CheckIn), CHIP_NO_ERROR);
      97              : 
      98            8 :     ByteSpan payloadByteSpan{ payload->Start(), payload->DataLength() };
      99            8 :     ICDClientInfo clientInfo;
     100            8 :     CounterType counter = 0;
     101              :     // If the check-in message processing fails, return CHIP_NO_ERROR and exit.
     102            8 :     CHIP_ERROR err = mpICDClientStorage->ProcessCheckInPayload(payloadByteSpan, clientInfo, counter);
     103           16 :     if (CHIP_NO_ERROR != err)
     104              :     {
     105            1 :         ChipLogError(ICD, "ProcessCheckInPayload failed: %" CHIP_ERROR_FORMAT, err.Format());
     106            1 :         return CHIP_NO_ERROR;
     107              :     }
     108            7 :     CounterType receivedCheckInCounterOffset = (counter - clientInfo.start_icd_counter) % kCheckInCounterMax;
     109              : 
     110              :     // Detect duplicate check-in messages and return CHIP_NO_ERROR on receiving a duplicate message
     111            7 :     if (receivedCheckInCounterOffset <= clientInfo.offset)
     112              :     {
     113            1 :         ChipLogError(ICD, "A duplicate check-in message was received and discarded");
     114            1 :         return CHIP_NO_ERROR;
     115              :     }
     116              : 
     117            6 :     clientInfo.offset = receivedCheckInCounterOffset;
     118            6 :     bool refreshKey   = (receivedCheckInCounterOffset > kKeyRefreshLimit);
     119              : 
     120            6 :     if (refreshKey)
     121              :     {
     122            1 :         ChipLogProgress(ICD, "Key Refresh is required");
     123            1 :         RefreshKeySender * refreshKeySender = mpCheckInDelegate->OnKeyRefreshNeeded(clientInfo, mpICDClientStorage);
     124            1 :         if (refreshKeySender == nullptr)
     125              :         {
     126            0 :             ChipLogError(ICD, "Key Refresh failed for node ID:" ChipLogFormatScopedNodeId,
     127              :                          ChipLogValueScopedNodeId(clientInfo.peer_node));
     128            0 :             return CHIP_NO_ERROR;
     129              :         }
     130            1 :         err = refreshKeySender->EstablishSessionToPeer();
     131            2 :         if (CHIP_NO_ERROR != err)
     132              :         {
     133            1 :             ChipLogError(ICD, "CASE session establishment failed with error : %" CHIP_ERROR_FORMAT, err.Format());
     134            1 :             mpCheckInDelegate->OnKeyRefreshDone(refreshKeySender, err);
     135            1 :             return CHIP_NO_ERROR;
     136              :         }
     137              :     }
     138              :     else
     139              :     {
     140            5 :         TEMPORARY_RETURN_IGNORED mpICDClientStorage->StoreEntry(clientInfo);
     141            5 :         mpCheckInDelegate->OnCheckInComplete(clientInfo);
     142              : #if CHIP_CONFIG_ENABLE_READ_CLIENT
     143            5 :         mpImEngine->OnActiveModeNotification(clientInfo.peer_node, clientInfo.monitored_subject);
     144              : #endif // CHIP_CONFIG_ENABLE_READ_CLIENT
     145              :     }
     146              : 
     147            5 :     return CHIP_NO_ERROR;
     148            8 : }
     149              : 
     150            0 : void CheckInHandler::OnResponseTimeout(Messaging::ExchangeContext * ec) {}
     151              : 
     152              : } // namespace app
     153              : } // namespace chip
        

Generated by: LCOV version 2.0-1