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