54b75c9be4
apple / swift (push) Successful in 55s
windows-host / package (push) Successful in 2m31s
android / android (push) Successful in 4m40s
ci / rust (push) Successful in 4m43s
ci / web (push) Successful in 30s
ci / docs-site (push) Successful in 34s
deb / build-publish (push) Successful in 2m9s
decky / build-publish (push) Successful in 11s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 14s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 21s
ci / bench (push) Successful in 4m44s
docker / deploy-docs (push) Successful in 19s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 8m6s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 8m19s
Follows the security audit (#5/#9): the GameStream-compat plane carries inherent on-path weaknesses that can't be fixed on the wire without breaking stock Moonlight — its pairing runs over plain HTTP (#9, MITM-able during the pairing window) and its legacy control encryption can reuse GCM nonces (#5, a passive eavesdropper can recover/forge input). The native punktfunk/1 plane (SPAKE2 PIN pairing + per-direction AEAD nonces) has neither. So flip the default to secure-by-default: - `serve` → native punktfunk/1 plane + management API ONLY (no GameStream surface). - `serve --gamestream` → ALSO the GameStream/Moonlight-compat planes (nvhttp pairing, RTSP, ENet control, _nvstream mDNS). Opt-in, logged with a trusted-LAN caveat. `--moonlight` is an alias. - The native plane is now ALWAYS on in `serve` (`--native` is a kept-for-compat no-op); the unified GameStream+native host is `serve --gamestream`. `gamestream::serve` gates the GameStream spawns (nvhttp/rtsp/control/mdns) on the flag; the native plane + mgmt + native-pairing handle always run. To avoid silently regressing validated Moonlight deployments, the explicit deployment configs PRESERVE Moonlight via `--gamestream` (each documents dropping it for a secure native-only host): the Linux systemd unit, the Steam Deck installer, and the Windows service default (DEFAULT_HOST_CMD). The bare `serve` default (new/manual use) is secure. Docs swept to match (host-cli, moonlight, quickstart, install, packaging READMEs, CLAUDE.md, README, …): Moonlight setup now instructs `--gamestream`; native/console refs use bare `serve`. OpenAPI regenerated (a stale "run `serve --native`" string). fmt + clippy clean; 94 host tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
147 lines
9.8 KiB
Markdown
147 lines
9.8 KiB
Markdown
# punktfunk
|
||
|
||
**Low-latency desktop and game streaming, Linux-first.** Run the host on a Linux machine — or a
|
||
Windows PC — with an NVIDIA GPU, connect from a Mac, PC, phone, tablet, or TV, and stream your desktop
|
||
or games — each device at its **own native resolution and refresh rate**, over your local network.
|
||
|
||
📖 **Documentation: [docs.punktfunk.unom.io](https://docs.punktfunk.unom.io)** — start with
|
||
[How It Works](https://docs.punktfunk.unom.io/docs/how-it-works) or the
|
||
[Quick Start](https://docs.punktfunk.unom.io/docs/quickstart).
|
||
|
||
punktfunk pairs a **virtual-display streaming host** with native clients on every platform. It speaks
|
||
the existing **GameStream** protocol, so any [Moonlight](https://moonlight-stream.org/) client works
|
||
day one — and adds its own faster **`punktfunk/1`** protocol that breaks the ~1 Gbps FEC wall with a
|
||
**GF(2¹⁶) Leopard-RS** transport. A single shared **Rust core** (`punktfunk-core`) holds the
|
||
protocol, FEC, and crypto, linked into the host and every client over a stable C ABI.
|
||
|
||
## What makes it different
|
||
|
||
- **Your device's exact mode.** For each client that connects, the host spins up a virtual display
|
||
sized to that device — 1080p60 to a laptop, 1440p120 to a desktop, 4K to a TV, all at once. No
|
||
letterboxing, no scaling, no rearranging your real monitors.
|
||
- **Low latency, GPU end to end.** Frames go straight from the compositor to the NVENC encoder with
|
||
zero CPU copies (dmabuf → CUDA/Vulkan → NVENC), over a transport tuned for responsiveness rather
|
||
than throughput. Stable 240 fps at 5120×1440; sub-millisecond capture-to-reassembly on a LAN.
|
||
- **Works with what you already have.** Any Moonlight/Artemis client connects over GameStream — and
|
||
native apps for macOS, Linux, Windows, and Android use the lower-latency `punktfunk/1` protocol.
|
||
- **Secure by default.** Hosts require a one-time SPAKE2 **PIN pairing**; after that, devices
|
||
reconnect on a pinned identity. No accounts, no cloud. Hosts auto-advertise over mDNS, so clients
|
||
find them on the network without typing an IP.
|
||
|
||
## Status
|
||
|
||
| Component | State |
|
||
|-----------|-------|
|
||
| **Core** — `punktfunk-core` + C ABI (protocol · FEC · crypto · QUIC) | ✅ Complete & hardened |
|
||
| **GameStream host** → stock Moonlight | ✅ Live end-to-end: pairing, RTSP, audio, per-client virtual output at native resolution, GPU zero-copy NVENC, gamepads |
|
||
| **Native protocol** — `punktfunk/1` | ✅ Validated live: QUIC control + GF(2¹⁶) FEC/AES-GCM data plane, PIN pairing, mDNS discovery, mid-stream mode renegotiation |
|
||
| **Windows host** (NVIDIA, x64) | 🟡 Implemented & shipping as a signed installer (DXGI capture · SudoVDA virtual display · NVENC · WASAPI · ViGEm); NVIDIA-only, newer than the Linux host |
|
||
| **macOS / iOS / tvOS client** (`clients/apple`) | ✅ Streaming live: VideoToolbox decode, controllers incl. DualSense, discovery, pairing, speed test |
|
||
| **Linux client** (`clients/linux`, GTK4) | ✅ Streaming live: FFmpeg + VAAPI zero-copy decode, PipeWire audio, SDL3 controllers; ships as Flatpak/apt/rpm/Arch |
|
||
| **Android client** (`clients/android`, phone + TV) | ✅ Streaming live: AMediaCodec decode + HDR10, Oboe audio, controllers, discovery, pairing |
|
||
| **Windows client** (`clients/windows`, WinUI 3) | 🟡 Stage 1 complete, ships as signed MSIX (x64 + ARM64); D3D11VA decode + HDR present pending on-glass validation |
|
||
| **Web console + management API** (`web/`) | ✅ TanStack console over the OpenAPI mgmt API: host status, paired devices, on-demand PIN pairing |
|
||
|
||
The **GameStream host works with a stock Moonlight client** — validated live on NVIDIA hardware
|
||
(RTX 5070 Ti, RTX 4090): PIN pairing that persists across restarts, an app catalog, RTSP/ENet/audio,
|
||
and **video at the client's exact resolution and refresh** via a per-session virtual output (KWin,
|
||
gamescope, Mutter, and Sway/wlroots backends), encoded with GPU **zero-copy** (dmabuf → CUDA/Vulkan →
|
||
NVENC) up to 5120×1440@240. The native **`punktfunk/1`** protocol adds a QUIC control plane and a
|
||
GF(2¹⁶) Leopard-FEC + AES-GCM data plane (p50 ~0.8 ms capture→reassembled at 720p120), with
|
||
mid-stream mode renegotiation and a wall-clock skew handshake so latency stays valid across machines.
|
||
Both run from **one process**: bare `punktfunk-host serve` is the **secure native-only default**
|
||
(`punktfunk/1` + the management API/web console), and `serve --gamestream` additionally enables the
|
||
GameStream/Moonlight-compat planes (opt-in, trusted-LAN only — GameStream has inherent on-path
|
||
weaknesses). The host is managed through a REST API and web console. Builds against FFmpeg 7 or 8.
|
||
|
||
Full milestone status: **[docs.punktfunk.unom.io/docs/status](https://docs.punktfunk.unom.io/docs/status)** ·
|
||
roadmap: **[/docs/roadmap](https://docs.punktfunk.unom.io/docs/roadmap)**.
|
||
|
||
## Install the host
|
||
|
||
Pick your platform and install from its package registry — the per-platform guide covers adding the
|
||
repo, first run, and the web console. The Linux host is the primary, most battle-tested path; a
|
||
Windows host (NVIDIA-only) also ships as a signed installer.
|
||
|
||
| Platform | Install | Guide |
|
||
|--------|---------|-------|
|
||
| **Ubuntu / Debian** (apt) | `sudo apt install punktfunk-host` *(after adding the repo)* | [Ubuntu — GNOME](https://docs.punktfunk.unom.io/docs/ubuntu-gnome) · [KDE](https://docs.punktfunk.unom.io/docs/ubuntu-kde) |
|
||
| **Fedora / Bazzite** (rpm-ostree) | `rpm-ostree install punktfunk punktfunk-web` *(or the bootc image)* | [Fedora — KDE](https://docs.punktfunk.unom.io/docs/fedora-kde) · [Bazzite](https://docs.punktfunk.unom.io/docs/bazzite) |
|
||
| **Arch / Steam Deck** (PKGBUILD / sysext) | `makepkg -si` *(Arch)* · sysext `.raw` *(SteamOS)* | [packaging/arch](packaging/arch/README.md) |
|
||
| **Windows** (NVIDIA, x64) | signed `setup.exe` from the package registry | [Windows Host](https://docs.punktfunk.unom.io/docs/windows-host) |
|
||
|
||
`punktfunk-host` is the streaming host; `punktfunk-web` is the browser console (pairing + status).
|
||
After install, run `punktfunk-host serve` inside your desktop session (the secure native default;
|
||
add `--gamestream` on a trusted LAN if you also want stock Moonlight clients), then pair from the web
|
||
console. Full instructions: **[docs.punktfunk.unom.io/docs/install](https://docs.punktfunk.unom.io/docs/install)**.
|
||
|
||
## Connect a client
|
||
|
||
| Streaming to… | Use |
|
||
|---|---|
|
||
| Mac, iPhone, iPad, Apple TV | The **Apple app** (`clients/apple`) — also on TestFlight |
|
||
| Linux desktop / laptop, Steam Deck | **`punktfunk-client`** (Flatpak / apt / rpm / Arch) |
|
||
| Android phone or TV | The **Android app** (`clients/android`) |
|
||
| Windows | Native **`punktfunk-client`** (signed MSIX) or **Moonlight** |
|
||
| Anything else (browser, old phone, smart TV) | **Moonlight** over GameStream |
|
||
|
||
Each client discovers hosts on the network automatically and does a one-time
|
||
[PIN pairing](https://docs.punktfunk.unom.io/docs/pairing). Per-device install steps:
|
||
**[/docs/install-client](https://docs.punktfunk.unom.io/docs/install-client)**.
|
||
|
||
## Build & test (from source)
|
||
|
||
For development, or as an install fallback where no package is available:
|
||
|
||
```sh
|
||
cargo build --workspace # the Rust core, host, Linux client, and probe (Linux & macOS)
|
||
cargo test --workspace # unit + loopback + proptest + C ABI harness
|
||
cargo clippy --workspace --all-targets -- -D warnings
|
||
cargo fmt --all --check
|
||
|
||
cargo run -p loss-harness # FEC loss-resilience sweep (no network needed)
|
||
bash crates/punktfunk-core/tests/c/run.sh # standalone C-ABI link + round-trip proof
|
||
```
|
||
|
||
The C header regenerates from `crates/punktfunk-core/src/abi.rs` on every build (cbindgen via
|
||
`build.rs`) into `include/punktfunk_core.h`. The Apple, Android, and Windows clients have their own
|
||
toolchains (Xcode/`swift build`, Gradle, and `cargo` on the MSVC target) — see each client's README
|
||
and the [docs site](https://docs.punktfunk.unom.io).
|
||
|
||
## Layout
|
||
|
||
```
|
||
crates/
|
||
punktfunk-core/ protocol · FEC · pacing · crypto · QUIC control plane — the C ABI (lib + cdylib + staticlib)
|
||
punktfunk-host/ Linux host: virtual displays · capture · encode · input · GameStream · punktfunk/1 · mgmt
|
||
clients/
|
||
apple/ macOS / iOS / tvOS app (Swift · VideoToolbox · Metal · GameController)
|
||
linux/ Linux desktop app (Rust · GTK4/libadwaita · FFmpeg/VAAPI · PipeWire · SDL3)
|
||
windows/ Windows desktop app (Rust · WinUI 3 · D3D11 · WASAPI · SDL3)
|
||
android/ Android phone + TV app (Kotlin · Rust JNI core · AMediaCodec · Oboe)
|
||
probe/ headless reference / measurement client for punktfunk/1
|
||
decky/ Steam Deck Decky plugin
|
||
web/ web console (TanStack) over the management API — status · devices · pairing
|
||
packaging/ apt · rpm / COPR · Arch · Flatpak · Bazzite bootc image
|
||
docs-site/ public documentation site (Fumadocs) — https://docs.punktfunk.unom.io
|
||
docs/ design notes & deep-dive plans
|
||
include/punktfunk_core.h cbindgen-generated C header (checked in)
|
||
tools/ latency-probe · loss-harness (measurement)
|
||
```
|
||
|
||
## Design invariants
|
||
|
||
- **One core, linked everywhere.** Protocol, FEC, and crypto live in `punktfunk-core` exactly once,
|
||
exposed over a stable, versioned C ABI (`punktfunk_abi_version()`, `PunktfunkConfig` carries its own
|
||
`struct_size`). Every native client links the same core.
|
||
- **No async on the hot path.** The per-frame pipeline uses native threads only; `tokio`/`quinn` are
|
||
gated behind the off-by-default `quic` feature (control plane only).
|
||
- **Native client resolution, no scaling.** Each session gets a virtual output at exactly the
|
||
client's WxH@Hz; each compositor keeps its own backend behind a shared `VirtualDisplay` trait.
|
||
- **FEC is the wall-breaker.** GF(2⁸) (≤255 shards/block) for Moonlight compatibility; GF(2¹⁶)
|
||
(≤65535 shards/block, SIMD, O(n log n)) for `punktfunk/1` to push past ~1 Gbps.
|
||
|
||
## License
|
||
|
||
MIT OR Apache-2.0.
|