[
https://issues.apache.org/jira/browse/GUACAMOLE-2303?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Ciro Iriarte updated GUACAMOLE-2303:
------------------------------------
Description:
h2. Summary
Add an optional session-resume capability so a short network drop doesn't end a
Guacamole session. Today a stall longer than ~15s closes the tunnel, and the
built-in reconnect starts a new session, so the user loses their work. This
lets the client rejoin the same live session instead. It's off by default.
h2. Problem
When the browser-to-server link stalls, the client tunnel's receiveTimeout
(default 15000ms) fires and the tunnel closes. The built-in reconnect then
opens a new connection, so the previous guacd session is gone and the user is
back at a login/parameter prompt with their work lost. There's currently no way
to recover a session after a drop.
The 15s threshold is easier to hit than it sounds:
* TCP retransmission backoff stretches short drops. On a netem test rig, an ~8s
outage left the tunnel frozen for ~14s, and a 20s outage closed the session.
* Ordinary WAN/mobile events go past it: Wi-Fi handoff and DHCP renewal,
cellular dead zones, VPN reconnects, laptop sleep/resume, NAT rebinding, and
background-tab throttling (the client's pings pause and a proxy idle timeout
then closes the socket).
h2. Proposal
Let a reconnecting client rejoin its existing guacd connection instead of
starting a new one. Three parts:
# guacd: an optional grace window on connection-sharing teardown. When the last
user of a connection disconnects, hold it for a configurable number of seconds
(GUACD_RESUME_GRACE, default 0 = off) before tearing it down, so a reconnecting
client can rejoin by connection ID. This uses the existing {{$<uuid>}} join
path.
# guacamole-client webapp: a session-scoped registry mapping a resume token to
the guacd connection ID. A reconnect that presents the token rejoins via
{{select $uuid}} (owner-checked, time-limited), and the old tunnel is closed.
# guacamole-common-js and the Angular client: a reconnect controller that,
after a drop on a connection that had reached OPEN, opens a fresh
WebSocketTunnel on the same Guacamole.Client (keeping display, input, and
streams), sends the resume token, and redisplays the last frame during the gap.
This also fixes a related problem: a dropped tunnel was reported as a terminal
TUNNEL_ERROR, which started the existing 15s reconnect-countdown notification
and replaced the client that had already resumed.
h2. Configuration and scope
* Off by default. GUACD_RESUME_GRACE defaults to 0 and the client controller is
disabled, so existing installs behave exactly as before.
* Suggested control: enable it per connection, with a server-side maximum
grace. Calling it "session resume" rather than a broad "WAN mode" seems clearer.
* It should be possible to turn off, and it should be off for share/anonymous
connections and anywhere a hard drop on disconnect is required.
h2. Evidence
* Recovers a 20s outage in every trial (8/8 through an nginx reverse proxy, 2/2
direct), rejoining the same guacd session (guacd logs {{Joining existing
connection $<uuid>}}) with work intact.
* Tested on SSH and VNC (VNC replays its framebuffer on rejoin).
* No change to steady-state input latency, which is bound by round-trip time
and isn't the target here.
* guacamole-common-js karma tests pass, including new coverage for the
reconnect tunnel lifecycle.
h2. Non-goals
* Not HA or session migration. The registry is per-JVM and in-memory, and
relies on the same session affinity the existing in-memory auth-token map
already needs. Rejoining across nodes is out of scope.
* Not a bandwidth or latency optimization; it's about recovering from a drop.
h2. Compatibility and risk
* The grace window holds a guacd session briefly after its last user leaves,
which changes teardown timing and uses resources, so it's opt-in and bounded.
* The resume token is currently the client-facing tunnel UUID; an opaque
single-use token would be a good follow-up.
* A "reconnecting" overlay with a manual retry is worth adding before enabling
this widely, since users tend to hit refresh, which throws away the client
state and prevents the resume.
h2. Patch
Implemented on forks, branch wan-optimization:
* github.com/ciroiriarte/guacamole-server -- guacd grace window
* github.com/ciroiriarte/guacamole-client -- webapp rebind, client reconnect
controller, diagnostics
* github.com/ciroiriarte/guacamole-manual -- reverse-proxy WAN-tuning docs
I can submit these as separate PRs and adjust the configuration to whatever
you'd prefer. A reasonable order:
# diagnostics/telemetry (off by default)
# client reconnect-lifecycle hardening (ignore stale tunnels, don't raise a
terminal error during an active retry, clean tunnel swap)
# the resume feature (guacd grace + webapp rebind + client controller)
# the reconnecting overlay and manual retry
was:
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.
Summary: [RFC] Optional session resume so a short network drop does not
end the session (was: [RFC] Opt-in work-preserving session resume across
transient network drops)
> [RFC] Optional session resume so a short network drop does not end the session
> ------------------------------------------------------------------------------
>
> Key: GUACAMOLE-2303
> URL: https://issues.apache.org/jira/browse/GUACAMOLE-2303
> Project: Guacamole
> Issue Type: New Feature
> Reporter: Ciro Iriarte
> Priority: Major
>
> h2. Summary
> Add an optional session-resume capability so a short network drop doesn't end
> a Guacamole session. Today a stall longer than ~15s closes the tunnel, and
> the built-in reconnect starts a new session, so the user loses their work.
> This lets the client rejoin the same live session instead. It's off by
> default.
> h2. Problem
> When the browser-to-server link stalls, the client tunnel's receiveTimeout
> (default 15000ms) fires and the tunnel closes. The built-in reconnect then
> opens a new connection, so the previous guacd session is gone and the user is
> back at a login/parameter prompt with their work lost. There's currently no
> way to recover a session after a drop.
> The 15s threshold is easier to hit than it sounds:
> * TCP retransmission backoff stretches short drops. On a netem test rig, an
> ~8s outage left the tunnel frozen for ~14s, and a 20s outage closed the
> session.
> * Ordinary WAN/mobile events go past it: Wi-Fi handoff and DHCP renewal,
> cellular dead zones, VPN reconnects, laptop sleep/resume, NAT rebinding, and
> background-tab throttling (the client's pings pause and a proxy idle timeout
> then closes the socket).
> h2. Proposal
> Let a reconnecting client rejoin its existing guacd connection instead of
> starting a new one. Three parts:
> # guacd: an optional grace window on connection-sharing teardown. When the
> last user of a connection disconnects, hold it for a configurable number of
> seconds (GUACD_RESUME_GRACE, default 0 = off) before tearing it down, so a
> reconnecting client can rejoin by connection ID. This uses the existing
> {{$<uuid>}} join path.
> # guacamole-client webapp: a session-scoped registry mapping a resume token
> to the guacd connection ID. A reconnect that presents the token rejoins via
> {{select $uuid}} (owner-checked, time-limited), and the old tunnel is closed.
> # guacamole-common-js and the Angular client: a reconnect controller that,
> after a drop on a connection that had reached OPEN, opens a fresh
> WebSocketTunnel on the same Guacamole.Client (keeping display, input, and
> streams), sends the resume token, and redisplays the last frame during the
> gap.
> This also fixes a related problem: a dropped tunnel was reported as a
> terminal TUNNEL_ERROR, which started the existing 15s reconnect-countdown
> notification and replaced the client that had already resumed.
> h2. Configuration and scope
> * Off by default. GUACD_RESUME_GRACE defaults to 0 and the client controller
> is disabled, so existing installs behave exactly as before.
> * Suggested control: enable it per connection, with a server-side maximum
> grace. Calling it "session resume" rather than a broad "WAN mode" seems
> clearer.
> * It should be possible to turn off, and it should be off for share/anonymous
> connections and anywhere a hard drop on disconnect is required.
> h2. Evidence
> * Recovers a 20s outage in every trial (8/8 through an nginx reverse proxy,
> 2/2 direct), rejoining the same guacd session (guacd logs {{Joining existing
> connection $<uuid>}}) with work intact.
> * Tested on SSH and VNC (VNC replays its framebuffer on rejoin).
> * No change to steady-state input latency, which is bound by round-trip time
> and isn't the target here.
> * guacamole-common-js karma tests pass, including new coverage for the
> reconnect tunnel lifecycle.
> h2. Non-goals
> * Not HA or session migration. The registry is per-JVM and in-memory, and
> relies on the same session affinity the existing in-memory auth-token map
> already needs. Rejoining across nodes is out of scope.
> * Not a bandwidth or latency optimization; it's about recovering from a drop.
> h2. Compatibility and risk
> * The grace window holds a guacd session briefly after its last user leaves,
> which changes teardown timing and uses resources, so it's opt-in and bounded.
> * The resume token is currently the client-facing tunnel UUID; an opaque
> single-use token would be a good follow-up.
> * A "reconnecting" overlay with a manual retry is worth adding before
> enabling this widely, since users tend to hit refresh, which throws away the
> client state and prevents the resume.
> h2. Patch
> Implemented on forks, branch wan-optimization:
> * github.com/ciroiriarte/guacamole-server -- guacd grace window
> * github.com/ciroiriarte/guacamole-client -- webapp rebind, client reconnect
> controller, diagnostics
> * github.com/ciroiriarte/guacamole-manual -- reverse-proxy WAN-tuning docs
> I can submit these as separate PRs and adjust the configuration to whatever
> you'd prefer. A reasonable order:
> # diagnostics/telemetry (off by default)
> # client reconnect-lifecycle hardening (ignore stale tunnels, don't raise a
> terminal error during an active retry, clean tunnel swap)
> # the resume feature (guacd grace + webapp rebind + client controller)
> # the reconnecting overlay and manual retry
--
This message was sent by Atlassian Jira
(v8.20.10#820010)