feat: HDR Step-0 colour-metadata transport + security-audit hardening
ci / rust (push) Failing after 45s
apple / swift (push) Successful in 57s
ci / web (push) Successful in 39s
ci / docs-site (push) Successful in 38s
windows-host / package (push) Successful in 3m26s
android / android (push) Successful in 3m40s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m24s
deb / build-publish (push) Successful in 2m10s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m22s
decky / build-publish (push) Successful in 25s
ci / bench (push) Successful in 4m44s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 16s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m4s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m7s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 3m5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 2m45s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 30s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m37s
flatpak / build-publish (push) Successful in 4m17s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 8m30s
docker / deploy-docs (push) Successful in 23s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 7m53s
ci / rust (push) Failing after 45s
apple / swift (push) Successful in 57s
ci / web (push) Successful in 39s
ci / docs-site (push) Successful in 38s
windows-host / package (push) Successful in 3m26s
android / android (push) Successful in 3m40s
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 1m24s
deb / build-publish (push) Successful in 2m10s
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Successful in 1m22s
decky / build-publish (push) Successful in 25s
ci / bench (push) Successful in 4m44s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 16s
windows / build (aarch64-pc-windows-msvc) (push) Successful in 1m4s
windows / build (x86_64-pc-windows-msvc) (push) Successful in 1m7s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 3m5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 2m45s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 30s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 2m37s
flatpak / build-publish (push) Successful in 4m17s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 8m30s
docker / deploy-docs (push) Successful in 23s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 7m53s
Two strands, entangled in punktfunk1.rs, committed together (one builds-green tree). HDR pipeline Step 0 — glass-to-glass colour-metadata transport (docs/hdr-pipeline-plan.md): - Protocol/ABI: ColorInfo on the Welcome + a 0xCE HdrMeta datagram carry the source colour space + HDR10 static mastering metadata (quic.rs, abi.rs connect_ex5 fixing caps=0). - New platform-independent, unit-tested HDR static-metadata helpers (hdr.rs): chromaticities (1/50000), mastering luminance (0.0001 cd/m2), MaxCLL/MaxFALL in HDR10/ST.2086 units. - Capture/encode hooks (capture.rs, encode.rs set_hdr_meta) + Linux client / probe plumbing. Security-audit hardening — top 3 from docs/security-review.md, each adversarially verified: - #1 [HIGH] Secret file permissions. The host key.pem/cert.pem and both trust stores are now written owner-only: 0600 + dir 0700 on Unix (mirrors mgmt_token), best-effort SYSTEM/Administrators/OWNER-only icacls DACL on Windows (%ProgramData% is Users-readable). Closes a local key-disclosure -> host-impersonation gap. New gamestream::{create_private_dir, write_secret_file} + a 0600 regression test. - #2 [HIGH] Native SPAKE2 PIN is single-use. The PIN is consumed the moment the host sends its key-confirmation (which lets the client test its one guess), before reading the proof, so any completed attempt -- right OR wrong -- disarms the window. A wrong PIN isn't observable host-side (the client aborts before sending its proof), so consuming on first attempt is what delivers the documented "one online guess" instead of an unbounded brute-force of the static 4-digit PIN. Test verifies single-use. - #3 [MEDIUM] RTSP packetSize is bounded ([64,2048] in stream_config) and VideoPacketizer::new uses saturating .max(1), killing a PRE-AUTH div-by-zero/underflow panic of the video thread. Tests for {0,15,16,17} + out-of-range rejection. fmt + clippy -D warnings clean; full workspace test suite green (93 host tests). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+158
-5
@@ -70,6 +70,18 @@
|
||||
// only where available (Linux hosts); otherwise the host falls back to X-Box 360.
|
||||
#define PUNKTFUNK_GAMEPAD_DUALSENSE 2
|
||||
|
||||
// Connect to a `punktfunk/1` host and start a session at `width`x`height`@`refresh_hz`.
|
||||
// Blocks up to `timeout_ms` for the handshake. Returns NULL on failure. Equivalent to
|
||||
// [`punktfunk_connect_ex`] with `compositor = PUNKTFUNK_COMPOSITOR_AUTO`.
|
||||
//
|
||||
// Video-capability bit for [`punktfunk_connect_ex5`] (`video_caps`): the client can decode a
|
||||
// 10-bit (Main10) HEVC stream. (Mirrors `quic::VIDEO_CAP_10BIT`.)
|
||||
#define PUNKTFUNK_VIDEO_CAP_10BIT 1
|
||||
|
||||
// Video-capability bit for [`punktfunk_connect_ex5`] (`video_caps`): the client can present
|
||||
// BT.2020 PQ HDR10 (implies 10-bit). (Mirrors `quic::VIDEO_CAP_HDR`.)
|
||||
#define PUNKTFUNK_VIDEO_CAP_HDR 2
|
||||
|
||||
// 16-byte AEAD authentication tag appended by GCM.
|
||||
#define TAG_LEN 16
|
||||
|
||||
@@ -233,7 +245,8 @@
|
||||
// demultiplexed by the first byte: input = [`crate::input::INPUT_MAGIC`] (0xC8, client→host),
|
||||
// audio = [`AUDIO_MAGIC`] (0xC9, host→client), rumble = [`RUMBLE_MAGIC`] (0xCA, host→client),
|
||||
// mic = [`MIC_MAGIC`] (0xCB, client→host), rich-input = [`RICH_INPUT_MAGIC`] (0xCC, client→host),
|
||||
// HID-output = [`HIDOUT_MAGIC`] (0xCD, host→client).
|
||||
// HID-output = [`HIDOUT_MAGIC`] (0xCD, host→client), HDR metadata = [`HDR_META_MAGIC`]
|
||||
// (0xCE, host→client).
|
||||
#define PUNKTFUNK_AUDIO_MAGIC 201
|
||||
#endif
|
||||
|
||||
@@ -261,6 +274,48 @@
|
||||
#define HIDOUT_MAGIC 205
|
||||
#endif
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// HDR static-metadata datagram tag, host → client (the static analog of the per-frame VUI;
|
||||
// see [`HdrMeta`]). Next tag after [`HIDOUT_MAGIC`].
|
||||
#define HDR_META_MAGIC 206
|
||||
#endif
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// CICP colour-primaries code point: BT.709.
|
||||
#define ColorInfo_CP_BT709 1
|
||||
#endif
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// CICP colour-primaries code point: BT.2020.
|
||||
#define ColorInfo_CP_BT2020 9
|
||||
#endif
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// CICP transfer code point: BT.709.
|
||||
#define ColorInfo_TRC_BT709 1
|
||||
#endif
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// CICP transfer code point: PQ (SMPTE ST.2084).
|
||||
#define ColorInfo_TRC_PQ 16
|
||||
#endif
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// CICP transfer code point: HLG (ARIB STD-B67 / BT.2100).
|
||||
#define ColorInfo_TRC_HLG 18
|
||||
#endif
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// CICP matrix code point: BT.709.
|
||||
#define ColorInfo_MC_BT709 1
|
||||
#endif
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// CICP matrix code point: BT.2020 non-constant-luminance. (Never emit 10 / constant-luminance —
|
||||
// no client decodes it.)
|
||||
#define ColorInfo_MC_BT2020_NCL 9
|
||||
#endif
|
||||
|
||||
// Stable C ABI status codes. `Ok` is 0; all errors are negative so callers can
|
||||
// test `rc < 0`. Do not renumber existing variants — only append.
|
||||
enum PunktfunkStatus
|
||||
@@ -331,6 +386,17 @@ typedef uint8_t PunktfunkInputKind;
|
||||
#endif // __STDC_VERSION__ >= 202311L
|
||||
#endif // __cplusplus
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// Per-session colour signalling (CICP / ITU-T H.273 code points) the host resolved for the
|
||||
// encoded video, carried on [`Welcome`]. A client configures its decoder/presenter from these
|
||||
// instead of inferring them from the bitstream VUI. An older host omits the bytes on the wire →
|
||||
// [`ColorInfo::SDR_BT709`] (the 8-bit BT.709 limited stream every pre-HDR build produced).
|
||||
//
|
||||
// The *static* HDR mastering metadata (ST.2086 + content light level) is larger and can change
|
||||
// mid-stream, so it rides the [`HDR_META_MAGIC`] datagram rather than this fixed struct.
|
||||
typedef struct ColorInfo ColorInfo;
|
||||
#endif
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// Opaque handle to a live `punktfunk/1` connection (QUIC control plane + UDP data plane, all
|
||||
// pumped on internal threads).
|
||||
@@ -447,6 +513,31 @@ typedef struct {
|
||||
} PunktfunkHidOutput;
|
||||
#endif
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// Static HDR metadata for an HDR session ([`punktfunk_connection_next_hdr_meta`]): SMPTE ST.2086
|
||||
// mastering display colour volume + CEA-861.3 content light level. All fields are in the standard
|
||||
// HDR10 SEI fixed-point units (primaries/white in 1/50000, luminance in 0.0001 cd/m²), ready for
|
||||
// DXGI `DXGI_HDR_METADATA_HDR10` / Apple `CAEDRMetadata` / Android `KEY_HDR_STATIC_INFO`.
|
||||
typedef struct {
|
||||
// Display-primaries x-chromaticities in 1/50000 units, ST.2086 order [green, blue, red].
|
||||
uint16_t display_primaries_x[3];
|
||||
// Display-primaries y-chromaticities in 1/50000 units, ST.2086 order [green, blue, red].
|
||||
uint16_t display_primaries_y[3];
|
||||
// White-point x-chromaticity, 1/50000 units.
|
||||
uint16_t white_point_x;
|
||||
// White-point y-chromaticity, 1/50000 units.
|
||||
uint16_t white_point_y;
|
||||
// Max display mastering luminance, 0.0001 cd/m² units.
|
||||
uint32_t max_display_mastering_luminance;
|
||||
// Min display mastering luminance, 0.0001 cd/m² units.
|
||||
uint32_t min_display_mastering_luminance;
|
||||
// Maximum content light level (MaxCLL), nits. 0 = unknown.
|
||||
uint16_t max_cll;
|
||||
// Maximum frame-average light level (MaxFALL), nits. 0 = unknown.
|
||||
uint16_t max_fall;
|
||||
} PunktfunkHdrMeta;
|
||||
#endif
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// One rich client→host input for the host's virtual DualSense
|
||||
// ([`punktfunk_connection_send_rich_input`]): a touchpad contact or a motion sample. Set `kind`
|
||||
@@ -498,6 +589,10 @@ typedef struct {
|
||||
uint32_t send_dropped;
|
||||
} PunktfunkProbeResult;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
@@ -576,10 +671,6 @@ int32_t punktfunk_host_poll_input(PunktfunkSession *s);
|
||||
PunktfunkStatus punktfunk_get_stats(PunktfunkSession *s, PunktfunkStats *out);
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// Connect to a `punktfunk/1` host and start a session at `width`x`height`@`refresh_hz`.
|
||||
// Blocks up to `timeout_ms` for the handshake. Returns NULL on failure. Equivalent to
|
||||
// [`punktfunk_connect_ex`] with `compositor = PUNKTFUNK_COMPOSITOR_AUTO`.
|
||||
//
|
||||
// Trust: `pin_sha256` (NULL or 32 bytes) is the expected SHA-256 fingerprint of the host's
|
||||
// certificate — a mismatching host is rejected. NULL = trust on first use; persist the
|
||||
// fingerprint written to `observed_sha256_out` (NULL or 32 bytes, filled on success) and
|
||||
@@ -701,6 +792,34 @@ PunktfunkConnection *punktfunk_connect_ex4(const char *host,
|
||||
uint32_t timeout_ms);
|
||||
#endif
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// Like [`punktfunk_connect_ex4`], but additionally advertises the embedder's video decode/present
|
||||
// capabilities as `video_caps` — a bitfield of `PUNKTFUNK_VIDEO_CAP_10BIT` (can decode 10-bit
|
||||
// Main10) and `PUNKTFUNK_VIDEO_CAP_HDR` (can present BT.2020 PQ HDR10). The host upgrades to a
|
||||
// 10-bit / HDR encode ONLY when the matching bit is set (and the host opted in); `0` keeps the
|
||||
// 8-bit BT.709 SDR stream. After connecting, read the resolved colour via
|
||||
// [`punktfunk_connection_color_info`] and drain the mastering metadata via
|
||||
// [`punktfunk_connection_next_hdr_meta`].
|
||||
//
|
||||
// # Safety
|
||||
// Same as [`punktfunk_connect`]; `launch_id`, when non-NULL, must be a NUL-terminated C string.
|
||||
PunktfunkConnection *punktfunk_connect_ex5(const char *host,
|
||||
uint16_t port,
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
uint32_t refresh_hz,
|
||||
uint32_t compositor,
|
||||
uint32_t gamepad,
|
||||
uint32_t bitrate_kbps,
|
||||
uint8_t video_caps,
|
||||
const char *launch_id,
|
||||
const uint8_t *pin_sha256,
|
||||
uint8_t *observed_sha256_out,
|
||||
const char *client_cert_pem,
|
||||
const char *client_key_pem,
|
||||
uint32_t timeout_ms);
|
||||
#endif
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// Generate a persistent client identity: a self-signed certificate + private key, both
|
||||
// PEM, NUL-terminated, written into the caller's buffers. Generate ONCE, store both
|
||||
@@ -795,6 +914,40 @@ PunktfunkStatus punktfunk_connection_next_hidout(PunktfunkConnection *c,
|
||||
uint32_t timeout_ms);
|
||||
#endif
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// Pull the next static HDR metadata update (ST.2086 mastering display + content light level) for
|
||||
// an HDR session, into `*out`. [`PunktfunkStatus::NoFrame`] on timeout, [`PunktfunkStatus::Closed`]
|
||||
// once the session ended. The host sends one near session start and re-sends it on mastering
|
||||
// changes / keyframes; apply the latest to the display (`SetHDRMetaData` / `CAEDRMetadata` /
|
||||
// `KEY_HDR_STATIC_INFO`). Only an HDR session (`punktfunk_connection_color_info` reports a PQ
|
||||
// transfer) ever emits these. Same threading rules as [`punktfunk_connection_next_rumble`] (one
|
||||
// puller, may run alongside the other planes).
|
||||
//
|
||||
// # Safety
|
||||
// `c` is a valid connection handle; `out` is writable for one `PunktfunkHdrMeta`.
|
||||
PunktfunkStatus punktfunk_connection_next_hdr_meta(PunktfunkConnection *c,
|
||||
PunktfunkHdrMeta *out,
|
||||
uint32_t timeout_ms);
|
||||
#endif
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// Read the session's resolved colour signalling + encode bit depth (from the host's Welcome).
|
||||
// Each out pointer is filled when non-NULL: `primaries`/`transfer`/`matrix` are CICP code points
|
||||
// (BT.709 = 1; BT.2020 = 9; PQ transfer = 16, HLG = 18; BT.2020-NCL matrix = 9), `full_range` is
|
||||
// 0 (limited) or 1 (full), `bit_depth` is 8 or 10. A `transfer` of 16/18 means HDR — configure an
|
||||
// HDR present path and drain [`punktfunk_connection_next_hdr_meta`]. Available immediately after a
|
||||
// successful connect (these don't change without a reconfigure).
|
||||
//
|
||||
// # Safety
|
||||
// `c` is a valid connection handle; each out pointer is NULL or writable for its scalar.
|
||||
PunktfunkStatus punktfunk_connection_color_info(PunktfunkConnection *c,
|
||||
uint8_t *primaries,
|
||||
uint8_t *transfer,
|
||||
uint8_t *matrix,
|
||||
uint8_t *full_range,
|
||||
uint8_t *bit_depth);
|
||||
#endif
|
||||
|
||||
#if defined(PUNKTFUNK_FEATURE_QUIC)
|
||||
// Send one input event to the host as a QUIC datagram (non-blocking enqueue).
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user