#[non_exhaustive]pub enum Attribute {
RecoveredByFec,
Retransmission,
DeliverToApplication,
TargetBitrateChanged {
bits_per_second: f64,
},
Custom(Arc<dyn Any + Send + Sync>),
}Expand description
A fact about a packet, attached by one interceptor and readable by the rest.
§Why it rides with the packet
Because it has to survive the journey. An interceptor that queues a packet and emits it later puts it back on the belt behind itself, where every interceptor ahead sees it again — so what was learned about that packet has to travel with it or be worked out twice. A side channel cannot manage that: it has no way to say which packet it refers to once the packet has been held, reordered or duplicated.
With Ein/Eout left as (), this is the only way information crosses interceptors.
§When there is no packet to ride
A connection-level fact — a bandwidth estimate, a keyframe request from the application — often
needs to travel when no media is going that way. The carrier for those is an RTCP packet with an
empty payload, Packet::Rtcp(vec![]), which is inert to every interceptor that
does not look for attributes and is dropped at the crate boundary once its attributes are read.
That makes an empty compound RTCP packet reserved: see Packet::Rtcp.
§Cost
AttributedPacket holds a Vec, which does not allocate while empty — and most packets carry
nothing. Lookup is a linear scan of a handful of words, cheaper than hashing.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
RecoveredByFec
Rebuilt by FEC rather than received: these bytes never arrived on the wire.
Not needed by the NACK generator, despite the obvious guess. The FEC decoder is wire-ward of
it, so a rebuilt packet reaches the generator on the read walk like any other arrival and
fills the gap in its receive log — there is nothing left to ask for, by ordering rather than
by inspection. tests/flexfec_receive.rs pins that.
It matters to anything that must distinguish arrived from present: an arrival recorder telling the remote a packet turned up, when in fact it was lost and rebuilt here, overstates what the path delivered.
Retransmission
A retransmission answering a NACK, not a first transmission.
Still new bytes on the wire, which is why a send history has to count it — counting it as an original tells a bandwidth estimator the path is carrying less than it is.
DeliverToApplication
Inbound RTCP an interceptor has decided the application should see.
NoopInterceptor ends the inbound RTCP path unless the packet
carries this, which makes forwarding a per-packet judgement by whichever interceptor is
qualified to make it, rather than a chain-wide setting. An SFU relaying keyframe requests
marks those and leaves the receiver reports its own chain is acting on alone; a chain-wide
switch could only offer all of it or none.
Usually attached by an interceptor the application supplies, since the application is what
knows which packets it can act on. Attaching it is the only way past the terminus:
re-emitting a copy does not work, because what an interceptor emits from poll_read rejoins
the belt behind itself, where the terminus is still ahead of it.
TargetBitrateChanged
The congestion controller’s estimate, in bits per second.
Rides outbound so the pacer reads it on the way past. A bitrate is connection state rather than a property of the packet carrying it — it travels this way because with no event channel there is nowhere else for it to go.
Custom(Arc<dyn Any + Send + Sync>)
Anything an application defines, so this enum is never a bottleneck on it.
Arc rather than Box so an attributed packet stays cheap to clone — the NACK responder
clones into its send buffer and the FEC encoder into its block, and neither should deep-copy
an application’s payload. Reached by type: AttributedPacket::custom.