Skip to main content

Interceptor

Trait Interceptor 

Source
pub trait Interceptor:
    Protocol<TaggedPacket, TaggedPacket, (), Rout = TaggedPacket, Wout = TaggedPacket, Eout = (), Time = Instant, Error = Error>
    + Send
    + Sync {
    // Required methods
    fn bind_local_stream(&mut self, info: &StreamInfo);
    fn unbind_local_stream(&mut self, info: &StreamInfo);
    fn bind_remote_stream(&mut self, info: &StreamInfo);
    fn unbind_remote_stream(&mut self, info: &StreamInfo);
}
Expand description

One interceptor of packet processing.

An interceptor is a sansio::Protocol like everything else in this stack: packets arrive through handle_read/handle_write and leave through poll_read/poll_write. What is different is that nothing is wired to anything — an interceptor does not know what is on either side of it. Registry builds a flat list and the chain it returns moves packets along it.

§The contract

What handle_* takes in, poll_* gives back. The chain hands you a packet, then asks what you have ready; whatever you return is what the next interceptor receives. So an interceptor that passes packets through still needs a queue — take the packet in handle_read, hand it back from poll_read.

ToDo
pass a packet throughqueue it in handle_*, return it from poll_*
transform itqueue the modified packet
drop or delay itqueue nothing; a delayed one is queued later, from handle_timeout
generate onequeue it whenever you like; it joins the walk from poll_*
act on a timerhandle_timeout, and report the deadline from poll_timeout

§What you emit continues

A packet returned from poll_write is handed to the next interceptor in the walk and passes through every one still ahead of it. Nothing can bypass an interceptor by being generated past it — which is the class of bug the previous, nested design allowed, and why a retransmission used to escape the pacer, the transport-wide numbering and the send history.

The same is true in reverse: it also means nothing reaches the wire or the application except by passing through the interceptors that follow it. An interceptor that keeps a packet to itself keeps it from everything downstream, deliberately.

§Direction

Read walks the list forwards, write walks it in reverse, so one ordering serves both: the first interceptor is closest to the network in both directions.

Required Methods§

Source

fn bind_local_stream(&mut self, info: &StreamInfo)

bind_local_stream lets you modify any outgoing RTP packets. It is called once for per LocalStream. The returned method will be called once per rtp packet.

Source

fn unbind_local_stream(&mut self, info: &StreamInfo)

unbind_local_stream is called when the Stream is removed. It can be used to clean up any data related to that track.

Source

fn bind_remote_stream(&mut self, info: &StreamInfo)

bind_remote_stream lets you modify any incoming RTP packets. It is called once for per RemoteStream. The returned method will be called once per rtp packet.

Source

fn unbind_remote_stream(&mut self, info: &StreamInfo)

unbind_remote_stream is called when the Stream is removed. It can be used to clean up any data related to that track.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

Source§

impl<P: Interceptor + ?Sized> Interceptor for &mut P

Blanket implementation for mutable references.

This lets a borrowed chain satisfy an Interceptor bound, so a function taking I: Interceptor by value can be called with &mut chain and leave ownership with the caller. It mirrors sansio::Protocol’s own &mut P implementation, and the same idiom in std (impl Read for &mut R, impl Iterator for &mut I).

This is only expressible because Interceptor does not require 'static: &'a mut P outlives only 'a. Registry::with is where the 'static bound is asked for instead — locally, by the one method that has to box what it is given.

Source§

impl<P: Interceptor + ?Sized> Interceptor for Box<P>

Implementors§