bitfold_protocol/
bandwidth.rs1use std::time::{Duration, Instant};
2
3#[derive(Debug, Clone)]
5pub struct BandwidthManager {
6 outgoing_bandwidth: u32,
8 incoming_bandwidth: u32,
10 bytes_sent_this_window: u32,
12 bytes_recv_this_window: u32,
14 window_start: Instant,
16 window_duration: Duration,
18}
19
20impl BandwidthManager {
21 pub fn new(outgoing_bw: u32, incoming_bw: u32, window_duration: Duration) -> Self {
23 Self {
24 outgoing_bandwidth: outgoing_bw,
25 incoming_bandwidth: incoming_bw,
26 bytes_sent_this_window: 0,
27 bytes_recv_this_window: 0,
28 window_start: Instant::now(),
29 window_duration,
30 }
31 }
32
33 pub fn unlimited() -> Self {
35 Self::new(0, 0, Duration::from_secs(1))
36 }
37
38 pub fn set_outgoing_bandwidth(&mut self, bytes_per_sec: u32) {
40 self.outgoing_bandwidth = bytes_per_sec;
41 }
42
43 pub fn set_incoming_bandwidth(&mut self, bytes_per_sec: u32) {
45 self.incoming_bandwidth = bytes_per_sec;
46 }
47
48 pub fn update_window(&mut self, now: Instant) {
50 if now.duration_since(self.window_start) >= self.window_duration {
51 self.bytes_sent_this_window = 0;
52 self.bytes_recv_this_window = 0;
53 self.window_start = now;
54 }
55 }
56
57 pub fn can_send_outgoing(&self, byte_count: usize) -> bool {
60 self.update_window_if_needed();
61
62 if self.outgoing_bandwidth == 0 {
63 return true; }
65
66 self.bytes_sent_this_window + byte_count as u32 <= self.outgoing_bandwidth
67 }
68
69 pub fn record_sent(&mut self, byte_count: usize) {
71 self.bytes_sent_this_window += byte_count as u32;
72 }
73
74 pub fn can_receive_incoming(&self, byte_count: usize) -> bool {
76 self.update_window_if_needed();
77
78 if self.incoming_bandwidth == 0 {
79 return true; }
81
82 self.bytes_recv_this_window + byte_count as u32 <= self.incoming_bandwidth
83 }
84
85 pub fn record_received(&mut self, byte_count: usize) {
87 self.bytes_recv_this_window += byte_count as u32;
88 }
89
90 pub fn outgoing_utilization(&self) -> f32 {
92 if self.outgoing_bandwidth == 0 {
93 return 0.0; }
95 self.bytes_sent_this_window as f32 / self.outgoing_bandwidth as f32
96 }
97
98 pub fn incoming_utilization(&self) -> f32 {
100 if self.incoming_bandwidth == 0 {
101 return 0.0; }
103 self.bytes_recv_this_window as f32 / self.incoming_bandwidth as f32
104 }
105
106 fn update_window_if_needed(&self) {
107 }
109}
110
111#[cfg(test)]
112mod tests {
113 use std::thread::sleep;
114
115 use super::*;
116
117 #[test]
118 fn test_unlimited_bandwidth() {
119 let bw = BandwidthManager::unlimited();
120
121 assert!(bw.can_send_outgoing(1_000_000));
123 assert!(bw.can_receive_incoming(1_000_000));
124 assert_eq!(bw.outgoing_utilization(), 0.0);
125 assert_eq!(bw.incoming_utilization(), 0.0);
126 }
127
128 #[test]
129 fn test_utilization() {
130 let mut bw = BandwidthManager::new(1000, 2000, Duration::from_secs(1));
131
132 bw.record_sent(500);
133 assert_eq!(bw.outgoing_utilization(), 0.5);
134
135 bw.record_received(1000);
136 assert_eq!(bw.incoming_utilization(), 0.5);
137 }
138
139 #[test]
140 fn test_outgoing_bandwidth_limit() {
141 let mut bw = BandwidthManager::new(1000, 0, Duration::from_secs(1));
142
143 assert!(bw.can_send_outgoing(500));
145 bw.record_sent(500);
146
147 assert!(bw.can_send_outgoing(500));
148 bw.record_sent(500);
149
150 assert!(!bw.can_send_outgoing(100));
152 }
153
154 #[test]
155 fn test_bandwidth_window_reset() {
156 let mut bw = BandwidthManager::new(1000, 0, Duration::from_millis(10));
157
158 bw.record_sent(1000);
159 assert!(!bw.can_send_outgoing(100));
160
161 sleep(Duration::from_millis(15));
163 bw.update_window(Instant::now());
164
165 assert!(bw.can_send_outgoing(500));
167 }
168}