pub(super) struct PacketLoopState {
pub(super) users: KeyedSlotStore<TransportSessionKey, RtcSessionState, SessionSlot>,
pub(super) routes: RouteTable,
pub(super) session_media: BTreeMap<TransportSessionKey, SessionMediaLookup>,
pub(super) rid_readiness_scratch: RidReadinessScratch,
pub(super) incoming_bitrate_counters: BTreeMap<TransportMediaId, Arc<MediaBitrateCounter>>,
pub(super) remote_addr_demux: RemoteAddrDemux,
pub(super) mid_registry: KeyedSlotStore<TransportMediaId, RegisteredMediaHandle, MediaSlot>,
pub(super) dirty_sessions: Vec<SlotHandle<SessionSlot>>,
pub(super) session_timeouts: BTreeMap<SlotHandle<SessionSlot>, Instant>,
pub(super) timeout_queue: BinaryHeap<Reverse<(Instant, SlotHandle<SessionSlot>)>>,
pub(super) next_media_id: u64,
}Expand description
authoritative mutable state for one RTC packet-loop worker
the packet loop owns this value without a mutex
control commands, UDP ingress, str0m polling and relay fanout all pass
through one mutable borrow so the media indexes can be updated together
command-facing APIs keep stable transport ids while hot queues use generation-checked handles
Fields§
§users: KeyedSlotStore<TransportSessionKey, RtcSessionState, SessionSlot>live worker-local RTC sessions
routes: RouteTablesource-scoped packet routing, relay and recovery state
session_media: BTreeMap<TransportSessionKey, SessionMediaLookup>session-scoped media lookup vectors for packet source resolution
rid_readiness_scratch: RidReadinessScratchreusable selected-RID readiness scratch vectors
incoming_bitrate_counters: BTreeMap<TransportMediaId, Arc<MediaBitrateCounter>>packet-loop write handles for incoming media bitrate accounting
remote_addr_demux: RemoteAddrDemuxworker-local UDP ingress demux hints
mid_registry: KeyedSlotStore<TransportMediaId, RegisteredMediaHandle, MediaSlot>primary media handle table keyed by stable transport media id
dirty_sessions: Vec<SlotHandle<SessionSlot>>sessions that must be polled before the worker waits again
session_timeouts: BTreeMap<SlotHandle<SessionSlot>, Instant>latest str0m timeout deadline per live session handle
timeout_queue: BinaryHeap<Reverse<(Instant, SlotHandle<SessionSlot>)>>timeout heap that may contain stale entries invalidated by session_timeouts
next_media_id: u64next worker-local media id from the disjoint range assigned at boot
Implementations§
Source§impl PacketLoopState
impl PacketLoopState
pub(super) fn register_incoming_bitrate_counter( &mut self, transport_media_id: TransportMediaId, counter: Arc<MediaBitrateCounter>, )
pub(super) fn remove_incoming_bitrate_counter( &mut self, transport_media_id: TransportMediaId, )
pub(super) fn record_incoming_bitrate( &self, transport_media_id: TransportMediaId, now: Instant, payload_bytes: usize, ) -> Option<IncomingBitrateObservation>
Source§impl PacketLoopState
impl PacketLoopState
pub(super) fn register_media_handle( &mut self, handle: RegisteredMediaHandle, ) -> TransportMediaId
pub(super) fn resolve_mid( &self, transport_media_id: TransportMediaId, ) -> Option<Mid>
pub(super) fn media_handle( &self, transport_media_id: TransportMediaId, ) -> Option<&RegisteredMediaHandle>
pub(super) fn producer_media_snapshot( &self, session_key: &TransportSessionKey, ) -> Vec<(TransportMediaId, Mid)>
pub(super) fn consumer_media_snapshot( &self, session_key: &TransportSessionKey, ) -> Vec<(TransportMediaId, Mid, TransportMediaId)>
pub(super) fn session_has_other_media_mid( &self, session_key: &TransportSessionKey, mid: Mid, excluded_transport_media_id: TransportMediaId, ) -> bool
Sourcepub(super) fn remove_media_handle(
&mut self,
transport_media_id: TransportMediaId,
) -> Option<RegisteredMediaHandle>
pub(super) fn remove_media_handle( &mut self, transport_media_id: TransportMediaId, ) -> Option<RegisteredMediaHandle>
remove one media handle and every dependent reverse index owned by it
producer removal clears source packet policy, incoming bitrate counters, decoder-refresh metadata, live RID state and SSRC lookups consumer removal clears only the consumer MID lookup because route and local rewrite teardown are owned by media lifecycle code
pub(super) fn session_has_registered_media( &self, session_key: &TransportSessionKey, ) -> bool
fn prune_empty_session_media(&mut self, session_key: &TransportSessionKey)
pub(super) fn take_expired_speaker_rooms( &mut self, now: Instant, ) -> BTreeSet<RoomInstanceId>
pub(super) fn src_media_for_mid( &self, src_key: &TransportSessionKey, source_mid: Mid, ) -> Option<TransportMediaId>
pub(super) fn src_media_for_ssrc( &self, src_key: &TransportSessionKey, source_ssrc: Ssrc, ) -> Option<TransportMediaId>
pub(super) fn source_rid_for_ssrc( &self, src_key: &TransportSessionKey, source_ssrc: Ssrc, ) -> Option<Rid>
Sourcepub(super) fn learn_producer_ssrc_binding(
&mut self,
session_key: &TransportSessionKey,
transport_media_id: TransportMediaId,
ssrc: Ssrc,
rid: Option<Rid>,
) -> bool
pub(super) fn learn_producer_ssrc_binding( &mut self, session_key: &TransportSessionKey, transport_media_id: TransportMediaId, ssrc: Ssrc, rid: Option<Rid>, ) -> bool
learn the SSRC chosen by a RID-only publisher from RTP header metadata
chrome can answer simulcast offers with RIDs but no SSRC attributes str0m can still demux the first packets through MID/RID header extensions the adapter must persist that discovery here because later packets may only carry the SSRC without this late binding, packet routing, RID gate metadata and bitrate accounting lose the producer as soon as the browser stops repeating mid/rid extensions
the binding is accepted only for the already resolved producer media id a same-session SSRC collision with a different media id is treated as a suspicious transport fact and ignored rather than stealing ownership
pub(super) fn learn_producer_ssrc_from_pkt( &mut self, source: &ForwardedPacketSource, transport_media_id: TransportMediaId, ssrc: Ssrc, rid: Option<Rid>, ) -> bool
fn learn_producer_ssrc_from_handle( &mut self, session_handle: SlotHandle<SessionSlot>, transport_media_id: TransportMediaId, ssrc: Ssrc, rid: Option<Rid>, ) -> bool
Sourcepub(super) fn active_consumer_kf_target(
&self,
consumer_key: &TransportSessionKey,
consumer_mid: Mid,
feedback_rid: Option<Rid>,
) -> Option<ConsumerKeyframeTarget>
pub(super) fn active_consumer_kf_target( &self, consumer_key: &TransportSessionKey, consumer_mid: Mid, feedback_rid: Option<Rid>, ) -> Option<ConsumerKeyframeTarget>
resolve consumer RTCP feedback to the currently active producer target
this is the packet-loop feedback path
missing indexes, removed routes and inactive routes are treated as stale
feedback because those can race with teardown after str0m emits a
request
selected destination gates override the feedback RID so RID-less browser PLI stays scoped to the routed simulcast layer
Sourcepub(super) fn set_consumer_dst_idx(
&mut self,
consumer_key: &TransportSessionKey,
consumer_mid: Mid,
consumer_media: TransportMediaId,
src_media: TransportMediaId,
dst_idx: Option<usize>,
)
pub(super) fn set_consumer_dst_idx( &mut self, consumer_key: &TransportSessionKey, consumer_mid: Mid, consumer_media: TransportMediaId, src_media: TransportMediaId, dst_idx: Option<usize>, )
updates the cached destination slot for one consumer MID binding
callers pass both sides of the route identity so a late repair from an old route cannot relink a MID to a different source
pub(super) fn consumer_dst_idx( &self, consumer_key: &TransportSessionKey, consumer_mid: Mid, consumer_media: TransportMediaId, src_media: TransportMediaId, ) -> Option<usize>
fn source_room_instance_id( &self, src_media: TransportMediaId, ) -> Option<RoomInstanceId>
pub(super) fn remove_session_media_handles( &mut self, session_key: &TransportSessionKey, ) -> Vec<(TransportMediaId, RegisteredMediaHandle)>
pub(super) fn refresh_producer_ssrcs( &mut self, session_key: &TransportSessionKey, mid: Mid, parameters: &MediaStream, )
Sourcepub(super) fn apply_producer_nack_policy(
&mut self,
session_key: &TransportSessionKey,
transport_media_id: TransportMediaId,
)
pub(super) fn apply_producer_nack_policy( &mut self, session_key: &TransportSessionKey, transport_media_id: TransportMediaId, )
Reapplies NACK suppression because SDP answers can recreate StreamRx.
pub(super) fn clear_producer_ssrcs_for_mid( &mut self, session_key: &TransportSessionKey, mid: Mid, )
fn clear_producer_ssrcs( &mut self, session_key: &TransportSessionKey, transport_media_id: TransportMediaId, )
Source§impl PacketLoopState
impl PacketLoopState
Sourcepub(super) fn mark_session_dirty(&mut self, session_key: &TransportSessionKey)
pub(super) fn mark_session_dirty(&mut self, session_key: &TransportSessionKey)
schedule a live session for the next packet-loop poll
missing sessions are ignored because teardown may race with already
queued wakeups
each live session can appear at most once until
Self::collect_ready_sessions clears its dirty bit
Sourcepub(super) fn has_dirty_sessions(&self) -> bool
pub(super) fn has_dirty_sessions(&self) -> bool
report whether the worker has session work that is due immediately
Sourcepub(super) fn collect_ready_sessions(
&mut self,
now: Instant,
ready_sessions: &mut Vec<SlotHandle<SessionSlot>>,
)
pub(super) fn collect_ready_sessions( &mut self, now: Instant, ready_sessions: &mut Vec<SlotHandle<SessionSlot>>, )
drain dirty sessions and due str0m timeouts into caller-owned scratch
this method is the session scheduler for the packet loop
it clears dirty bits for live sessions, skips removed sessions and lazily
discards timeout heap entries whose deadline no longer matches
Self::session_timeouts
stale handles are skipped before replacement sessions can be polled
the output is sorted and deduplicated so a session that is both dirty and timed out is polled once in the current turn
Sourcepub(super) fn update_session_timeout_by_handle(
&mut self,
session_handle: SlotHandle<SessionSlot>,
next_timeout: Option<Instant>,
)
pub(super) fn update_session_timeout_by_handle( &mut self, session_handle: SlotHandle<SessionSlot>, next_timeout: Option<Instant>, )
replace the next str0m timeout deadline by worker-local handle
stale handles are ignored because the session has already left this worker or the slot now belongs to a later generation
Sourcepub(super) fn next_timeout_deadline(&mut self) -> Option<Instant>
pub(super) fn next_timeout_deadline(&mut self) -> Option<Instant>
return the earliest live str0m timeout deadline
stale heap entries are removed while searching this includes entries for handles whose slot generation no longer names a live session callers may invoke this before awaiting because it does not borrow any session state after returning
Sourcepub(super) fn clear_session_schedule(
&mut self,
session_key: &TransportSessionKey,
)
pub(super) fn clear_session_schedule( &mut self, session_key: &TransportSessionKey, )
remove all explicit scheduler state for a session being torn down
stale timeout heap entries can remain because the deadline map no longer validates them stale handles are also rejected by generation checks before polling
Trait Implementations§
Source§impl Default for PacketLoopState
impl Default for PacketLoopState
Source§fn default() -> PacketLoopState
fn default() -> PacketLoopState
Auto Trait Implementations§
impl Freeze for PacketLoopState
impl !RefUnwindSafe for PacketLoopState
impl Send for PacketLoopState
impl Sync for PacketLoopState
impl Unpin for PacketLoopState
impl UnsafeUnpin for PacketLoopState
impl UnwindSafe for PacketLoopState
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more