phantom_protocol/transport/
scheduler.rs1use crate::transport::types::{LegType, SchedulerMode};
16use parking_lot::RwLock;
17use std::collections::HashMap;
18use std::sync::atomic::{AtomicU32, AtomicU64, Ordering};
19
20pub struct PathInfo {
21 pub leg_type: LegType,
22 pub rtt_ms: u32,
23 pub loss_percent: u8,
24 pub active: bool,
25 pub bytes_sent: u64,
26}
27
28impl PathInfo {
29 pub fn new(leg_type: LegType) -> Self {
30 Self {
31 leg_type,
32 rtt_ms: 150, loss_percent: 0,
34 active: true,
35 bytes_sent: 0,
36 }
37 }
38}
39
40pub struct Scheduler {
41 mode: RwLock<SchedulerMode>,
42 paths: RwLock<HashMap<LegType, PathInfo>>,
43 #[allow(dead_code)]
44 rr_counter: AtomicU32,
45 total_bytes: AtomicU64,
46}
47
48impl Scheduler {
49 pub fn new(mode: SchedulerMode) -> Self {
50 Self {
51 mode: RwLock::new(mode),
52 paths: RwLock::new(HashMap::new()),
53 rr_counter: AtomicU32::new(0),
54 total_bytes: AtomicU64::new(0),
55 }
56 }
57
58 pub fn register_path(&self, leg_type: LegType) {
59 let mut paths = self.paths.write();
60 paths
61 .entry(leg_type)
62 .or_insert_with(|| PathInfo::new(leg_type));
63 }
64
65 pub fn set_path_available(&self, leg_type: LegType, available: bool) {
66 let mut paths = self.paths.write();
67 if let Some(path) = paths.get_mut(&leg_type) {
68 path.active = available;
69 }
70 }
71
72 pub fn select_paths(&self, is_priority: bool) -> Vec<LegType> {
73 let paths = self.paths.read();
74 let mode = self.mode.read();
75
76 let mut available: Vec<_> = paths.iter().filter(|(_, p)| p.active).collect();
77
78 if available.is_empty() {
79 return Vec::new();
80 }
81
82 if is_priority {
83 available.sort_by_key(|(_, p)| p.rtt_ms);
85 return vec![*available[0].0];
86 }
87
88 match *mode {
89 SchedulerMode::LowLatency => {
90 available.sort_by_key(|(_, p)| p.rtt_ms);
91 vec![*available[0].0]
92 }
93 SchedulerMode::HighThroughput => {
94 available.iter().map(|(t, _)| **t).collect()
96 }
97 SchedulerMode::Reliability | SchedulerMode::Stealth => {
98 available.sort_by_key(|(_, p)| p.rtt_ms);
100 available.iter().take(2).map(|(t, _)| **t).collect()
101 }
102 }
103 }
104
105 pub fn update_rtt(&self, leg_type: LegType, rtt: u32) {
106 let mut paths = self.paths.write();
107 if let Some(path) = paths.get_mut(&leg_type) {
108 path.rtt_ms = rtt;
109 }
110 }
111
112 pub fn record_sent(&self, leg_type: LegType, bytes: u64) {
113 let mut paths = self.paths.write();
114 if let Some(path) = paths.get_mut(&leg_type) {
115 path.bytes_sent += bytes;
116 }
117 self.total_bytes.fetch_add(bytes, Ordering::Relaxed);
118 }
119}