live-contribution: the link record's magic is WLK1, no longer the clip record's WCL1 #604
150 changed files with 378 additions and 147 deletions
|
|
@ -4,6 +4,13 @@ All notable changes to the Joule Code standard are recorded here. The format fol
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Changed — `joule-moq-ingest`: the contribution link record's magic is `WLK1`
|
||||||
|
|
||||||
|
- **Wire change.** `linkrec::MAGIC` is `WLK1` (WAI `extensions/live-contribution.md` §6.2), so the link record no
|
||||||
|
longer shares `WCL1` with WAI's clip record (live-recording §5.1), which had it first. A part written before this
|
||||||
|
change is refused as `malformed`; nothing else in the record changes. `joule-moq-ingest-link-vectors` writes
|
||||||
|
`.wlk1` files, and adds `clip_record_magic`, a part bearing the clip record's magic, refused `malformed`.
|
||||||
|
|
||||||
### Changed — `joule-moq-relay`: one object held once, and a socket that keeps what arrives
|
### Changed — `joule-moq-relay`: one object held once, and a socket that keeps what arrives
|
||||||
|
|
||||||
- **`limits.quic_socket_buffer_bytes`** (4 MiB by default, and for the links a relay dials too): the
|
- **`limits.quic_socket_buffer_bytes`** (4 MiB by default, and for the links a relay dials too): the
|
||||||
|
|
|
||||||
|
|
@ -222,7 +222,7 @@ stream and the first AAC stream go to the video and audio tracks as WHIP's frame
|
||||||
access unit (one ADTS frame) an object, the PTS on the room clock; a PES missing a packet is
|
access unit (one ADTS frame) an object, the PTS on the room clock; a PES missing a packet is
|
||||||
dropped whole. The catalog declares the owner's `link` track.
|
dropped whole. The catalog declares the owner's `link` track.
|
||||||
|
|
||||||
**The link record** (`linkrec`, `WCL1`): every `[contrib] record_interval_ms` and when the
|
**The link record** (`linkrec`, `WLK1`): every `[contrib] record_interval_ms` and when the
|
||||||
session ends, the gateway signs a part: the sequence numbers passed, each delivered at the
|
session ends, the gateway signs a part: the sequence numbers passed, each delivered at the
|
||||||
first try, recovered, dropped or outstanding, the loss runs, requests, retransmissions, round
|
first try, recovered, dropped or outstanding, the loss runs, requests, retransmissions, round
|
||||||
trips and recovery times, chained to the part before and naming each media track's receipt
|
trips and recovery times, chained to the part before and naming each media track's receipt
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ retry_after_s = 2 # what a 409 asks a player to wait
|
||||||
|
|
||||||
[summary]
|
[summary]
|
||||||
# out_path = "sessions.jsonl" # session records, one JSON line each; absent: kept in memory only
|
# out_path = "sessions.jsonl" # session records, one JSON line each; absent: kept in memory only
|
||||||
# link_out_path = "links.hex" # contribution link records (WCL1), one hexadecimal line each
|
# link_out_path = "links.hex" # contribution link records (WLK1), one hexadecimal line each
|
||||||
|
|
||||||
[rtmp]
|
[rtmp]
|
||||||
# Enhanced RTMP ingest (live-ingest §12); off unless a listener is set.
|
# Enhanced RTMP ingest (live-ingest §12); off unless a listener is set.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
//! `joule-moq-ingest-link-vectors`: the conformance corpus of the contribution link record,
|
//! `joule-moq-ingest-link-vectors`: the conformance corpus of the contribution link record,
|
||||||
//! `WCL1` (WAI `extensions/live-contribution.md` §6), written from fixed seeds, so the
|
//! `WLK1` (WAI `extensions/live-contribution.md` §6), written from fixed seeds, so the
|
||||||
//! same bytes every run.
|
//! same bytes every run.
|
||||||
//!
|
//!
|
||||||
//! ```text
|
//! ```text
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
//! joule-moq-ingest-link-vectors --check <wai/live-conformance/links> regenerate and compare
|
//! joule-moq-ingest-link-vectors --check <wai/live-conformance/links> regenerate and compare
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! Each vector is a part (one `.wcl1` file) or a series (several, in order), with the
|
//! Each vector is a part (one `.wlk1` file) or a series (several, in order), with the
|
||||||
//! outcome §6.5 and §6.6 give it: accepted, or refused with its reason (and, in a series,
|
//! outcome §6.5 and §6.6 give it: accepted, or refused with its reason (and, in a series,
|
||||||
//! the index of the part refused). Each refused vector breaks one rule and keeps every
|
//! the index of the part refused). Each refused vector breaks one rule and keeps every
|
||||||
//! other: where a rule after the signature is broken, the record is signed again.
|
//! other: where a rule after the signature is broken, the record is signed again.
|
||||||
|
|
@ -111,7 +111,7 @@ struct Out {
|
||||||
|
|
||||||
impl Out {
|
impl Out {
|
||||||
fn part(&mut self, name: &str, bytes: Vec<u8>, outcome: Result<(), Reason>, note: &str) {
|
fn part(&mut self, name: &str, bytes: Vec<u8>, outcome: Result<(), Reason>, note: &str) {
|
||||||
let file = format!("{name}.wcl1");
|
let file = format!("{name}.wlk1");
|
||||||
let mut v = json!({"name": name, "kind": "part", "files": [file], "note": note});
|
let mut v = json!({"name": name, "kind": "part", "files": [file], "note": note});
|
||||||
match outcome {
|
match outcome {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
|
|
@ -132,7 +132,7 @@ impl Out {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn series(&mut self, name: &str, parts: Vec<Vec<u8>>, outcome: Result<(), (usize, Reason)>, note: &str) {
|
fn series(&mut self, name: &str, parts: Vec<Vec<u8>>, outcome: Result<(), (usize, Reason)>, note: &str) {
|
||||||
let files: Vec<String> = (0..parts.len()).map(|i| format!("{name}.{i}.wcl1")).collect();
|
let files: Vec<String> = (0..parts.len()).map(|i| format!("{name}.{i}.wlk1")).collect();
|
||||||
let mut v = json!({"name": name, "kind": "series", "files": files, "note": note});
|
let mut v = json!({"name": name, "kind": "series", "files": files, "note": note});
|
||||||
let got = linkrec::verify_series(&parts);
|
let got = linkrec::verify_series(&parts);
|
||||||
match outcome {
|
match outcome {
|
||||||
|
|
@ -204,7 +204,10 @@ fn corpus() -> Out {
|
||||||
o.part("truncated", good[..good.len() - 1].to_vec(), Err(Reason::Truncated), "the signature's last byte missing");
|
o.part("truncated", good[..good.len() - 1].to_vec(), Err(Reason::Truncated), "the signature's last byte missing");
|
||||||
let mut b = good.clone();
|
let mut b = good.clone();
|
||||||
b[0] = b'X';
|
b[0] = b'X';
|
||||||
o.part("bad_magic", b, Err(Reason::Malformed), "not WCL1");
|
o.part("bad_magic", b, Err(Reason::Malformed), "not WLK1");
|
||||||
|
let mut b = good.clone();
|
||||||
|
b[..4].copy_from_slice(b"WCL1");
|
||||||
|
o.part("clip_record_magic", b, Err(Reason::Malformed), "the clip record's magic, WCL1 (live-recording §5.1)");
|
||||||
let mut b = good.clone();
|
let mut b = good.clone();
|
||||||
b.push(0);
|
b.push(0);
|
||||||
o.part("trailing_byte", b, Err(Reason::Malformed), "a byte after the signature");
|
o.part("trailing_byte", b, Err(Reason::Malformed), "a byte after the signature");
|
||||||
|
|
@ -440,7 +443,7 @@ fn main() -> ExitCode {
|
||||||
if let Ok(rd) = std::fs::read_dir(&dir) {
|
if let Ok(rd) = std::fs::read_dir(&dir) {
|
||||||
for e in rd.flatten() {
|
for e in rd.flatten() {
|
||||||
let n = e.file_name().to_string_lossy().into_owned();
|
let n = e.file_name().to_string_lossy().into_owned();
|
||||||
if (n.ends_with(".wcl1") || n == "vectors.json") && !files.contains_key(&n) {
|
if (n.ends_with(".wlk1") || n == "vectors.json") && !files.contains_key(&n) {
|
||||||
eprintln!("not generated: {n}");
|
eprintln!("not generated: {n}");
|
||||||
bad += 1;
|
bad += 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -544,7 +544,7 @@ pub struct SummaryConfig {
|
||||||
/// Each session's record is appended here as one JSON line, when set.
|
/// Each session's record is appended here as one JSON line, when set.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub out_path: Option<PathBuf>,
|
pub out_path: Option<PathBuf>,
|
||||||
/// Each contribution link record part (`WCL1`) is appended here, as one line of
|
/// Each contribution link record part (`WLK1`) is appended here, as one line of
|
||||||
/// hexadecimal, when set.
|
/// hexadecimal, when set.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub link_out_path: Option<PathBuf>,
|
pub link_out_path: Option<PathBuf>,
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
//! (live-ingest §7) and its arrival from the link as its arrival: the same objects,
|
//! (live-ingest §7) and its arrival from the link as its arrival: the same objects,
|
||||||
//! groups, catalog and receipts as a WHIP session's (live-ingest §4 to §8).
|
//! groups, catalog and receipts as a WHIP session's (live-ingest §4 to §8).
|
||||||
//! - **The link record.** Every `record_interval_ms`, and when the session ends, the gateway
|
//! - **The link record.** Every `record_interval_ms`, and when the session ends, the gateway
|
||||||
//! signs a part of the link's `WCL1` record ([`crate::linkrec`]) and publishes it on the
|
//! signs a part of the link's `WLK1` record ([`crate::linkrec`]) and publishes it on the
|
||||||
//! owner's `link` track with its receipts: every sequence number delivered, recovered,
|
//! owner's `link` track with its receipts: every sequence number delivered, recovered,
|
||||||
//! dropped or outstanding, the requests and the round trips, and the head of every media
|
//! dropped or outstanding, the requests and the round trips, and the head of every media
|
||||||
//! track's receipt chain at the part's end.
|
//! track's receipt chain at the part's end.
|
||||||
|
|
|
||||||
|
|
@ -422,7 +422,7 @@ impl Gateway {
|
||||||
self.rtmp.lock().unwrap().iter().map(|(k, h)| (k.clone(), h.frames.load(Ordering::Relaxed))).collect()
|
self.rtmp.lock().unwrap().iter().map(|(k, h)| (k.clone(), h.frames.load(Ordering::Relaxed))).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Every contribution link record part (`WCL1`) signed so far.
|
/// Every contribution link record part (`WLK1`) signed so far.
|
||||||
pub fn link_records(&self) -> Vec<Vec<u8>> {
|
pub fn link_records(&self) -> Vec<Vec<u8>> {
|
||||||
self.contrib.records.lock().unwrap().clone()
|
self.contrib.records.lock().unwrap().clone()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
//! - **SRT and RIST** ([`contrib`]): contribution over UDP with retransmission, from
|
//! - **SRT and RIST** ([`contrib`]): contribution over UDP with retransmission, from
|
||||||
//! `joule-contrib`, into the same tracks: a one-time session from `/srt` or `/rist`
|
//! `joule-contrib`, into the same tracks: a one-time session from `/srt` or `/rist`
|
||||||
//! under the room grant, the transport stream demultiplexed, H.264, HEVC and AAC
|
//! under the room grant, the transport stream demultiplexed, H.264, HEVC and AAC
|
||||||
//! carried; and the link's own record, `WCL1` ([`linkrec`]), signed part by part on the
|
//! carried; and the link's own record, `WLK1` ([`linkrec`]), signed part by part on the
|
||||||
//! owner's `link` track.
|
//! owner's `link` track.
|
||||||
//!
|
//!
|
||||||
//! The WebRTC stack is `str0m` (sans-IO, MIT OR Apache-2.0) with its pure-Rust crypto
|
//! The WebRTC stack is `str0m` (sans-IO, MIT OR Apache-2.0) with its pure-Rust crypto
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
//! The contribution link record, `WCL1` (WAI `extensions/live-contribution.md` §6): what a
|
//! The contribution link record, `WLK1` (WAI `extensions/live-contribution.md` §6): what a
|
||||||
//! contribution link over SRT or RIST carried, lost, recovered and dropped, and how long it
|
//! contribution link over SRT or RIST carried, lost, recovered and dropped, and how long it
|
||||||
//! took, signed by the gateway that received it, part by part, each part chained to the one
|
//! took, signed by the gateway that received it, part by part, each part chained to the one
|
||||||
//! before and naming the head of every media track's receipt chain at its end.
|
//! before and naming the head of every media track's receipt chain at its end.
|
||||||
|
|
@ -11,7 +11,7 @@ use crate::room::{sha256, verify_strict, Reason as RoomReason};
|
||||||
use ed25519_dalek::{Signer, SigningKey};
|
use ed25519_dalek::{Signer, SigningKey};
|
||||||
use joule_contrib::stats::{Part, Run, Summary};
|
use joule_contrib::stats::{Part, Run, Summary};
|
||||||
|
|
||||||
pub const MAGIC: &[u8; 4] = b"WCL1";
|
pub const MAGIC: &[u8; 4] = b"WLK1";
|
||||||
pub const VERSION: u8 = 1;
|
pub const VERSION: u8 = 1;
|
||||||
pub const DOMAIN: &[u8] = b"wai:contrib-link\x01";
|
pub const DOMAIN: &[u8] = b"wai:contrib-link\x01";
|
||||||
pub const MAX_TRACKS: usize = 8;
|
pub const MAX_TRACKS: usize = 8;
|
||||||
|
|
|
||||||
122
wai/CHANGELOG.md
122
wai/CHANGELOG.md
|
|
@ -6,6 +6,128 @@ wire format may change and such changes are recorded here.
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### The contribution link record has its own magic, `WLK1`
|
||||||
|
|
||||||
|
- **Wire change.** The contribution link record ([extensions/live-contribution.md](extensions/live-contribution.md)
|
||||||
|
§6.2) begins `WLK1`, no longer `WCL1`. The clip record of live-recording §5.1 had `WCL1` first; the link record,
|
||||||
|
added later, took the same four bytes, so a reader that tells records apart by their magic could not tell a link
|
||||||
|
record from a clip record, and the registry listed `WCL1` for the clip record alone. `WCL1` stays the clip
|
||||||
|
record's. A link record written before this change is `malformed` to a reader of this revision (§6.5 step 2), as a
|
||||||
|
new one is to a reader of the earlier revision; the signature's domain, `wai:contrib-link` 0x01, and every other
|
||||||
|
field are unchanged.
|
||||||
|
- **The registry** lists `WLK1` as a magic of live-contribution §6.2 (REGISTRY.md and `codecs/registry.rs`).
|
||||||
|
- **The corpus** [`live-conformance/links/`](live-conformance/links/) is regenerated with the new magic, each vector
|
||||||
|
file now `.wlk1`, and gains `clip_record_magic`: a part that bears the clip record's magic, refused `malformed`.
|
||||||
|
`live_contribution_verify.py` reads `WLK1`, and requires that a copy of each accepted part given the clip record's
|
||||||
|
magic is refused. `joule-moq-ingest` writes and reads `WLK1` (`linkrec::MAGIC`).
|
||||||
|
- **The reverse:** a record with the link record's magic is not a clip record. The live-recording corpus
|
||||||
|
[`live-conformance/recordings/`](live-conformance/recordings/) gains the clip `link_record_magic`: chunk 4's clip
|
||||||
|
record beginning `WLK1` and signed under it, refused `malformed` at the clip (live-recording §5.2, which now names
|
||||||
|
`WLK1` among the other magics). `live_record_verify.py` requires the same refusal of a copy of each accepted clip
|
||||||
|
given `WLK1`.
|
||||||
|
- **Breaking:** the corpus's index names the new files, and the files under the old magic are gone:
|
||||||
|
`record:corpus:wai/live-conformance/links/vectors.json`,
|
||||||
|
`record:corpus:wai/live-conformance/links/altered_count.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/bad_key.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/bad_magic.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/bad_signature.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/bytes_without_delivery.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/count_mismatch.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/empty_span.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/first_part_with_parent.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/first_try_over_delivered.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/last_byte_two.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/last_without_reason.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/later_part_without_parent.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/margin_past_window.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/margin_without_recovery.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/mode_unknown.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/no_window.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/outstanding_not_last.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/protocol_unknown.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/reason_unknown.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/reason_without_last.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/recovery_disordered.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/recovery_empty_with_figures.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/recovery_samples.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/requested_below_requests.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/rist_main_aes192.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/rist_main_psk256.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/rist_simple.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/rist_simple_encrypted.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/rtt_disordered.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/rtt_empty_with_figures.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/run_empty.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/run_outside.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/run_overfull.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/run_overfull_alone.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/runs_overlap.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/runs_past_bound.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/runs_short.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/runs_truncated.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_head_moved_without_groups.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_head_moved_without_groups.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_cipher.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_cipher.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_grant.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_grant.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_hop.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_hop.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_mode.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_mode.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_principal.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_principal.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_protocol.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_protocol.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_room.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_room.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_session.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_session.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_window.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_other_window.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_part_after_last.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_part_after_last.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_sequence_gap.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_sequence_gap.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_skips_a_part.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_skips_a_part.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_skips_a_part.2.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_starts_late.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_starts_late.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_three_parts.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_three_parts.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_three_parts.2.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_time_gap.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_time_gap.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_track_added.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_track_added.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_track_added.2.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_track_alias_changed.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_track_alias_changed.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_track_dropped.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_track_dropped.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_wrong_parent.0.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_wrong_parent.1.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/series_wrong_parent.2.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/small_order_r.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/srt_caller_aes192.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/srt_cipher_100.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/srt_last_outstanding.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/srt_listener_clean.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/srt_recovered.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/too_large.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/track_head_without_groups.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/track_zero_digest.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/tracks_not_begun.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/tracks_past_bound.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/tracks_unsorted.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/trailing_byte.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/truncated.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/truncated_byte_two.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/truncated_not_full.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/two_dropped.wcl1`,
|
||||||
|
`record:corpus:wai/live-conformance/links/unknown_version.wcl1`.
|
||||||
|
|
||||||
### Tariff version 6: a job priced per endpoint, a third party's usage billed, and an upscale and a tone mapping billed by what re-derives them
|
### Tariff version 6: a job priced per endpoint, a third party's usage billed, and an upscale and a tone mapping billed by what re-derives them
|
||||||
|
|
||||||
- **Tariff and invoice version 6** ([extensions/receipt-ledger.md](extensions/receipt-ledger.md) §4.9). A job price names
|
- **Tariff and invoice version 6** ([extensions/receipt-ledger.md](extensions/receipt-ledger.md) §4.9). A job price names
|
||||||
|
|
|
||||||
|
|
@ -407,6 +407,7 @@ and a role are fixed once registered.
|
||||||
| `WKL1` | magic | defined | key-release §4.1 |
|
| `WKL1` | magic | defined | key-release §4.1 |
|
||||||
| `WKT1` | magic | defined | key-release §9.3 |
|
| `WKT1` | magic | defined | key-release §9.3 |
|
||||||
| `WLI1` | magic | defined | receipt-ledger §6.1 |
|
| `WLI1` | magic | defined | receipt-ledger §6.1 |
|
||||||
|
| `WLK1` | magic | defined | live-contribution §6.2 |
|
||||||
| `WLT1` | magic | defined | receipt-ledger §4.1 |
|
| `WLT1` | magic | defined | receipt-ledger §4.1 |
|
||||||
| `WLU1` | magic | defined | channel-lineup §6.1 |
|
| `WLU1` | magic | defined | channel-lineup §6.1 |
|
||||||
| `WMA1` | magic | defined | live-messaging §8 |
|
| `WMA1` | magic | defined | live-messaging §8 |
|
||||||
|
|
|
||||||
|
|
@ -1098,7 +1098,7 @@ And for **contribution over UDP with retransmission** — `wai.live.contribution
|
||||||
Profile, VSF TR-06-2:2024 Main Profile), each admitted by a one-time session a publisher
|
Profile, VSF TR-06-2:2024 Main Profile), each admitted by a one-time session a publisher
|
||||||
obtains under its room grant, its MPEG transport stream demultiplexed into the room's tracks
|
obtains under its room grant, its MPEG transport stream demultiplexed into the room's tracks
|
||||||
as one envelope an access unit with first-hop receipts. The gateway signs the **link
|
as one envelope an access unit with first-hop receipts. The gateway signs the **link
|
||||||
record**, `WCL1`, part by part: every sequence number delivered at the first try,
|
record**, `WLK1`, part by part: every sequence number delivered at the first try,
|
||||||
recovered within the receive window, dropped, or outstanding when the link ended, the
|
recovered within the receive window, dropped, or outstanding when the link ended, the
|
||||||
retransmission requests, the round trips and the recovery times, each part chained to the
|
retransmission requests, the round trips and the recovery times, each part chained to the
|
||||||
one before and naming the head of every media track's receipt chain; a verifier recomputes
|
one before and naming the head of every media track's receipt chain; a verifier recomputes
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
> session under its room grant; its encoder sends an MPEG transport stream over the
|
> session under its room grant; its encoder sends an MPEG transport stream over the
|
||||||
> transport; the gateway demultiplexes it and carries each access unit as one envelope on
|
> transport; the gateway demultiplexes it and carries each access unit as one envelope on
|
||||||
> the room's tracks with first-hop receipts, as it carries a WHIP publisher's frames.
|
> the room's tracks with first-hop receipts, as it carries a WHIP publisher's frames.
|
||||||
> Registers the record `wai.live.contribution`: the **contribution link record**, `WCL1`,
|
> Registers the record `wai.live.contribution`: the **contribution link record**, `WLK1`,
|
||||||
> which the gateway signs part by part while the link runs: what became of every sequence
|
> which the gateway signs part by part while the link runs: what became of every sequence
|
||||||
> number (delivered at the first try, recovered within the receive window, dropped when its
|
> number (delivered at the first try, recovered within the receive window, dropped when its
|
||||||
> time passed, or outstanding when the link ended), the retransmission requests and the
|
> time passed, or outstanding when the link ended), the retransmission requests and the
|
||||||
|
|
@ -339,7 +339,7 @@ measured before the first sequence number fall into the first part.
|
||||||
|
|
||||||
| field | size | meaning |
|
| field | size | meaning |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `magic` | 4 | `WCL1` (ASCII) |
|
| `magic` | 4 | `WLK1` (ASCII) |
|
||||||
| `version` | 1 | 1 |
|
| `version` | 1 | 1 |
|
||||||
| `room` | 32 | the room id |
|
| `room` | 32 | the room id |
|
||||||
| `hop` | 32 | the gateway's key, which signs the record and the tracks' receipts |
|
| `hop` | 32 | the gateway's key, which signs the record and the tracks' receipts |
|
||||||
|
|
@ -416,8 +416,9 @@ fails, with its reason:
|
||||||
1. The record is at most 11 295 bytes (§6.7): otherwise `record_too_large`.
|
1. The record is at most 11 295 bytes (§6.7): otherwise `record_too_large`.
|
||||||
2. It reads, field by field in §6.2's order, to exactly its last byte, with `tracks` at most
|
2. It reads, field by field in §6.2's order, to exactly its last byte, with `tracks` at most
|
||||||
8 and runs at most 512: `truncated` when it ends early; `unknown_version` for a version
|
8 and runs at most 512: `truncated` when it ends early; `unknown_version` for a version
|
||||||
other than 1; `malformed` for another magic, a byte after `sig`, a count past its bound,
|
other than 1; `malformed` for another magic (live-recording §5.1's clip record, `WCL1`,
|
||||||
or a `last` or `truncated` other than 0 and 1.
|
among them), a byte after `sig`, a count past its bound, or a `last` or `truncated` other
|
||||||
|
than 0 and 1.
|
||||||
3. The signature verifies under `hop`, strictly, as SPEC §7 *Signatures* requires: a key
|
3. The signature verifies under `hop`, strictly, as SPEC §7 *Signatures* requires: a key
|
||||||
that fails that rule's steps 1 or 2 is `bad_key`, a signature that fails a later step
|
that fails that rule's steps 1 or 2 is `bad_key`, a signature that fails a later step
|
||||||
`bad_signature`.
|
`bad_signature`.
|
||||||
|
|
|
||||||
|
|
@ -345,8 +345,9 @@ start and `trim_out` at the end; the clip's bytes are its parts'.
|
||||||
### 5.2 Reading and rules
|
### 5.2 Reading and rules
|
||||||
|
|
||||||
A reader reads exactly the bytes it is given, as live-events §3.3 reads a record with
|
A reader reads exactly the bytes it is given, as live-events §3.3 reads a record with
|
||||||
`WCL1` for `WEV1` (`truncated`, `malformed`, `unknown_version`), and refuses a record that
|
`WCL1` for `WEV1` (`truncated`, `malformed`, `unknown_version`; another magic is
|
||||||
breaks any of these rules as `clip_record_invalid`:
|
`malformed`, live-contribution §6.2's link record, `WLK1`, among them), and refuses a
|
||||||
|
record that breaks any of these rules as `clip_record_invalid`:
|
||||||
|
|
||||||
- *k* is 1 to 16, and no take is named by two parts;
|
- *k* is 1 to 16, and no take is named by two parts;
|
||||||
- in each part, `count` is at least 1; each chunk's `index` is `first` plus its position,
|
- in each part, `count` is at least 1; each chunk's `index` is `first` plus its position,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# links — the contribution link record, `WCL1`
|
# links — the contribution link record, `WLK1`
|
||||||
|
|
||||||
The corpus of [live-contribution](../../extensions/live-contribution.md) §6: parts of the
|
The corpus of [live-contribution](../../extensions/live-contribution.md) §6: parts of the
|
||||||
link record a gateway signs while it receives an SRT or RIST link, and series of them.
|
link record a gateway signs while it receives an SRT or RIST link, and series of them.
|
||||||
|
|
@ -8,7 +8,7 @@ link record a gateway signs while it receives an SRT or RIST link, and series of
|
||||||
the index of the part refused), for an accepted part its `digest` and a `summary` of its
|
the index of the part refused), for an accepted part its `digest` and a `summary` of its
|
||||||
fields, and a `note` on what it shows. `hop` is the signing key, `hop_seed` the seed it is
|
fields, and a `note` on what it shows. `hop` is the signing key, `hop_seed` the seed it is
|
||||||
made from, so anyone can sign a new vector the same way.
|
made from, so anyone can sign a new vector the same way.
|
||||||
- Each `.wcl1` file is one record's bytes.
|
- Each `.wlk1` file is one record's bytes.
|
||||||
|
|
||||||
Accepted vectors cover each protocol and mode, each key length, a session's last part with
|
Accepted vectors cover each protocol and mode, each key length, a session's last part with
|
||||||
sequence numbers outstanding, a part whose loss runs are truncated, tracks not yet begun,
|
sequence numbers outstanding, a part whose loss runs are truncated, tracks not yet begun,
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
wai/live-conformance/links/series_other_cipher.0.wlk1
Normal file
BIN
wai/live-conformance/links/series_other_cipher.0.wlk1
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
wai/live-conformance/links/series_other_grant.0.wlk1
Normal file
BIN
wai/live-conformance/links/series_other_grant.0.wlk1
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
wai/live-conformance/links/series_other_hop.0.wlk1
Normal file
BIN
wai/live-conformance/links/series_other_hop.0.wlk1
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
wai/live-conformance/links/series_other_mode.0.wlk1
Normal file
BIN
wai/live-conformance/links/series_other_mode.0.wlk1
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
wai/live-conformance/links/series_other_principal.0.wlk1
Normal file
BIN
wai/live-conformance/links/series_other_principal.0.wlk1
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
wai/live-conformance/links/series_other_protocol.0.wlk1
Normal file
BIN
wai/live-conformance/links/series_other_protocol.0.wlk1
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
wai/live-conformance/links/series_other_room.0.wlk1
Normal file
BIN
wai/live-conformance/links/series_other_room.0.wlk1
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
wai/live-conformance/links/series_other_session.0.wlk1
Normal file
BIN
wai/live-conformance/links/series_other_session.0.wlk1
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
wai/live-conformance/links/series_other_window.0.wlk1
Normal file
BIN
wai/live-conformance/links/series_other_window.0.wlk1
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
wai/live-conformance/links/series_part_after_last.1.wlk1
Normal file
BIN
wai/live-conformance/links/series_part_after_last.1.wlk1
Normal file
Binary file not shown.
Binary file not shown.
BIN
wai/live-conformance/links/series_sequence_gap.0.wlk1
Normal file
BIN
wai/live-conformance/links/series_sequence_gap.0.wlk1
Normal file
Binary file not shown.
Binary file not shown.
BIN
wai/live-conformance/links/series_sequence_gap.1.wlk1
Normal file
BIN
wai/live-conformance/links/series_sequence_gap.1.wlk1
Normal file
Binary file not shown.
Binary file not shown.
BIN
wai/live-conformance/links/series_skips_a_part.0.wlk1
Normal file
BIN
wai/live-conformance/links/series_skips_a_part.0.wlk1
Normal file
Binary file not shown.
Binary file not shown.
BIN
wai/live-conformance/links/series_skips_a_part.1.wlk1
Normal file
BIN
wai/live-conformance/links/series_skips_a_part.1.wlk1
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
wai/live-conformance/links/series_starts_late.0.wlk1
Normal file
BIN
wai/live-conformance/links/series_starts_late.0.wlk1
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
wai/live-conformance/links/series_three_parts.0.wlk1
Normal file
BIN
wai/live-conformance/links/series_three_parts.0.wlk1
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue