| /* |
| * Copyright (c) 2020 Project CHIP Authors |
| * All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /** |
| * @file |
| * This file defines the classes corresponding to CHIP reliable message |
| * protocol. |
| */ |
| |
| #pragma once |
| |
| #include <array> |
| #include <stdint.h> |
| |
| #include <messaging/ExchangeContext.h> |
| #include <messaging/ReliableMessageProtocolConfig.h> |
| |
| #include <lib/core/CHIPError.h> |
| #include <lib/support/BitFlags.h> |
| #include <lib/support/Pool.h> |
| #include <system/SystemLayer.h> |
| #include <system/SystemPacketBuffer.h> |
| #include <transport/raw/MessageHeader.h> |
| |
| namespace chip { |
| namespace Messaging { |
| |
| class ExchangeContext; |
| using ExchangeHandle = ReferenceCountedHandle<ExchangeContext>; |
| |
| enum class SendMessageFlags : uint16_t; |
| class ReliableMessageContext; |
| |
| class ReliableMessageMgr |
| { |
| public: |
| /** |
| * @class RetransTableEntry |
| * |
| * @brief |
| * This class is part of the CHIP Reliable Messaging Protocol and is used |
| * to keep track of CHIP messages that have been sent and are expecting an |
| * acknowledgment back. If the acknowledgment is not received within a |
| * specific timeout, the message would be retransmitted from this table. |
| * |
| */ |
| struct RetransTableEntry |
| { |
| RetransTableEntry(ReliableMessageContext * rc); |
| ~RetransTableEntry(); |
| |
| ExchangeHandle ec; /**< The context for the stored CHIP message. */ |
| EncryptedPacketBufferHandle retainedBuf; /**< The packet buffer holding the CHIP message. */ |
| uint16_t nextRetransTimeTick; /**< A counter representing the next retransmission time for the message. */ |
| uint8_t sendCount; /**< A counter representing the number of times the message has been sent. */ |
| }; |
| |
| public: |
| ReliableMessageMgr(BitMapObjectPool<ExchangeContext, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS> & contextPool); |
| ~ReliableMessageMgr(); |
| |
| void Init(chip::System::Layer * systemLayer, SessionManager * sessionManager); |
| void Shutdown(); |
| |
| /** |
| * Return a tick counter value given a time period. |
| * |
| * @param[in] period Timestamp value of in milliseconds. |
| * |
| * @return Tick count for the time period. |
| */ |
| uint64_t GetTickCounterFromTimePeriod(System::Clock::Milliseconds64 period); |
| |
| /** |
| * Return a tick counter value between the given time and the stored time. |
| * |
| * @param[in] newTime Timestamp value of in milliseconds. |
| * |
| * @return Tick count of the difference between the given time and the stored time. |
| */ |
| uint64_t GetTickCounterFromTimeDelta(System::Clock::Timestamp newTime); |
| |
| /** |
| * Iterate through active exchange contexts and retrans table entries. If an |
| * action needs to be triggered by ReliableMessageProtocol time facilities, |
| * execute that action. |
| */ |
| void ExecuteActions(); |
| |
| /** |
| * Handle physical wakeup of system due to ReliableMessageProtocol wakeup. |
| * |
| */ |
| static void Timeout(System::Layer * aSystemLayer, void * aAppState); |
| |
| /** |
| * Add a CHIP message into the retransmission table to be subsequently resent if a corresponding acknowledgment |
| * is not received within the retransmission timeout. |
| * |
| * @param[in] rc A pointer to the ExchangeContext object. |
| * |
| * @param[out] rEntry A pointer to a pointer of a retransmission table entry added into the table. |
| * |
| * @retval #CHIP_ERROR_RETRANS_TABLE_FULL If there is no empty slot left in the table for addition. |
| * @retval #CHIP_NO_ERROR On success. |
| */ |
| CHIP_ERROR AddToRetransTable(ReliableMessageContext * rc, RetransTableEntry ** rEntry); |
| |
| /** |
| * Start retranmisttion of cached encryped packet for current entry. |
| * |
| * @param[in] entry A pointer to a retransmission table entry added into the table. |
| * |
| * @retval #CHIP_NO_ERROR On success. |
| */ |
| void StartRetransmision(RetransTableEntry * entry); |
| |
| /** |
| * Pause retranmisttion of current exchange for specified period. |
| * |
| * @param[in] rc A pointer to the ExchangeContext object. |
| * |
| * @param[in] PauseTimeMillis Pause period in milliseconds. |
| * |
| * @retval #CHIP_NO_ERROR On success. |
| */ |
| void PauseRetransmision(ReliableMessageContext * rc, uint32_t PauseTimeMillis); |
| |
| /** |
| * Re-start retranmisttion of cached encryped packets for the given ReliableMessageContext. |
| * |
| * @param[in] rc The ReliableMessageContext to resume retransmission for. |
| * |
| * @retval #CHIP_NO_ERROR On success. |
| */ |
| void ResumeRetransmision(ReliableMessageContext * rc); |
| |
| /** |
| * Iterate through active exchange contexts and retrans table entries. Clear the entry matching |
| * the specified ExchangeContext and the message ID from the retransmision table. |
| * |
| * @param[in] rc A pointer to the ExchangeContext object. |
| * @param[in] ackMessageCounter The acknowledged message counter of the received packet. |
| * |
| * @retval #CHIP_NO_ERROR On success. |
| */ |
| bool CheckAndRemRetransTable(ReliableMessageContext * rc, uint32_t ackMessageCounter); |
| |
| /** |
| * Send the specified entry from the retransmission table. |
| * |
| * @param[in] entry A pointer to a retransmission table entry object that needs to be sent. |
| * |
| * @return #CHIP_NO_ERROR On success, else corresponding CHIP_ERROR returned from SendMessage. |
| */ |
| CHIP_ERROR SendFromRetransTable(RetransTableEntry * entry); |
| |
| /** |
| * Clear entries matching a specified ExchangeContext. |
| * |
| * @param[in] rc A pointer to the ExchangeContext object. |
| * |
| */ |
| void ClearRetransTable(ReliableMessageContext * rc); |
| |
| /** |
| * Clear an entry in the retransmission table. |
| * |
| * @param[in] rEntry A reference to the RetransTableEntry object. |
| * |
| */ |
| void ClearRetransTable(RetransTableEntry & rEntry); |
| |
| /** |
| * Fail entries matching a specified ExchangeContext. |
| * |
| * @param[in] rc A pointer to the ExchangeContext object. |
| * |
| * @param[in] err The error for failing table entries. |
| * |
| */ |
| void FailRetransTableEntries(ReliableMessageContext * rc, CHIP_ERROR err); |
| |
| /** |
| * Iterate through active exchange contexts and retrans table entries. |
| * Determine how many ReliableMessageProtocol ticks we need to sleep before we |
| * need to physically wake the CPU to perform an action. Set a timer to go off |
| * when we next need to wake the system. |
| * |
| */ |
| void StartTimer(); |
| |
| /** |
| * Stop the timer for retransmistion on current node. |
| * |
| */ |
| void StopTimer(); |
| |
| /** |
| * Calculate number of virtual ReliableMessageProtocol ticks that have expired |
| * since we last called this function. Iterate through active exchange contexts |
| * and retrans table entries, subtracting expired virtual ticks to synchronize |
| * wakeup times with the current system time. Do not perform any actions beyond |
| * updating tick counts, actions will be performed by the physical |
| * ReliableMessageProtocol timer tick expiry. |
| * |
| */ |
| void ExpireTicks(); |
| |
| #if CHIP_CONFIG_TEST |
| // Functions for testing |
| int TestGetCountRetransTable(); |
| void TestSetIntervalShift(uint16_t value) { mTimerIntervalShift = value; } |
| #endif // CHIP_CONFIG_TEST |
| |
| private: |
| BitMapObjectPool<ExchangeContext, CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS> & mContextPool; |
| chip::System::Layer * mSystemLayer; |
| System::Clock::Timestamp mTimeStampBase; // ReliableMessageProtocol timer base value to add offsets to evaluate timeouts |
| System::Clock::Timestamp mCurrentTimerExpiry; // Tracks when the ReliableMessageProtocol timer will next expire |
| uint16_t mTimerIntervalShift; // ReliableMessageProtocol Timer tick period shift |
| |
| /* Placeholder function to run a function for all exchanges */ |
| template <typename Function> |
| void ExecuteForAllContext(Function function) |
| { |
| mContextPool.ForEachActiveObject([&](auto * ec) { |
| function(ec->GetReliableMessageContext()); |
| return true; |
| }); |
| } |
| |
| void TicklessDebugDumpRetransTable(const char * log); |
| |
| // ReliableMessageProtocol Global tables for timer context |
| BitMapObjectPool<RetransTableEntry, CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE> mRetransTable; |
| }; |
| |
| } // namespace Messaging |
| } // namespace chip |