Coverage Report

Created: 2025-09-02 06:46

/src/connectedhomeip/src/messaging/ReliableMessageContext.h
Line
Count
Source (jump to first uncovered line)
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 defines the reliable message context for the CHIP Message
21
 *      Layer. The context is one-on-one relationship with a chip session.
22
 */
23
24
#pragma once
25
26
#include <stdint.h>
27
#include <string.h>
28
29
#include <messaging/ReliableMessageProtocolConfig.h>
30
31
#include <lib/core/CHIPError.h>
32
#include <lib/core/ReferenceCounted.h>
33
#include <lib/support/DLLUtil.h>
34
#include <messaging/ReliableMessageProtocolConfig.h>
35
#include <system/SystemLayer.h>
36
#include <transport/raw/MessageHeader.h>
37
38
namespace chip {
39
namespace app {
40
class TestCommandInteraction;
41
class TestReadInteraction;
42
class TestWriteInteraction;
43
} // namespace app
44
namespace Messaging {
45
46
class ChipMessageInfo;
47
class ExchangeContext;
48
enum class MessageFlagValues : uint32_t;
49
class ReliableMessageMgr;
50
51
class ReliableMessageContext
52
{
53
public:
54
    ReliableMessageContext();
55
56
    /**
57
     * Flush the pending Ack for current exchange.
58
     *
59
     */
60
    CHIP_ERROR FlushAcks();
61
62
    /**
63
     * Take the pending peer ack message counter from the context.  This must
64
     * only be called when HasPiggybackAckPending() is true.  After this call,
65
     * IsAckPending() will be false; it's the caller's responsibility to send
66
     * the ack.
67
     */
68
    uint32_t TakePendingPeerAckMessageCounter()
69
296
    {
70
296
        SetAckPending(false);
71
296
        return mPendingPeerAckMessageCounter;
72
296
    }
73
74
    /**
75
     * Check whether we have a mPendingPeerAckMessageCounter. The counter is
76
     * valid once we receive a message which requests an ack. Once
77
     * mPendingPeerAckMessageCounter is valid, it never stops being valid.
78
     */
79
    bool HasPiggybackAckPending() const;
80
81
    /**
82
     *  Send a SecureChannel::StandaloneAck message.
83
     *
84
     *  @note  When sent via UDP, the null message is sent *without* requesting an acknowledgment,
85
     *  even in the case where the auto-request acknowledgment feature has been enabled on the
86
     *  exchange.
87
     *
88
     *  @retval  #CHIP_ERROR_NO_MEMORY   If no available PacketBuffers.
89
     *  @retval  #CHIP_NO_ERROR          If the method succeeded or the error wasn't critical.
90
     *  @retval  other                    Another critical error returned by SendMessage().
91
     */
92
    CHIP_ERROR SendStandaloneAckMessage();
93
94
    /**
95
     *  Determine whether an acknowledgment will be requested whenever a message is sent for the exchange.
96
     *
97
     *  @return Returns 'true' an acknowledgment will be requested whenever a message is sent, else 'false'.
98
     */
99
    bool AutoRequestAck() const;
100
101
    /**
102
     * Set whether an acknowledgment should be requested whenever a message is sent.
103
     *
104
     * @param[in] autoReqAck            A Boolean indicating whether or not an
105
     *                                  acknowledgment should be requested whenever a
106
     *                                  message is sent.
107
     */
108
    void SetAutoRequestAck(bool autoReqAck);
109
110
    /**
111
     *  Determine whether there is already an acknowledgment pending to be sent to the peer on this exchange.
112
     *
113
     *  @return Returns 'true' if there is already an acknowledgment pending  on this exchange, else 'false'.
114
     */
115
    bool IsAckPending() const;
116
117
    /// Determine whether the reliable message context is waiting for an ack.
118
    bool IsWaitingForAck() const;
119
120
    /// Set whether the reliable message context is waiting for an ack.
121
    void SetWaitingForAck(bool waitingForAck);
122
123
    /// Set if this exchange is requesting Sleepy End Device active mode
124
    void SetRequestingActiveMode(bool activeMode);
125
126
    /// Determine whether this exchange is a EphemeralExchange for replying a StandaloneAck
127
    bool IsEphemeralExchange() const;
128
129
    /**
130
     * Get the reliable message manager that corresponds to this reliable
131
     * message context.
132
     */
133
    ReliableMessageMgr * GetReliableMessageMgr();
134
135
protected:
136
    bool WaitingForResponseOrAck() const;
137
    void SetWaitingForResponseOrAck(bool waitingForResponseOrAck);
138
139
    enum class Flags : uint16_t
140
    {
141
        /// When set, signifies that this context is the initiator of the exchange.
142
        kFlagInitiator = (1u << 0),
143
144
        /// When set, signifies that a response is expected for a message that is being sent.
145
        kFlagResponseExpected = (1u << 1),
146
147
        /// When set, automatically request an acknowledgment whenever a message is sent via UDP.
148
        kFlagAutoRequestAck = (1u << 2),
149
150
        /// When set, signifies the reliable message context is waiting for an
151
        /// ack: a message that needs an ack has been sent, no ack has been
152
        /// received, and we have not yet run out of MRP retries.
153
        kFlagWaitingForAck = (1u << 3),
154
155
        /// When set, signifies that there is an acknowledgment pending to be sent back.
156
        kFlagAckPending = (1u << 4),
157
158
        /// When set, signifies that mPendingPeerAckMessageCounter is valid.
159
        /// The counter is valid once we receive a message which requests an ack.
160
        /// Once mPendingPeerAckMessageCounter is valid, it never stops being valid.
161
        kFlagAckMessageCounterIsValid = (1u << 5),
162
163
        /// When set, signifies that this exchange is waiting for a call to SendMessage.
164
        kFlagWillSendMessage = (1u << 6),
165
166
        /// When set, we have had Close() or Abort() called on us already.
167
        kFlagClosed = (1u << 7),
168
169
        /// When set, signifies that the exchange created sorely for replying a StandaloneAck
170
        kFlagEphemeralExchange = (1u << 8),
171
172
        /// When set, ignore session being released, because we are releasing it ourselves.
173
        kFlagIgnoreSessionRelease = (1u << 9),
174
175
        // This flag is used to determine if the peer (receiver) should be considered active or not.
176
        // When set, sender knows it has received at least one application-level message
177
        // from the peer and can assume the peer (receiver) is active.
178
        // If the flag is not set, we don't know if the peer (receiver) is active or not.
179
        kFlagReceivedAtLeastOneMessage = (1u << 10),
180
181
        /// When set:
182
        ///
183
        /// (1) We sent a message that expected a response (hence
184
        ///     IsResponseExpected() is true).
185
        /// (2) We have received neither a response nor an ack for that message.
186
        kFlagWaitingForResponseOrAck = (1u << 11),
187
    };
188
189
    BitFlags<Flags> mFlags; // Internal state flags
190
191
private:
192
    void HandleRcvdAck(uint32_t ackMessageCounter);
193
    CHIP_ERROR HandleNeedsAck(uint32_t messageCounter, BitFlags<MessageFlagValues> messageFlags);
194
    CHIP_ERROR HandleNeedsAckInner(uint32_t messageCounter, BitFlags<MessageFlagValues> messageFlags);
195
    ExchangeContext * GetExchangeContext();
196
197
    /**
198
     *  Set if an acknowledgment needs to be sent back to the peer on this exchange.
199
     *
200
     *  @param[in]  inAckPending A Boolean indicating whether (true) or not
201
     *                          (false) an acknowledgment should be sent back
202
     *                          in response to a received message.
203
     */
204
    void SetAckPending(bool inAckPending);
205
206
    // Set our pending peer ack message counter and any other state needed to ensure that we
207
    // will send that ack at some point.
208
    void SetPendingPeerAckMessageCounter(uint32_t aPeerAckMessageCounter);
209
210
    friend class ReliableMessageMgr;
211
    friend class ExchangeContext;
212
    friend class ExchangeMessageDispatch;
213
    friend class ::chip::app::TestCommandInteraction;
214
    friend class ::chip::app::TestReadInteraction;
215
    friend class ::chip::app::TestWriteInteraction;
216
217
    System::Clock::Timestamp mNextAckTime; // Next time for triggering Solo Ack
218
    uint32_t mPendingPeerAckMessageCounter;
219
};
220
221
inline bool ReliableMessageContext::AutoRequestAck() const
222
343
{
223
343
    return mFlags.Has(Flags::kFlagAutoRequestAck);
224
343
}
225
226
inline bool ReliableMessageContext::IsAckPending() const
227
2.88k
{
228
2.88k
    return mFlags.Has(Flags::kFlagAckPending);
229
2.88k
}
230
231
inline bool ReliableMessageContext::IsWaitingForAck() const
232
570
{
233
570
    return mFlags.Has(Flags::kFlagWaitingForAck);
234
570
}
235
236
inline bool ReliableMessageContext::HasPiggybackAckPending() const
237
343
{
238
343
    return mFlags.Has(Flags::kFlagAckMessageCounterIsValid);
239
343
}
240
241
inline void ReliableMessageContext::SetAutoRequestAck(bool autoReqAck)
242
1.60k
{
243
1.60k
    mFlags.Set(Flags::kFlagAutoRequestAck, autoReqAck);
244
1.60k
}
245
246
inline void ReliableMessageContext::SetAckPending(bool inAckPending)
247
2.20k
{
248
2.20k
    mFlags.Set(Flags::kFlagAckPending, inAckPending);
249
2.20k
}
250
251
inline bool ReliableMessageContext::IsEphemeralExchange() const
252
285
{
253
285
    return mFlags.Has(Flags::kFlagEphemeralExchange);
254
285
}
255
256
inline bool ReliableMessageContext::WaitingForResponseOrAck() const
257
0
{
258
0
    return mFlags.Has(Flags::kFlagWaitingForResponseOrAck);
259
0
}
260
261
inline void ReliableMessageContext::SetWaitingForResponseOrAck(bool waitingForResponseOrAck)
262
0
{
263
0
    mFlags.Set(Flags::kFlagWaitingForResponseOrAck, waitingForResponseOrAck);
264
0
}
265
266
} // namespace Messaging
267
} // namespace chip