Skip to content

api: create a session at the size it will be shown at, and reuse a fresh Pending one - #280

Open
jseifeddine wants to merge 1 commit into
sol1:mainfrom
jseifeddine:feat/initial-session-size
Open

jseifeddine wants to merge 1 commit into
sol1:mainfrom
jseifeddine:feat/initial-session-size

Conversation

@jseifeddine

@jseifeddine jseifeddine commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Based on current main on its own: one commit, nothing from any other open PR. Nothing from the UI chain. Part 1/2 of #257.

Sizing

The entry connect request carries the screen's size as well as the window's (screen_width/screen_height, sent by every connect site in connections.html and the client's relaunch). initial_session_size() picks the size the session will be shown at: an RDP/VNC entry that opens fullscreen on connect is created at the screen's size, everything else at the window's, and every RDP size is rounded down to the 16px grid that guacd's display channel (patches/007) rounds the first post-connect size send to. Creation and that send agree, guacd coalesces them, and there is no resize, no H.264 decoder rebuild and no flash on connect. The client's post-connect size send is unchanged (as @pletch asked in #255).

Reuse

A repeat Connect on the same entry within 15 s is handed the Pending session (guacd connected, owner never attached) this user just created for it instead of opening a duplicate. See "Review changes" for the match rule.

#238 reconciliation

#238 (native/HiDPI resolution, display_scale) has not merged. Both sizes here are CSS pixels, matching today's post-connect send. When #238 lands, the mod-16 rounding must be applied to the device-pixel size, after the devicePixelRatio multiply; initial_session_size() carries that note at the rounding site. Whichever lands second reconciles.

Review changes

  • The reuse match now runs on the fully built CreateSessionRequest and includes its credentials. CreateSessionRequest::credential_fingerprint() is a SHA-256 over the target and every credential field (username, password, private key, domain, auth package, KDC, jump hosts and their credentials, container and Proxmox credentials), tagged and length-prefixed. It is stored on the Session at creation and compared by find_reusable_session(); it is never logged or returned to a client. A retry with a different password, key or domain, such as a mistyped prompt, therefore gets a new session rather than the old Pending one with the old credentials.
  • Reuse is further scoped to the same user, the same entry key, Pending status with a live guacd stream, and sessions younger than SessionManager::REUSABLE_PENDING_SECS (15 s).
  • Rebased onto main on its own; the stacked history is gone.

Testing

  • cargo fmt --check, cargo clippy --all-targets -- -D warnings, cargo test, and the plain-node client tests (tests/*.mjs).
  • Sizing: fullscreen_sizing_applies_to_bitmap_sessions_only, round_down_mod16_floors_at_sixteen.
  • Reuse: credential_fingerprint_tracks_target_and_credentials, fresh_pending_session_reused_for_same_entry_and_credentials, retry_with_different_credentials_gets_a_new_session, reuse_is_scoped_to_user_entry_status_and_age.
  • Manual (earlier, on the stacked branch): RDP fullscreen-on-connect from a 1710×1112 Mac, guacd log shows one size and no resize after connect; two quick Connects on the same entry open one session.

@davekempe

Copy link
Copy Markdown
Member

The sizing part looks good, and Tim's note from #255 still applies once #238 lands (round after the devicePixelRatio multiply).

One bug in the reuse: find_reusable_session runs after the request is built, so a retry within 15 seconds with different credentials (say a mistyped password at the prompt) gets the old Pending session with the old credentials. Maybe only reuse when the request carries no credentials of its own, or include them in the match.

Also, since the PRs are stacked, could you rebase this onto main on its own so it can be taken separately?

@jseifeddine

Copy link
Copy Markdown
Contributor Author

Rebased onto main on its own (88e72bc, one commit, nothing from the UI chain), so it can go in separately. The reuse now matches on the fully built request including its credentials: a SHA-256 fingerprint over the target and every credential field is stored on the Pending session and compared in find_reusable_session, so a retry with a mistyped password within 15 s gets a new session instead of the old one with the old credentials; the hash is compared only, never logged. Tests cover the same-creds reuse, the different-password retry, and the user/entry/status/age scoping. Sizing is as before and the client's post-connect size send stays. #238 isn't merged yet, so I left a note at the rounding site that the mod-16 rounding has to move after the devicePixelRatio multiply when it lands.

The CI audit failure on this branch is the new quinn-proto advisories, not this change; #283 bumps the lockfile and the run goes green once that is in.

@jseifeddine
jseifeddine marked this pull request as ready for review October 13, 2026 03:16
…esh Pending one

Sizing. The entry connect request now carries the screen's size as well
as the window's (screen_width/screen_height, sent by every connect site
in connections.html and the client's relaunch). initial_session_size()
picks the size the session will be shown at: an RDP/VNC entry that opens
fullscreen on connect is created at the screen's size, everything else at
the window's, and every RDP size is rounded down to the 16px grid that
guacd's display channel (patches/007) rounds the first post-connect size
send to. Creation and that send therefore agree, guacd coalesces them,
and there is no resize, no H.264 decoder rebuild and no flash on
connect. The client's post-connect size send stays as it is.

Reuse. A repeat Connect on the same entry within 15 s no longer opens a
duplicate: a Pending session (guacd connected, owner never attached) this
user created for the entry is handed back instead. The match is made on
the fully built CreateSessionRequest and includes its credentials:
CreateSessionRequest::credential_fingerprint() is a SHA-256 over the
target and every credential field (username, password, private key,
domain, auth package, KDC, jump hosts and their credentials, container
and Proxmox credentials), stored on the Session and compared, never
logged or served. A retry with a different password, key or domain, such
as a mistyped prompt, gets a new session rather than the old Pending one
with the old credentials. Reuse is also scoped to the same user, the
same entry key, Pending status with a live guacd stream, and sessions
younger than SessionManager::REUSABLE_PENDING_SECS.

sol1#238 (native/HiDPI resolution, display_scale) has not merged: both sizes
here are CSS pixels, matching today's post-connect send. When it lands
the mod-16 rounding must be applied to the device-pixel size, after the
devicePixelRatio multiply; the rounding site carries that note.

Tests: fullscreen_sizing_applies_to_bitmap_sessions_only and
round_down_mod16_floors_at_sixteen (api);
credential_fingerprint_tracks_target_and_credentials,
fresh_pending_session_reused_for_same_entry_and_credentials,
retry_with_different_credentials_gets_a_new_session and
reuse_is_scoped_to_user_entry_status_and_age (session).

Part 1/2 of sol1#257.
@jseifeddine
jseifeddine force-pushed the feat/initial-session-size branch from 88e72bc to d11d18f Compare October 13, 2026 07:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants