#![allow(unused_variables)]
use std::time::Instant;
use super::CongestionController;
use super::CongestionStats;
use crate::connection::rtt::RttEstimator;
use crate::connection::space::SentPacket;
use crate::RecoveryConfig;
#[derive(Debug)]
pub struct DummyConfig {
initial_congestion_window: u64,
}
impl DummyConfig {
pub fn from(conf: &RecoveryConfig) -> Self {
let max_datagram_size = conf.max_datagram_size as u64;
let initial_congestion_window = conf
.initial_congestion_window
.saturating_mul(max_datagram_size);
Self {
initial_congestion_window,
}
}
}
impl Default for DummyConfig {
fn default() -> Self {
Self {
initial_congestion_window: 10 * crate::DEFAULT_SEND_UDP_PAYLOAD_SIZE as u64,
}
}
}
#[derive(Debug)]
pub struct Dummy {
cwnd: u64,
stats: CongestionStats,
}
impl Dummy {
pub fn new(conf: DummyConfig) -> Self {
Self {
cwnd: conf.initial_congestion_window,
stats: Default::default(),
}
}
}
impl CongestionController for Dummy {
fn name(&self) -> &str {
"DUMMY"
}
fn on_sent(&mut self, now: Instant, packet: &mut SentPacket, bytes_in_flight: u64) {
let sent_bytes = packet.sent_size as u64;
self.stats.bytes_in_flight = bytes_in_flight;
self.stats.bytes_sent_in_total = self.stats.bytes_sent_in_total.saturating_add(sent_bytes);
}
fn begin_ack(&mut self, now: Instant, bytes_in_flight: u64) {
}
fn on_ack(
&mut self,
packet: &mut SentPacket,
now: Instant,
app_limited: bool,
rtt: &RttEstimator,
bytes_in_flight: u64,
) {
let acked_bytes = packet.sent_size as u64;
self.stats.bytes_in_flight = bytes_in_flight;
self.stats.bytes_acked_in_total =
self.stats.bytes_acked_in_total.saturating_add(acked_bytes);
}
fn end_ack(&mut self) {
}
fn on_congestion_event(
&mut self,
now: Instant,
packet: &SentPacket,
is_persistent_congestion: bool,
lost_bytes: u64,
bytes_in_flight: u64,
) {
self.stats.bytes_lost_in_total = self.stats.bytes_lost_in_total.saturating_add(lost_bytes);
self.stats.bytes_in_flight = bytes_in_flight;
}
fn in_slow_start(&self) -> bool {
false
}
fn in_recovery(&self, sent_time: Instant) -> bool {
false
}
fn congestion_window(&self) -> u64 {
self.cwnd
}
fn initial_window(&self) -> u64 {
self.cwnd
}
fn minimal_window(&self) -> u64 {
self.cwnd
}
fn stats(&self) -> &CongestionStats {
&self.stats
}
fn pacing_rate(&self) -> Option<u64> {
None
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
#[test]
fn dummy_init() {
let conf = RecoveryConfig {
initial_congestion_window: 10,
max_datagram_size: 1200,
..RecoveryConfig::default()
};
let d = Dummy::new(DummyConfig::from(&conf));
assert_eq!(d.name(), "DUMMY");
assert_eq!(d.congestion_window(), 1200 * 10);
assert_eq!(d.initial_window(), 1200 * 10);
assert_eq!(d.minimal_window(), 1200 * 10);
assert_eq!(d.in_slow_start(), false);
assert_eq!(d.in_recovery(Instant::now()), false);
assert_eq!(d.stats().bytes_in_flight, 0);
assert_eq!(d.pacing_rate(), None);
}
#[test]
fn dummy_stats() {
let conf = RecoveryConfig {
initial_congestion_window: 10,
max_datagram_size: 1200,
..RecoveryConfig::default()
};
let mut d = Dummy::new(DummyConfig::from(&conf));
let rtt = Duration::from_millis(100);
let rtt_estimator = RttEstimator::new(rtt);
let now = Instant::now();
let mut pkt = SentPacket {
pkt_num: 0,
ack_eliciting: true,
in_flight: true,
sent_size: 1200,
..SentPacket::default()
};
d.on_sent(now, &mut pkt, 1200);
assert_eq!(d.stats().bytes_in_flight, 1200);
assert_eq!(d.stats().bytes_sent_in_total, 1200);
let now = now + rtt;
d.begin_ack(now, 1200);
d.on_ack(&mut pkt, now, true, &rtt_estimator, 0);
d.end_ack();
assert_eq!(d.stats().bytes_in_flight, 0);
assert_eq!(d.stats().bytes_acked_in_total, 1200);
let mut pkt = SentPacket {
pkt_num: 0,
ack_eliciting: true,
in_flight: true,
sent_size: 1400,
..SentPacket::default()
};
d.on_sent(now, &mut pkt, 1400);
assert_eq!(d.stats().bytes_in_flight, 1400);
assert_eq!(d.stats().bytes_sent_in_total, 2600);
d.on_congestion_event(now, &pkt, false, 1400, 0);
assert_eq!(d.stats().bytes_in_flight, 0);
assert_eq!(d.stats().bytes_lost_in_total, 1400);
}
}