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!(
212 with_max_idle_timeout,
216 max_idle_timeout,
217 Duration);
218
219 #[deprecated(
221 note = "use with_max_open_local_bidirectional_streams and with_max_open_remote_bidirectional_streams instead"
222 )]
223 pub fn with_max_open_bidirectional_streams(
224 mut self,
225 value: u64,
226 ) -> Result<Self, ValidationError> {
227 self.max_open_local_bidirectional_streams = value.try_into()?;
228 self.max_open_remote_bidirectional_streams = value.try_into()?;
229 Ok(self)
230 }
231
232 pub fn with_max_open_local_bidirectional_streams(
236 mut self,
237 value: u64,
238 ) -> Result<Self, ValidationError> {
239 self.max_open_local_bidirectional_streams = value.try_into()?;
240 Ok(self)
241 }
242
243 pub fn with_max_open_remote_bidirectional_streams(
247 mut self,
248 value: u64,
249 ) -> Result<Self, ValidationError> {
250 self.max_open_remote_bidirectional_streams = value.try_into()?;
251 Ok(self)
252 }
253
254 setter!(
255 with_max_open_local_unidirectional_streams,
256 max_open_local_unidirectional_streams,
257 u64
258 );
259 setter!(
260 with_max_open_remote_unidirectional_streams,
261 max_open_remote_unidirectional_streams,
262 u64
263 );
264 setter!(with_max_ack_delay, max_ack_delay, Duration);
265 setter!(
266 with_max_active_connection_ids,
267 max_active_connection_ids,
268 u64
269 );
270 setter!(with_stream_batch_size, stream_batch_size, u8);
271 setter!(with_ack_elicitation_interval, ack_elicitation_interval, u8);
272 setter!(with_max_ack_ranges, ack_ranges_limit, u8);
273 setter!(
274 with_max_send_buffer_size,
286 max_send_buffer_size,
287 u32
288 );
289 setter!(
290 with_max_handshake_duration,
291 max_handshake_duration,
292 Duration
293 );
294 setter!(
295 with_max_keep_alive_period,
301 max_keep_alive_period,
302 Duration);
303 pub fn with_active_connection_migration(
308 mut self,
309 enabled: bool,
310 ) -> Result<Self, ValidationError> {
311 if enabled {
312 self.migration_support = MigrationSupport::Enabled
313 } else {
314 self.migration_support = MigrationSupport::Disabled
315 }
316 Ok(self)
317 }
318
319 pub fn with_initial_round_trip_time(
325 mut self,
326 value: Duration,
327 ) -> Result<Self, ValidationError> {
328 ensure!(
329 value >= recovery::MIN_RTT,
330 Err(ValidationError(
331 "provided value must be at least 1 microsecond",
332 ))
333 );
334
335 self.initial_round_trip_time = value;
336 Ok(self)
337 }
338
339 #[cfg(feature = "unstable-limits")]
340 setter!(
341 with_anti_amplification_multiplier,
347 anti_amplification_multiplier,
348 u8
349 );
350
351 pub fn with_pto_jitter_percentage(mut self, value: u8) -> Result<Self, ValidationError> {
362 ensure!(
363 value <= MAX_PTO_JITTER_PERCENTAGE,
364 Err(ValidationError(
365 "PTO jitter percentage must be between 0 and 50"
366 ))
367 );
368 self.pto_jitter_percentage = value;
369 Ok(self)
370 }
371
372 #[doc(hidden)]
373 #[inline]
374 pub fn pto_jitter_percentage(&self) -> u8 {
375 self.pto_jitter_percentage
376 }
377
378 #[doc(hidden)]
381 #[inline]
382 pub fn load_peer<A, B, C, D>(&mut self, peer_parameters: &TransportParameters<A, B, C, D>) {
383 self.max_idle_timeout
384 .load_peer(&peer_parameters.max_idle_timeout);
385 }
386
387 #[doc(hidden)]
388 #[inline]
389 pub const fn ack_settings(&self) -> ack::Settings {
390 ack::Settings {
391 ack_delay_exponent: self.ack_delay_exponent.as_u8(),
392 max_ack_delay: self.max_ack_delay.as_duration(),
393 ack_ranges_limit: self.ack_ranges_limit,
394 ack_elicitation_interval: self.ack_elicitation_interval,
395 }
396 }
397
398 #[doc(hidden)]
399 #[inline]
400 pub const fn initial_flow_control_limits(&self) -> InitialFlowControlLimits {
401 InitialFlowControlLimits {
402 stream_limits: self.initial_stream_limits(),
403 max_data: self.data_window.as_varint(),
404 max_open_remote_bidirectional_streams: self
405 .max_open_remote_bidirectional_streams
406 .as_varint(),
407 max_open_remote_unidirectional_streams: self
408 .max_open_remote_unidirectional_streams
409 .as_varint(),
410 }
411 }
412
413 #[doc(hidden)]
414 #[inline]
415 pub const fn initial_stream_limits(&self) -> InitialStreamLimits {
416 InitialStreamLimits {
417 max_data_bidi_local: self.bidirectional_local_data_window.as_varint(),
418 max_data_bidi_remote: self.bidirectional_remote_data_window.as_varint(),
419 max_data_uni: self.unidirectional_data_window.as_varint(),
420 }
421 }
422
423 #[doc(hidden)]
424 #[inline]
425 pub fn stream_limits(&self) -> stream::Limits {
426 stream::Limits {
427 max_send_buffer_size: self.max_send_buffer_size,
428 max_open_local_unidirectional_streams: self.max_open_local_unidirectional_streams,
429 max_open_local_bidirectional_streams: self.max_open_local_bidirectional_streams,
430 }
431 }
432
433 #[doc(hidden)]
434 #[inline]
435 pub fn max_idle_timeout(&self) -> Option<Duration> {
436 self.max_idle_timeout.as_duration()
437 }
438
439 #[doc(hidden)]
440 #[inline]
441 pub fn max_handshake_duration(&self) -> Duration {
442 self.max_handshake_duration
443 }
444
445 #[doc(hidden)]
446 #[inline]
447 pub fn max_keep_alive_period(&self) -> Duration {
448 self.max_keep_alive_period
449 }
450
451 #[doc(hidden)]
452 #[inline]
453 pub fn initial_round_trip_time(&self) -> Duration {
454 self.initial_round_trip_time
455 }
456
457 #[doc(hidden)]
458 #[inline]
459 pub fn active_migration_enabled(&self) -> bool {
460 matches!(self.migration_support, MigrationSupport::Enabled)
461 }
462
463 #[doc(hidden)]
464 #[inline]
465 pub fn anti_amplification_multiplier(&self) -> u8 {
466 self.anti_amplification_multiplier
467 }
468
469 #[doc(hidden)]
470 #[inline]
471 pub fn stream_batch_size(&self) -> u8 {
472 self.stream_batch_size
473 }
474}
475
476#[must_use]
477#[derive(Debug)]
478pub struct UpdatableLimits<'a>(&'a mut Limits);
479
480impl<'a> UpdatableLimits<'a> {
481 pub fn new(limits: &'a mut Limits) -> UpdatableLimits<'a> {
482 UpdatableLimits(limits)
483 }
484
485 pub fn with_stream_batch_size(&mut self, size: u8) {
486 self.0.stream_batch_size = size;
487 }
488}
489
490pub trait Limiter: 'static + Send {
492 fn on_connection(&mut self, info: &ConnectionInfo) -> Limits;
493
494 #[inline]
497 #[cfg(feature = "alloc")]
498 fn on_post_handshake(&mut self, info: &HandshakeInfo, limits: &mut UpdatableLimits) {
499 let _ = info;
500 let _ = limits;
501 }
502}
503
504impl Limiter for Limits {
506 fn on_connection(&mut self, _into: &ConnectionInfo) -> Limits {
507 *self
508 }
509 #[cfg(feature = "alloc")]
510 fn on_post_handshake(&mut self, _info: &HandshakeInfo, _limits: &mut UpdatableLimits) {}
511}
512
513#[cfg(test)]
514mod tests {
515 use super::*;
516
517 #[test]
519 fn limit_validation() {
520 let mut data = u32::MAX as u64 + 1;
521 let limits = Limits::default();
522 assert!(limits.with_data_window(data).is_err());
523 assert!(limits.with_bidirectional_local_data_window(data).is_err());
524 assert!(limits.with_bidirectional_remote_data_window(data).is_err());
525 assert!(limits.with_unidirectional_data_window(data).is_err());
526
527 data = u32::MAX as u64;
528 assert!(limits.with_data_window(data).is_ok());
529 assert!(limits.with_bidirectional_local_data_window(data).is_ok());
530 assert!(limits.with_bidirectional_remote_data_window(data).is_ok());
531 assert!(limits.with_unidirectional_data_window(data).is_ok());
532 }
533
534 #[test]
536 fn updatable_limits() {
537 let mut limits = Limits::default();
538 assert_eq!(limits.stream_batch_size, 1);
539 let mut updatable_limits = UpdatableLimits::new(&mut limits);
540 let new_size = 10;
541 updatable_limits.with_stream_batch_size(new_size);
542 assert_eq!(limits.stream_batch_size, new_size);
543 }
544
545 #[test]
546 fn pto_jitter_percentage_default() {
547 let limits = Limits::new();
548 assert_eq!(
549 limits.pto_jitter_percentage(),
550 DEFAULT_PTO_JITTER_PERCENTAGE
551 );
552
553 let limits = Limits::default();
554 assert_eq!(
555 limits.pto_jitter_percentage(),
556 DEFAULT_PTO_JITTER_PERCENTAGE
557 );
558 }
559
560 #[test]
561 fn pto_jitter_percentage_valid_values() {
562 let limits = Limits::new();
563
564 for value in 0..=MAX_PTO_JITTER_PERCENTAGE {
566 let result = limits.with_pto_jitter_percentage(value);
567 assert!(result.is_ok(), "Value {} should be valid", value);
568 let limits = result.unwrap();
569 assert_eq!(limits.pto_jitter_percentage(), value);
570 }
571 }
572
573 #[test]
574 fn pto_jitter_percentage_invalid_values() {
575 let limits = Limits::new();
576
577 for value in (MAX_PTO_JITTER_PERCENTAGE + 1)..=255 {
579 let result = limits.with_pto_jitter_percentage(value);
580 assert!(result.is_err(), "Value {} should be invalid", value);
581
582 if let Err(ValidationError(msg)) = result {
583 assert_eq!(msg, "PTO jitter percentage must be between 0 and 50");
584 } else {
585 panic!("Expected ValidationError for value {}", value);
586 }
587 }
588 }
589
590 #[test]
591 fn pto_jitter_percentage_edge_cases() {
592 let limits = Limits::new();
593
594 let result = limits.with_pto_jitter_percentage(0);
596 assert!(result.is_ok());
597 assert_eq!(result.unwrap().pto_jitter_percentage(), 0);
598
599 let result = limits.with_pto_jitter_percentage(MAX_PTO_JITTER_PERCENTAGE);
600 assert!(result.is_ok());
601 assert_eq!(
602 result.unwrap().pto_jitter_percentage(),
603 MAX_PTO_JITTER_PERCENTAGE
604 );
605
606 let result = limits.with_pto_jitter_percentage(MAX_PTO_JITTER_PERCENTAGE + 1);
607 assert!(result.is_err());
608 }
609
610 #[test]
611 fn pto_jitter_percentage_chaining() {
612 let result = Limits::new()
614 .with_pto_jitter_percentage(25)
615 .and_then(|l| l.with_stream_batch_size(5));
616
617 assert!(result.is_ok());
618 let limits = result.unwrap();
619 assert_eq!(limits.pto_jitter_percentage(), 25);
620 assert_eq!(limits.stream_batch_size(), 5);
621 }
622
623 #[test]
624 fn pto_jitter_percentage_getter() {
625 let mut limits = Limits::new();
626
627 assert_eq!(limits.pto_jitter_percentage(), 0);
629
630 limits = limits.with_pto_jitter_percentage(30).unwrap();
632 assert_eq!(limits.pto_jitter_percentage(), 30);
633
634 limits = limits.with_pto_jitter_percentage(15).unwrap();
636 assert_eq!(limits.pto_jitter_percentage(), 15);
637 }
638}