871ebb31ce
Client-side supersampling/downscaling: the client asks the host to render and encode at chosen-resolution × scale (the host does no scaling) and the presenter rescales the decoded frame to the display. >1 supersamples for sharpness; <1 lightens the host GPU and the link. Default 1.0 = Native, the prior behavior. The geometry lives once in punktfunk_core::render_scale (multiply, preserve aspect ratio, floor to even, clamp to the codec's per-axis ceiling — 4096 for H.264, 8192 otherwise), the Rust twin of the Apple client's RenderScale.swift, consumed by the native session client, the presenter's match-window path, the Windows/Linux settings UIs, Decky, and Android (settings + host connect + unit test). Implemented and platform-verified by the Apple-client-features session (Linux+Android+Apple green there); the punktfunk-core wiring (pub mod render_scale) is restored here after being lost in a working-tree reconciliation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
95 lines
4.9 KiB
Rust
95 lines
4.9 KiB
Rust
//! # punktfunk-core
|
||
//!
|
||
//! The shared protocol / transport / FEC core for the punktfunk low-latency streaming
|
||
//! stack. It is compiled exactly once and linked by every host and client — directly
|
||
//! as a Rust `lib`, or across the [C ABI](crate::abi) by Swift / Kotlin / C clients.
|
||
//!
|
||
//! Everything platform-specific (capture, encode, decode, present, input injection)
|
||
//! lives *outside* this crate. What lives *here*:
|
||
//!
|
||
//! - [`fec`] — erasure coding. GF(2⁸) for GameStream/Moonlight compatibility (P1) and
|
||
//! GF(2¹⁶) Leopard-RS (P2) which removes the ~1 Gbps per-frame shard-count ceiling.
|
||
//! - [`packet`] — `#[repr(C)]` zero-copy wire framing: splitting an access unit into
|
||
//! FEC blocks of MTU-sized shards and reassembling them on the far side.
|
||
//! - [`crypto`] — AES-128-GCM session sealing, matching GameStream in P1.
|
||
//! - [`session`] — the host (submit frame → FEC → packetize → seal → send) and client
|
||
//! (recv → open → reorder → FEC recover → reassemble) state machines.
|
||
//! - [`transport`] — pluggable packet I/O (in-process loopback for tests; UDP for real).
|
||
//! - [`abi`] — the `extern "C"` surface and `cbindgen`-generated `punktfunk_core.h`.
|
||
//!
|
||
//! ## Threading contract
|
||
//!
|
||
//! Nothing in the per-frame path touches an async runtime. `tokio`/`quinn` are gated
|
||
//! behind the off-by-default `quic` feature and used only for the control plane.
|
||
|
||
#![forbid(unsafe_op_in_unsafe_fn)]
|
||
|
||
pub mod abi;
|
||
#[cfg(feature = "quic")]
|
||
mod abr;
|
||
pub mod audio;
|
||
#[cfg(feature = "quic")]
|
||
pub mod client;
|
||
/// Client-side shared-clipboard transport: the per-session task that runs the fetch-stream accept
|
||
/// loop, drives outbound fetches, and serves inbound ones — surfaced to the embedder as poll
|
||
/// events. Wire codecs live in [`quic`]; the OS pasteboard integration lives in the native client.
|
||
#[cfg(feature = "quic")]
|
||
pub mod clipboard;
|
||
pub mod config;
|
||
pub mod crypto;
|
||
pub mod error;
|
||
pub mod fec;
|
||
pub mod input;
|
||
pub mod packet;
|
||
#[cfg(feature = "quic")]
|
||
pub mod quic;
|
||
pub mod reanchor;
|
||
pub mod reject;
|
||
pub mod render_scale;
|
||
pub mod session;
|
||
pub mod stats;
|
||
#[cfg(feature = "tls")]
|
||
pub mod tls;
|
||
pub mod transport;
|
||
pub mod wol;
|
||
|
||
pub use config::{CompositorPref, Config, FecConfig, FecScheme, Mode, ProtocolPhase, Role};
|
||
pub use error::{PunktfunkError, PunktfunkStatus, Result};
|
||
pub use session::{Frame, Session};
|
||
pub use stats::Stats;
|
||
|
||
/// Bump on any breaking change to the [C ABI](crate::abi). Mirrors
|
||
/// `punktfunk_abi_version()` and is checked by clients before use.
|
||
///
|
||
/// v2: `punktfunk_connect` gained `client_cert_pem`/`client_key_pem` (pairing identities);
|
||
/// added `punktfunk_pair` / `punktfunk_generate_identity` / `punktfunk_connection_request_mode`.
|
||
/// v3: added `punktfunk_wake_on_lan` (Wake-on-LAN magic packet; the host's wake MAC(s) reach
|
||
/// clients out-of-band via the mDNS `mac` TXT record, so no connection is required to wake).
|
||
/// v4: added `punktfunk_probe` (bounded, trust-agnostic, mDNS-independent reachability handshake —
|
||
/// the display-side companion to dial-first, so saved-host "online" pips reflect real reachability).
|
||
/// v5: added `punktfunk_connection_next_rumble2` (rumble pull that also yields the self-terminating
|
||
/// TTL of a v2 envelope; `punktfunk_connection_next_rumble` is unchanged and drops it). Additive —
|
||
/// the wire is backward-compatible (the envelope is a length-tolerant tail on 0xCA), so
|
||
/// [`WIRE_VERSION`] is unchanged.
|
||
/// v6: added the `punktfunk_reanchor_gate_*` surface (post-loss freeze-until-reanchor gate for the
|
||
/// Swift client; Rust embedders use [`reanchor::ReanchorGate`] directly). Additive, client-local —
|
||
/// no wire change, so [`WIRE_VERSION`] is unchanged.
|
||
/// v7: added `punktfunk_connect_ex8` (`status_out` — typed connect-failure reporting, including
|
||
/// the host-rejection block `PUNKTFUNK_STATUS_REJECTED_*` decoded from the host's QUIC
|
||
/// application close) and the `PunktfunkStatus` −20 block itself. Additive — the close codes are
|
||
/// new application-close vocabulary an old peer simply never sends/reads, so [`WIRE_VERSION`] is
|
||
/// unchanged.
|
||
/// v8: added the shared-clipboard client surface — `punktfunk_connection_host_caps` and
|
||
/// `punktfunk_connection_clipboard_{control,offer,fetch,serve,cancel}` +
|
||
/// `punktfunk_connection_next_clipboard`. Additive; the wire grows only backward-compatible control
|
||
/// messages (0x40-0x44) and a new `Welcome::host_caps` bit, so [`WIRE_VERSION`] is unchanged.
|
||
pub const ABI_VERSION: u32 = 8;
|
||
|
||
/// The punktfunk/1 **wire** version — what `Hello`/`Welcome` carry and hosts equality-check.
|
||
/// Deliberately its own constant: [`ABI_VERSION`] tracks the embeddable **C surface**
|
||
/// (functions a client links), which can grow without changing a single wire byte — v3's
|
||
/// `punktfunk_wake_on_lan` is client-local, and riding the C-ABI bump onto the wire locked
|
||
/// every new client out of every deployed host ("ABI mismatch: client 3 host 2", observed
|
||
/// live). Bump this ONLY when the handshake/planes actually change incompatibly.
|
||
pub const WIRE_VERSION: u32 = 2;
|