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