1use crate::Interceptor;
4use crate::{Packet, StreamInfo, TaggedPacket};
5use sansio::Protocol;
6use shared::error::Error;
7use std::collections::VecDeque;
8use std::time::Instant;
9
10#[derive(Default)]
50pub struct NoopInterceptor {
51 rtcp_readable: bool,
52 read_queue: VecDeque<TaggedPacket>,
53 write_queue: VecDeque<TaggedPacket>,
54}
55
56impl NoopInterceptor {
57 pub fn new(rtcp_readable: bool) -> Self {
63 Self {
64 rtcp_readable,
65 ..Default::default()
66 }
67 }
68}
69
70impl Protocol<TaggedPacket, TaggedPacket, ()> for NoopInterceptor {
71 type Rout = TaggedPacket;
72 type Wout = TaggedPacket;
73 type Eout = ();
74 type Error = Error;
75 type Time = Instant;
76
77 fn handle_read(&mut self, msg: TaggedPacket) -> Result<(), Self::Error> {
78 let keep = match msg.message.packet {
79 Packet::Rtp(_) => true,
80 Packet::Rtcp(_) => self.rtcp_readable,
82 };
83 if keep {
84 self.read_queue.push_back(msg);
85 }
86 Ok(())
87 }
88
89 fn poll_read(&mut self) -> Option<Self::Rout> {
90 self.read_queue.pop_front()
91 }
92
93 fn handle_write(&mut self, msg: TaggedPacket) -> Result<(), Self::Error> {
94 self.write_queue.push_back(msg);
95 Ok(())
96 }
97
98 fn poll_write(&mut self) -> Option<Self::Wout> {
99 self.write_queue.pop_front()
100 }
101}
102
103impl Interceptor for NoopInterceptor {
104 fn bind_local_stream(&mut self, _info: &StreamInfo) {}
105 fn unbind_local_stream(&mut self, _info: &StreamInfo) {}
106 fn bind_remote_stream(&mut self, _info: &StreamInfo) {}
107 fn unbind_remote_stream(&mut self, _info: &StreamInfo) {}
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113 use crate::{AttributedPacket, Registry, StreamInfo};
114 use sansio::Protocol;
115 use shared::TransportContext;
116 use shared::error::Error;
117 use std::collections::VecDeque;
118 use std::time::Instant;
119
120 fn packet(message: Packet) -> TaggedPacket {
121 TaggedPacket {
122 now: Instant::now(),
123 transport: TransportContext::default(),
124 message: AttributedPacket::new(message),
125 }
126 }
127
128 #[test]
129 fn inbound_rtcp_does_not_reach_the_application() {
130 let mut chain = Registry::new().build();
131
132 chain.handle_read(packet(Packet::Rtcp(vec![]))).unwrap();
133 assert!(chain.poll_read().is_none());
134 }
135
136 #[test]
137 fn inbound_rtp_passes_through() {
138 let mut chain = Registry::new().build();
139
140 chain
141 .handle_read(packet(Packet::Rtp(rtp::Packet::default())))
142 .unwrap();
143 assert!(chain.poll_read().is_some());
144 }
145
146 #[test]
148 fn outbound_rtcp_is_not_affected() {
149 let mut chain = Registry::new().build();
150
151 chain.handle_write(packet(Packet::Rtcp(vec![]))).unwrap();
152 assert!(chain.poll_write().is_some());
153 }
154
155 #[test]
158 fn stages_before_it_still_see_inbound_rtcp() {
159 #[derive(Default)]
160 struct Counter {
161 seen: std::sync::Arc<std::sync::atomic::AtomicUsize>,
162 read_queue: VecDeque<TaggedPacket>,
163 write_queue: VecDeque<TaggedPacket>,
164 }
165 impl Protocol<TaggedPacket, TaggedPacket, ()> for Counter {
166 type Rout = TaggedPacket;
167 type Wout = TaggedPacket;
168 type Eout = ();
169 type Error = Error;
170 type Time = Instant;
171
172 fn handle_read(&mut self, msg: TaggedPacket) -> Result<(), Self::Error> {
173 if matches!(msg.message.packet, Packet::Rtcp(_)) {
174 self.seen.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
175 }
176 self.read_queue.push_back(msg);
177 Ok(())
178 }
179
180 fn poll_read(&mut self) -> Option<Self::Rout> {
181 self.read_queue.pop_front()
182 }
183
184 fn handle_write(&mut self, msg: TaggedPacket) -> Result<(), Self::Error> {
185 self.write_queue.push_back(msg);
186 Ok(())
187 }
188
189 fn poll_write(&mut self) -> Option<Self::Wout> {
190 self.write_queue.pop_front()
191 }
192
193 fn handle_timeout(&mut self, _now: Instant) -> Result<(), Self::Error> {
194 Ok(())
195 }
196
197 fn poll_timeout(&mut self) -> Option<Self::Time> {
198 None
199 }
200 }
201 impl Interceptor for Counter {
202 fn bind_local_stream(&mut self, _info: &StreamInfo) {}
203 fn unbind_local_stream(&mut self, _info: &StreamInfo) {}
204 fn bind_remote_stream(&mut self, _info: &StreamInfo) {}
205 fn unbind_remote_stream(&mut self, _info: &StreamInfo) {}
206 }
207 let counter = Counter::default();
208 let seen = counter.seen.clone();
209 let mut chain = Registry::new().with(counter).build();
210
211 chain.handle_read(packet(Packet::Rtcp(vec![]))).unwrap();
212
213 assert_eq!(1, seen.load(std::sync::atomic::Ordering::Relaxed));
214 assert!(chain.poll_read().is_none(), "but it stops at the terminus");
215 }
216}