pub struct CongestionControlInterceptor<E: BandwidthEstimator> { /* private fields */ }Expand description
Records every departing packet, resolves the remote’s feedback against it, and drives a
BandwidthEstimator.
§Where this belongs in the chain
Wire-most. It is the only position that sees every byte that leaves: nothing exits the chain except through the interceptors ahead of it in the walk, so a retransmission emitted by the NACK responder and a repair packet emitted by the FEC encoder both arrive here, already paced and already numbered. An estimator reading a history that omits them sees fewer bytes than are on the wire, infers headroom, and raises the target during loss — a positive feedback loop that is hard to spot, because the estimator’s own accounting stays internally consistent throughout.
It also has to be below the pacer, so packet.now is the instant the packet was released
rather than the instant the application enqueued it. A pacer can hold a packet for tens of
milliseconds; counting that as network delay is exactly the error that makes a delay-based
estimate collapse.
§How the estimate gets out
On the read leg, attached to the feedback packet that produced it, as
Attribute::TargetBitrateChanged. The pacer sits application-ward of this interceptor, so it
sees that packet after this one does and reads the attribute on its way past. That is the only
leg the estimate can cross on: on the write leg this interceptor is last, and anything it
attached would already have gone by everything that cares.
Implementations§
Trait Implementations§
Source§impl<E: BandwidthEstimator> Interceptor for CongestionControlInterceptor<E>
impl<E: BandwidthEstimator> Interceptor for CongestionControlInterceptor<E>
Source§fn bind_local_stream(&mut self, info: &StreamInfo)
fn bind_local_stream(&mut self, info: &StreamInfo)
Source§fn unbind_local_stream(&mut self, info: &StreamInfo)
fn unbind_local_stream(&mut self, info: &StreamInfo)
Source§fn bind_remote_stream(&mut self, _info: &StreamInfo)
fn bind_remote_stream(&mut self, _info: &StreamInfo)
Source§fn unbind_remote_stream(&mut self, _info: &StreamInfo)
fn unbind_remote_stream(&mut self, _info: &StreamInfo)
Source§impl<E: BandwidthEstimator> Protocol<TransportMessage<AttributedPacket>, TransportMessage<AttributedPacket>, ()> for CongestionControlInterceptor<E>
impl<E: BandwidthEstimator> Protocol<TransportMessage<AttributedPacket>, TransportMessage<AttributedPacket>, ()> for CongestionControlInterceptor<E>
Source§fn poll_timeout(&mut self) -> Option<Self::Time>
fn poll_timeout(&mut self) -> Option<Self::Time>
Whatever the estimator wants, and None when it wants nothing.
This interceptor has no timer of its own: pruning is bounded work that can ride any wake-up, and asking for one on its own account would wake the whole chain on an idle connection.