LCOV - code coverage report
Current view: top level - messaging - ReliableMessageContext.cpp (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 55 61 90.2 %
Date: 2024-02-15 08:20:41 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /*
       2             :  *    Copyright (c) 2020-2021 Project CHIP Authors
       3             :  *    All rights reserved.
       4             :  *
       5             :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6             :  *    you may not use this file except in compliance with the License.
       7             :  *    You may obtain a copy of the License at
       8             :  *
       9             :  *        http://www.apache.org/licenses/LICENSE-2.0
      10             :  *
      11             :  *    Unless required by applicable law or agreed to in writing, software
      12             :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13             :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14             :  *    See the License for the specific language governing permissions and
      15             :  *    limitations under the License.
      16             :  */
      17             : 
      18             : /**
      19             :  *    @file
      20             :  *      This file implements the CHIP reliable message protocol.
      21             :  *
      22             :  */
      23             : 
      24             : #include <inttypes.h>
      25             : 
      26             : #include <messaging/ExchangeContext.h>
      27             : #include <messaging/ExchangeMgr.h>
      28             : #include <messaging/ReliableMessageContext.h>
      29             : 
      30             : #include <app/AppConfig.h>
      31             : #include <lib/core/CHIPEncoding.h>
      32             : #include <lib/support/CodeUtils.h>
      33             : #include <lib/support/Defer.h>
      34             : #include <messaging/ErrorCategory.h>
      35             : #include <messaging/Flags.h>
      36             : #include <messaging/ReliableMessageMgr.h>
      37             : #include <platform/PlatformManager.h>
      38             : #include <protocols/Protocols.h>
      39             : #include <protocols/secure_channel/Constants.h>
      40             : 
      41             : using namespace chip::DeviceLayer;
      42             : 
      43             : namespace chip {
      44             : namespace Messaging {
      45             : 
      46        3268 : ReliableMessageContext::ReliableMessageContext() : mNextAckTime(0), mPendingPeerAckMessageCounter(0) {}
      47             : 
      48       28081 : ExchangeContext * ReliableMessageContext::GetExchangeContext()
      49             : {
      50       28081 :     return static_cast<ExchangeContext *>(this);
      51             : }
      52             : 
      53       33058 : ReliableMessageMgr * ReliableMessageContext::GetReliableMessageMgr()
      54             : {
      55       33058 :     return static_cast<ExchangeContext *>(this)->GetExchangeMgr()->GetReliableMessageMgr();
      56             : }
      57             : 
      58       15840 : void ReliableMessageContext::SetWaitingForAck(bool waitingForAck)
      59             : {
      60       15840 :     mFlags.Set(Flags::kFlagWaitingForAck, waitingForAck);
      61       15840 : }
      62             : 
      63        3360 : CHIP_ERROR ReliableMessageContext::FlushAcks()
      64             : {
      65        3360 :     CHIP_ERROR err = CHIP_NO_ERROR;
      66             : 
      67        3360 :     if (IsAckPending())
      68             :     {
      69        1524 :         err = SendStandaloneAckMessage();
      70             : 
      71        1524 :         if (err == CHIP_NO_ERROR)
      72             :         {
      73        1521 :             ChipLogDetail(ExchangeManager,
      74             :                           "Flushed pending ack for MessageCounter:" ChipLogFormatMessageCounter
      75             :                           " on exchange " ChipLogFormatExchange,
      76             :                           mPendingPeerAckMessageCounter, ChipLogValueExchange(GetExchangeContext()));
      77             :         }
      78             :     }
      79             : 
      80        3360 :     return err;
      81             : }
      82             : 
      83             : /**
      84             :  *  Process received Ack. Remove the corresponding message context from the RetransTable and execute the application
      85             :  *  callback
      86             :  *
      87             :  *  @note
      88             :  *    This message is part of the CHIP Reliable Messaging protocol.
      89             :  *
      90             :  *  @param[in]    ackMessageCounter         The acknowledged message counter of the incoming message.
      91             :  */
      92        7786 : void ReliableMessageContext::HandleRcvdAck(uint32_t ackMessageCounter)
      93             : {
      94             :     // Msg is an Ack; Check Retrans Table and remove message context
      95        7786 :     if (GetReliableMessageMgr()->CheckAndRemRetransTable(this, ackMessageCounter))
      96             :     {
      97        7775 :         SetWaitingForResponseOrAck(false);
      98             :     }
      99             :     else
     100             :     {
     101             :         // This can happen quite easily due to a packet with a piggyback ack
     102             :         // being lost and retransmitted.
     103          11 :         ChipLogDetail(ExchangeManager,
     104             :                       "CHIP MessageCounter:" ChipLogFormatMessageCounter " not in RetransTable on exchange " ChipLogFormatExchange,
     105             :                       ackMessageCounter, ChipLogValueExchange(GetExchangeContext()));
     106             :     }
     107        7786 : }
     108             : 
     109        7857 : CHIP_ERROR ReliableMessageContext::HandleNeedsAck(uint32_t messageCounter, BitFlags<MessageFlagValues> messageFlags)
     110             : {
     111        7857 :     CHIP_ERROR err = HandleNeedsAckInner(messageCounter, messageFlags);
     112             : 
     113             :     // Schedule next physical wakeup on function exit
     114        7857 :     GetReliableMessageMgr()->StartTimer();
     115             : 
     116        7857 :     return err;
     117             : }
     118             : 
     119        7857 : CHIP_ERROR ReliableMessageContext::HandleNeedsAckInner(uint32_t messageCounter, BitFlags<MessageFlagValues> messageFlags)
     120             : 
     121             : {
     122             :     // If the message IS a duplicate there will never be a response to it, so we
     123             :     // should not wait for one and just immediately send a standalone ack.
     124        7857 :     if (messageFlags.Has(MessageFlagValues::kDuplicateMessage))
     125             :     {
     126           5 :         ChipLogDetail(ExchangeManager,
     127             :                       "Forcing tx of solitary ack for duplicate MessageCounter:" ChipLogFormatMessageCounter
     128             :                       " on exchange " ChipLogFormatExchange,
     129             :                       messageCounter, ChipLogValueExchange(GetExchangeContext()));
     130             : 
     131           5 :         bool wasAckPending = IsAckPending() && mPendingPeerAckMessageCounter != messageCounter;
     132             : 
     133           5 :         bool messageCounterWasValid = HasPiggybackAckPending();
     134             : 
     135             :         // Temporary store currently pending ack message counter (even if there is none).
     136           5 :         uint32_t tempAckMessageCounter = mPendingPeerAckMessageCounter;
     137             : 
     138           5 :         SetPendingPeerAckMessageCounter(messageCounter);
     139           5 :         CHIP_ERROR err = SendStandaloneAckMessage();
     140             : 
     141           5 :         if (wasAckPending)
     142             :         {
     143             :             // Restore previously pending ack message counter.
     144           0 :             SetPendingPeerAckMessageCounter(tempAckMessageCounter);
     145             :         }
     146           5 :         else if (messageCounterWasValid)
     147             :         {
     148             :             // Restore the previous value, so later piggybacks will pick it up,
     149             :             // but don't set out "ack is pending" state, because we didn't use
     150             :             // to have it set.
     151           2 :             mPendingPeerAckMessageCounter = tempAckMessageCounter;
     152             :         }
     153             :         // Otherwise don't restore the invalid old mPendingPeerAckMessageCounter
     154             :         // value, so we preserve the invariant that once we have had an ack
     155             :         // pending we always have a valid mPendingPeerAckMessageCounter.
     156             : 
     157           5 :         return err;
     158             :     }
     159             :     // Otherwise, the message IS NOT a duplicate.
     160             : 
     161        7852 :     if (IsAckPending())
     162             :     {
     163           0 :         ChipLogDetail(ExchangeManager,
     164             :                       "Pending ack queue full; forcing tx of solitary ack for MessageCounter:" ChipLogFormatMessageCounter
     165             :                       " on exchange " ChipLogFormatExchange,
     166             :                       mPendingPeerAckMessageCounter, ChipLogValueExchange(GetExchangeContext()));
     167             :         // Send the Ack for the currently pending Ack in a SecureChannel::StandaloneAck message.
     168           0 :         ReturnErrorOnFailure(SendStandaloneAckMessage());
     169             :     }
     170             : 
     171             :     // Replace the Pending ack message counter.
     172        7852 :     SetPendingPeerAckMessageCounter(messageCounter);
     173             :     using namespace System::Clock::Literals;
     174        7852 :     mNextAckTime = System::SystemClock().GetMonotonicTimestamp() + CHIP_CONFIG_RMP_DEFAULT_ACK_TIMEOUT;
     175        7852 :     return CHIP_NO_ERROR;
     176             : }
     177             : 
     178        1531 : CHIP_ERROR ReliableMessageContext::SendStandaloneAckMessage()
     179             : {
     180             :     // Allocate a buffer for the null message
     181        1531 :     System::PacketBufferHandle msgBuf = MessagePacketBuffer::New(0);
     182        1531 :     if (msgBuf.IsNull())
     183             :     {
     184           0 :         return CHIP_ERROR_NO_MEMORY;
     185             :     }
     186             : 
     187        3062 :     CHIP_ERROR err = GetExchangeContext()->SendMessage(Protocols::SecureChannel::MsgType::StandaloneAck, std::move(msgBuf),
     188        1531 :                                                        BitFlags<SendMessageFlags>{ SendMessageFlags::kNoAutoRequestAck });
     189        1531 :     if (IsSendErrorNonCritical(err))
     190             :     {
     191           0 :         ChipLogError(ExchangeManager,
     192             :                      "Non-crit err %" CHIP_ERROR_FORMAT " sending solitary ack for MessageCounter:" ChipLogFormatMessageCounter
     193             :                      " on exchange " ChipLogFormatExchange,
     194             :                      err.Format(), mPendingPeerAckMessageCounter, ChipLogValueExchange(GetExchangeContext()));
     195           0 :         return CHIP_NO_ERROR;
     196             :     }
     197        1531 :     if (err != CHIP_NO_ERROR)
     198             :     {
     199           3 :         ChipLogError(ExchangeManager,
     200             :                      "Failed to send Solitary ack for MessageCounter:" ChipLogFormatMessageCounter
     201             :                      " on exchange " ChipLogFormatExchange ":%" CHIP_ERROR_FORMAT,
     202             :                      mPendingPeerAckMessageCounter, ChipLogValueExchange(GetExchangeContext()), err.Format());
     203             :     }
     204             : 
     205        1531 :     return err;
     206        1531 : }
     207             : 
     208        7881 : void ReliableMessageContext::SetPendingPeerAckMessageCounter(uint32_t aPeerAckMessageCounter)
     209             : {
     210        7881 :     mPendingPeerAckMessageCounter = aPeerAckMessageCounter;
     211        7881 :     SetAckPending(true);
     212        7881 :     mFlags.Set(Flags::kFlagAckMessageCounterIsValid);
     213        7881 : }
     214             : 
     215             : } // namespace Messaging
     216             : } // namespace chip

Generated by: LCOV version 1.14