xref: /webrtc/interceptor/src/lib.rs (revision 0283fb34)
1 #![warn(rust_2018_idioms)]
2 #![allow(dead_code)]
3 
4 use async_trait::async_trait;
5 use error::Result;
6 use std::collections::HashMap;
7 use std::future::Future;
8 use std::pin::Pin;
9 use std::sync::Arc;
10 
11 use stream_info::StreamInfo;
12 
13 pub mod chain;
14 mod error;
15 pub mod mock;
16 pub mod nack;
17 pub mod noop;
18 pub mod registry;
19 pub mod report;
20 pub mod stats;
21 pub mod stream_info;
22 pub mod stream_reader;
23 pub mod twcc;
24 
25 pub use error::Error;
26 
27 /// Attributes are a generic key/value store used by interceptors
28 pub type Attributes = HashMap<usize, usize>;
29 
30 /// InterceptorBuilder provides an interface for constructing interceptors
31 pub trait InterceptorBuilder {
build(&self, id: &str) -> Result<Arc<dyn Interceptor + Send + Sync>>32     fn build(&self, id: &str) -> Result<Arc<dyn Interceptor + Send + Sync>>;
33 }
34 
35 /// Interceptor can be used to add functionality to you PeerConnections by modifying any incoming/outgoing rtp/rtcp
36 /// packets, or sending your own packets as needed.
37 #[async_trait]
38 pub trait Interceptor {
39     /// bind_rtcp_reader lets you modify any incoming RTCP packets. It is called once per sender/receiver, however this might
40     /// change in the future. The returned method will be called once per packet batch.
bind_rtcp_reader( &self, reader: Arc<dyn RTCPReader + Send + Sync>, ) -> Arc<dyn RTCPReader + Send + Sync>41     async fn bind_rtcp_reader(
42         &self,
43         reader: Arc<dyn RTCPReader + Send + Sync>,
44     ) -> Arc<dyn RTCPReader + Send + Sync>;
45 
46     /// bind_rtcp_writer lets you modify any outgoing RTCP packets. It is called once per PeerConnection. The returned method
47     /// will be called once per packet batch.
bind_rtcp_writer( &self, writer: Arc<dyn RTCPWriter + Send + Sync>, ) -> Arc<dyn RTCPWriter + Send + Sync>48     async fn bind_rtcp_writer(
49         &self,
50         writer: Arc<dyn RTCPWriter + Send + Sync>,
51     ) -> Arc<dyn RTCPWriter + Send + Sync>;
52 
53     /// bind_local_stream lets you modify any outgoing RTP packets. It is called once for per LocalStream. The returned method
54     /// will be called once per rtp packet.
bind_local_stream( &self, info: &StreamInfo, writer: Arc<dyn RTPWriter + Send + Sync>, ) -> Arc<dyn RTPWriter + Send + Sync>55     async fn bind_local_stream(
56         &self,
57         info: &StreamInfo,
58         writer: Arc<dyn RTPWriter + Send + Sync>,
59     ) -> Arc<dyn RTPWriter + Send + Sync>;
60 
61     /// unbind_local_stream is called when the Stream is removed. It can be used to clean up any data related to that track.
unbind_local_stream(&self, info: &StreamInfo)62     async fn unbind_local_stream(&self, info: &StreamInfo);
63 
64     /// bind_remote_stream lets you modify any incoming RTP packets. It is called once for per RemoteStream. The returned method
65     /// will be called once per rtp packet.
bind_remote_stream( &self, info: &StreamInfo, reader: Arc<dyn RTPReader + Send + Sync>, ) -> Arc<dyn RTPReader + Send + Sync>66     async fn bind_remote_stream(
67         &self,
68         info: &StreamInfo,
69         reader: Arc<dyn RTPReader + Send + Sync>,
70     ) -> Arc<dyn RTPReader + Send + Sync>;
71 
72     /// unbind_remote_stream is called when the Stream is removed. It can be used to clean up any data related to that track.
unbind_remote_stream(&self, info: &StreamInfo)73     async fn unbind_remote_stream(&self, info: &StreamInfo);
74 
close(&self) -> Result<()>75     async fn close(&self) -> Result<()>;
76 }
77 
78 /// RTPWriter is used by Interceptor.bind_local_stream.
79 #[async_trait]
80 pub trait RTPWriter {
81     /// write a rtp packet
write(&self, pkt: &rtp::packet::Packet, attributes: &Attributes) -> Result<usize>82     async fn write(&self, pkt: &rtp::packet::Packet, attributes: &Attributes) -> Result<usize>;
83 }
84 
85 pub type RTPWriterBoxFn = Box<
86     dyn (Fn(
87             &rtp::packet::Packet,
88             &Attributes,
89         ) -> Pin<Box<dyn Future<Output = Result<usize>> + Send + Sync>>)
90         + Send
91         + Sync,
92 >;
93 pub struct RTPWriterFn(pub RTPWriterBoxFn);
94 
95 #[async_trait]
96 impl RTPWriter for RTPWriterFn {
97     /// write a rtp packet
write(&self, pkt: &rtp::packet::Packet, attributes: &Attributes) -> Result<usize>98     async fn write(&self, pkt: &rtp::packet::Packet, attributes: &Attributes) -> Result<usize> {
99         self.0(pkt, attributes).await
100     }
101 }
102 
103 /// RTPReader is used by Interceptor.bind_remote_stream.
104 #[async_trait]
105 pub trait RTPReader {
106     /// read a rtp packet
read(&self, buf: &mut [u8], attributes: &Attributes) -> Result<(usize, Attributes)>107     async fn read(&self, buf: &mut [u8], attributes: &Attributes) -> Result<(usize, Attributes)>;
108 }
109 
110 pub type RTPReaderBoxFn = Box<
111     dyn (Fn(
112             &mut [u8],
113             &Attributes,
114         ) -> Pin<Box<dyn Future<Output = Result<(usize, Attributes)>> + Send + Sync>>)
115         + Send
116         + Sync,
117 >;
118 pub struct RTPReaderFn(pub RTPReaderBoxFn);
119 
120 #[async_trait]
121 impl RTPReader for RTPReaderFn {
122     /// read a rtp packet
read(&self, buf: &mut [u8], attributes: &Attributes) -> Result<(usize, Attributes)>123     async fn read(&self, buf: &mut [u8], attributes: &Attributes) -> Result<(usize, Attributes)> {
124         self.0(buf, attributes).await
125     }
126 }
127 
128 /// RTCPWriter is used by Interceptor.bind_rtcpwriter.
129 #[async_trait]
130 pub trait RTCPWriter {
131     /// write a batch of rtcp packets
write( &self, pkts: &[Box<dyn rtcp::packet::Packet + Send + Sync>], attributes: &Attributes, ) -> Result<usize>132     async fn write(
133         &self,
134         pkts: &[Box<dyn rtcp::packet::Packet + Send + Sync>],
135         attributes: &Attributes,
136     ) -> Result<usize>;
137 }
138 
139 pub type RTCPWriterBoxFn = Box<
140     dyn (Fn(
141             &[Box<dyn rtcp::packet::Packet + Send + Sync>],
142             &Attributes,
143         ) -> Pin<Box<dyn Future<Output = Result<usize>> + Send + Sync>>)
144         + Send
145         + Sync,
146 >;
147 
148 pub struct RTCPWriterFn(pub RTCPWriterBoxFn);
149 
150 #[async_trait]
151 impl RTCPWriter for RTCPWriterFn {
152     /// write a batch of rtcp packets
write( &self, pkts: &[Box<dyn rtcp::packet::Packet + Send + Sync>], attributes: &Attributes, ) -> Result<usize>153     async fn write(
154         &self,
155         pkts: &[Box<dyn rtcp::packet::Packet + Send + Sync>],
156         attributes: &Attributes,
157     ) -> Result<usize> {
158         self.0(pkts, attributes).await
159     }
160 }
161 
162 /// RTCPReader is used by Interceptor.bind_rtcpreader.
163 #[async_trait]
164 pub trait RTCPReader {
165     /// read a batch of rtcp packets
read(&self, buf: &mut [u8], attributes: &Attributes) -> Result<(usize, Attributes)>166     async fn read(&self, buf: &mut [u8], attributes: &Attributes) -> Result<(usize, Attributes)>;
167 }
168 
169 pub type RTCPReaderBoxFn = Box<
170     dyn (Fn(
171             &mut [u8],
172             &Attributes,
173         ) -> Pin<Box<dyn Future<Output = Result<(usize, Attributes)>> + Send + Sync>>)
174         + Send
175         + Sync,
176 >;
177 
178 pub struct RTCPReaderFn(pub RTCPReaderBoxFn);
179 
180 #[async_trait]
181 impl RTCPReader for RTCPReaderFn {
182     /// read a batch of rtcp packets
read(&self, buf: &mut [u8], attributes: &Attributes) -> Result<(usize, Attributes)>183     async fn read(&self, buf: &mut [u8], attributes: &Attributes) -> Result<(usize, Attributes)> {
184         self.0(buf, attributes).await
185     }
186 }
187 
188 /// Helper for the tests.
189 #[cfg(test)]
190 mod test {
191     use std::future::Future;
192     use std::time::Duration;
193 
timeout_or_fail<T>(duration: Duration, future: T) -> T::Output where T: Future,194     pub async fn timeout_or_fail<T>(duration: Duration, future: T) -> T::Output
195     where
196         T: Future,
197     {
198         tokio::time::timeout(duration, future)
199             .await
200             .expect("should not time out")
201     }
202 }
203