|
wired
libc-free QUIC/HTTP3 SDK in C for x86_64-linux
|
One in-flight relayed publisher stream: which publisher-side stream (pub_stream_id) this relay follows, and – per subscriber slot index in the owning track's subs[] – the subscriber-side uni stream its bytes are forwarded on. More...
#include <moqtrun.h>
Data Fields | |
| int | in_use |
| 1 while this relay follows a publisher stream. | |
| u64 | pub_stream_id |
| The publisher-side stream this relay follows (its key). | |
| u8 | hdr [WIRED_MOQTRUN_RELAY_HDR_MAX] |
| The stream's opening SUBGROUP_HEADER, as received. | |
| usz | hdr_len |
| Bytes of hdr in use. | |
| u8 | default_pub_prio |
| The track's DEFAULT_PUBLISHER_PRIORITY when this relay started: the Publisher Priority of a header that omits it (12.4). | |
| i32 | frag_idx |
| Index of the hub's frag_pool buffer holding the fragment, -1 when none is held (frag_len 0). | |
| usz | frag_len |
| Bytes of the held fragment; 0 when none is held. | |
| u64 | sub_stream_id [WIRED_MOQTRUN_MAX_SUBS] |
| Per sub slot i of the track's subs[]: the subscriber-side uni stream this relay forwards on, valid while sub_stream_set[i]. | |
| int | sub_stream_set [WIRED_MOQTRUN_MAX_SUBS] |
| Per sub slot i: 1 once sub_stream_id[i] is open. | |
| u8 | sub_busy_streak [WIRED_MOQTRUN_MAX_SUBS] |
| Consecutive rounds sub slot i's stream_send was refused (saturates at 255): reaching WIRED_MOQTRUN_RESET_AFTER_BUSY sheds the stream (io.stream_reset) so the next round re-opens fresh at the newest frame instead of replaying the stale backlog. | |
| i32 | rel_idx |
| Index into the hub's rel_pool while this relay runs reliably (its bytes ride a moqtrel ring instead of the drop-on-refusal path); -1 is the default: the lossy relay above, untouched. | |
| moqdata_objseq | seq |
| Object-ID chaining state after the last whole Object relayed, and the stream's Group ID: lets header-less later deliveries resolve each Object's Location (11.4.2) for the track's Largest Object. | |
| u64 | group_id |
| The stream's Group ID, from its SUBGROUP_HEADER. | |
| u64 | frag_ms |
| Clock (wired_moqt_tick) at which the held fragment's first byte arrived: the age of the torn Object it starts (draft 8). | |
| u32 | sub_expired |
| Bit i: sub slot i's stream was reset for OBJECT_DELIVERY_TIMEOUT and is not reopened for this Subgroup (draft 8). | |
| u32 | sub_reframe |
| Bit i: sub slot i's stream was late-opened header-only; the first Object it is sent gets its Object ID Delta rewritten to the absolute Object ID (the first Object of a stream, draft-22 11.3.1). | |
| u64 | subgroup_id |
| The stream's Subgroup ID (a mode-0b01 header's first Object ID, spelled out in a late-opened stream's header): SUBGROUP_FILTER's input. | |
| u8 | pub_prio |
| The stream's Publisher Priority (the header's, else the track's default): PRIORITY_FILTER's input. | |
One in-flight relayed publisher stream: which publisher-side stream (pub_stream_id) this relay follows, and – per subscriber slot index in the owning track's subs[] – the subscriber-side uni stream its bytes are forwarded on.
Keyed by the PUBLISHER's stream id, never per-track or per-sub alone: several publisher streams can be in flight at once on one track (a real browser delivers a chat message's bytes and its FIN as two separate calls, so message N's still-open relay overlaps message N+1's data – a single per-track/per-sub binding made N+1 append onto N's subscriber stream and N's late FIN unresolvable, wedging the subscriber's read-to-EOF forever).
hdr/hdr_len keep a copy of the stream's opening SUBGROUP_HEADER bytes for subscribers that join AFTER the relay started (the audio track's one long-lived stream typically opens before any peer has subscribed): a late joiner's stream is opened carrying the saved header alone, so its decoder sees a well-formed stream head even though it missed the original opening round (moqtrun_relay_late_open). On a ring-backed (reliable) relay whose ring still holds everything past the header, the late joiner then reads the whole stream from there (moqtrun_rel_late_attach_all).
frag_idx/frag_len hold the bytes past the LAST COMPLETE Object boundary of the most recent delivery, prepended to the next one before relaying (moqtrun_relay_normalize): deliveries slice the publisher's stream at arbitrary byte positions, but a relay round that gets dropped for one subscriber (stream_send refusing while its previous round is unACKed) vanishes WHOLE from that subscriber's stream – if the round ended mid-Object, the subscriber's decoder read the next round's bytes as the torn Object's continuation and mis-framed everything after it, forever (observed live: voice went permanently silent minutes into every call while rx bytes kept arriving). Forwarding only whole Objects makes every droppable round self-delimiting.
| u8 wired_moqtrun_relay::sub_busy_streak[WIRED_MOQTRUN_MAX_SUBS] |
Consecutive rounds sub slot i's stream_send was refused (saturates at 255): reaching WIRED_MOQTRUN_RESET_AFTER_BUSY sheds the stream (io.stream_reset) so the next round re-opens fresh at the newest frame instead of replaying the stale backlog.
Any accepted round zeroes it.