Skip to main content

rmt_flute/
lib.rs

1//! Multicast object-delivery wire formats: **ALC / LCT / FLUTE / NORM**.
2//!
3//! This crate parses and serializes the binary headers used to deliver files
4//! and streams over IP multicast. Every format here is **IETF RMT** (Reliable
5//! Multicast Transport) — RFC 5651, RFC 5775, RFC 6726, RFC 5740. No
6//! broadcast-specific standard is implemented by this crate.
7//!
8//! Several delivery systems are layered *on top* of these formats and are
9//! consumers of this crate rather than owners of it: **DVB** (DVB-IPTV and
10//! DVB-MABR / ETSI TS 103 769 file delivery), **3GPP** (MBMS/eMBMS download
11//! delivery), and **ATSC 3.0** (ROUTE, A/331 Annex A — written as a
12//! profile-and-delta on RFC 5651/5775/6726).
13//!
14//! Renamed from `dvb-flute` at 0.4.0: the old name named one consumer of an
15//! IETF standard rather than the standard itself, and read as a layering
16//! error once non-DVB consumers needed to depend on it. All `dvb-flute`
17//! versions are yanked; there is no shim.
18//!
19//! Implements:
20//!
21//! - [`LctHeader`] — the **Layered Coding Transport** header (RFC 5651 §5). The
22//!   fixed first word carries `V`/`C`/`PSI`/`S`/`O`/`H`/`A`/`B`, `HDR_LEN` and
23//!   the Codepoint; the `C`, `S`, `O` and `H` flags then drive the byte-widths
24//!   of the **CCI**, **TSI** and **TOI** fields (`4*(C+1)`, `4*S+2*H`,
25//!   `4*O+2*H` bytes). The shared `H` half-word feeds both TSI *and* TOI. Flag
26//!   bits and `HDR_LEN` are recomputed on serialize from the typed field
27//!   lengths — there is no raw passthrough.
28//! - [`HeaderExtension`] — the LCT/NORM header-extension chain (RFC 5651 §5.2):
29//!   variable-length (`HET` 0..=127, carries `HEL`) and fixed-length (`HET`
30//!   128..=255, one word) forms; with [`ExtTime`] (EXT_TIME) and the
31//!   [`LctExtType`] registry (EXT_NOP/EXT_AUTH/EXT_TIME).
32//! - [`AlcPacket`] — an **Asynchronous Layered Coding** packet (RFC 5775):
33//!   LCT header + an opaque FEC Payload ID + the encoding-symbol payload, plus
34//!   `EXT_FTI` (HET 64) and the Small-Block-Systematic [`FecPayloadId128`].
35//! - [`ExtFdt`] / [`ExtCenc`] — the **FLUTE** (RFC 6726) fixed-length LCT
36//!   extensions `EXT_FDT` (HET 192) and `EXT_CENC` (HET 193), plus the TOI = 0
37//!   FDT-Instance convention. The FDT Instance body is XML and is **out of
38//!   scope** of this binary crate — it rides as the packet payload.
39//! - [`NormCommonHeader`] + [`NormData`] / [`NormInfo`] / [`NormCmd`] / [`NormFeedback`] — the
40//!   **NORM** (RFC 5740) common header and message types (NORM_INFO / NORM_DATA /
41//!   NORM_CMD / NORM_NACK / NORM_ACK / NORM_REPORT).
42//! - [`SourceBlockPartition`] — the FEC Building Block's (RFC 5052 §9.1)
43//!   scheme-agnostic **Block Partitioning Algorithm**: given a transport
44//!   object's Transfer-Length, Encoding-Symbol-Length and
45//!   Maximum-Source-Block-Length, derive the number of source blocks and each
46//!   block's length in symbols. The common substrate `dvb-mabr` and
47//!   `atsc3-route` both need (issue #944) without hardcoding any FEC scheme's
48//!   FEC Payload ID or Scheme-specific OTI layout.
49//!
50//! ⚠ **FEC Payload ID** bit layouts are FEC-scheme dependent (RFC 5052 / the FEC
51//! Scheme document) and are **not** defined by ALC/NORM themselves; this crate
52//! exposes them as opaque byte slices (the caller supplies the length), with
53//! [`FecPayloadId128`] provided as one concrete illustrative layout.
54//!
55//! All integer fields are big-endian. `#![no_std]` + `alloc`; depends only on
56//! `broadcast-common`.
57//!
58//! # Examples
59//!
60//! Build an LCT header from typed fields (flag-driven CCI/TSI/TOI widths) and
61//! round-trip it:
62//!
63//! ```
64//! use rmt_flute::{LctHeader, LCT_VERSION};
65//!
66//! let cci = [0u8; 4]; // C = 0
67//! let tsi = [0u8; 4]; // S = 1, H = 0
68//! let hdr = LctHeader {
69//!     version: LCT_VERSION,
70//!     psi: 0,
71//!     close_session: false,
72//!     close_object: false,
73//!     codepoint: 0,
74//!     cci: &cci,
75//!     tsi: &tsi,
76//!     toi: &[],
77//!     extensions: vec![],
78//! };
79//! let mut buf = vec![0u8; hdr.serialized_len()];
80//! hdr.serialize_into(&mut buf).unwrap();
81//! let (re, used) = LctHeader::parse(&buf).unwrap();
82//! assert_eq!(used, buf.len());
83//! assert_eq!(re, hdr);
84//! ```
85#![no_std]
86#![cfg_attr(docsrs, feature(doc_cfg))]
87#![warn(missing_docs)]
88// Runnable examples, embedded so they render on docs.rs and stay in sync with
89// the actual `examples/*.rs` files (shown, not compiled).
90#![doc = "\n## Runnable examples\n"]
91#![doc = "Run with `cargo run -p rmt-flute --example <name>`.\n"]
92#![doc = "\n### `build_lct`\n\n```rust,ignore"]
93#![doc = include_str!("../examples/build_lct.rs")]
94#![doc = "```\n\n### `parse_flute`\n\n```rust,ignore"]
95#![doc = include_str!("../examples/parse_flute.rs")]
96#![doc = "```"]
97
98extern crate alloc;
99
100mod alc;
101mod error;
102mod ext;
103mod fec;
104mod flute;
105mod lct;
106mod lct_ext;
107mod norm;
108
109pub use alc::{
110    AlcPacket, FEC_PAYLOAD_ID_128_LEN, FecPayloadId128, HET_EXT_FTI as ALC_HET_EXT_FTI, PSI_SPI,
111};
112pub use error::{Error, Result};
113pub use ext::{FIXED_HET_MIN, HeaderExtension, WORD, chain_len, parse_chain, serialize_chain};
114pub use fec::SourceBlockPartition;
115pub use flute::{
116    CencAlgorithm, ExtCenc, ExtFdt, FDT_INSTANCE_ID_MAX, FLUTE_VERSION, HET_EXT_CENC, HET_EXT_FDT,
117    TOI_FDT,
118};
119pub use lct::{FIXED_HEADER_LEN, LCT_VERSION, LctHeader};
120pub use lct_ext::{
121    ExtTime, HET_EXT_AUTH as LCT_HET_EXT_AUTH, HET_EXT_NOP, HET_EXT_TIME, LctExtType, USE_ERT,
122    USE_SCT_HIGH, USE_SCT_LOW, USE_SLC,
123};
124pub use norm::{
125    COMMON_HEADER_LEN, FEEDBACK_FIXED_LEN, HET_EXT_AUTH as NORM_HET_EXT_AUTH, HET_EXT_CC,
126    HET_EXT_FTI as NORM_HET_EXT_FTI, HET_EXT_RATE, NORM_FLAG_EXPLICIT, NORM_FLAG_FILE,
127    NORM_FLAG_INFO, NORM_FLAG_REPAIR, NORM_FLAG_STREAM, NORM_FLAG_UNRELIABLE, NORM_INFO_FIXED_LEN,
128    NORM_NODE_ANY, NORM_NODE_NONE, NORM_VERSION, NormAckType, NormCmd, NormCmdType,
129    NormCommonHeader, NormData, NormFeedback, NormInfo, NormMessageType, SENDER_WORD_LEN,
130    SenderWord,
131};