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.
| To | Do |
|---|---|
| pass a packet through | queue it in handle_*, return it from poll_* |
| transform it | queue the modified packet |
| drop or delay it | queue nothing; a delayed one is queued later, from handle_timeout |
| generate one | queue it whenever you like; it joins the walk from poll_* |
| act on a timer | handle_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§
Sourcefn bind_local_stream(&mut self, info: &StreamInfo)
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.
Sourcefn unbind_local_stream(&mut self, info: &StreamInfo)
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.
Sourcefn bind_remote_stream(&mut self, info: &StreamInfo)
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.
Sourcefn unbind_remote_stream(&mut self, info: &StreamInfo)
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.
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.