feat(clients): signal explicit exit (QUIT_CLOSE_CODE) on deliberate disconnect

The core's deliberate-quit close (NativeClient::disconnect_quit → QUIT_CLOSE_CODE,
host skips the keep-alive linger) was implemented but never called by any client.
Wire it to each client's explicit user-disconnect action — NOT to a network drop /
host-ended / app-background (those keep the linger for a reconnect):

- core: new C-ABI punktfunk_connection_disconnect_quit(c) for the ABI clients
- Linux (direct-core): Ctrl+Alt+Shift+D + the controller escape chord
- Windows (direct-core): Ctrl+Alt+Shift+D
- Apple (C-ABI): PunktfunkConnection.disconnectQuit() + a `deliberate` flag on
  SessionModel.disconnect() (sessionEnded passes false → keeps the linger)
- Android (JNI): new nativeDisconnectQuit export, called from the back gesture +
  the Select+Start+L1+R1 chord (not the host-gone watchdog)
- probe already did this via --quit (77871d6)

Verified: core + Linux client + Android (cargo-ndk + gradle) build clean;
Windows/Apple compile-checked by CI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-06 13:37:45 +00:00
parent eaaf176adf
commit 91fadce900
9 changed files with 91 additions and 4 deletions
+12
View File
@@ -1501,6 +1501,18 @@ PunktfunkStatus punktfunk_connection_probe_result(const PunktfunkConnection *c,
PunktfunkProbeResult *out);
#endif
#if defined(PUNKTFUNK_FEATURE_QUIC)
// Signal a **deliberate quit** (a user "stop", not a network drop) before closing: the connection
// closes with [`QUIT_CLOSE_CODE`] instead of code 0, so the host tears the session down immediately
// (skips the keep-alive linger) rather than holding it for a reconnect. Call this right before
// [`punktfunk_connection_close`] on a user-initiated disconnect; a plain close (network drop,
// backgrounding) leaves the linger intact. NULL is a no-op.
//
// # Safety
// `c` was returned by [`punktfunk_connect`] and remains valid (closed via `punktfunk_connection_close`).
void punktfunk_connection_disconnect_quit(PunktfunkConnection *c);
#endif
#if defined(PUNKTFUNK_FEATURE_QUIC)
// Close the connection and free the handle (joins the internal threads). NULL is a no-op.
//