open-standards/joule-code/joule-code-rs/crates/joule-moq-relay/relay.example.toml
Transaction Science dcfb9068a1
All checks were successful
joule-code conformance gate / joule-moq-relay, every target (pull_request) Successful in 3m12s
joule-code conformance gate / joule-moq-relay, its own energy on a counter (macos) (pull_request) Successful in 48s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 3m24s
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 9s
joule-code conformance gate / joule-moq-ingest, every target (pull_request) Successful in 5m44s
joule-code conformance gate / Build + round-trip C1-C4 vectors (pull_request) Successful in 1m24s
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (pull_request) Successful in 9s
joule-moq-remote host agent / joule-moq-remote · does this change touch it (pull_request) Successful in 7s
WAI examples / WAI examples · does this change touch them (pull_request) Successful in 9s
wai-fleet service / does this change touch it (pull_request) Successful in 7s
joule-moq-room room service / joule-moq-room · does this change touch it (pull_request) Successful in 6s
WAI Studio / does this change touch it (pull_request) Successful in 6s
joule-moq-web browser client / joule-moq-web · does this change touch it (pull_request) Successful in 6s
wai-app and Create / wai-app · does this change touch it (pull_request) Successful in 6s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (pull_request) Successful in 38s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (pull_request) Successful in 59s
wai-fleet service / service · linux (pull_request) Successful in 2m18s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (pull_request) Successful in 2m58s
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (pull_request) Successful in 30s
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (pull_request) Successful in 1m44s
WAI examples / WAI examples · portable · linux (pull_request) Successful in 10m15s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 7m20s
WAI examples / WAI examples · android-app · linux-arm64 (pull_request) Successful in 5m37s
WAI Studio / Studio in WebKit · linux (pull_request) Successful in 12m3s
joule-moq-room room service / joule-moq-room, every target (pull_request) Successful in 4m11s
joule-moq-remote host agent / joule-moq-remote, every target (macos) (pull_request) Successful in 1m7s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 11m32s
wai-fleet service / service · macos (pull_request) Successful in 57s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (pull_request) Successful in 13m39s
wai-app and Create / wai-app · Create, browser end-to-end (macos) (pull_request) Successful in 5m54s
WAI Studio / Studio in Chromium and Firefox · macos (pull_request) Successful in 11m14s
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (pull_request) Successful in 13m7s
joule-moq-relay: a fan-out holds up no other track, and each core has its own socket
A big room's fan-out held the relay's one lock for as long as it took to reach
every subscriber, so every other room waited. A track's subscribers are now copy
on write: a fan-out takes a snapshot under the lock and delivers outside it, so
the time under the lock no longer grows with the audience.

With a snapshot, a fan-out could still push to a subscription that has just
left, which would put a stream after its cancel or past its PUBLISH_DONE count.
So a subscription is marked gone under its own lock, and a fan-out holds that
lock across each push: a push comes before the mark, or sees it and isn't made.

One UDP socket and one endpoint driver carried every peer's packets. The
listener now binds one socket per core on its one port, each its own endpoint.
Steering by address, which SO_REUSEPORT does by default, would end a session
whenever a viewer's address changed: its packets would reach a socket holding no
such connection. So a small kernel filter steers by the first byte of the
connection ID, and each socket's endpoint issues IDs that come back to it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-02 19:05:27 -05:00

158 lines
7 KiB
TOML

