Matter SDK Coverage Report
Current view: top level - app/icd/client - CheckInHandler.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 87.9 % 58 51
Test Date: 2025-01-17 19:00:11 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 :     if (mpExchangeManager)
      74              :     {
      75            1 :         mpExchangeManager->UnregisterUnsolicitedMessageHandlerForType(Protocols::SecureChannel::MsgType::ICD_CheckIn);
      76            1 :         mpExchangeManager = nullptr;
      77              :     }
      78            1 : }
      79              : 
      80            0 : CHIP_ERROR CheckInHandler::OnUnsolicitedMessageReceived(const PayloadHeader & payloadHeader, ExchangeDelegate *& newDelegate)
      81              : {
      82              :     // Return error for wrong message type
      83            0 :     VerifyOrReturnError(payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::ICD_CheckIn),
      84              :                         CHIP_ERROR_INVALID_MESSAGE_TYPE);
      85              : 
      86            0 :     newDelegate = this;
      87            0 :     return CHIP_NO_ERROR;
      88              : }
      89              : 
      90            8 : CHIP_ERROR CheckInHandler::OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader,
      91              :                                              System::PacketBufferHandle && payload)
      92              : {
      93              :     // If the message type is not ICD_CheckIn, return CHIP_NO_ERROR and exit
      94            8 :     VerifyOrReturnError(payloadHeader.HasMessageType(Protocols::SecureChannel::MsgType::ICD_CheckIn), CHIP_NO_ERROR);
      95              : 
      96            8 :     ByteSpan payloadByteSpan{ payload->Start(), payload->DataLength() };
      97            8 :     ICDClientInfo clientInfo;
      98            8 :     CounterType counter = 0;
      99              :     // If the check-in message processing fails, return CHIP_NO_ERROR and exit.
     100            8 :     CHIP_ERROR err = mpICDClientStorage->ProcessCheckInPayload(payloadByteSpan, clientInfo, counter);
     101            8 :     if (CHIP_NO_ERROR != err)
     102              :     {
     103            1 :         ChipLogError(ICD, "ProcessCheckInPayload failed: %" CHIP_ERROR_FORMAT, err.Format());
     104            1 :         return CHIP_NO_ERROR;
     105              :     }
     106            7 :     CounterType receivedCheckInCounterOffset = (counter - clientInfo.start_icd_counter) % kCheckInCounterMax;
     107              : 
     108              :     // Detect duplicate check-in messages and return CHIP_NO_ERROR on receiving a duplicate message
     109            7 :     if (receivedCheckInCounterOffset <= clientInfo.offset)
     110              :     {
     111            1 :         ChipLogError(ICD, "A duplicate check-in message was received and discarded");
     112            1 :         return CHIP_NO_ERROR;
     113              :     }
     114              : 
     115            6 :     clientInfo.offset = receivedCheckInCounterOffset;
     116            6 :     bool refreshKey   = (receivedCheckInCounterOffset > kKeyRefreshLimit);
     117              : 
     118            6 :     if (refreshKey)
     119              :     {
     120            1 :         ChipLogProgress(ICD, "Key Refresh is required");
     121            1 :         RefreshKeySender * refreshKeySender = mpCheckInDelegate->OnKeyRefreshNeeded(clientInfo, mpICDClientStorage);
     122            1 :         if (refreshKeySender == nullptr)
     123              :         {
     124            0 :             ChipLogError(ICD, "Key Refresh failed for node ID:" ChipLogFormatScopedNodeId,
     125              :                          ChipLogValueScopedNodeId(clientInfo.peer_node));
     126            0 :             return CHIP_NO_ERROR;
     127              :         }
     128            1 :         err = refreshKeySender->EstablishSessionToPeer();
     129            1 :         if (CHIP_NO_ERROR != err)
     130              :         {
     131            1 :             ChipLogError(ICD, "CASE session establishment failed with error : %" CHIP_ERROR_FORMAT, err.Format());
     132            1 :             mpCheckInDelegate->OnKeyRefreshDone(refreshKeySender, err);
     133            1 :             return CHIP_NO_ERROR;
     134              :         }
     135              :     }
     136              :     else
     137              :     {
     138            5 :         mpICDClientStorage->StoreEntry(clientInfo);
     139            5 :         mpCheckInDelegate->OnCheckInComplete(clientInfo);
     140              : #if CHIP_CONFIG_ENABLE_READ_CLIENT
     141            5 :         mpImEngine->OnActiveModeNotification(clientInfo.peer_node);
     142              : #endif // CHIP_CONFIG_ENABLE_READ_CLIENT
     143              :     }
     144              : 
     145            5 :     return CHIP_NO_ERROR;
     146            8 : }
     147              : 
     148            0 : void CheckInHandler::OnResponseTimeout(Messaging::ExchangeContext * ec) {}
     149              : 
     150              : } // namespace app
     151              : } // namespace chip
        

Generated by: LCOV version 2.0-1