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