1#[cfg(feature = "alloc")]
4use crate::application::ServerName;
5use crate::{
6 ack,
7 event::{api::SocketAddress, IntoEvent},
8 inet, recovery, stream,
9 transport::parameters::{
10 AckDelayExponent, ActiveConnectionIdLimit, InitialFlowControlLimits, InitialMaxData,
11 InitialMaxStreamDataBidiLocal, InitialMaxStreamDataBidiRemote, InitialMaxStreamDataUni,
12 InitialMaxStreamsBidi, InitialMaxStreamsUni, InitialStreamLimits, MaxAckDelay,
13 MaxDatagramFrameSize, MaxIdleTimeout, MigrationSupport, TransportParameters,
14 },
15};
16#[cfg(feature = "alloc")]
17use bytes::Bytes;
18use core::time::Duration;
19use s2n_codec::decoder_invariant;
20
21pub use crate::transport::parameters::ValidationError;
22
23const MAX_HANDSHAKE_DURATION_DEFAULT: Duration = Duration::from_secs(10);
24
25const MAX_KEEP_ALIVE_PERIOD_DEFAULT: Duration = Duration::from_secs(30);
34
35pub const ANTI_AMPLIFICATION_MULTIPLIER: u8 = 3;
40
41pub const DEFAULT_STREAM_BATCH_SIZE: u8 = 1;
42
43pub const MAX_PTO_JITTER_PERCENTAGE: u8 = 50;
47pub const DEFAULT_PTO_JITTER_PERCENTAGE: u8 = 0;
48
49#[non_exhaustive]
50#[derive(Debug)]
51pub struct ConnectionInfo<'a> {
52 pub remote_address: SocketAddress<'a>,
53}
54
55impl<'a> ConnectionInfo<'a> {
56 #[inline]
57 #[doc(hidden)]
58 pub fn new(remote_address: &'a inet::SocketAddress) -> Self {
59 Self {
60 remote_address: remote_address.into_event(),
61 }
62 }
63}
64
65#[non_exhaustive]
66#[derive(Debug)]
67#[cfg(feature = "alloc")]
68pub struct HandshakeInfo<'a> {
69 pub remote_address: SocketAddress<'a>,
70 pub server_name: Option<&'a ServerName>,
71 pub application_protocol: &'a Bytes,
72}
73
74#[cfg(feature = "alloc")]
75impl<'a> HandshakeInfo<'a> {
76 pub fn new(
77 remote_address: &'a inet::SocketAddress,
78 server_name: Option<&'a ServerName>,
79 application_protocol: &'a Bytes,
80 ) -> HandshakeInfo<'a> {
81 Self {
82 remote_address: remote_address.into_event(),
83 server_name,
84 application_protocol,
85 }
86 }
87}
88
89#[derive(Clone, Copy, Debug)]
90pub struct Limits {
91 pub(crate) max_idle_timeout: MaxIdleTimeout,
92 pub(crate) data_window: InitialMaxData,
93 pub(crate) bidirectional_local_data_window: InitialMaxStreamDataBidiLocal,
94 pub(crate) bidirectional_remote_data_window: InitialMaxStreamDataBidiRemote,
95 pub(crate) unidirectional_data_window: InitialMaxStreamDataUni,
96 pub(crate) max_open_local_bidirectional_streams: stream::limits::LocalBidirectional,
97 pub(crate) max_open_local_unidirectional_streams: stream::limits::LocalUnidirectional,
98 pub(crate) max_open_remote_bidirectional_streams: InitialMaxStreamsBidi,
99 pub(crate) max_open_remote_unidirectional_streams: InitialMaxStreamsUni,
100 pub(crate) max_ack_delay: MaxAckDelay,
101 pub(crate) ack_delay_exponent: AckDelayExponent,
102 pub(crate) max_active_connection_ids: ActiveConnectionIdLimit,
103 pub(crate) ack_elicitation_interval: u8,
104 pub(crate) ack_ranges_limit: u8,
105 pub(crate) max_send_buffer_size: stream::limits::MaxSendBufferSize,
106 pub(crate) max_handshake_duration: Duration,
107 pub(crate) max_keep_alive_period: Duration,
108 pub(crate) max_datagram_frame_size: MaxDatagramFrameSize,
109 pub(crate) initial_round_trip_time: Duration,
110 pub(crate) migration_support: MigrationSupport,
111 pub(crate) anti_amplification_multiplier: u8,
112 pub(crate) stream_batch_size: u8,
113 pub(crate) pto_jitter_percentage: u8,
114}
115
116impl Default for Limits {
117 fn default() -> Self {
118 Self::new()
119 }
120}
121
122macro_rules! setter {
123 ($(#[doc = $doc:literal])* $name:ident, $field:ident, $inner:ty $(, |$validate_value:ident| $validation:block)?) => {
124 $(#[doc = $doc])*
125 pub fn $name(mut self, value: $inner) -> Result<Self, ValidationError> {
126 $(
127 let $validate_value = value;
128 $validation
129 )?
130 self.$field = value.try_into()?;
131 Ok(self)
132 }
133 };
134}
135
136impl Limits {
137 pub const fn new() -> Self {
138 Self {
139 max_idle_timeout: MaxIdleTimeout::RECOMMENDED,
140 data_window: InitialMaxData::RECOMMENDED,
141 bidirectional_local_data_window: InitialMaxStreamDataBidiLocal::RECOMMENDED,
142 bidirectional_remote_data_window: InitialMaxStreamDataBidiRemote::RECOMMENDED,
143 unidirectional_data_window: InitialMaxStreamDataUni::RECOMMENDED,
144 max_open_local_bidirectional_streams: stream::limits::LocalBidirectional::RECOMMENDED,
145 max_open_local_unidirectional_streams: stream::limits::LocalUnidirectional::RECOMMENDED,
146 max_open_remote_bidirectional_streams: InitialMaxStreamsBidi::RECOMMENDED,
147 max_open_remote_unidirectional_streams: InitialMaxStreamsUni::RECOMMENDED,
148 max_ack_delay: MaxAckDelay::RECOMMENDED,
149 ack_delay_exponent: AckDelayExponent::RECOMMENDED,
150 max_active_connection_ids: ActiveConnectionIdLimit::RECOMMENDED,
151 ack_elicitation_interval: ack::Settings::RECOMMENDED.ack_elicitation_interval,
152 ack_ranges_limit: ack::Settings::RECOMMENDED.ack_ranges_limit,
153 max_send_buffer_size: stream::Limits::RECOMMENDED.max_send_buffer_size,
154 max_handshake_duration: MAX_HANDSHAKE_DURATION_DEFAULT,
155 max_keep_alive_period: MAX_KEEP_ALIVE_PERIOD_DEFAULT,
156 max_datagram_frame_size: MaxDatagramFrameSize::DEFAULT,
157 initial_round_trip_time: recovery::DEFAULT_INITIAL_RTT,
158 migration_support: MigrationSupport::RECOMMENDED,
159 anti_amplification_multiplier: ANTI_AMPLIFICATION_MULTIPLIER,
160 stream_batch_size: DEFAULT_STREAM_BATCH_SIZE,
161 pto_jitter_percentage: DEFAULT_PTO_JITTER_PERCENTAGE,
162 }
163 }
164
165 setter!(with_data_window, data_window, u64, |validate_value| {
172 decoder_invariant!(
173 validate_value <= u32::MAX.into(),
174 "data_window must be <= u32::MAX"
175 );
176 });
177 setter!(
178 with_bidirectional_local_data_window,
179 bidirectional_local_data_window,
180 u64,
181 |validate_value| {
182 decoder_invariant!(
183 validate_value <= u32::MAX.into(),
184 "bidirectional_local_data_window must be <= u32::MAX"
185 );
186 }
187 );
188 setter!(
189 with_bidirectional_remote_data_window,
190 bidirectional_remote_data_window,
191 u64,
192 |validate_value| {
193 decoder_invariant!(
194 validate_value <= u32::MAX.into(),
195 "bidirectional_remote_data_window must be <= u32::MAX"
196 );
197 }
198 );
199 setter!(
200 with_unidirectional_data_window,
201 unidirectional_data_window,
202 u64,
203 |validate_value| {
204 decoder_invariant!(
205 validate_value <= u32::MAX.into(),
206 "unidirectional_data_window must be <= u32::MAX"
207 );
208 }
209 );
210
211 setter!(with_max_idle_timeout, max_idle_timeout, Duration);
212
213 #[deprecated(
215 note = "use with_max_open_local_bidirectional_streams and with_max_open_remote_bidirectional_streams instead"
216 )]
217 pub fn with_max_open_bidirectional_streams(
218 mut self,
219 value: u64,
220 ) -> Result<Self, ValidationError> {
221 self.max_open_local_bidirectional_streams = value.try_into()?;
222 self.max_open_remote_bidirectional_streams = value.try_into()?;
223 Ok(self)
224 }
225
226 pub fn with_max_open_local_bidirectional_streams(
230 mut self,
231 value: u64,
232 ) -> Result<Self, ValidationError> {
233 self.max_open_local_bidirectional_streams = value.try_into()?;
234 Ok(self)
235 }
236
237 pub fn with_max_open_remote_bidirectional_streams(
241 mut self,
242 value: u64,
243 ) -> Result<Self, ValidationError> {
244 self.max_open_remote_bidirectional_streams = value.try_into()?;
245 Ok(self)
246 }
247
248 setter!(
249 with_max_open_local_unidirectional_streams,
250 max_open_local_unidirectional_streams,
251 u64
252 );
253 setter!(
254 with_max_open_remote_unidirectional_streams,
255 max_open_remote_unidirectional_streams,
256 u64
257 );
258 setter!(with_max_ack_delay, max_ack_delay, Duration);
259 setter!(
260 with_max_active_connection_ids,
261 max_active_connection_ids,
262 u64
263 );
264 setter!(with_stream_batch_size, stream_batch_size, u8);
265 setter!(with_ack_elicitation_interval, ack_elicitation_interval, u8);
266 setter!(with_max_ack_ranges, ack_ranges_limit, u8);
267 setter!(
268 with_max_send_buffer_size,
280 max_send_buffer_size,
281 u32
282 );
283 setter!(
284 with_max_handshake_duration,
285 max_handshake_duration,
286 Duration
287 );
288 setter!(with_max_keep_alive_period, max_keep_alive_period, Duration);
289 pub fn with_active_connection_migration(
294 mut self,
295 enabled: bool,
296 ) -> Result<Self, ValidationError> {
297 if enabled {
298 self.migration_support = MigrationSupport::Enabled
299 } else {
300 self.migration_support = MigrationSupport::Disabled
301 }
302 Ok(self)
303 }
304
305 pub fn with_initial_round_trip_time(
311 mut self,
312 value: Duration,
313 ) -> Result<Self, ValidationError> {
314 ensure!(
315 value >= recovery::MIN_RTT,
316 Err(ValidationError(
317 "provided value must be at least 1 microsecond",
318 ))
319 );
320
321 self.initial_round_trip_time = value;
322 Ok(self)
323 }
324
325 #[cfg(feature = "unstable-limits")]
326 setter!(
327 with_anti_amplification_multiplier,
333 anti_amplification_multiplier,
334 u8
335 );
336
337 pub fn with_pto_jitter_percentage(mut self, value: u8) -> Result<Self, ValidationError> {
348 ensure!(
349 value <= MAX_PTO_JITTER_PERCENTAGE,
350 Err(ValidationError(
351 "PTO jitter percentage must be between 0 and 50"
352 ))
353 );
354 self.pto_jitter_percentage = value;
355 Ok(self)
356 }
357
358 #[doc(hidden)]
359 #[inline]
360 pub fn pto_jitter_percentage(&self) -> u8 {
361 self.pto_jitter_percentage
362 }
363
364 #[doc(hidden)]
367 #[inline]
368 pub fn load_peer<A, B, C, D>(&mut self, peer_parameters: &TransportParameters<A, B, C, D>) {
369 self.max_idle_timeout
370 .load_peer(&peer_parameters.max_idle_timeout);
371 }
372
373 #[doc(hidden)]
374 #[inline]
375 pub const fn ack_settings(&self) -> ack::Settings {
376 ack::Settings {
377 ack_delay_exponent: self.ack_delay_exponent.as_u8(),
378 max_ack_delay: self.max_ack_delay.as_duration(),
379 ack_ranges_limit: self.ack_ranges_limit,
380 ack_elicitation_interval: self.ack_elicitation_interval,
381 }
382 }
383
384 #[doc(hidden)]
385 #[inline]
386 pub const fn initial_flow_control_limits(&self) -> InitialFlowControlLimits {
387 InitialFlowControlLimits {
388 stream_limits: self.initial_stream_limits(),
389 max_data: self.data_window.as_varint(),
390 max_open_remote_bidirectional_streams: self
391 .max_open_remote_bidirectional_streams
392 .as_varint(),
393 max_open_remote_unidirectional_streams: self
394 .max_open_remote_unidirectional_streams
395 .as_varint(),
396 }
397 }
398
399 #[doc(hidden)]
400 #[inline]
401 pub const fn initial_stream_limits(&self) -> InitialStreamLimits {
402 InitialStreamLimits {
403 max_data_bidi_local: self.bidirectional_local_data_window.as_varint(),
404 max_data_bidi_remote: self.bidirectional_remote_data_window.as_varint(),
405 max_data_uni: self.unidirectional_data_window.as_varint(),
406 }
407 }
408
409 #[doc(hidden)]
410 #[inline]
411 pub fn stream_limits(&self) -> stream::Limits {
412 stream::Limits {
413 max_send_buffer_size: self.max_send_buffer_size,
414 max_open_local_unidirectional_streams: self.max_open_local_unidirectional_streams,
415 max_open_local_bidirectional_streams: self.max_open_local_bidirectional_streams,
416 }
417 }
418
419 #[doc(hidden)]
420 #[inline]
421 pub fn max_idle_timeout(&self) -> Option<Duration> {
422 self.max_idle_timeout.as_duration()
423 }
424
425 #[doc(hidden)]
426 #[inline]
427 pub fn max_handshake_duration(&self) -> Duration {
428 self.max_handshake_duration
429 }
430
431 #[doc(hidden)]
432 #[inline]
433 pub fn max_keep_alive_period(&self) -> Duration {
434 self.max_keep_alive_period
435 }
436
437 #[doc(hidden)]
438 #[inline]
439 pub fn initial_round_trip_time(&self) -> Duration {
440 self.initial_round_trip_time
441 }
442
443 #[doc(hidden)]
444 #[inline]
445 pub fn active_migration_enabled(&self) -> bool {
446 matches!(self.migration_support, MigrationSupport::Enabled)
447 }
448
449 #[doc(hidden)]
450 #[inline]
451 pub fn anti_amplification_multiplier(&self) -> u8 {
452 self.anti_amplification_multiplier
453 }
454
455 #[doc(hidden)]
456 #[inline]
457 pub fn stream_batch_size(&self) -> u8 {
458 self.stream_batch_size
459 }
460}
461
462#[must_use]
463#[derive(Debug)]
464pub struct UpdatableLimits<'a>(&'a mut Limits);
465
466impl<'a> UpdatableLimits<'a> {
467 pub fn new(limits: &'a mut Limits) -> UpdatableLimits<'a> {
468 UpdatableLimits(limits)
469 }
470
471 pub fn with_stream_batch_size(&mut self, size: u8) {
472 self.0.stream_batch_size = size;
473 }
474}
475
476pub trait Limiter: 'static + Send {
478 fn on_connection(&mut self, info: &ConnectionInfo) -> Limits;
479
480 #[inline]
483 #[cfg(feature = "alloc")]
484 fn on_post_handshake(&mut self, info: &HandshakeInfo, limits: &mut UpdatableLimits) {
485 let _ = info;
486 let _ = limits;
487 }
488}
489
490impl Limiter for Limits {
492 fn on_connection(&mut self, _into: &ConnectionInfo) -> Limits {
493 *self
494 }
495 #[cfg(feature = "alloc")]
496 fn on_post_handshake(&mut self, _info: &HandshakeInfo, _limits: &mut UpdatableLimits) {}
497}
498
499#[cfg(test)]
500mod tests {
501 use super::*;
502
503 #[test]
505 fn limit_validation() {
506 let mut data = u32::MAX as u64 + 1;
507 let limits = Limits::default();
508 assert!(limits.with_data_window(data).is_err());
509 assert!(limits.with_bidirectional_local_data_window(data).is_err());
510 assert!(limits.with_bidirectional_remote_data_window(data).is_err());
511 assert!(limits.with_unidirectional_data_window(data).is_err());
512
513 data = u32::MAX as u64;
514 assert!(limits.with_data_window(data).is_ok());
515 assert!(limits.with_bidirectional_local_data_window(data).is_ok());
516 assert!(limits.with_bidirectional_remote_data_window(data).is_ok());
517 assert!(limits.with_unidirectional_data_window(data).is_ok());
518 }
519
520 #[test]
522 fn updatable_limits() {
523 let mut limits = Limits::default();
524 assert_eq!(limits.stream_batch_size, 1);
525 let mut updatable_limits = UpdatableLimits::new(&mut limits);
526 let new_size = 10;
527 updatable_limits.with_stream_batch_size(new_size);
528 assert_eq!(limits.stream_batch_size, new_size);
529 }
530
531 #[test]
532 fn pto_jitter_percentage_default() {
533 let limits = Limits::new();
534 assert_eq!(
535 limits.pto_jitter_percentage(),
536 DEFAULT_PTO_JITTER_PERCENTAGE
537 );
538
539 let limits = Limits::default();
540 assert_eq!(
541 limits.pto_jitter_percentage(),
542 DEFAULT_PTO_JITTER_PERCENTAGE
543 );
544 }
545
546 #[test]
547 fn pto_jitter_percentage_valid_values() {
548 let limits = Limits::new();
549
550 for value in 0..=MAX_PTO_JITTER_PERCENTAGE {
552 let result = limits.with_pto_jitter_percentage(value);
553 assert!(result.is_ok(), "Value {} should be valid", value);
554 let limits = result.unwrap();
555 assert_eq!(limits.pto_jitter_percentage(), value);
556 }
557 }
558
559 #[test]
560 fn pto_jitter_percentage_invalid_values() {
561 let limits = Limits::new();
562
563 for value in (MAX_PTO_JITTER_PERCENTAGE + 1)..=255 {
565 let result = limits.with_pto_jitter_percentage(value);
566 assert!(result.is_err(), "Value {} should be invalid", value);
567
568 if let Err(ValidationError(msg)) = result {
569 assert_eq!(msg, "PTO jitter percentage must be between 0 and 50");
570 } else {
571 panic!("Expected ValidationError for value {}", value);
572 }
573 }
574 }
575
576 #[test]
577 fn pto_jitter_percentage_edge_cases() {
578 let limits = Limits::new();
579
580 let result = limits.with_pto_jitter_percentage(0);
582 assert!(result.is_ok());
583 assert_eq!(result.unwrap().pto_jitter_percentage(), 0);
584
585 let result = limits.with_pto_jitter_percentage(MAX_PTO_JITTER_PERCENTAGE);
586 assert!(result.is_ok());
587 assert_eq!(
588 result.unwrap().pto_jitter_percentage(),
589 MAX_PTO_JITTER_PERCENTAGE
590 );
591
592 let result = limits.with_pto_jitter_percentage(MAX_PTO_JITTER_PERCENTAGE + 1);
593 assert!(result.is_err());
594 }
595
596 #[test]
597 fn pto_jitter_percentage_chaining() {
598 let result = Limits::new()
600 .with_pto_jitter_percentage(25)
601 .and_then(|l| l.with_stream_batch_size(5));
602
603 assert!(result.is_ok());
604 let limits = result.unwrap();
605 assert_eq!(limits.pto_jitter_percentage(), 25);
606 assert_eq!(limits.stream_batch_size(), 5);
607 }
608
609 #[test]
610 fn pto_jitter_percentage_getter() {
611 let mut limits = Limits::new();
612
613 assert_eq!(limits.pto_jitter_percentage(), 0);
615
616 limits = limits.with_pto_jitter_percentage(30).unwrap();
618 assert_eq!(limits.pto_jitter_percentage(), 30);
619
620 limits = limits.with_pto_jitter_percentage(15).unwrap();
622 assert_eq!(limits.pto_jitter_percentage(), 15);
623 }
624}