Line data Source code
1 : /*
2 : * Copyright (c) 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 configuration parameters that are required
21 : * for the CHIP Reliable Messaging Protocol.
22 : *
23 : */
24 : #include <messaging/ReliableMessageMgr.h>
25 :
26 : #include <app/icd/server/ICDServerConfig.h>
27 : #include <platform/CHIPDeviceConfig.h>
28 : #include <platform/CHIPDeviceLayer.h>
29 : #include <system/SystemClock.h>
30 :
31 : #if CHIP_CONFIG_ENABLE_ICD_SERVER
32 : #include <app/icd/server/ICDConfigurationData.h> // nogncheck
33 : #endif
34 :
35 : #include <optional>
36 :
37 : namespace chip {
38 :
39 : using namespace System::Clock::Literals;
40 :
41 : #if CONFIG_BUILD_FOR_HOST_UNIT_TEST
42 : namespace {
43 : // Use std::optional for globals to avoid static initializers
44 : std::optional<System::Clock::Timeout> gIdleRetransTimeoutOverride;
45 : std::optional<System::Clock::Timeout> gActiveRetransTimeoutOverride;
46 : std::optional<System::Clock::Timeout> gActiveThresholdTimeOverride;
47 : } // namespace
48 :
49 11 : void OverrideLocalMRPConfig(System::Clock::Timeout idleRetransTimeout, System::Clock::Timeout activeRetransTimeout,
50 : System::Clock::Timeout activeThresholdTime)
51 : {
52 11 : gIdleRetransTimeoutOverride = idleRetransTimeout;
53 11 : gActiveRetransTimeoutOverride = activeRetransTimeout;
54 11 : gActiveThresholdTimeOverride = activeThresholdTime;
55 11 : }
56 :
57 12 : void ClearLocalMRPConfigOverride()
58 : {
59 12 : gActiveRetransTimeoutOverride = std::nullopt;
60 12 : gIdleRetransTimeoutOverride = std::nullopt;
61 12 : gActiveThresholdTimeOverride = std::nullopt;
62 12 : }
63 : #endif
64 :
65 : #if CHIP_DEVICE_CONFIG_ENABLE_DYNAMIC_MRP_CONFIG
66 : namespace {
67 :
68 : // This is not a static member of ReliableMessageProtocolConfig because the free
69 : // function GetLocalMRPConfig() needs access to it.
70 : // Use std::optional to avoid a static initializer
71 : std::optional<ReliableMessageProtocolConfig> sDynamicLocalMPRConfig;
72 :
73 : } // anonymous namespace
74 :
75 : bool ReliableMessageProtocolConfig::SetLocalMRPConfig(const Optional<ReliableMessageProtocolConfig> & localMRPConfig)
76 : {
77 : auto oldConfig = GetLocalMRPConfig();
78 : sDynamicLocalMPRConfig = localMRPConfig.std_optional();
79 : return oldConfig != GetLocalMRPConfig();
80 : }
81 : #endif // CHIP_DEVICE_CONFIG_ENABLE_DYNAMIC_MRP_CONFIG
82 :
83 155617 : ReliableMessageProtocolConfig GetDefaultMRPConfig()
84 : {
85 : // Default MRP intervals are defined in spec <4.12.8. Parameters and Constants>
86 : static constexpr const System::Clock::Milliseconds32 idleRetransTimeout = 500_ms32;
87 : static constexpr const System::Clock::Milliseconds32 activeRetransTimeout = 300_ms32;
88 : static constexpr const System::Clock::Milliseconds16 activeThresholdTime = 4000_ms16;
89 : static_assert(activeThresholdTime == kDefaultActiveTime, "Different active defaults?");
90 155617 : return ReliableMessageProtocolConfig(idleRetransTimeout, activeRetransTimeout, activeThresholdTime);
91 : }
92 :
93 10750 : Optional<ReliableMessageProtocolConfig> GetLocalMRPConfig()
94 : {
95 10750 : ReliableMessageProtocolConfig config(CHIP_CONFIG_MRP_LOCAL_IDLE_RETRY_INTERVAL, CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL);
96 :
97 : #if CHIP_DEVICE_CONFIG_ENABLE_DYNAMIC_MRP_CONFIG
98 : if (sDynamicLocalMPRConfig.has_value())
99 : {
100 : config = sDynamicLocalMPRConfig.value();
101 : }
102 : #endif // CHIP_DEVICE_CONFIG_ENABLE_DYNAMIC_MRP_CONFIG
103 :
104 : #if CHIP_CONFIG_ENABLE_ICD_SERVER
105 : // TODO ICD LIT shall not advertise the SII key
106 : // Increase local MRP retry intervals by ICD polling intervals. That is, intervals for
107 : // which the device can be at sleep and not be able to receive any messages).
108 : config.mIdleRetransTimeout += ICDConfigurationData::GetInstance().GetSlowPollingInterval();
109 : config.mActiveRetransTimeout += ICDConfigurationData::GetInstance().GetFastPollingInterval();
110 : config.mActiveThresholdTime = ICDConfigurationData::GetInstance().GetActiveModeThreshold();
111 : #endif
112 :
113 : #if CONFIG_BUILD_FOR_HOST_UNIT_TEST
114 10750 : if (gIdleRetransTimeoutOverride.has_value())
115 : {
116 73 : config.mIdleRetransTimeout = gIdleRetransTimeoutOverride.value();
117 : }
118 :
119 10750 : if (gActiveRetransTimeoutOverride.has_value())
120 : {
121 73 : config.mActiveRetransTimeout = gActiveRetransTimeoutOverride.value();
122 : }
123 :
124 10750 : if (gActiveThresholdTimeOverride.has_value())
125 : {
126 73 : config.mActiveThresholdTime = gActiveThresholdTimeOverride.value();
127 : }
128 : #endif
129 :
130 21500 : return (config == GetDefaultMRPConfig()) ? Optional<ReliableMessageProtocolConfig>::Missing()
131 10750 : : Optional<ReliableMessageProtocolConfig>::Value(config);
132 : }
133 :
134 18307 : System::Clock::Timeout GetRetransmissionTimeout(System::Clock::Timeout activeInterval, System::Clock::Timeout idleInterval,
135 : System::Clock::Timeout lastActivityTime, System::Clock::Timeout activityThreshold,
136 : bool isFirstMessageOnExchange)
137 : {
138 18307 : auto timeSinceLastActivity = (System::SystemClock().GetMonotonicTimestamp() - lastActivityTime);
139 :
140 : // Calculate the retransmission timeout and take into account that an active/idle state change can happen
141 : // in the middle.
142 18307 : System::Clock::Timestamp timeout(0);
143 109842 : for (uint8_t i = 0; i < CHIP_CONFIG_RMP_DEFAULT_MAX_RETRANS + 1; i++)
144 : {
145 91535 : auto baseInterval = activeInterval;
146 : // If we are calculating the timeout for the initial message, we never know whether the peer is active or not, choose
147 : // active/idle interval from PeerActiveMode of session per 4.11.2.1. Retransmissions.
148 : // If we are calculating the timeout for response message, we know the peer is active, always choose active interval.
149 91535 : if (isFirstMessageOnExchange)
150 : {
151 12260 : baseInterval = ((timeSinceLastActivity + timeout) < activityThreshold) ? activeInterval : idleInterval;
152 : }
153 91535 : timeout += Messaging::ReliableMessageMgr::GetBackoff(baseInterval, i, /* computeMaxPossible */ true);
154 : }
155 :
156 18307 : return timeout;
157 : }
158 :
159 : } // namespace chip
|