# wai-relay (crate joule-moq-relay): an example configuration. Every field is optional; these are the
# defaults unless a comment says otherwise. Nothing secret belongs here: keys are files
# the operator provides, and tokens are named by their SHA-256.
# Native QUIC (ALPN moqt-22) and WebTransport over HTTP/3 (ALPN h3), one UDP port.
quic_listen = "127.0.0.1:4443"
# The WebSocket fallback (plain HTTP upgrade; put TLS in front of it).
websocket_listen = "127.0.0.1:4480"
# The path of the WebTransport CONNECT and of the WebSocket upgrade.
path = "/moq"
# The New Session URI a shutdown GOAWAY names; empty reuses the current one.
goaway_uri = ""
[tls]
# cert_path = "/etc/joule-moq-relay/fullchain.pem"
# key_path = "/etc/joule-moq-relay/key.pem"
# Without files: a development certificate for these names, its SHA-256 printed.
dev_names = ["localhost", "127.0.0.1", "::1"]
[cache]
max_bytes = 268435456
[limits]
max_sessions = 4096
max_requests = 256
max_uni_streams = 1024
max_request_updates = 16
max_auth_token_cache_size = 16384
max_rendezvous_ms = 30000
upstream_timeout_ms = 5000
fill_timeout_ms = 2000
write_concurrency = 8
max_object_bytes = 16777216
unknown_alias_wait_ms = 1000
goaway_timeout_ms = 5000
# 0 for each of these: no limit. A session at max_session_ms is closed; one sending past
# max_ingress_kbps (averaged over ingress_burst_ms) is closed; the binary exits with status
# 70 past max_resident_mb. A rule with `unlimited = true` exempts its sessions from the first
# two.
max_session_ms = 0
max_ingress_kbps = 0
ingress_burst_ms = 4000
max_resident_mb = 0
# The most relays a request may have passed through (its RELAY_PATH), and the wait before an
# upstream link is dialed again, doubled on each failure to 30 s.
max_relay_hops = 8
upstream_reconnect_ms = 1000
websocket_buffer_bytes = 67108864
idle_timeout_ms = 30000
quic_socket_buffer_bytes = 4194304 # each UDP socket's buffers; the system caps them (net.core.rmem_max on Linux)
quic_sockets = 0 # UDP sockets on the one port: 0 is one per core up to 16 (Linux; elsewhere one)
quic_send_window_bytes = 1048576
quic_stream_window_bytes = 16777216 # a stream's flow-control window: more than the largest group a door holds
quic_connection_window_bytes = 67108864 # a session's, all its streams together: what bounds the bytes it leaves unread; never below the stream window
[receipts]
receipts_track_suffix = "_receipts"
# Check objects in this namespace against their receipts at the door (example; not a
# default). An empty trust list accepts any key whose signature verifies. A field "*"
# matches any field; `trust_field = 1` with `prefix = ["*", "*", "video"]` would accept, in
# each room, the key its namespace's second field names (WAI live-rooms §6.1).
[[receipts.door]]
prefix = ["example", "live"]
trust = []
hold_ms = 2000
[summary]
# key_path = "/etc/joule-moq-relay/summary-seed"
# out_path = "/var/log/joule-moq-relay/sessions.jsonl"
# The relay's own energy in its per-hop session records (WAI live-metering §8): "auto"
# reads the counter the host offers (macOS: the relay process's CPU energy; Linux: the CPU
# packages' RAPL energy, only with dedicated_host = true, the statement that this host runs
# the relay alone); "off" reads none, and every record carries the unmetered marker.
[metering]
energy = "auto"
dedicated_host = false
# The room grants tokens carry, for the per-hop session records of WAI rooms (an example;
# not a default): a session whose SETUP presents this token runs under this grant.
[[metering.grants]]
token_sha256 = "1df4b07d05b9b3b1115b4b6b22af319a2f99564a2fa2573a34896063c7513c10"
grant = "0000000000000000000000000000000000000000000000000000000000000001"
joules_ceiling_micro = 5000000
funds_ceiling = 500
currency = "EUR"
[auth]
required = false
# An example grant; the hash below is of the placeholder string "replace-me".
[[auth.grants]]
prefix = ["example"]
token_sha256 = "1df4b07d05b9b3b1115b4b6b22af319a2f99564a2fa2573a34896063c7513c10"
publish = true
subscribe = true
# true: the token is a room grant's record (WAI live-rooms §4.1), honoured only on a
# session whose SETUP proved possession of its principal's key (§10.5.2).
proof = false
# true: a session presenting this token is exempt from max_session_ms and max_ingress_kbps.
unlimited = false
# true: the token may seek back, fetching a track below its live edge (WAI live-rooms
# §10.6). A room grant from an authority below seeks back when its powers hold seek.
seek = false
# The DVR store (an example; not a default): a window of the tracks under each prefix, kept
# on disk with their receipts and served to FETCH below the live edge (WAI live-recording
# §8). Groups go oldest first, whole, past max_age_s (at most 86400, 24 hours) or past
# max_bytes for the window's tracks together. The store survives a restart: on start every
# object is checked against its receipt again, and one that does not verify is dropped,
# counted, and never served. `room_keys` are the room authorities and clocks whose decision
# events withhold what they deny or redact (WAI live-moderation §6.3). `takedown_keys` are the
# services whose signed takedowns the store honours (WAI takedown §10.1): it forgets what each
# covers and signs a purge under purges/ with the summary key.
[dvr]
path = "/var/lib/joule-moq-relay/dvr"
room_keys = []
takedown_keys = []
[[dvr.window]]
prefix = ["*"]
max_age_s = 900
max_bytes = 4294967296
# The floor of WAI rooms (WAI co-performance §6): the relay reads each room's turn schedules
# and handovers from the events tracks it forwards, and does not forward a media object a
# performer publishes out of turn under a schedule that refuses. A schedule is honoured from a
# room key (these, and the keys of `auth.authorities`) or from a principal whose session proved
# a grant with the direct power. Absent: the relay holds no floor. The relay counts each
# author's audience inputs in the order of its chain (co-performance §7.3): an input that arrives
# ahead of a gap in its author's chain waits up to `hold_ms` for the gap to fill, and is refused
# `input_out_of_order` if it has not.
[floor]
room_keys = []
hold_ms = 2000
# A room authority (an example; not a default): every WRG1 grant its key signs is honoured,
# beside its proof and within its window, with the rights live-rooms §10.2 gives it. `rooms`
# narrows it to these room ids; empty, every room it grants.
# [[auth.authorities]]
# key = "<the authority's Ed25519 key, hex>"
# rooms = []
# Relays this one dials (relay-to-relay cascading): a SUBSCRIBE, FETCH or TRACK_STATUS for a
# track no session here publishes, under one of `prefixes`, goes to the first whose session is
# open; namespaces published here under them are published there. Trust is one of ca_path,
# cert_sha256 (a pinned certificate) and native_roots; ws:// takes none. The token is read from
# token_path and must hash to token_sha256.
#
# [[upstream]]
# name = "home"
# url = "wss://home.example/moq"
# transport = "websocket"
# prefixes = [["*"]]
# native_roots = true
# token_sha256 = "<64 hex digits>"
# token_path = "/etc/joule-moq-relay/home.token"