open-standards/joule-code/joule-code-rs/crates/joule-contrib
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Transaction Science d698f47278
Some checks failed
joule-code conformance gate / joule-moq-relay, its own energy on a counter (macos) (push) Successful in 52s
joule-code conformance gate / Build + round-trip C1-C4 vectors (push) Successful in 1m38s
joule-code conformance gate / joule-moq-relay, every target (push) Successful in 3m7s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Failing after 4m22s
wai release binaries build on Windows / the seven release binaries · windows (push) Successful in 14m14s
joule-code conformance gate / joule-moq-ingest, every target (push) Successful in 21m40s
joule-moq-room room service / joule-moq-room · does this change touch it (push) Has been cancelled
joule-moq-room room service / joule-moq-room, every target (push) Has been cancelled
joule-contrib: process CPU time on Windows, and the release's seven Windows binaries build on main
cpu_us() declared POSIX getrusage for every target, so linking wai-ingest
for x86_64-pc-windows-msvc failed (LNK2019, unresolved external symbol
getrusage) and wai-v0.5.0's Windows leg produced no archive. It is now
getrusage on unix, GetProcessTimes (kernel32) on Windows, and zero where
a platform gives no process CPU time.

Nothing built those binaries on Windows before a release. A new workflow
builds the same seven the Windows archive holds, with the release job's
directories, packages, features and --locked, in debug (which links each
one): nightly, and on a push to main that changes a joule-code crate the
archive builds from.

Checked: joule-contrib type-checks and passes clippy -D warnings for
x86_64-pc-windows-msvc, and its 33 lib tests pass natively (Thor).

Changelog: none
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 11:44:18 -05:00
..
src joule-contrib: process CPU time on Windows, and the release's seven Windows binaries build on main 2026-11-09 11:44:18 -05:00
tests joule-contrib: a RIST listener whose task was ended is closed from outside it 2026-11-09 10:49:49 -05:00
Cargo.toml Cargo: no minimum-supported-version floor, because the policy is latest stable 2026-11-03 17:42:20 -05:00
README.md joule-contrib: a RIST listener whose task was ended is closed from outside it 2026-11-09 10:49:49 -05:00

joule-contrib

Contribution over UDP with retransmission, for WAI's ingest gateway: SRT (draft-sharabayko-srt-01) and RIST (VSF TR-06-1:2020 Simple Profile, VSF TR-06-2:2024 Main Profile), the MPEG transport stream both carry, and an account of what became of every sequence number. WAI's extensions/live-contribution.md profiles them; joule-moq-ingest uses this crate to bring a contribution link into a room's tracks.

SRT

srt::Listener serves many callers on one UDP port, each connection found by the socket ID its packets name; srt::call calls a listener. Both run the caller-listener handshake of the draft's §4.3.1 (the SYN cookie, the HSv5 extensions, the stream ID, the key material), and live mode (§7.1): every message one packet, TSBPD over the negotiated latency, too-late drop, ACK/ACKACK with the RTT estimate, immediate and periodic NAKs, retransmission, AES-CTR with the key wrapped (RFC 3394) under PBKDF2-HMAC-SHA1. A listener decides each caller through an Admission, which sees the stream ID and gives the passphrase, the role (receive or send) and the latency, or a rejection code. Listener::close returns once the port is closed: the listener's task and every connection's (each holds the socket) ended and awaited, each connection's SHUTDOWN sent. Dropping a listener only tells its task to go.

RIST (feature rist)

rist::RistListener receives one flow: the Simple Profile's RTP on an even port P and RTCP on P + 1, or the Main Profile's GRE-over-UDP tunnel on one port, in reduced overhead mode with the VSF EtherType or the legacy one, keep-alives, and PSK (PBKDF2-HMAC-SHA256 over the GRE nonce, AES-CTR on the GRE sequence number). It takes the first flow whose CNAME is the one it expects, and, under PSK, whose packets decrypt. It requests what is missing with range or bitmask requests, measures the RTT with the RTT echo, and delivers each packet a buffer after it was expected. RistListener::close returns once its port (the Simple Profile's two) is closed; dropping it only tells its task to go. RistListener::closer gives a RistCloser, which closes it the same way from outside the task that holds it, after that task has been ended and dropped the listener unclosed. rist::send is the sender of either profile.

The account

stats::Account records what a receiver did with every sequence number, in order: delivered at the first try, recovered within the window, dropped when its time passed, or outstanding when the link ended; the loss runs, the requests sent and the numbers they named, the retransmissions, duplicates and late arrivals received, the round trips, how long each recovery took and its least margin. It is cut into parts, which the gateway signs as the link record.

The transport stream

ts::Demux reads the PAT and PMT (each section's CRC checked) and reassembles each stream's PES packets, with the PTS extended past 33 bits; a PES missing a packet is dropped whole and counted. ts::Mux writes a program of one video and one audio stream, and ts::Pacer times a stream's chunks by its PCR.

Tools

binary what
joule-contrib-send sends a transport stream file (paced by its PCR) or a synthetic program over SRT (calling or listening) or RIST
joule-contrib-recv receives over SRT or RIST into a file, and prints the link's account
joule-contrib-bench one link on loopback, both ends in the process: the payload rate, CPU time and energy, with a lossy path if asked

URLs: srt://HOST:PORT?streamid=…&passphrase=…&pbkeylen=16&latency=MS (calls; srt://:PORT listens), rist://HOST:PORT?profile=simple|main&cname=…&secret=…&aes-type=128|256&buffer=MS.

Tests

test what
unit tests RFC 3394, RFC 6070 and TR-06-2 Annex B vectors, SP 800-38A's CTR vector; the packet formats; the TR-06-1 Appendix A requests; the TS multiplexer against the demultiplexer, a lost packet, the PTS wrap; the account
srt_link SRT on loopback through a proxy that drops datagrams each way, every payload in order, the account of every sequence number; each key length, a wrong and a missing passphrase, the rejection codes; a packet held for the latency window; a listener that sends to a caller that receives
rist_link the Simple Profile with range and bitmask requests through lossy proxies; the Main Profile in the clear, under PSK of each length and in the legacy format; another CNAME and another passphrase refused
listener_close from a task on a runtime of one worker, an SRT listener and a RIST listener of each profile closed many times, with a peer connected and without: each port binds at once when the close returns, and an SRT connection's link reads listener_stopped; a RIST listener held by a task that is ended, closed through its RistCloser, binds at once too
interop (ignored) against each transport's reference tools run locally, named by WAI_SRT_LIVE_TRANSMIT, WAI_RISTSENDER and WAI_RISTRECEIVER: their caller and senders into this crate and this crate into their listener and receivers, byte for byte, encrypted and through lossy paths. With --ignored, a tool not named fails the test

The lossy module's proxy drops, delays and reorders datagrams from a fixed seed.

Patents

VSF TR-06-1:2020 and TR-06-2:2024 each carry an intellectual property notice: a patent is claimed to read on their protocol sections, and its holder has assured the forum that it will license the claims to implementers. The RIST code is therefore built only with the feature rist, which no default build turns on; whether a distributed build carries it is a licensing decision for the distributor (extensions/live-contribution.md §10).

Dependencies

AES, CTR, HMAC, SHA-1 and SHA-256 from RustCrypto (MIT OR Apache-2.0); PBKDF2 (RFC 8018) and AES key wrap (RFC 3394) are written here over them. tokio, serde, serde_json, hex, tracing and rand_core: MIT or Apache-2.0. No C library is linked.

Licence

Apache-2.0.