Ciro Iriarte created GUACAMOLE-2303:
---------------------------------------
Summary: [RFC] Opt-in work-preserving session resume across
transient network drops
Key: GUACAMOLE-2303
URL: https://issues.apache.org/jira/browse/GUACAMOLE-2303
Project: Guacamole
Issue Type: New Feature
Reporter: Ciro Iriarte
h2. Summary
This RFC proposes an *opt-in, work-preserving session resume* capability so a
Guacamole session survives a transient network drop instead of dying and
forcing the user back to a fresh login with lost work. It is *off by default*
and changes no existing behavior.
h2. Problem
When the browser{{<->}}server link stalls, the client tunnel's
{{receiveTimeout}} (default 15000ms) fires and the tunnel self-closes. The
built-in reconnect then establishes a *brand-new* connection -- the previous
guacd session is gone, so the user is returned to a login/parameter prompt and
loses whatever they were doing. A transient drop is therefore not recoverable
today.
Two points make this reach real users rather than only long outages:
* The 15s threshold is easier to hit than a 15s outage, because TCP
retransmission backoff amplifies short drops. On a controlled {{netem}} rig, an
~8s blackout produced a ~14s frozen tunnel; a 20s blackout killed the session.
* Common WAN/mobile events exceed it: Wi-Fi AP handoff + DHCP renewal, cellular
dead zones (trains/tunnels/elevators), VPN reconnects, laptop sleep/resume, NAT
rebinding, and background-tab timer throttling (client pings pause, then a
reverse-proxy idle timeout closes the socket).
h2. Proposal
A three-tier, opt-in mechanism that lets a reconnecting client *rejoin the same
live guacd connection* rather than start a new one:
# *guacd* -- a bounded grace window on the connection-sharing teardown path.
When the last user of a shared connection disconnects, optionally hold the
connection for a short configurable period ({{GUACD_RESUME_GRACE}} seconds,
default {{0}} = off) before teardown, so a reconnecting client can rejoin it by
connection ID. Reuses the existing {{$<uuid>}} join path; no new subsystem.
# *guacamole-client webapp* -- a session-scoped resume registry mapping a
client-held resume token to the guacd connection ID. A reconnect presenting the
token rebinds via {{select $uuid}} (owner-checked and time-bounded); the
abandoned prior tunnel is reaped on resume.
# *guacamole-common-js + webapp (Angular)* -- a reconnect controller that, on a
retryable drop after the connection had reached OPEN, reconnects over a *fresh*
{{Guacamole.WebSocketTunnel}} on the *same* {{Guacamole.Client}} (preserving
display, input, and streams), appending the resume token. The last-rendered
frame is redisplayed during the gap.
Also included: suppression of a spurious teardown where a dropped tunnel
surfaced as a terminal {{TUNNEL_ERROR}}, which armed the stock 15s
reconnect-countdown notification and replaced the already-resumed client.
h2. Configuration and scope
* *Off by default*, entirely opt-in. {{GUACD_RESUME_GRACE}} defaults to {{0}};
the client reconnect controller defaults to disabled. Existing deployments are
unaffected.
* Recommended surface: enable per-connection (an admin-set connection
parameter) with a global server-side maximum grace. Suggested framing is
"session resume" / "keep session alive", not a broad "WAN mode".
* Should be disable-able, and off, for share/anonymous connections and for
security profiles that require a hard drop on disconnect.
h2. Evidence
* Recovers a hard 20s outage *10/10* end to end -- 8/8 through an nginx reverse
proxy (the typical production topology) and 2/2 direct -- with the same guacd
session rejoined ({{Joining existing connection $<uuid>}}) and work preserved.
* Verified on both *SSH* and *VNC* (bitmap framebuffer replays on rejoin).
* No change to steady-state input latency (that is RTT-bound and explicitly not
a goal here).
* guacamole-common-js karma suite green, including added coverage for the
reconnect tunnel lifecycle.
h2. Non-goals
* Not HA / session migration: the resume registry is per-JVM in-memory and
relies on the same session affinity that Guacamole's existing in-memory
auth-token map already requires. Cross-node resume is out of scope.
* Not a bandwidth or latency optimization; it targets *recoverability*, not
throughput.
h2. Compatibility and risk
* The grace window intentionally holds a guacd session briefly after its last
user leaves (a resource and disconnect-semantics change) -- hence opt-in,
bounded, and per-connection.
* Resume tokens are currently the client-facing tunnel UUID; an opaque,
single-use token is a recommended follow-up.
* A "reconnecting..." overlay plus manual-resume fallback is recommended before
broad rollout, because the user's instinct to press F5/refresh destroys client
state and prevents resume.
h2. Patch offering
Implemented on forks, branch {{wan-optimization}}:
* {{github.com/ciroiriarte/guacamole-server}} -- guacd grace window
* {{github.com/ciroiriarte/guacamole-client}} -- webapp resume rebind + client
reconnect controller + connection diagnostics
* {{github.com/ciroiriarte/guacamole-manual}} -- reverse-proxy WAN-tuning
documentation
Happy to submit as staged, reviewable pull requests and to align the
configuration surface with maintainer preferences. Suggested staging:
# Connection diagnostics/telemetry (off by default).
# Client reconnect-lifecycle hardening (stale-tunnel isolation, no terminal
error during active retry, clean tunnel swap).
# The bounded per-connection resume feature (guacd grace + webapp rebind +
client controller).
# The "reconnecting" overlay and manual-resume fallback.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)