Skip to content

fix(server): start each connection's network measurements fresh - #2048

Closed
Greg Lamberson (glamberson) wants to merge 1 commit into
Devolutions:masterfrom
lamco-admin:fix/server-autodetect-per-connection
Closed

Greg Lamberson (glamberson) wants to merge 1 commit into
Devolutions:masterfrom
lamco-admin:fix/server-autodetect-per-connection

Conversation

@glamberson

Copy link
Copy Markdown
Contributor

Summary

  • enable_autodetect creates one AutoDetectManager for the life of the server, and the RTT, baseline-RTT and bandwidth handles were never cleared between connections. On a server that serves one client after another, the next client inherited the previous one's measurements: baseRTT (the lowest RTT seen, MS-RDPBCGR 2.2.14.1.5) stayed at the previous client's floor, the handles reported the previous client's figures until overwritten, and a measurement the previous client left pending held up the next one's.
  • Each connection now starts with a fresh manager and the three handles back at u32::MAX ("not measured"), where display_suppressed is already reset, on both the normal path and a preemption winner. The bandwidth generation counter is left as it is: it counts completed measurements, and a reset is not one.
  • The connection-scoped state struct proposed in ironrdp-server: introduce a connection-scoped state struct #1978 would make this reset structural; until then it sits with the other per-connection resets.

Validation

cargo xtask check fmt/lints/tests/typos/locks all pass. A new test in ironrdp-testsuite-core sets the handles to stale values, runs a connection that ends at once, and checks they read u32::MAX again; it fails without the reset.

enable_autodetect creates one AutoDetectManager for the life of the
server, and the RTT, baseline-RTT and bandwidth handles were never
cleared between connections. On a server that serves one client after
another, the next client inherited the previous one's measurements:
baseRTT (the lowest RTT seen, MS-RDPBCGR 2.2.14.1.5) stayed at the
previous client's floor, the handles reported the previous client's
figures until overwritten, and a measurement the previous client left
pending held up the next one's.

Each connection now starts with a fresh manager and the three handles
back at u32::MAX ("not measured"), where display_suppressed is already
reset, on both the normal path and a preemption winner. The bandwidth
generation counter is left as it is: it counts completed measurements,
and a reset is not one.
@github-actions github-actions Bot added kind/protocol Affects RDP or related protocol behavior risk/medium Behavioral change that does not substantially alter a core public API size/S Size: up to 199 counted lines and 5 files; exceeds XS in either measure triage/overlap Possible overlap with another pull request; advisory only labels Sep 29, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This pull request may overlap with #2034.

Both are fix(server) changes in crates/ironrdp-server that reset stale per-connection state at the start of every connection in the same connection-setup region (serve_negotiated / run_connection_inner) of server.rs, so they plausibly touch overlapping code. They reset different state, though: #2034 discards queued session events, while this PR extracts reset_connection_state and clears auto-detect measurements.

This notice is advisory only. Automated review continues as usual, and how these pull requests relate is for maintainers and authors to decide.

Note

LLM-assisted content (no human feedback).

@github-actions github-actions Bot added the needs-review A human reviewer is the current next actor label Sep 29, 2026
@CBenoit Benoît Cortier (CBenoit) added automation-failed Exact-head automated classification or review failed or was unavailable and removed needs-review A human reviewer is the current next actor labels Sep 30, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #2048 extracts the per-connection display-suppression reset into reset_connection_state and extends it to clear the AutoDetectManager and the RTT/baseRTT/bandwidth handles (u32::MAX) on both the normal and preemption-winner paths, with a regression test. Independent inspection confirms the reset is applied at both entry points (server.rs:2036, 2188), the is_some() guard is required to avoid flipping rtt_snapshot() on disabled servers, storing u32::MAX unconditionally is a documented no-op when auto-detect is off, and the new test uses existing public APIs. Protocol semantics are sound: MS-RDPBCGR scopes network measurements and SuppressOutput state to one connection. Only protocol reported a valid finding; it is refined: its premise that the generation counter is documented as a freshness pairing overstates the doc (its documented meaning is completed Bandwidth Measure transactions, which a reset is not), but the residual point stands that the Relaxed sentinel store is unpaired, so…

Comment on lines +2179 to +2181
self.autodetect_rtt.store(u32::MAX, Ordering::Relaxed);
self.autodetect_baseline_rtt.store(u32::MAX, Ordering::Relaxed);
self.autodetect_bandwidth.store(u32::MAX, Ordering::Relaxed);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[protocol] Bandwidth-handle reset is invisible to embedders watching the generation counter — low 🟡 — reset_connection_state stores u32::MAX into autodetect_rtt/autodetect_baseline_rtt/autodetect_bandwidth with Relaxed and, unlike every measurement mutation (server.rs:3975, 3989), performs no paired autodetect_bandwidth_generation increment. Not incrementing is correct per the counter's documented meaning ('increments every time a Bandwidth Measure transaction completes', lines 764-766) and the PR body's stated rationale. The residual issue is that the store has no release at all, so an embedder relying on the documented Release/Acquire pattern to observe bandwidth changes will never learn that the previous connection's figure was cleared for the new connection. Wire behavior is unaffected: the fresh AutoDetectManager ensures Network Characteristics Results are correct (MS-RDPBCGR 2.2.14.1.5). An embedder-facing doc note on the reset, or an Acquire-visible signal, would close the gap.

@github-actions github-actions Bot added ai-reviewed/1 One automated review completed needs-author-action The pull request author is the current next actor and removed automation-failed Exact-head automated classification or review failed or was unavailable labels Sep 30, 2026
@glamberson

Copy link
Copy Markdown
Contributor Author

Closing this in favour of #2059, which makes the same reset structural by giving each connection its own state, as proposed on #1978. It also advances the bandwidth generation counter on reset, which this PR left alone, and that is the right behaviour for embedders that reread the bandwidth when the generation moves.

This branch was successfully deployed

1 active deployment
llm-providers — a820e83d Deployed Sep 29, 2026 by glamberson via Classify pull request #1138
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-reviewed/1 One automated review completed kind/protocol Affects RDP or related protocol behavior needs-author-action The pull request author is the current next actor risk/medium Behavioral change that does not substantially alter a core public API size/S Size: up to 199 counted lines and 5 files; exceeds XS in either measure triage/overlap Possible overlap with another pull request; advisory only

Development

Successfully merging this pull request may close these issues.

2 participants