From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- third_party/rust/neqo-transport/tests/sim/delay.rs | 102 +++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 third_party/rust/neqo-transport/tests/sim/delay.rs (limited to 'third_party/rust/neqo-transport/tests/sim/delay.rs') diff --git a/third_party/rust/neqo-transport/tests/sim/delay.rs b/third_party/rust/neqo-transport/tests/sim/delay.rs new file mode 100644 index 0000000000..34cb923084 --- /dev/null +++ b/third_party/rust/neqo-transport/tests/sim/delay.rs @@ -0,0 +1,102 @@ +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(clippy::module_name_repetitions)] + +use std::{ + collections::BTreeMap, + convert::TryFrom, + fmt::{self, Debug}, + ops::Range, + time::{Duration, Instant}, +}; + +use neqo_common::Datagram; +use neqo_transport::Output; + +use super::{Node, Rng}; + +/// An iterator that shares a `Random` instance and produces uniformly +/// random `Duration`s within a specified range. +pub struct RandomDelay { + start: Duration, + max: u64, + rng: Option, +} + +impl RandomDelay { + /// Make a new random `Duration` generator. This panics if the range provided + /// is inverted (i.e., `bounds.start > bounds.end`), or spans 2^64 + /// or more nanoseconds. + /// A zero-length range means that random values won't be taken from the Rng + pub fn new(bounds: Range) -> Self { + let max = u64::try_from((bounds.end - bounds.start).as_nanos()).unwrap(); + Self { + start: bounds.start, + max, + rng: None, + } + } + + pub fn set_rng(&mut self, rng: Rng) { + self.rng = Some(rng); + } + + pub fn next(&mut self) -> Duration { + let mut rng = self.rng.as_ref().unwrap().borrow_mut(); + let r = rng.random_from(0..self.max); + self.start + Duration::from_nanos(r) + } +} + +pub struct Delay { + random: RandomDelay, + queue: BTreeMap, +} + +impl Delay { + pub fn new(bounds: Range) -> Self { + Self { + random: RandomDelay::new(bounds), + queue: BTreeMap::default(), + } + } + + fn insert(&mut self, d: Datagram, now: Instant) { + let mut t = now + self.random.next(); + while self.queue.contains_key(&t) { + // This is a little inefficient, but it avoids drops on collisions, + // which are super-common for a fixed delay. + t += Duration::from_nanos(1); + } + self.queue.insert(t, d); + } +} + +impl Node for Delay { + fn init(&mut self, rng: Rng, _now: Instant) { + self.random.set_rng(rng); + } + + fn process(&mut self, d: Option, now: Instant) -> Output { + if let Some(dgram) = d { + self.insert(dgram, now); + } + if let Some((&k, _)) = self.queue.range(..=now).next() { + Output::Datagram(self.queue.remove(&k).unwrap()) + } else if let Some(&t) = self.queue.keys().next() { + Output::Callback(t - now) + } else { + Output::None + } + } +} + +impl Debug for Delay { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("delay") + } +} -- cgit v1.2.3