feat(clients): Wake-on-LAN in apple/linux/windows/android/decky

Each client learns a host's MAC from the mDNS `mac` TXT while it's awake, persists it on the saved-host record, and — when reconnecting to an offline host — sends a magic packet before connecting, plus an explicit "Wake host" action. Apple wraps the C-ABI; linux/windows call the core fn directly (linux also gains a --wake CLI mode); android via a new nativeWakeOnLan JNI export (the mDNS browse record gains a 7th mac field); decky shells out to the linux client's --wake before launching the stream.

iOS/tvOS need the managed com.apple.developer.networking.multicast entitlement (pending Apple approval), so the wake path + UI are gated off via PunktfunkConnection.wakeOnLANAvailable and the entitlement is commented out — keeping iOS/tvOS releasable. MAC-learning stays active on every platform so it lights up the moment it's ungated. macOS works today.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-04 13:37:14 +02:00
parent 3bf14a3df7
commit fb709d68ce
33 changed files with 558 additions and 24 deletions
+8
View File
@@ -22,6 +22,9 @@ pub struct DiscoveredHost {
/// `None` when not advertised (older host / standalone `punktfunk1-host`); the
/// library client then falls back to the well-known default.
pub mgmt_port: Option<u16>,
/// Wake-on-LAN MAC(s) from the mDNS `mac` TXT (comma-separated `aa:bb:cc:dd:ee:ff`), which the
/// hosts page persists onto the matching saved host so it can wake it later. Empty if absent.
pub mac: Vec<String>,
}
/// One discovery update for the UI's advert map.
@@ -81,6 +84,11 @@ pub fn browse() -> async_channel::Receiver<DiscoveryEvent> {
fp_hex: val("fp"),
pair: val("pair"),
mgmt_port: val("mgmt").parse().ok(),
mac: val("mac")
.split(',')
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect(),
})
}
ServiceEvent::ServiceRemoved(_ty, fullname) => {