1#[cfg(test)]
4#[path = "../../tests/settings/assertions.rs"]
5mod tests;
6
7use std::env::var;
8
9use log::warn;
10
11use super::builder::SettingsBuilder;
12use super::error::SettingsError;
13use super::override_map::{Key, OverrideMap, SettingType};
14use super::statics::keys;
15use crate::bytes::BytePool;
16use crate::utils::sync::AsyncExecutor;
17
18fn try_env_override<T: SettingType>(key: &Key<T>) -> Option<T> {
21 let env_str = var(key.name).ok()?;
22 T::try_parse(&env_str).or_else(|| {
23 warn!("Environment variable '{}' set to '{}' cannot be parsed, using default", key.name, env_str);
24 None
25 })
26}
27
28pub struct Settings<AE: AsyncExecutor> {
35 overrides: OverrideMap,
36 executor: AE,
37 pool: BytePool,
38 mtu: usize,
39}
40
41impl<AE: AsyncExecutor> Settings<AE> {
42 pub(super) fn new(overrides: OverrideMap, executor: AE, pool: BytePool, mtu: usize) -> Self {
44 Self {
45 overrides,
46 executor,
47 pool,
48 mtu,
49 }
50 }
51
52 #[inline]
56 pub fn get<T: SettingType + Copy>(&self, key: &Key<T>) -> T {
57 if let Some(value) = self.overrides.get(key.name) {
58 return T::from_value(*value);
59 }
60
61 if let Some(value) = try_env_override(key) {
62 return value;
63 }
64
65 key.default
66 }
67
68 #[inline]
70 pub fn set<T: SettingType>(&mut self, key: &Key<T>, value: T) {
71 self.overrides.insert(key.name, value.to_value());
72 }
73
74 #[inline]
76 pub fn pool(&self) -> &BytePool {
77 &self.pool
78 }
79
80 #[inline]
82 pub fn mtu(&self) -> usize {
83 self.mtu
84 }
85
86 #[inline]
88 pub fn executor(&self) -> &AE {
89 &self.executor
90 }
91
92 pub(super) fn assert(&self) -> Result<(), SettingsError> {
94 let assert_min_max_u64 = |min_key: &Key<u64>, max_key: &Key<u64>| -> Result<(), SettingsError> {
96 let min_val = self.get(min_key);
97 let max_val = self.get(max_key);
98 if min_val > max_val {
99 return Err(SettingsError::AssertionFailed {
100 message: format!("{} ({}) must be <= {} ({})", min_key.name, min_val, max_key.name, max_val),
101 });
102 }
103 Ok(())
104 };
105
106 let assert_min_max_f64 = |min_key: &Key<f64>, max_key: &Key<f64>| -> Result<(), SettingsError> {
108 let min_val = self.get(min_key);
109 let max_val = self.get(max_key);
110 if min_val > max_val {
111 return Err(SettingsError::AssertionFailed {
112 message: format!("{} ({}) must be <= {} ({})", min_key.name, min_val, max_key.name, max_val),
113 });
114 }
115 Ok(())
116 };
117
118 let assert_default_in_range = |min_key: &Key<u64>, default_key: &Key<u64>, max_key: &Key<u64>| -> Result<(), SettingsError> {
120 let min_val = self.get(min_key);
121 let default_val = self.get(default_key);
122 let max_val = self.get(max_key);
123 if default_val < min_val || default_val > max_val {
124 return Err(SettingsError::AssertionFailed {
125 message: format!("{} ({}) must be within [{} ({}), {} ({})]", default_key.name, default_val, min_key.name, min_val, max_key.name, max_val),
126 });
127 }
128 Ok(())
129 };
130
131 let assert_unit_exclusive = |key: &Key<f64>| -> Result<(), SettingsError> {
133 let val = self.get(key);
134 if val <= 0.0 || val >= 1.0 {
135 return Err(SettingsError::AssertionFailed {
136 message: format!("{} ({}) must be in (0, 1)", key.name, val),
137 });
138 }
139 Ok(())
140 };
141
142 let assert_unit_inclusive = |key: &Key<f64>| -> Result<(), SettingsError> {
144 let val = self.get(key);
145 if !(0.0..=1.0).contains(&val) {
146 return Err(SettingsError::AssertionFailed {
147 message: format!("{} ({}) must be in [0, 1]", key.name, val),
148 });
149 }
150 Ok(())
151 };
152
153 let assert_float_positive = |key: &Key<f64>| -> Result<(), SettingsError> {
155 let val = self.get(key);
156 if val <= 0.0 {
157 return Err(SettingsError::AssertionFailed {
158 message: format!("{} ({}) must be positive", key.name, val),
159 });
160 }
161 Ok(())
162 };
163
164 let assert_int_positive = |key: &Key<u64>| -> Result<(), SettingsError> {
166 let val = self.get(key);
167 if val == 0 {
168 return Err(SettingsError::AssertionFailed {
169 message: format!("{} ({}) must be greater than zero", key.name, val),
170 });
171 }
172 Ok(())
173 };
174
175 assert_min_max_u64(&keys::FAKE_BODY_LENGTH_MIN, &keys::FAKE_BODY_LENGTH_MAX)?;
177 assert_min_max_u64(&keys::FAKE_BODY_CONSTANT_LENGTH_MIN, &keys::FAKE_BODY_CONSTANT_LENGTH_MAX)?;
178 assert_min_max_f64(&keys::DECOY_FALLTHROUGH_PACKETS_MIN, &keys::DECOY_FALLTHROUGH_PACKETS_MAX)?;
179 assert_min_max_u64(&keys::FAKE_HEADER_LENGTH_MIN, &keys::FAKE_HEADER_LENGTH_MAX)?;
180 assert_min_max_u64(&keys::HEALTH_CHECK_NEXT_IN_MIN, &keys::HEALTH_CHECK_NEXT_IN_MAX)?;
181 assert_min_max_u64(&keys::TIMEOUT_MIN, &keys::TIMEOUT_MAX)?;
182 assert_min_max_u64(&keys::RTT_MIN, &keys::RTT_MAX)?;
183 assert_min_max_u64(&keys::DECOY_LENGTH_MIN, &keys::DECOY_LENGTH_MAX)?;
184 assert_min_max_u64(&keys::DECOY_NOISY_DECOY_LENGTH_MIN, &keys::DECOY_NOISY_LENGTH_MAX)?;
185 assert_min_max_u64(&keys::DECOY_HEAVY_LENGTH_MIN, &keys::DECOY_LENGTH_MAX)?;
186 assert_min_max_u64(&keys::DECOY_HEAVY_DELAY_MIN, &keys::DECOY_HEAVY_DELAY_MAX)?;
187 assert_min_max_u64(&keys::DECOY_NOISY_DELAY_MIN, &keys::DECOY_NOISY_DELAY_MAX)?;
188 assert_min_max_u64(&keys::DECOY_SPARSE_DELAY_MIN, &keys::DECOY_SPARSE_DELAY_MAX)?;
189 assert_min_max_u64(&keys::DECOY_SPARSE_LENGTH_MIN, &keys::DECOY_SPARSE_LENGTH_MAX)?;
190 assert_min_max_u64(&keys::DECOY_SMOOTH_DELAY_MIN, &keys::DECOY_SMOOTH_DELAY_MAX)?;
191 assert_min_max_u64(&keys::DECOY_SMOOTH_LENGTH_MIN, &keys::DECOY_SMOOTH_LENGTH_MAX)?;
192 assert_min_max_u64(&keys::DECOY_MAINTENANCE_LENGTH_MIN, &keys::DECOY_MAINTENANCE_LENGTH_MAX)?;
193 assert_min_max_u64(&keys::DECOY_MAINTENANCE_DELAY_MIN, &keys::DECOY_MAINTENANCE_DELAY_MAX)?;
194 assert_min_max_u64(&keys::DECOY_REPLICATION_DELAY_MIN, &keys::DECOY_REPLICATION_DELAY_MAX)?;
195 assert_min_max_u64(&keys::DECOY_SUBHEADER_LENGTH_MIN, &keys::DECOY_SUBHEADER_LENGTH_MAX)?;
196 assert_min_max_f64(&keys::DECOY_REPLICATION_PROBABILITY_MIN, &keys::DECOY_REPLICATION_PROBABILITY_MAX)?;
197 assert_min_max_f64(&keys::FAKE_HEADER_VOLATILE_CHANGE_PROB_MIN, &keys::FAKE_HEADER_VOLATILE_CHANGE_PROB_MAX)?;
198 assert_min_max_u64(&keys::FAKE_HEADER_SWITCHING_TIMEOUT_MIN_MS, &keys::FAKE_HEADER_SWITCHING_TIMEOUT_MAX_MS)?;
199
200 assert_default_in_range(&keys::RTT_MIN, &keys::RTT_DEFAULT, &keys::RTT_MAX)?;
202 assert_default_in_range(&keys::TIMEOUT_MIN, &keys::TIMEOUT_DEFAULT, &keys::TIMEOUT_MAX)?;
203 assert_default_in_range(&keys::DECOY_HEAVY_DELAY_MIN, &keys::DECOY_HEAVY_DELAY_DEFAULT, &keys::DECOY_HEAVY_DELAY_MAX)?;
204 assert_default_in_range(&keys::DECOY_NOISY_DELAY_MIN, &keys::DECOY_NOISY_DELAY_DEFAULT, &keys::DECOY_NOISY_DELAY_MAX)?;
205 assert_default_in_range(&keys::DECOY_SPARSE_DELAY_MIN, &keys::DECOY_SPARSE_DELAY_DEFAULT, &keys::DECOY_SPARSE_DELAY_MAX)?;
206 assert_default_in_range(&keys::DECOY_SMOOTH_DELAY_MIN, &keys::DECOY_SMOOTH_DELAY_DEFAULT, &keys::DECOY_SMOOTH_DELAY_MAX)?;
207
208 let next_in_min = self.get(&keys::HEALTH_CHECK_NEXT_IN_MIN);
210 let timeout_max = self.get(&keys::TIMEOUT_MAX);
211 if next_in_min <= timeout_max {
212 return Err(SettingsError::AssertionFailed {
213 message: format!("{} ({}) must be > {} ({})", keys::HEALTH_CHECK_NEXT_IN_MIN.name, next_in_min, keys::TIMEOUT_MAX.name, timeout_max),
214 });
215 }
216
217 assert_unit_exclusive(&keys::RTT_ALPHA)?;
219 assert_unit_exclusive(&keys::RTT_BETA)?;
220 assert_unit_exclusive(&keys::DECOY_CURRENT_ALPHA)?;
221 assert_unit_exclusive(&keys::DECOY_REFERENCE_ALPHA)?;
222
223 assert_unit_inclusive(&keys::FAKE_HEADER_PROBABILITY)?;
225 assert_unit_inclusive(&keys::SEND_BYTES_JITTER)?;
226 assert_unit_inclusive(&keys::DECOY_FALLTHROUGH_PACKETS_MIN)?;
227 assert_unit_inclusive(&keys::DECOY_FALLTHROUGH_PACKETS_MAX)?;
228 assert_unit_inclusive(&keys::FAKE_HEADER_VOLATILE_CHANGE_PROB_MIN)?;
229 assert_unit_inclusive(&keys::FAKE_HEADER_VOLATILE_CHANGE_PROB_MAX)?;
230
231 let chunk = self.get(&keys::SEND_BYTES_CHUNK);
234 if chunk != 0 && (chunk as usize) > self.mtu() {
235 return Err(SettingsError::AssertionFailed {
236 message: format!("{} ({}) must be ≤ MTU ({}) or 0 (sentinel)", keys::SEND_BYTES_CHUNK.name, chunk, self.mtu()),
237 });
238 }
239
240 assert_float_positive(&keys::TIMEOUT_RTT_FACTOR)?;
242 assert_float_positive(&keys::HANDSHAKE_NEXT_IN_FACTOR)?;
243 assert_float_positive(&keys::DECOY_BYTE_RATE_CAP)?;
244 assert_float_positive(&keys::DECOY_BYTE_RATE_FACTOR)?;
245
246 assert_int_positive(&keys::FAKE_BODY_WEIGHT_EMPTY)?;
248 assert_int_positive(&keys::FAKE_BODY_WEIGHT_RANDOM)?;
249 assert_int_positive(&keys::FAKE_BODY_WEIGHT_CONSTANT)?;
250 assert_int_positive(&keys::FAKE_BODY_WEIGHT_SERVICE)?;
251 assert_int_positive(&keys::FAKE_HEADER_FIELD_WEIGHT_RANDOM)?;
252 assert_int_positive(&keys::FAKE_HEADER_FIELD_WEIGHT_CONSTANT)?;
253 assert_int_positive(&keys::FAKE_HEADER_FIELD_WEIGHT_VOLATILE)?;
254 assert_int_positive(&keys::FAKE_HEADER_FIELD_WEIGHT_SWITCHING)?;
255 assert_int_positive(&keys::FAKE_HEADER_FIELD_WEIGHT_INCREMENTAL)?;
256 assert_int_positive(&keys::DECOY_MAINTENANCE_WEIGHT_NONE)?;
257 assert_int_positive(&keys::DECOY_MAINTENANCE_WEIGHT_RANDOM)?;
258 assert_int_positive(&keys::DECOY_MAINTENANCE_WEIGHT_TIMED)?;
259 assert_int_positive(&keys::DECOY_MAINTENANCE_WEIGHT_SIZED)?;
260 assert_int_positive(&keys::DECOY_MAINTENANCE_WEIGHT_BOTH)?;
261 assert_int_positive(&keys::DECOY_REPLICATION_WEIGHT_NONE)?;
262 assert_int_positive(&keys::DECOY_REPLICATION_WEIGHT_MAINTENANCE)?;
263 assert_int_positive(&keys::DECOY_REPLICATION_WEIGHT_ALL)?;
264 assert_int_positive(&keys::DECOY_SUBHEADER_WEIGHT_NONE)?;
265 assert_int_positive(&keys::DECOY_SUBHEADER_WEIGHT_MAINTENANCE)?;
266 assert_int_positive(&keys::DECOY_SUBHEADER_WEIGHT_ALL)?;
267 assert_int_positive(&keys::DECOY_PROVIDER_WEIGHT_SIMPLE)?;
268 assert_int_positive(&keys::DECOY_PROVIDER_WEIGHT_SPARSE)?;
269 assert_int_positive(&keys::DECOY_PROVIDER_WEIGHT_NOISY)?;
270 assert_int_positive(&keys::DECOY_PROVIDER_WEIGHT_SMOOTH)?;
271 assert_int_positive(&keys::DECOY_PROVIDER_WEIGHT_HEAVY)?;
272 assert_int_positive(&keys::FAKE_HEADER_SWITCHING_TIMEOUT_MIN_MS)?;
273
274 Ok(())
275 }
276}
277
278impl<AE: AsyncExecutor> Default for Settings<AE> {
279 #[inline]
280 fn default() -> Self {
281 SettingsBuilder::new().build().expect("default settings must be valid")
282 }
283}