phantom_protocol/transport/
multiplexer.rs1use crate::transport::types::SequenceNumber;
11use bytes::Bytes;
12use dashmap::DashMap;
13use std::sync::atomic::{AtomicU32, Ordering};
14use tokio::sync::mpsc;
15
16#[derive(Debug, Clone, PartialEq, Eq)]
18pub enum StreamMessage {
19 Data(Bytes),
21 Ack(SequenceNumber),
23 Close,
25}
26
27pub struct StreamDemultiplexer {
41 streams: DashMap<u32, mpsc::Sender<StreamMessage>>,
43 control_tx: mpsc::Sender<Bytes>,
45 next_stream_id: AtomicU32,
47}
48
49pub struct StreamHandle {
51 pub stream_id: u32,
53 pub rx: mpsc::Receiver<StreamMessage>,
55}
56
57impl StreamDemultiplexer {
58 pub fn new(control_buffer: usize) -> (Self, mpsc::Receiver<Bytes>) {
63 let (control_tx, control_rx) = mpsc::channel(control_buffer);
64 let mux = Self {
65 streams: DashMap::new(),
66 control_tx,
67 next_stream_id: AtomicU32::new(2), };
69 (mux, control_rx)
70 }
71
72 pub fn open_stream(&self, buffer_size: usize) -> StreamHandle {
76 let stream_id = self.next_stream_id.fetch_add(1, Ordering::Relaxed);
77 let (tx, rx) = mpsc::channel(buffer_size);
78 self.streams.insert(stream_id, tx);
79 StreamHandle { stream_id, rx }
80 }
81
82 pub fn register_stream(&self, stream_id: u32, buffer_size: usize) -> StreamHandle {
84 let (tx, rx) = mpsc::channel(buffer_size);
85 self.streams.insert(stream_id, tx);
86 let _ = self
88 .next_stream_id
89 .fetch_max(stream_id + 1, Ordering::Relaxed);
90 StreamHandle { stream_id, rx }
91 }
92
93 pub fn close_stream(&self, stream_id: u32) {
95 self.streams.remove(&stream_id);
96 }
97
98 pub fn route_data(&self, stream_id: u32, payload: Bytes) -> bool {
103 if stream_id == 0 {
104 return self.control_tx.try_send(payload).is_ok();
106 }
107
108 if let Some(sender) = self.streams.get(&stream_id) {
109 sender.try_send(StreamMessage::Data(payload)).is_ok()
110 } else {
111 log::warn!(
112 "StreamDemultiplexer: dropping data for unknown stream_id={}",
113 stream_id
114 );
115 false
116 }
117 }
118
119 pub async fn route_data_async(&self, stream_id: u32, payload: Bytes) -> bool {
121 if stream_id == 0 {
122 return self.control_tx.send(payload).await.is_ok();
123 }
124
125 if let Some(sender) = self.streams.get(&stream_id) {
126 sender.send(StreamMessage::Data(payload)).await.is_ok()
127 } else {
128 log::warn!(
129 "StreamDemultiplexer: dropping data for unknown stream_id={}",
130 stream_id
131 );
132 false
133 }
134 }
135
136 pub fn route_ack(&self, stream_id: u32, seq: SequenceNumber) -> bool {
141 if stream_id == 0 {
142 return false;
143 }
144 if let Some(sender) = self.streams.get(&stream_id) {
145 sender.try_send(StreamMessage::Ack(seq)).is_ok()
146 } else {
147 false
148 }
149 }
150
151 pub fn route_close(&self, stream_id: u32) -> bool {
153 if stream_id == 0 {
154 return false;
155 }
156 if let Some(sender) = self.streams.get(&stream_id) {
157 sender.try_send(StreamMessage::Close).is_ok()
158 } else {
159 false
160 }
161 }
162
163 pub async fn route_ack_async(&self, stream_id: u32, seq: SequenceNumber) -> bool {
165 if stream_id == 0 {
166 return false;
167 }
168
169 if let Some(sender) = self.streams.get(&stream_id) {
170 sender.send(StreamMessage::Ack(seq)).await.is_ok()
171 } else {
172 log::warn!(
173 "StreamDemultiplexer: dropping ACK for unknown stream_id={}",
174 stream_id
175 );
176 false
177 }
178 }
179
180 pub async fn route_close_async(&self, stream_id: u32) -> bool {
182 if stream_id == 0 {
183 return false;
184 }
185
186 if let Some(sender) = self.streams.get(&stream_id) {
187 sender.send(StreamMessage::Close).await.is_ok()
188 } else {
189 log::warn!(
190 "StreamDemultiplexer: dropping CLOSE for unknown stream_id={}",
191 stream_id
192 );
193 false
194 }
195 }
196
197 pub fn active_stream_count(&self) -> usize {
199 self.streams.len()
200 }
201
202 pub fn has_stream(&self, stream_id: u32) -> bool {
204 self.streams.contains_key(&stream_id)
205 }
206}
207
208#[cfg(test)]
209mod tests {
210 use super::*;
211
212 #[tokio::test]
213 async fn test_demux_open_and_route() {
214 let (demux, _ctrl_rx) = StreamDemultiplexer::new(16);
215
216 let handle = demux.open_stream(16);
217 let sid = handle.stream_id;
218 let mut rx = handle.rx;
219
220 assert!(demux.has_stream(sid));
221 assert_eq!(demux.active_stream_count(), 1);
222
223 let data = Bytes::from_static(b"hello stream");
225 assert!(demux.route_data(sid, data.clone()));
226
227 let received = rx.recv().await.unwrap();
229 assert_eq!(received, StreamMessage::Data(data));
230 }
231
232 #[tokio::test]
233 async fn test_demux_control_channel() {
234 let (demux, mut ctrl_rx) = StreamDemultiplexer::new(16);
235
236 let data = Bytes::from_static(b"control msg");
237 assert!(demux.route_data(0, data.clone()));
238
239 let received = ctrl_rx.recv().await.unwrap();
240 assert_eq!(received, data);
241 }
242
243 #[tokio::test]
244 async fn test_demux_unknown_stream() {
245 let (demux, _ctrl_rx) = StreamDemultiplexer::new(16);
246
247 let data = Bytes::from_static(b"lost");
249 assert!(!demux.route_data(999, data));
250 }
251
252 #[tokio::test]
253 async fn test_demux_close_stream() {
254 let (demux, _ctrl_rx) = StreamDemultiplexer::new(16);
255
256 let handle = demux.open_stream(16);
257 let sid = handle.stream_id;
258 assert!(demux.has_stream(sid));
259
260 demux.close_stream(sid);
261 assert!(!demux.has_stream(sid));
262 assert_eq!(demux.active_stream_count(), 0);
263 }
264
265 #[tokio::test]
266 async fn test_demux_multiple_streams() {
267 let (demux, _ctrl_rx) = StreamDemultiplexer::new(16);
268
269 let h1 = demux.open_stream(16);
270 let h2 = demux.open_stream(16);
271 let h3 = demux.open_stream(16);
272
273 assert_ne!(h1.stream_id, h2.stream_id);
274 assert_ne!(h2.stream_id, h3.stream_id);
275 assert_eq!(demux.active_stream_count(), 3);
276 }
277}