Skip to main content

moq_net/
lib.rs

1//! # moq-net: Media over QUIC networking layer
2//!
3//! `moq-net` is the networking layer for Media over QUIC: real-time pub/sub with built-in
4//! caching, fan-out, and prioritization, on top of QUIC. Sub-second latency at massive scale.
5//! At session setup it negotiates one of two wire protocols: the simplified `moq-lite`
6//! protocol (the default) or the full IETF `moq-transport` protocol.
7//!
8//! ## API
9//! The API is built around Producer/Consumer pairs, with the hierarchy:
10//! - [origin::Consumer]: A collection of [broadcast::Consumer]s, produced by one or more [Session]s.
11//! - [broadcast::Consumer]: A collection of [track::Consumer]s, produced by a single publisher.
12//! - [track::Consumer]: A collection of [group::Info]s, delivered out-of-order until expired.
13//! - [group::Info]: A collection of [frame::Info]s, delivered in order until cancelled.
14//! - [frame::Info]: Chunks of data with an upfront size.
15//!
16//! Each level lives in its own module (`broadcast`, `track`, `group`, `frame`, `origin`,
17//! `announce`) that owns the short `Producer` / `Consumer` / `Info` names.
18//!
19//! Traffic counters for the levels above live in [`stats`]: build a [`stats::Registry`]
20//! and hand each session a [`stats::Session`] via [`Client::with_stats`] /
21//! [`Server::with_stats`]. Publishing the counters as MoQ broadcasts lives in the
22//! `moq-stats` crate.
23//!
24//! ## Compatibility
25//! The API exposes the intersection of features supported by both protocols, intentionally
26//! keeping it small rather than polluting it with half-baked features.
27//!
28//! The library is forwards-compatible with the full IETF specification and supports
29//! moq-transport drafts 14+ via version negotiation. Everything will work perfectly,
30//! so long as your application uses the API as defined above.
31//!
32//! For example, there's no concept of "sub-group". When connecting to a moq-transport
33//! implementation, we use `sub-group=0` for all frames and silently drop any received
34//! frames not in `sub-group=0`. If your application genuinely needs multiple sub-groups,
35//! tell me *why* and we can figure something out.
36//!
37//! ## Producers and Consumers
38//! Each level of the hierarchy is split into a Producer / Consumer pair:
39//! - The **Producer** is the writer: it appends new state (publishes a broadcast,
40//!   starts a group, writes frames, closes a track).
41//! - The **Consumer** is a reader: each consumer holds its own independent view
42//!   of the producer's state, with its own cursor through the stream.
43//!
44//! Both halves are cheaply clonable so you can hand out multiple handles. Cloning
45//! a consumer creates another reader (each at its own cursor); cloning a producer
46//! gives another writer that contributes to the same shared state. Closing the
47//! last producer signals consumers that no more updates are coming.
48//!
49//! ## Driving and time
50//! This library never spawns tasks or reads the clock. [`Client::connect`] and
51//! [`Server::accept`] take an initial [`time::Instant`] and return
52//! `(Session, Driver)`. Poll the [`Driver`] with the current instant and a
53//! [`kio::Waiter`], then wake on external activity or at the deadline it
54//! returns; [`time::run`] does exactly that on tokio or the browser. The last
55//! [`Session`] drop requests closure; dropping the driver cancels it.
56//!
57//! [`origin::Producer::new`] also returns a producer and driver. Its driver runs
58//! route changes, serving, linger, teardown, and the origin's cache expiration.
59//! Standalone caches expose [`cache::Pool::gc`]. Frame read/write methods
60//! clear their expiration timestamp for the next cleanup pass. Datagrams use a bounded
61//! FIFO; model read/write APIs take no wall-clock time.
62//!
63//! Both drivers implement [`time::Driver`]. `moq-uring` drives thread-local
64//! transports on its own timer heap. Tests advance time by supplying a later
65//! instant.
66
67#![warn(missing_docs)]
68// The browser transport is `!Send`, so on wasm the shared state behind these `Arc`s is
69// too and clippy suggests `Rc`. The same code is genuinely cross-thread on native, so
70// `Arc` stays and the lint is unactionable here.
71#![cfg_attr(target_arch = "wasm32", allow(clippy::arc_with_non_send_sync))]
72
73mod client;
74mod coding;
75mod driver;
76mod error;
77pub mod goaway;
78// Not part of the public API: compiled only for the crate's own tests and for the
79// `fuzz/` harness.
80#[cfg(any(test, feature = "fuzz"))]
81#[doc(hidden)]
82pub mod fuzz;
83mod ietf;
84mod lite;
85mod model;
86pub mod path;
87mod recv;
88pub mod setup;
89mod tail;
90#[cfg(test)]
91mod test_interop;
92mod util;
93mod version;
94
95mod runtime;
96pub mod server;
97pub mod session;
98pub mod stats;
99pub mod time;
100pub mod transport;
101
102pub use client::*;
103pub use coding::{BoundsExceeded, DecodeError, EncodeError, VarInt};
104pub use driver::Driver;
105pub use error::*;
106/// The session direction a client advertises in its SETUP (moq-lite-05+).
107pub use lite::Role;
108pub use model::*;
109pub use path::{AsPath, InvalidPattern, Path, PathOwned, Pattern, Patterns};
110pub use server::Server;
111pub use session::Session;
112pub use version::*;
113
114// Re-export the bytes crate
115pub use bytes;
116
117// Re-export the transport trait, since it bounds the Client/Server entry points.
118pub use web_transport_trait;
119
120// Re-export the kio crate, since it appears in the public API (e.g. poll_* waiters).
121pub use kio;