Dependency currency wave: skia-safe 0.99, the RustCrypto digest-0.11 family, jni 0.22 and ten more — plus the notices they invalidated #193
Merged
enricobuehler
merged 26 commits from 2026-08-13 12:41:57 +00:00
worktree-dep-currency-wave into main
26
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4903c9d3b5 |
docs(host): the P-256 identity comment still named ring's backend
ci / docs-site (pull_request) Successful in 1m25s
apple / swift (pull_request) Successful in 2m15s
apple / distribute (pull_request) Skipped
apple / screenshots (pull_request) Skipped
ci / bun-nix (pull_request) Successful in 2m33s
ci / web (pull_request) Successful in 3m26s
windows-client / client (arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (pull_request) Successful in 6m20s
android / android (pull_request) Successful in 7m34s
windows-client / client (x64, , x86_64-pc-windows-msvc, C:\t) (pull_request) Successful in 9m4s
ci / rust-arm64 (pull_request) Successful in 16m13s
nix / flake (pull_request) Successful in 16m36s
ci / rust (pull_request) Successful in 47m49s
#192 moved rcgen to aws-lc-rs and removed ring from the tree, but this comment still explained the P-256 path in terms of "rcgen's ring backend". It also cross-references gamestream::cert's note, which this branch already corrected — so leaving it made the two contradict each other. The substance is unchanged and still load-bearing: rcgen generates EC keys directly, while RSA has to be generated by the `rsa` crate and handed to rcgen to self-sign, because no rcgen backend will generate an RSA key. |
||
|
|
a4af1ee8bd |
chore(deps): regenerate third-party notices for the currency wave
Covers all five generated files, not just the root one: the four per-client copies are scoped to the binaries their package installs, so they move independently of the workspace-wide file. Root: 571 -> 575 crates, reflecting this wave (skia-safe 0.99, the RustCrypto digest-0.11 family, jni 0.22, x11rb 0.14, reis 0.7, xkbcommon 0.9, wasapi 0.24, windows-service 0.8.1, x509-parser 0.18, rand 0.9, base64 0.23, libloading 0.9, mdns-sd 0.21 + if-addrs 0.15, rcgen 0.14, criterion 0.8, android_logger 0.15). The per-client diffs are much larger than the wave alone explains, because they were never regenerated after #192: all four still attributed `ring` and named no aws-lc-rs at all. Since #192 removed ring from the tree entirely, the shipped Acknowledgements screens have been crediting a crypto library the clients do not carry while omitting the one they do. They now catch up on both changes at once. (`ring` still appears via the generator's deliberate `--all-features` over-approximation, which sees quinn-proto's wasm-only edge; that is by design — listing an unlinked crate is untidy, omitting a linked one is the failure the file exists to prevent.) Also stops gen-third-party-notices.sh preferring `cargo about` for the root file. That preference was silently destructive: cargo-about only sees CARGO dependencies, so it drops every VENDORED_TREES entry -- pyrowave, the Granite subset, volk, Vulkan-Headers, the Font Awesome brand icons, Simple Icons -- which are third-party sources shipped inside first-party crates under their own licences. Measured today: cargo-about emitted 7,274 lines / ~514 crates with zero mentions of volk, Vulkan-Headers or Font Awesome, against the python generator's 17,324 / 575 with all of them. Merely having cargo-about on PATH was enough to degrade the file, so anyone regenerating after this commit would have undone it. cargo-about remains what the CI licence gate runs -- that job asks a different question (is every licence in the about.toml allowlist) and writes to /dev/null. Both licence-gate legs pass: `cargo about generate about.hbs --fail` and the drivers-workspace leg, RC=0. |
||
|
|
5cd4da4b46 |
Merge branch 'worktree-agent-a3a9cb8eda476b361' into worktree-dep-currency-wave
# Conflicts: # Cargo.lock # crates/punktfunk-host/Cargo.toml |
||
|
|
59346b46dc | Merge branch 'worktree-agent-acec77fec2148a724' into worktree-dep-currency-wave | ||
|
|
76b80cffb5 | Merge branch 'worktree-agent-aaab7ab43ea5de9c8' into worktree-dep-currency-wave | ||
|
|
9e492bfec3 | Merge branch 'worktree-agent-a5cf35a576dde87f5' into worktree-dep-currency-wave | ||
|
|
692bfbaa4f | Merge branch 'worktree-agent-a220ca550d5f8734b' into worktree-dep-currency-wave | ||
|
|
f9932e0873 | Merge branch 'worktree-agent-a61772a0f20a2e4f1' into worktree-dep-currency-wave | ||
|
|
bd987d373e |
chore(deps): criterion 0.5 -> 0.8 (dev-only, benches)
Dev-dependency of punktfunk-core only — it ships in nothing. `default-features =
false, features = ["cargo_bench_support"]` carries over unchanged; that feature
still exists in 0.8 and still keeps plotters/rayon out of a headless CI run.
One source change, and it is a lint issue rather than an API one.
`criterion::black_box` survives in 0.8 but is `#[deprecated]` — it now just
forwards to `std::hint::black_box` — and benches ARE compiled by
`cargo clippy --workspace --all-targets -- -D warnings`, so keeping the criterion
import would have turned a deprecation warning into a failed lint gate. The
bench imports the std one directly.
What CI actually consumes from criterion is the on-disk result layout, so that
was checked rather than assumed: 0.8 still writes
`target/criterion/<group>/<id>/new/estimates.json`, and the key
scripts/bench/compare.py reads — `median.point_estimate` — is still there:
$ cargo bench -p punktfunk-core --bench pipeline -- --warm-up-time 1 --measurement-time 3
... 12/12 benchmarks reported, e.g. pipeline/gf16/1048576 thrpt: [537 MiB/s 540 MiB/s 542 MiB/s]
$ find target/criterion -name estimates.json | wc -l
24
$ python3 -c 'import json; print(json.load(open(".../crypto/seal/new/estimates.json"))["median"]["point_estimate"])'
817.96
Verified on CachyOS (rustc 1.96.0):
cargo clippy -p punktfunk-core --all-targets --locked -- -D warnings OK (this is what compiles the bench)
cargo clippy --workspace --all-targets --locked -- -D warnings OK
cargo bench -p punktfunk-core --bench pipeline --locked -- --test 12/12 Success
cargo bench -p punktfunk-core --bench pipeline --locked -- --warm-up-time 1 --measurement-time 3 OK (CI's exact line)
cargo test -p punktfunk-core --locked 210 + 8 + 1 passed, 0 failed
cargo fmt --all --check clean
|
||
|
|
deb83ecc48 |
chore(deps): rcgen 0.13 -> 0.14 in core and the host
Both declarations keep `default-features = false, features = ["aws_lc_rs",
"pem"]`, which stays load-bearing in 0.14: `ring` is still in rcgen's DEFAULT
feature set, so dropping `default-features = false` would drag the backend this
tree deliberately left back in. Verified after the bump — `cargo tree -i ring`
finds nothing on x86_64-unknown-linux-gnu, x86_64-pc-windows-msvc,
aarch64-apple-darwin or aarch64-linux-android.
One breaking change reached us. `CertifiedKey`'s key field was renamed
`key_pair` -> `signing_key` (the struct is now generic, `CertifiedKey<S:
SigningKey>`), which hits the two `generate_simple_self_signed` callers in
core's quic/endpoint.rs — the dev/test server endpoint and `generate_identity`.
Both are a field rename; `KeyPair` still provides `serialize_der`/`serialize_pem`.
Everything the GAMESTREAM identity depends on survives unchanged, which is what
this bump's precondition was about: `KeyPair::from_pkcs8_pem_and_sign_algo`,
`PKCS_RSA_SHA256`, `CertificateParams::new`, `date_time_ymd`, `self_signed`,
`Certificate::pem`. The split in gamestream/cert.rs is therefore untouched — the
RSA-2048 key is still minted by the `rsa` crate and handed to rcgen only to load
and self-sign, because rcgen cannot generate an RSA key on the backend we use.
That path is asserted, not assumed:
cargo test -p punktfunk-host --bins --locked gamestream::cert 3 passed, 0 failed
generate_mints_a_loadable_rsa2048_identity ok (fresh-install keygen)
moonlight_shaped_peer_completes_a_tls12_mutual_handshake ok
tls13_negotiates_the_post_quantum_group ok (X25519MLKEM768 by name)
Verified on CachyOS (rustc 1.96.0):
cargo clippy --workspace --all-targets --locked -- -D warnings OK
cargo clippy -p punktfunk-host -p punktfunk-core --locked -- -D warnings OK (shipping build)
cargo test --workspace --locked 78 test binaries, all ok, 0 failed
cargo fmt --all --check clean
|
||
|
|
2718b7d4bd |
chore(deps): mdns-sd 0.20 -> 0.21 and if-addrs 0.13 -> 0.15, together
One commit because splitting them accomplishes nothing: mdns-sd 0.20 ALREADY
depends on if-addrs 0.15, so while our own five crates declared 0.13 the tree
carried both copies no matter which of the two moved first. Moving them together
is what collapses it:
$ cargo tree -d | grep '^if-addrs'
(no output)
Neither needed a source change. mdns-sd 0.21's public API is purely additive
over 0.20.3 — the sole new item is `ServiceDaemon::set_max_packet_size`, and
`ServiceInfo`'s surface is byte-identical — so `ServiceDaemon`/`ServiceInfo`/
`ServiceEvent`/`ResolvedService` behave as before at all six call sites
(host discovery + gamestream mdns, pf-client-core, and the Android, Windows and
probe clients). if-addrs 0.15 keeps 0.13's `Interface`/`IfAddr` shape, and we
only ever read those.
The one real change is a FEATURE, not a version. if-addrs has `link-local`, and
mdns-sd declares if-addrs with it on. Once our crates share that single copy,
unification turns it on for our calls too — meaning `get_if_addrs()` now also
reports fe80:: interfaces (and, on Windows, 169.254.x.x). Rather than inherit
that silently, punktfunk-core and punktfunk-host now NAME the feature. Two
reasons: it is what every real build gets anyway, so a standalone `cargo test -p
punktfunk-core` should not enumerate a different set of NICs than the host does;
and for the consumer here — Wake-on-LAN — it is the behaviour we want, since a
NIC is wake-capable whether or not it currently holds a routable address.
Verified on CachyOS (rustc 1.96.0):
cargo clippy --workspace --all-targets --locked -- -D warnings OK
cargo test --workspace --locked OK, 0 failed
cargo test -p punktfunk-host --bins --locked 501 passed, 0 failed, 2 ignored
cargo test ... gamestream::cert 3 passed
cargo fmt --all --check clean
(One `cargo test --workspace` attempt failed with E0463 "can't find crate for
pf_frame" in a doc-test. That is the target dir having only clippy's .rmeta for
a crate a doc-test wants to LINK, not anything in this change; a plain re-run
after cargo test built the rlibs was green.)
|
||
|
|
99c3a47bbf |
chore(deps): libloading 0.8 -> 0.9 across the five crates that dlopen
All five declarations move together (pf-encode twice — Linux and Windows —
plus pf-client-core, pf-zerocopy and punktfunk-host), because a split would
have compiled two copies of a crate whose whole job is holding a process-wide
dlopen handle.
No source changes. 0.9 replaces the concrete parameter types with sealed traits
— `Library::new(impl AsFilename)` and `Library::get(impl AsSymbolName)` — and
both cover what our 16 call sites already pass: `&str` literals for the sonames
(`libnvidia-encode.so.1`, `libva.so.2`, `libnvidia-ml.so.1`, `libcuda.so.1`) and
`&[u8; N]` NUL-terminated byte literals for the symbols, which 0.9 implements
explicitly alongside `&[u8]`. MSRV rises to 1.88; the workspace pins 1.96.
libloading 0.8 does not leave the lock, and shouldn't: what remains is
`clang-sys` under `bindgen`, reached only as a BUILD-dependency of
ffmpeg-sys-next / libspa-sys / pyrowave-sys. That copy runs at build time and is
linked into nothing we ship.
Verified on CachyOS (rustc 1.96.0):
cargo clippy --workspace --all-targets --locked -- -D warnings OK
cargo clippy -p pf-encode --all-targets --locked --features nvenc,vulkan-encode,pyrowave -- -D warnings OK
(the only leg that compiles enc/linux/nvenc_cuda.rs, where the `lib.get(b"…\0")` calls live)
cargo clippy -p punktfunk-host -p pf-encode -p pf-zerocopy -p pf-client-core --locked -- -D warnings OK (shipping build)
cargo test -p punktfunk-host --bins --locked 501 passed, 0 failed, 2 ignored
cargo test -p pf-encode --locked 33 passed, 5 ignored
cargo test -p pf-zerocopy --locked 40 passed
cargo fmt --all --check clean
|
||
|
|
677b8ceb41 |
chore(deps): base64 0.22 -> 0.23 in the host and pf-update-check
ureq 3 already pulls 0.23, so the tree compiled both minors purely because our two direct declarations named the older one. The API we use — `Engine`, `engine::general_purpose::STANDARD`, `encode`/`decode` — is unchanged in 0.23; no source edits. Both are declared `default-features = false, features = ["std"]` rather than taking the defaults. 0.23 added `simd-unsafe` (hand-written AVX2/NEON engines) as a DEFAULT-ON feature, and ureq declares base64 with default features off, so today that code is not in the tree. Accepting the defaults here would unify the feature on and quietly add an unsafe SIMD engine to every artifact as a side effect of a currency bump. Whether to enable it is a perf question deserving a measurement and its own commit; this one changes versions, not exposure. `std` covers every call site (encode to `String`, decode to `Vec`). base64 0.22 does NOT leave the tree: `rcgen` -> `pem` 3.0.6 is now its sole remaining consumer, and it stays one after the rcgen 0.14 bump later in this batch — 0.14 still depends on `pem` "3.0.2", which resolves to the same 3.0.6, which still uses base64 0.22. Clearing that last copy is upstream's move (a `pem` release on 0.23), not ours. Verified on CachyOS (rustc 1.96.0): cargo clippy -p punktfunk-host -p pf-update-check --locked --all-targets -- -D warnings OK cargo clippy -p punktfunk-host -p pf-update-check --locked -- -D warnings OK (shipping build) cargo test -p punktfunk-host --bins --locked 501 passed, 0 failed, 2 ignored cargo test -p pf-update-check --locked 32 passed, 0 failed cargo fmt --all --check clean |
||
|
|
4358261387 |
chore(deps): rand 0.8 -> 0.9 in the host, the last crate speaking the old major
punktfunk-core and pf-client-core were already on 0.9; the host sat on 0.8 by
drift, not by decision, so every build compiled two rand majors to satisfy six
call sites. Mechanical at five of them (`thread_rng()` -> `rng()`,
`gen_range` -> `random_range`); the sixth is the interesting one.
`RsaPrivateKey::new` is bounded on rand_core **0.6**'s `CryptoRngCore`. rand
0.9's `ThreadRng` implements rand_core 0.9's traits — same names, different
crate — so the RSA-2048 keygen in gamestream/cert.rs stopped satisfying the
bound the moment the version moved. It now draws from `rsa::rand_core::OsRng`:
rsa's own re-export, which is by construction the traits rsa compiled against,
so the two rand_core majors never have to meet in our source. That needs
`features = ["getrandom"]` on rsa (not one of its defaults) — and it must be
declared HERE rather than left to feature unification, because dropping our own
rand 0.8 also dropped the `std` feature that used to switch `rand_core/getrandom`
on as a side effect.
What this does and does not clear. The GAMESTREAM host keeps rand 0.8 +
rand_chacha 0.3 — `rsa` drags them in through `num-bigint-dig`, which is not
ours to move:
$ cargo tree -i rand@0.8.7
rand v0.8.7
└── num-bigint-dig v0.8.6
└── rsa v0.9.10
└── punktfunk-host
The NATIVE-ONLY host (--no-default-features, no rsa) now sheds both entirely —
`cargo tree -p punktfunk-host --no-default-features --features pyrowave -i
rand@0.8.7` and the same for rand_chacha@0.3.1 both report no match. rand_core
0.6 stays in every flavour regardless: `crypto-common` (under aes-gcm) needs it,
which no rand bump can change.
`windows/install.rs`'s `random_password` is the one site a Linux box cannot
type-check; the edit there is the identical `thread_rng()` -> `rng()` the five
compiled sites took.
Verified on CachyOS (rustc 1.96.0):
cargo clippy -p punktfunk-host --locked --all-targets -- -D warnings OK
cargo clippy -p punktfunk-host --locked -- -D warnings OK (shipping build: no --all-targets)
cargo clippy -p punktfunk-host --no-default-features --features pyrowave --all-targets --locked -- -D warnings OK
cargo test -p punktfunk-host --bins --locked 501 passed, 0 failed, 2 ignored
cargo test ... gamestream::cert 3 passed (incl. the fresh-install RSA-2048 keygen)
cargo fmt --all --check clean
|
||
|
|
8020fb6711 |
chore(deps): x509-parser 0.16 -> 0.18, and thiserror 1.0 leaves the host graph
x509-parser 0.16 pinned the old asn1-rs 0.6 / der-parser 9 / oid-registry 0.7
chain, and every one of those still depended on thiserror 1.0. It was the ONLY
thing doing so — so the host compiled two thiserror majors (and two
thiserror-impl proc macros) for one crate's error types. 0.18 moves the chain to
asn1-rs 0.7 + thiserror 2, which is the same major the rest of the tree already
uses, and the 1.0 half disappears — for the host, on every target and including
dev-dependencies:
$ cargo tree -p punktfunk-host --target all -e normal,build,dev -i thiserror@1
error: package ID specification `thiserror@1` did not match any packages
Scope that claim honestly: this clears the HOST graph, not the workspace.
thiserror 1.0 is still built, reached by `jni` 0.21 AND by the vendored
`ndk` 0.9.0, both under punktfunk-client-android. That is a different graph
and a different bump.
No source change was needed. The one API shift that could have reached us —
asn1-rs 0.7 making `BitString::data` a `Cow<[u8]>` instead of a `&[u8]` — lands
on `x509.signature_value.data.to_vec()` in gamestream/cert.rs and
gamestream/pairing.rs, and `to_vec()` goes through Deref either way. Both are
Moonlight pairing-hash inputs, so they are covered by the gamestream::cert
tests rather than taken on faith. nom 7 and nom 8 were already both in the lock;
this adds no new duplicate.
Verified on CachyOS (rustc 1.96.0):
cargo clippy -p punktfunk-host --locked --all-targets -- -D warnings OK
cargo clippy -p punktfunk-host --locked -- -D warnings OK (shipping build: no --all-targets)
cargo clippy -p punktfunk-host --no-default-features --features pyrowave --all-targets --locked -- -D warnings OK
cargo test -p punktfunk-host --bins --locked 501 passed, 0 failed, 2 ignored
cargo test ... gamestream::cert 3 passed
cargo tree -i ring nothing to print
|
||
|
|
49a8f4f1d1 |
chore(deps): xkbcommon 0.8 -> 0.9
Version currency for the virtual-keyboard keymap in pf-inject's wlroots path
(`inject/linux/wlr.rs`), the crate's only consumer.
Additive on the Rust side: one new wrapper, `Keymap::key_get_mods_for_level`,
and the `extern` declaration behind it. Nothing we call changed shape -- we use
`Context::new`, `Keymap::new_from_names`, `get_as_string`, `State::new`,
`Keycode::new`, `KeyDirection` and the `serialize_mods`/`serialize_layout` pair,
all untouched. The feature set is unchanged too: `default = ["wayland"]` in both
releases, so `x11` -- the feature that would pull `as-raw-xcb-connection` -- stays
off and this links only `libxkbcommon`, exactly as before.
The one thing worth writing down is the new symbol's floor. On .25's
libxkbcommon 1.13.1 it reads
`xkb_keymap_key_get_mods_for_level@@V_1.0.0`, so the declaration wants
libxkbcommon >= 1.0.0 (2020) if it is ever referenced. Nothing in the workspace
calls the wrapper, so no relocation for it reaches our binaries -- and every ship
target clears 1.0 by years regardless (Ubuntu 22.04 is 1.4, Debian 12 is 1.5,
Debian 13 is 1.7). pf-inject's test binary, which unlike the rlib actually links,
builds and runs clean.
Two internal fixes come along, both in constructors we do not use:
`new_from_string` passes the Rust string's pointer + length to
`xkb_keymap_new_from_buffer` instead of round-tripping through a `CString`
(whose `unwrap()` panicked on an interior NUL), and `new_from_fd` passes the
full mapped `size` rather than `size - 1`.
Verified on .25 (Ubuntu 26.04, `CARGO_BUILD_JOBS=2`), all rc=0:
cargo build -p pf-inject --locked
cargo clippy -p pf-inject --locked -- -D warnings
cargo clippy -p pf-inject --all-targets --locked -- -D warnings
cargo test -p pf-inject --locked 127 passed, 0 failed, 8 ignored
+ motion_contract: 7 passed, 0 failed
cargo check -p punktfunk-host --locked
cargo clippy -p punktfunk-host --locked -- -D warnings
cargo fmt --all --check
Clippy is run BOTH ways because host CI lints without `--all-targets`.
`cargo tree -i ring` stays empty.
|
||
|
|
72c7c3b17f |
chore(deps): reis 0.6.1 -> 0.7.1
Version currency for the libei path. pf-inject is the only consumer -- reis is a
pure-Rust implementation of the EI wire protocol, so this links nothing new and
still needs no libei on the host. The release tracks libei protocol 1.5.0 ->
1.6.0.
**Nothing in our API surface moved.** `ei::Context::new`, `handshake_tokio`,
`reis::tokio::EiConvertEventStream` and `reis::event::{Device, DeviceCapability,
EiEvent, Region}` all keep their shape; `Region`'s six fields are byte-identical.
The two enums grew variants for libei 1.6's `ei_text` (`EiEvent::TextKeysym` /
`TextUtf8`, `DeviceCapability::Text`), which compiles because `handle_ei`'s match
ends in `_ => {}` and the capability set we bind is written out explicitly. The
handshake now ADVERTISES `ei_text` as a supported interface, so a 1.6 EIS may
offer one; we never bind it and never emit on it.
**Behaviour we inherit, all of it upstream bug fixes:**
- Frames now commit per device. 0.6 held one global pending queue, so an
`ei_device.frame` from device A committed device B's timestamped events under
A's timestamp. Inert for us -- we are an EI *sender*, and the events we
receive are device lifecycle plus `KeyboardModifiers`, none of which are the
timestamped kind that queue -- but strictly more correct.
- `Device::interface()` now forgets an interface when the server sends its
`destroyed` event, and `DeviceRemoved` un-registers the device's interfaces
from the converter's reverse map. Our `slot.interface::<ei::Button>()` and
friends therefore stop handing back a proxy for a torn-down interface instead
of emitting into a dead object.
- `Device`, `Seat` and `Object` now hash consistently with their `PartialEq`.
Both were already `Arc::ptr_eq`; `Hash` used the protocol object id, which is
a broken pair. We keep devices in a `Vec` and compare with `==`/`!=`, so this
changes nothing here.
- The wire backend rejects a header length above libei's 1 MiB `max_msglen`
BEFORE waiting for that many bytes, so a malformed length no longer parks the
reader until the connection dies.
**The host graph loses the `futures` facade crate.** reis's `tokio` feature
depended on `futures`; 0.7 depends on `futures-util` directly, which pf-inject
already declares. `cargo tree --target all -i futures` now names only relm4 (the
GTK Linux client), and `futures` + `futures-executor` are gone from
punktfunk-host's Linux tree (`futures-task` stays, under futures-util). Lockfile
delta is one package: `reis` 0.6.1 -> 0.7.1 with `futures` -> `futures-util` in
its dep list; the workspace package SET is unchanged, since relm4 and glib still
need those crates for the GTK client.
Verified on .25 (Ubuntu 26.04, `CARGO_BUILD_JOBS=2`), all rc=0:
cargo build -p pf-inject --locked
cargo clippy -p pf-inject --locked -- -D warnings
cargo clippy -p pf-inject --all-targets --locked -- -D warnings
cargo test -p pf-inject --locked 127 passed, 0 failed, 8 ignored
+ motion_contract: 7 passed, 0 failed
cargo check -p punktfunk-host --locked
cargo clippy -p punktfunk-host --locked -- -D warnings
cargo fmt --all --check
Clippy is run BOTH ways because host CI lints without `--all-targets`.
`cargo tree -i ring` stays empty.
|
||
|
|
d73bdcdcc1 |
chore(deps): jni 0.21 → 0.22 for the Android JNI bridge
Version currency, but a real API migration rather than a version-number edit — and the
payoff is bigger than "one crate is newer", because jni 0.22 was ALREADY in this .so:
`rustls-platform-verifier` (via quinn-proto, for Android cert verification) depends on it,
so pinning 0.21 here compiled two complete jni copies into one library. Matching the
version collapses them.
Eliminated, measured as the delta in THIRD-PARTY-NOTICES.txt (582 → 571 crates, nothing
added): jni 0.21.1, its `cesu8`, and — because jni 0.21 was the SOLE consumer of
windows-sys 0.45.0, the oldest crate in the tree — that whole windows-rs 0.42 generation:
windows-sys 0.45.0, windows-targets 0.42.2 and its seven per-arch import libraries. Eleven
crates, carried for a `cfg(windows)` dependency of an Android-only bridge.
NOT eliminated, contrary to what the sweep expected — recorded in the manifest so the next
person does not re-derive it. thiserror 1.0 and the jni-sys 0.3/0.4 split both survive,
because jni was never their only source:
thiserror 1.0.69 ← vendor/ndk 0.9.0 (+ asn1-rs/x509-parser, host side)
jni-sys 0.3.1 ← vendor/ndk 0.9.0 AND crates.io ndk-sys 0.6
jni's share of both is gone; the remainder is the ndk stack. jni-sys 0.3.1 is itself a
facade crate over 0.4.1, so the split cannot close until ndk and ndk-sys move, and `ndk` is
vendored for a one-line visibility patch — changing its dependency versions would mean
rewriting the vendored snapshot instead of reading it as a diff against upstream. Left
alone deliberately.
The migration itself, across 66 native methods in 10 files:
* `JNIEnv` split into `EnvUnowned` (the FFI-safe native-method argument) and `Env` (where
the JNI calls live). The 41 methods that never touched the environment are a type
rename; the 22 that do now acquire an `Env` inside `EnvUnowned::with_env` and map the
outcome with an `ErrorPolicy`.
* `LogErrorAndDefault` everywhere, chosen to PRESERVE behaviour: the old code swallowed
JNI errors and returned a default, and this logs and returns the same default. The
throwing policy would have been a behaviour change (new Java exceptions out of methods
that previously failed quietly), which is not what a currency bump should do.
* `with_env` also catches panics, which is exactly what the crate's own `jni_guard` did,
so the guard is folded into it where the two would have nested. It stays on the methods
that take no `Env`. ONE exception, marked at the call site: `nativeNextHidout` returns
-1 as its failure sentinel, and every error policy resolves to `T::default()` — which
for `jint` is 0, a *valid* byte count. That method keeps `jni_guard(-1, …)` outside and
uses `with_env_no_catch` inside so the sentinel survives the panic path unchanged.
* `jboolean` is `bool` in jni-sys 0.4, not `u8` — a type change, not a rename, and the
reason for most of the mechanical diff (`down != 0` → `down`, `return 0` → `false`).
* `Env::get_string` is deprecated in favour of `JString::try_to_string`, and CI runs
clippy with `-D warnings`, so the call sites moved rather than being left to warn.
Likewise `set_/get_*_array_region` → `JPrimitiveArray::set_region`/`get_region`.
* `Env::get_native_interface()` is now `Env::get_raw()` — the raw pointer handed to
`ndk::NativeWindow::from_surface`. The `as *mut _` cast next to it was already commented
as bridging jni-sys skew between `jni` and `ndk`; that skew is now real (0.4 vs 0.3)
rather than hypothetical, so the comment says so.
* Return types moved from raw `jni::sys::jstring`/`jdoubleArray`/`jintArray` to
`JString`/`JDoubleArray`/`JIntArray`, because `resolve()` requires `T: Default` and raw
pointers have no `Default`. All three are `#[repr(transparent)]` over the same
`jobject`, so the exported ABI is unchanged and `Default` IS the null reference the old
code returned explicitly.
Kotlin and Gradle needed NO changes, checked rather than assumed: every affected
`external fun` in NativeBridge.kt already declares `Boolean` / `String?` / `IntArray?` /
`DoubleArray?`, which is what these signatures still present to the JVM, and the Gradle
side only shells out to cargo-ndk without naming a jni version.
Verified on NDK 30.0.14904198, both shipping ABIs, using the environment
clients/android/kit/build.gradle.kts hands cargo-ndk:
cargo clippy -p punktfunk-client-android --all-targets -- -D warnings → ok (host)
cargo test -p punktfunk-client-android → 20 passed
cargo ndk -t arm64-v8a --platform 28 clippy … -- -D warnings → ok
cargo ndk -t armeabi-v7a --platform 28 clippy … -- -D warnings → ok
cargo ndk -t arm64-v8a -t armeabi-v7a --platform 28 build → both .so LINKED
scripts/ci/check-android-jni-imports.sh … 28 → 2 ABI(s) clean at the API-28 floor
That last one matters for this change specifically: a cdylib links with dangling undefined
symbols, so the floor check is the only thing that would catch jni 0.22 hard-importing an
NDK entry point above minSdk 28 — the shape of the 0.9.0 `System.loadLibrary` regression.
It is clean.
`cargo tree -i ring` stays empty on host and on aarch64-linux-android.
|
||
|
|
93b4c725a6 |
chore(deps): x11rb 0.13 -> 0.14
Version currency for the three crates that speak core X11: pf-capture's XFixes
cursor source, pf-vdisplay's gamescope splash client, and pf-client-core's
gamescope overlay watcher. Nothing outside the workspace pulls x11rb, so all
three move together and no two versions coexist in the lock.
**The no-libxcb property survives, which is the whole reason those manifests
say `default-features = false`.** 0.14 declares no `default` feature either, so
that flag is still the belt to the braces; `libc` and `as-raw-xcb-connection`
are still optional and still reachable only through `allow-unsafe-code`, and
`dl-libxcb` still requires it too. `cargo tree -e features -i x11rb -p
pf-capture` resolves to exactly `xfixes` -> `render` + `shape` and nothing else,
and neither `as-raw-xcb-connection` nor any other libxcb-linking crate appears
in Cargo.lock. `RustConnection` remains the only connection type, so no host or
client package gains a C dependency.
**One upstream behaviour change does land**, and it is why the `SessionBind` doc
in gamescope.rs moved. 0.14 removed the abstract-unix-socket attempt from
`rust_connection::stream` -- `ConnectAddress::Socket` is now documented as
"Connect to this Unix socket by path" -- so `@/tmp/.X11-unix/X<n>` is no longer
tried ahead of the filesystem path. That doc asserted the ATTACH route's XFixes
cursor reader reached the display over the abstract socket; it now records what
is actually load-bearing. On ATTACH the session belongs to
`gamescope-session-plus`, we arm no bind, its `/tmp` is the real one, and
`punktfunk-host.service` sets no `PrivateTmp` (nor does the NixOS host unit), so
`/tmp/.X11-unix/X<n>` is exactly where `DISPLAY` says it is. The two conditions
that would have needed the abstract fallback still cannot coincide: the bind
only arms for a resolved `punktfunk-gamescope`, whose patch level 2+ makes
`SessionPlan::gamescope_cursor` false and the reader is never spawned. The
splash client is gamescope's own nested child, inside the namespace, and reads
the bound directory directly. If those ever do have to coexist the reader logs
and retries forever and the stream runs without a composited pointer -- the doc
now says so instead of promising a fallback that no longer exists.
The rest of the 0.13.2 -> 0.14.0 delta is inert here: `AtomEnum::CUT_BUFFE_Rn`
was respelled `CUT_BUFFERn` (unused), the optional `raw-window-handle` went
0.5 -> 0.6 and `libloading`'s range widened (both features off), and the MSRV
moved 1.64 -> 1.68 against a 1.96 toolchain.
Verified on .25 (Ubuntu 26.04, `CARGO_BUILD_JOBS=2`), all rc=0:
cargo build -p pf-capture -p pf-client-core -p pf-vdisplay --locked
cargo clippy -p pf-capture -p pf-client-core -p pf-vdisplay --locked -- -D warnings
cargo clippy -p pf-capture -p pf-client-core -p pf-vdisplay --all-targets --locked -- -D warnings
cargo test -p pf-capture --locked 68 passed, 0 failed
cargo test -p pf-vdisplay --locked 210 passed, 0 failed, 3 ignored
cargo check -p punktfunk-host --locked
cargo fmt --all --check
Clippy is run BOTH ways on purpose: host CI lints without `--all-targets`, so a
`#[cfg(test)]`-only import would pass the local run and fail the shipping build.
`cargo tree -i ring` stays empty.
|
||
|
|
c814340607 |
build: drop the aarch64 --cfg aes_armv8 / polyval_armv8 flags, measured obsolete
aes 0.9 runtime-detects the ARMv8-Crypto backend on aarch64 via `cpufeatures` and polyval 0.7
picks its armv8 PMULL intrinsics by target_arch, so neither cfg exists any more — passing them
is inert. That retires a real footgun rather than tidying a file: a RUSTFLAGS env var overrides
config rustflags ENTIRELY, so every aarch64 lane that set its own (cargo-ndk does so internally
for every Android arm64-v8a build) silently dropped both and ran SOFTWARE AES on the per-packet
decrypt path.
Measured before deleting, `crypto/open_in_place` (1408-byte MTU shard, AES-128-GCM, single core,
Mac15,14 M3 Ultra, four runs back to back under identical background load):
aes 0.8 + both cfgs 2.19 GiB/s
aes 0.8, cfgs stripped 225 MiB/s ~10x cliff — reproduces the recorded ~240 MiB/s
aes 0.9 + both cfgs 5.28 GiB/s
aes 0.9, cfgs stripped 5.28 GiB/s identical to 4 s.f.
The ChaCha20-Poly1305 series of the same bench was the control and moved 0.07% across the cfg
toggle at both versions, so the toggle demonstrably reached only the AES path. A final run with
the flags actually deleted (not merely RUSTFLAGS-overridden) reproduced 5.29 GiB/s.
.cargo/config.toml is kept as a tombstone carrying that table so the flags are not reintroduced.
The two CI comments that warned about losing these cfgs to a RUSTFLAGS override are updated —
mold in ci/cargo-config-mold.toml is now the only thing such an override can cost.
|
||
|
|
1fb081a1f0 |
chore(deps): move pf-console-ui from skia-safe 0.87 to 0.99
Twelve skia-safe releases (0.88 … 0.99), carrying Skia milestones 140 through 150, every one of them breaking under 0.x semver. Only three of those changes actually reach this crate — the Vulkan surface/backend-texture path, the textlayout/paragraph typography and RuntimeEffect all came through untouched: * m143 (skia-safe 0.91) DELETED SkPath's mutating API. `Path::new()` followed by `move_to`/`line_to`/`arc_to`/`close` no longer compiles at all — geometry is built through `PathBuilder` now and frozen with `snapshot()`/`detach()`. That is the entire error list: 34 E0599s over eight call sites (the hint-bar triangles and the PlayStation triangle in `glyphs.rs`, the chevron / space / backspace / check icons in `widgets.rs`, the padlock shackle in `screens/home.rs`). Each becomes a `PathBuilder` detached at the draw call, so the path is still built and thrown away once per draw exactly as before. * 0.93 deprecated the `gradient_shader` module in favour of `gradient`. Only a warning, but the Format/clippy gate runs `-D warnings`, so it is a hard break for us. The three gradients — the panel stroke in `theme.rs`, the connect-overlay vignette in `shell/overlays.rs`, the host monogram in `screens/home.rs` — now build a `gradient::Gradient` from `gradient::Colors::new_evenly_spaced` plus `Interpolation::default()`. That default (unpremul interpolation, destination colour space, shorter hue) is what the old `flags: None` argument mapped to, so the pixels do not move. The new API takes `Color4f` directly, which drops the `.to_color()` 8-bit round-trip the old signature forced. * 0.98 deprecated `vk::BackendContext::new` in favour of a builder (upstream #1292). `skia_overlay.rs` now calls `BackendContext::new_builder(...)` + `build()`, passing `max_api_version: None` so Skia keeps deriving its cap from `vkEnumerateInstanceVersion()` — bit-for-bit what `new()` passed. `build()` is the unsafe half, so the SAFETY proof moved down onto it. `ash` is untouched and stays on the workspace's exact `=0.38.0+1.3.281` pin: skia-safe lists ash only as a DEV dependency, so the bump cannot reach it. The prebuilt-binary assumption still holds — verified from the build log, not from the release page: skia-bindings printed `DOWNLOAD AND INSTALL SUCCEEDED` for `skia-binaries-a25a0fdb7d90429aa2d1-x86_64-unknown-linux-gnu-jpegd-jpege-pdf-textlayout-vulkan`, so no CI leg compiles Skia from source. The asset name DID change: `jpeg` joined skia-safe's default feature set between 0.87 and 0.99, so `jpegd-jpege` is now in the name. We take defaults, so the JPEG codecs came along — which is a fix in disguise, since `screens/library.rs` hands host poster art straight to `Image::from_encoded`, and JPEG posters used to fall out as "undecodable". The Cargo.toml comment now records the verified asset names and the silent-source- build trap for the next bump. Verified on 192.168.1.21, x86_64-unknown-linux-gnu, toolchain 1.96.0: cargo build -p pf-console-ui exit 0 cargo clippy -p pf-console-ui --all-targets -- -D warnings exit 0 cargo test -p pf-console-ui 82 passed, 1 ignored cargo fmt --all --check exit 0 |
||
|
|
2b13b6353a |
deps: move the RustCrypto wave to aes 0.9 / aes-gcm 0.11 / sha2 0.11 / hmac 0.13 / cbc 0.2 / chacha20poly1305 0.11
These six share the `crypto-common` and `digest` traits, so they move as ONE change — a
partial bump leaves crates on incompatible trait generations that cannot interoperate.
The point is to delete a footgun, not for version hygiene. `aes` 0.8 only enabled ARMv8
hardware AES on aarch64 behind `--cfg aes_armv8`, and `polyval` 0.6 gated its PMULL GHASH
path behind `--cfg polyval_armv8`. A RUSTFLAGS env var OVERRIDES config rustflags
ENTIRELY, so any aarch64 lane that sets its own (cargo-ndk does this internally for every
Android build) silently dropped both and fell back to software AES on the per-packet
decrypt path. `aes` 0.9 runtime-detects via `cpufeatures` on aarch64 and `polyval` 0.7
selects its armv8 intrinsics backend by target_arch, so neither cfg exists any more.
API changes this generation forces:
- `AeadInPlace` -> `AeadInOut`; `{encrypt,decrypt}_in_place_detached` ->
`{encrypt,decrypt}_inout_detached` taking an `InOutBuf`.
- `generic-array` -> `hybrid-array`: `Array::from_slice` is deprecated in favour of the
infallible `&[u8; N] -> &Array<u8, UN>` reference cast, or `TryFrom` for runtime slices.
- `Mac::new_from_slice` moved to `KeyInit::new_from_slice`.
- `BlockEncrypt`/`BlockDecrypt` -> `BlockCipherEncrypt`/`BlockCipherDecrypt`;
`BlockEncryptMut` -> `BlockModeEncrypt`; `encrypt_padded_vec_mut` -> `encrypt_padded_vec`.
`rsa` 0.9 is the one crate that cannot come along: it is built on `digest` 0.10 and its
0.10 line is still release-candidate only, which is not something the Moonlight pairing
ceremony should ride. Its `sha2` feature re-exports the digest its own traits speak, so the
three sites where a digest appears as an `rsa` TYPE PARAMETER (cert.rs, pairing.rs, tls.rs)
now take `rsa::sha2::Sha256` explicitly; everything else in the crate is on sha2 0.11.
The GameStream wire formats are untouched — AES-128-ECB no-padding, the CBC audio path, and
the GCM control-stream seal all keep their exact byte behaviour; only the type plumbing moved.
|
||
|
|
dfde5080cc |
chore(deps): windows-service 0.7 -> 0.8 (host + tray), removing the last windows-sys 0.52 in the tree
Version currency for the SCM plumbing behind `punktfunk-host service` (the
dispatcher, control handler and ServiceManager install) and the tray's
unprivileged QUERY_STATUS probe. No code changed in either crate.
The payoff is dependency unification, not the API. `windows-service 0.7` was the
ONLY crate in the workspace still pulling `windows-sys 0.52`, so it alone kept a
fourth windows-sys major compiling. It resolves to 0.8.1, which moves to
`windows-sys 0.61` — a version the tree already builds — and the duplicate
disappears:
cargo tree -d --target x86_64-pc-windows-msvc | grep '^windows-sys v'
before: 0.45.0, 0.52.0, 0.59.0, 0.61.2
after: 0.45.0, 0.59.0, 0.61.2
Note 0.8.0 would NOT have been enough — it lands on windows-sys 0.59. 0.8.1 is
the release that reaches 0.61, hence the `"0.8"` caret plus the comment pinning
the reasoning to the manifest.
The 0.7 -> 0.8 delta is tiny and touches nothing this tree calls: `ServiceAccess`
gains READ_CONTROL / WRITE_DAC / WRITE_OWNER (additive), and `Service::raw_handle`
changes return type from `Security::SC_HANDLE` to `Services::SC_HANDLE` as a
consequence of the windows-sys bump — we never call it. `ScHandle` is crate-private
upstream. No enum gained variants, and the service control handler's match already
ends in a `_ =>` arm, so the `#[non_exhaustive]` types stay safe.
What remains duplicated (deliberately out of scope here): windows-sys 0.45 via
`jni`, and 0.59 via `punktfunk-core` + `if-addrs`.
|
||
|
|
00245499e0 |
chore(deps): android_logger 0.14 → 0.15
Version currency for the Android client's only `log` backend. No code change: 0.15 is almost entirely an internal refactor (the single `lib.rs` split into `config`/`arrays`/ `id`/`platform_log_writer`/`tests`), and the surface this crate uses — `init_once`, `Config::default`, `with_max_level`, `with_tag` — is untouched. The lockfile delta is the version and checksum alone: no dependency was added, removed or re-resolved, and the third-party crate count stays at 582. The one thing 0.15 adds that we must NOT take is recorded next to the dependency: the new opt-in `android-api-30` feature filters levels through `__android_log_is_loggable_len` so logcat's `setprop log.tag.*` overrides are honoured, but it HARD-LINKS that API-30 symbol. Against our minSdk-28 floor that is a `System.loadLibrary` failure on Android 9/10 — the identical shape of the ndk 0.9.0 `AMediaCodec_setOnFrameRenderedCallback` break the manifest already warns about a few lines further down. Default features keep it off; the comment explains why so nobody "completes" the upgrade by enabling it. Verified with cargo-ndk (NDK 30.0.14904198), which is the only way to exercise this crate at all — `android_logger` sits behind `cfg(target_os = "android")`, so the host workspace build never compiles it: cargo ndk -t arm64-v8a check -p punktfunk-client-android → ok cargo ndk -t armeabi-v7a check -p punktfunk-client-android → ok Checked, not built: these are `cargo check` runs, not a linked `.so` and not an APK. |
||
|
|
94e3629905 |
chore(deps): wasapi 0.23 -> 0.24 (Windows audio), and correct the five comments that still describe its fixed GetDevice bug
Version currency for the crate behind the host's WASAPI loopback capture and virtual mic, and the Windows client's render/capture path. No behavior change. The 0.23 -> 0.24 API delta is almost entirely additive (device-change notification callbacks, `AudioMeterInformation`, `HardwareSupport`, `DeviceState: Clone + Copy`). The single removal is `AudioClient::get_bufferframecount`, deprecated since 0.17 in favour of `get_buffer_size` — this tree never called it, so no call site moved. 0.24 also fixes upstream the dangling-`PCWSTR` bug this tree routes around in five places: `DeviceEnumerator::get_device` used to build its argument as `PCWSTR::from_raw(HSTRING::from(id).as_ptr())`, dropping the `HSTRING` at the end of that statement so `GetDevice` read freed memory. Those five comments asserted the bug in the PRESENT tense and are now wrong, so they are corrected here rather than left to mislead. The workarounds themselves STAY: `open_wasapi_device` is still the one resolution path whose errors name the endpoint id and whose `IMMDevice` `probe_activation` needs, and `device_by_id` additionally filters to ACTIVE endpoints (`EnumAudioEndpoints(dir, DEVICE_STATE_ACTIVE)`), which the crate's `get_device` does not. Removing them is a behavior change, not currency. ⚠ This does NOT collapse the duplicate windows-rs. wasapi 0.24 still depends on `windows ^0.62` / `windows-core ^0.62` exactly as 0.23 did, so the crates.io `windows 0.62.2` still sits alongside the pinned git copy that `clients/windows` uses. That duplicate costs build time and binary size, not correctness, and the blanket `[patch.crates-io] windows` that would collapse it stays ruled out — the pinned rev uses header-named features while a dozen manifests still use the old `Win32_*` namespace features. |
||
|
|
2d037aa443 |
test(gamestream): cover the TLS 1.2 Moonlight handshake and pin the post-quantum group
PR #192 moved the rustls backend to aws-lc-rs and merged before CI reported. Two of the things it changed here shipped with no assertion behind them. `generate()` mints the RSA-2048 host identity and runs ONLY when no cert exists, so no upgraded box ever re-executes it — a fresh install is the only thing that would have found a regression. It was reached by other tests via `ServerIdentity::ephemeral()`, but purely as a fixture: nothing checked that what came back was still RSA-2048, which is the one property Moonlight requires. The handshake behaviour had no coverage at all, and the GameStream TLS path is the single place a legacy peer meets the new backend. Three tests: - generate_mints_a_loadable_rsa2048_identity — the fresh-install path, asserting the cert signature is 256 bytes (RSA-2048) rather than depending on an `rsa` accessor that could change shape. - moonlight_shaped_peer_completes_a_tls12_mutual_handshake — a peer that pins out of band, as Moonlight does, presenting an RSA-2048 client cert against the real `tls::server_config`. - tls13_negotiates_the_post_quantum_group — pins X25519MLKEM768 by name, so a provider or feature regression that silently drops ML-KEM back to a classical curve fails here instead of in the field. Also corrects the comment on `generate()`. It opened by asserting the workspace is ring-only because aws-lc-sys breaks Windows CI, and explained that rcgen's *ring* backend is what loads the RSA key. Both are now false: rcgen is on aws_lc_rs and loads and self-signs the key fine — verified, not assumed. rcgen still cannot GENERATE an RSA key on either backend, which is the part of the comment that remains true and load-bearing. Verified on Linux (Ubuntu 26.04, x86_64): 3/3 pass, clippy clean both with and without --all-targets (host CI lints without it), and the native-only `--no-default-features --features pyrowave` build still checks clean — the whole module is gamestream-gated, so it compiles out there. |