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