• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 // Configuration macros for the transfer module.
16 #pragma once
17 
18 #include <chrono>
19 #include <cinttypes>
20 #include <limits>
21 
22 #include "pw_chrono/system_clock.h"
23 #include "pw_preprocessor/compiler.h"
24 
25 // The log level to use for this module. Logs below this level are omitted.
26 #ifndef PW_TRANSFER_CONFIG_LOG_LEVEL
27 #define PW_TRANSFER_CONFIG_LOG_LEVEL PW_LOG_LEVEL_INFO
28 #endif  // PW_TRANSFER_CONFIG_LOG_LEVEL
29 
30 // Turns on logging of individual chunks. Data and parameter chunk logging has
31 // additional configuration
32 #ifndef PW_TRANSFER_CONFIG_DEBUG_CHUNKS
33 #define PW_TRANSFER_CONFIG_DEBUG_CHUNKS 0
34 #endif  // PW_TRANSFER_CONFIG_DEBUG_CHUNKS
35 
36 // Turns on logging of data and parameter chunks.
37 #ifndef PW_TRANSFER_CONFIG_DEBUG_DATA_CHUNKS
38 #define PW_TRANSFER_CONFIG_DEBUG_DATA_CHUNKS 0
39 #endif  // PW_TRANSFER_CONFIG_DEBUG_DATA_CHUNKS
40 
41 #ifdef PW_TRANSFER_DEFAULT_MAX_RETRIES
42 #pragma message(                                      \
43     "PW_TRANSFER_DEFAULT_MAX_RETRIES is deprecated; " \
44     "Use PW_TRANSFER_DEFAULT_MAX_CLIENT_RETRIES and " \
45     "PW_TRANSFER_DEFAULT_MAX_SERVER_RETRIES instead.")
46 #endif  // PW_TRANSFER_DEFAULT_MAX_RETRIES
47 
48 #ifdef PW_TRANSFER_DEFAULT_TIMEOUT_MS
49 #pragma message(                                     \
50     "PW_TRANSFER_DEFAULT_TIMEOUT_MS is deprecated; " \
51     "Use PW_TRANSFER_DEFAULT_CLIENT_TIMEOUT_MS and " \
52     "PW_TRANSFER_DEFAULT_SERVER_TIMEOUT_MS instead.")
53 #endif  // PW_TRANSFER_DEFAULT_TIMEOUT_MS
54 
55 // The default maximum number of times a transfer client should retry sending a
56 // chunk when no response is received. Can later be configured per-transfer when
57 // starting one.
58 #ifndef PW_TRANSFER_DEFAULT_MAX_CLIENT_RETRIES
59 
60 // Continue to accept the old deprecated setting until projects have migrated.
61 #ifdef PW_TRANSFER_DEFAULT_MAX_RETRIES
62 #define PW_TRANSFER_DEFAULT_MAX_CLIENT_RETRIES PW_TRANSFER_DEFAULT_MAX_RETRIES
63 #else
64 #define PW_TRANSFER_DEFAULT_MAX_CLIENT_RETRIES 3
65 #endif  // PW_TRANSFER_DEFAULT_MAX_RETRIES
66 
67 #endif  // PW_TRANSFER_DEFAULT_MAX_CLIENT_RETRIES
68 
69 static_assert(PW_TRANSFER_DEFAULT_MAX_CLIENT_RETRIES >= 0 &&
70               PW_TRANSFER_DEFAULT_MAX_CLIENT_RETRIES <=
71                   static_cast<uint32_t>(std::numeric_limits<uint8_t>::max()));
72 
73 // The default maximum number of times a transfer server should retry sending a
74 // chunk when no response is received.
75 //
76 // In typical setups, retries are driven by the client, and timeouts on the
77 // server are used only to clean up resources, so this defaults to 0.
78 #ifndef PW_TRANSFER_DEFAULT_MAX_SERVER_RETRIES
79 
80 // Continue to accept the old deprecated setting until projects have migrated.
81 #ifdef PW_TRANSFER_DEFAULT_MAX_RETRIES
82 #define PW_TRANSFER_DEFAULT_MAX_SERVER_RETRIES PW_TRANSFER_DEFAULT_MAX_RETRIES
83 #else
84 #define PW_TRANSFER_DEFAULT_MAX_SERVER_RETRIES 0
85 #endif  // PW_TRANSFER_DEFAULT_MAX_RETRIES
86 
87 #endif  // PW_TRANSFER_DEFAULT_MAX_SERVER_RETRIES
88 
89 // GCC emits spurious -Wtype-limits warnings for the static_assert.
90 PW_MODIFY_DIAGNOSTICS_PUSH();
91 PW_MODIFY_DIAGNOSTIC_GCC(ignored, "-Wtype-limits");
92 static_assert(PW_TRANSFER_DEFAULT_MAX_SERVER_RETRIES >= 0 &&
93               PW_TRANSFER_DEFAULT_MAX_SERVER_RETRIES <=
94                   std::numeric_limits<uint8_t>::max());
95 PW_MODIFY_DIAGNOSTICS_POP();
96 
97 // The default maximum number of times a transfer should retry sending a chunk
98 // over the course of its entire lifetime.
99 // This number should be high, particularly if long-running transfers are
100 // expected. Its purpose is to prevent transfers from getting stuck in an
101 // infinite loop.
102 #ifndef PW_TRANSFER_DEFAULT_MAX_LIFETIME_RETRIES
103 #define PW_TRANSFER_DEFAULT_MAX_LIFETIME_RETRIES \
104   (static_cast<uint32_t>(PW_TRANSFER_DEFAULT_MAX_CLIENT_RETRIES) * 1000u)
105 #endif  // PW_TRANSFER_DEFAULT_MAX_LIFETIME_RETRIES
106 
107 static_assert(PW_TRANSFER_DEFAULT_MAX_LIFETIME_RETRIES >
108                   PW_TRANSFER_DEFAULT_MAX_CLIENT_RETRIES &&
109               PW_TRANSFER_DEFAULT_MAX_LIFETIME_RETRIES <=
110                   std::numeric_limits<uint32_t>::max());
111 
112 // The default amount of time, in milliseconds, to wait for a chunk to arrive
113 // in a transfer client before retrying. This can later be configured
114 // per-transfer.
115 #ifndef PW_TRANSFER_DEFAULT_CLIENT_TIMEOUT_MS
116 
117 // Continue to accept the old deprecated setting until projects have migrated.
118 #ifdef PW_TRANSFER_DEFAULT_TIMEOUT_MS
119 #define PW_TRANSFER_DEFAULT_CLIENT_TIMEOUT_MS PW_TRANSFER_DEFAULT_TIMEOUT_MS
120 #else
121 #define PW_TRANSFER_DEFAULT_CLIENT_TIMEOUT_MS 2000
122 #endif  // PW_TRANSFER_DEFAULT_TIMEOUT_MS
123 
124 #endif  // PW_TRANSFER_DEFAULT_CLIENT_TIMEOUT_MS
125 
126 static_assert(PW_TRANSFER_DEFAULT_CLIENT_TIMEOUT_MS > 0);
127 
128 // The default amount of time, in milliseconds, to wait for a chunk to arrive
129 // on the server before retrying. This can later be configured per-transfer.
130 #ifndef PW_TRANSFER_DEFAULT_SERVER_TIMEOUT_MS
131 
132 // Continue to accept the old deprecated setting until projects have migrated.
133 #ifdef PW_TRANSFER_DEFAULT_TIMEOUT_MS
134 #define PW_TRANSFER_DEFAULT_SERVER_TIMEOUT_MS PW_TRANSFER_DEFAULT_TIMEOUT_MS
135 #else
136 #define PW_TRANSFER_DEFAULT_SERVER_TIMEOUT_MS \
137   (static_cast<uint32_t>(PW_TRANSFER_DEFAULT_CLIENT_TIMEOUT_MS) * 5u)
138 #endif  // PW_TRANSFER_DEFAULT_TIMEOUT_MS
139 
140 #endif  // PW_TRANSFER_DEFAULT_SERVER_TIMEOUT_MS
141 
142 static_assert(PW_TRANSFER_DEFAULT_SERVER_TIMEOUT_MS > 0);
143 
144 // The default amount of time, in milliseconds, for a client to wait for an
145 // initial response from the transfer server before retrying. This can later be
146 // configured // per-transfer.
147 //
148 // This is set separately to PW_TRANSFER_DEFAULT_CLIENT_TIMEOUT_MS as transfers
149 // may require additional time for resource initialization (e.g. erasing a flash
150 // region before writing to it).
151 #ifndef PW_TRANSFER_DEFAULT_INITIAL_TIMEOUT_MS
152 #define PW_TRANSFER_DEFAULT_INITIAL_TIMEOUT_MS \
153   PW_TRANSFER_DEFAULT_CLIENT_TIMEOUT_MS
154 #endif  // PW_TRANSFER_DEFAULT_INITIAL_TIMEOUT_MS
155 
156 static_assert(PW_TRANSFER_DEFAULT_INITIAL_TIMEOUT_MS > 0);
157 
158 // The fractional position within a window at which a receive transfer should
159 // extend its window size to minimize the amount of time the transmitter
160 // spends blocked.
161 //
162 // For example, a divisor of 2 will extend the window when half of the
163 // requested data has been received, a divisor of three will extend at a third
164 // of the window, and so on.
165 #ifndef PW_TRANSFER_DEFAULT_EXTEND_WINDOW_DIVISOR
166 #define PW_TRANSFER_DEFAULT_EXTEND_WINDOW_DIVISOR 2
167 #endif  // PW_TRANSFER_DEFAULT_EXTEND_WINDOW_DIVISOR
168 
169 static_assert(PW_TRANSFER_DEFAULT_EXTEND_WINDOW_DIVISOR > 1);
170 
171 // Number of chunks to send repetitative logs at full rate before reducing to
172 // rate_limit. Retransmit parameter chunks will restart at this chunk count
173 // limit.
174 // Default is first 10 parameter logs will be sent, then reduced to one log
175 // every `RATE_PERIOD_MS`
176 #ifndef PW_TRANSFER_LOG_DEFAULT_CHUNKS_BEFORE_RATE_LIMIT
177 #define PW_TRANSFER_LOG_DEFAULT_CHUNKS_BEFORE_RATE_LIMIT 10
178 #endif  // PW_TRANSFER_LOG_DEFAULT_CHUNKS_BEFORE_RATE_LIMIT
179 
180 static_assert(PW_TRANSFER_LOG_DEFAULT_CHUNKS_BEFORE_RATE_LIMIT > 0);
181 
182 // The minimum time between repetative logs after the rate limit has been
183 // applied (after CHUNKS_BEFORE_RATE_LIMIT parameter chunks).
184 // Default is to reduce repetative logs to once every 10 seconds after
185 // `CHUNKS_BEFORE_RATE_LIMIT` parameter chunks have been sent.
186 #ifndef PW_TRANSFER_LOG_DEFAULT_RATE_PERIOD_MS
187 #define PW_TRANSFER_LOG_DEFAULT_RATE_PERIOD_MS 10000
188 #endif  // PW_TRANSFER_DEFAULT_MIN_RATE_PERIOD_MS
189 
190 static_assert(PW_TRANSFER_LOG_DEFAULT_RATE_PERIOD_MS >= 0);
191 
192 // Maximum time to wait for a transfer event to be processed before dropping
193 // further queued events. In systems which can perform long-running operations
194 // to process transfer data, this can be used to prevent threads from blocking
195 // for extended periods. A value of 0 results in indefinite blocking.
196 #ifndef PW_TRANSFER_EVENT_PROCESSING_TIMEOUT_MS
197 #define PW_TRANSFER_EVENT_PROCESSING_TIMEOUT_MS \
198   PW_TRANSFER_DEFAULT_CLIENT_TIMEOUT_MS
199 #endif  // PW_TRANSFER_EVENT_PROCESSING_TIMEOUT_MS
200 
201 static_assert(PW_TRANSFER_EVENT_PROCESSING_TIMEOUT_MS >= 0);
202 
203 namespace pw::transfer::cfg {
204 
205 inline constexpr uint8_t kDefaultMaxClientRetries =
206     PW_TRANSFER_DEFAULT_MAX_CLIENT_RETRIES;
207 inline constexpr uint8_t kDefaultMaxServerRetries =
208     PW_TRANSFER_DEFAULT_MAX_SERVER_RETRIES;
209 inline constexpr uint16_t kDefaultMaxLifetimeRetries =
210     PW_TRANSFER_DEFAULT_MAX_LIFETIME_RETRIES;
211 
212 inline constexpr chrono::SystemClock::duration kDefaultClientTimeout =
213     chrono::SystemClock::for_at_least(
214         std::chrono::milliseconds(PW_TRANSFER_DEFAULT_CLIENT_TIMEOUT_MS));
215 inline constexpr chrono::SystemClock::duration kDefaultServerTimeout =
216     chrono::SystemClock::for_at_least(
217         std::chrono::milliseconds(PW_TRANSFER_DEFAULT_SERVER_TIMEOUT_MS));
218 
219 inline constexpr chrono::SystemClock::duration kDefaultInitialChunkTimeout =
220     chrono::SystemClock::for_at_least(
221         std::chrono::milliseconds(PW_TRANSFER_DEFAULT_INITIAL_TIMEOUT_MS));
222 
223 inline constexpr uint32_t kDefaultExtendWindowDivisor =
224     PW_TRANSFER_DEFAULT_EXTEND_WINDOW_DIVISOR;
225 
226 inline constexpr uint16_t kLogDefaultChunksBeforeRateLimit =
227     PW_TRANSFER_LOG_DEFAULT_CHUNKS_BEFORE_RATE_LIMIT;
228 inline constexpr chrono::SystemClock::duration kLogDefaultRateLimit =
229     chrono::SystemClock::for_at_least(
230         std::chrono::milliseconds(PW_TRANSFER_LOG_DEFAULT_RATE_PERIOD_MS));
231 
232 inline constexpr bool kWaitForEventProcessingIndefinitely =
233     PW_TRANSFER_EVENT_PROCESSING_TIMEOUT_MS == 0;
234 inline constexpr chrono::SystemClock::duration kEventProcessingTimeout =
235     chrono::SystemClock::for_at_least(
236         std::chrono::milliseconds(PW_TRANSFER_EVENT_PROCESSING_TIMEOUT_MS));
237 
238 }  // namespace pw::transfer::cfg
239