summaryrefslogtreecommitdiff
path: root/crates/tor-proto/src/congestion/fixed.rs
blob: 3607e99bfdd131b8f44948acc01441ea1a99f239 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! Implementation of the Fixed Window congestion control algorithm.
//!
//! This is used by the circuit reactor in order to decide when to send data and SENDMEs.
//!
//! The vanilla flow control system of fixed window SENDMEs in the spec.

use crate::Result;

use super::{
    rtt::RoundtripTimeEstimator,
    sendme::{self, WindowParams},
    CongestionControlAlgorithm, CongestionSignals, CongestionWindow, State,
};

/// Fixed window algorithm which is essentially the SENDME v0 with fixed receive and send window
/// size.
#[derive(Clone, Debug)]
pub(crate) struct FixedWindow {
    /// Window used to say how many cells we can receive.
    recvwindow: sendme::CircRecvWindow,
    /// Window used to say how many cells we can send.
    sendwindow: sendme::CircSendWindow,
}

impl FixedWindow {
    /// Create a new `FixedWindow` form a given initial sendwindow size.
    ///
    /// Note: the initial recvwindow size is given by [`sendme::CircParams::start`].
    pub(crate) fn new(initial_window: u16) -> Self {
        Self {
            recvwindow: sendme::CircRecvWindow::new(sendme::CircParams::start()),
            sendwindow: sendme::CircSendWindow::new(initial_window),
        }
    }
}

impl CongestionControlAlgorithm for FixedWindow {
    fn is_next_cell_sendme(&self) -> bool {
        self.sendwindow.should_record_tag()
    }

    fn can_send(&self) -> bool {
        self.sendwindow.window() > 0
    }

    fn cwnd(&self) -> Option<&CongestionWindow> {
        None
    }

    fn sendme_received(
        &mut self,
        _state: &mut State,
        _rtt: &mut RoundtripTimeEstimator,
        _signals: CongestionSignals,
    ) -> Result<()> {
        self.sendwindow.put()
    }

    fn sendme_sent(&mut self) -> Result<()> {
        self.recvwindow.put();
        Ok(())
    }

    fn data_received(&mut self) -> Result<bool> {
        self.recvwindow.take()
    }

    fn data_sent(&mut self) -> Result<()> {
        self.sendwindow.take()
    }

    #[cfg(test)]
    fn send_window(&self) -> u32 {
        u32::from(self.sendwindow.window())
    }
}