fix(server): start each connection's network measurements fresh - #2048
Greg Lamberson (glamberson) wants to merge 1 commit into
Conversation
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.
|
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: 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). |
There was a problem hiding this comment.
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…
| 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); |
There was a problem hiding this comment.
[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.
|
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. |
Summary
enable_autodetectcreates oneAutoDetectManagerfor 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.u32::MAX("not measured"), wheredisplay_suppressedis 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.Validation
cargo xtask check fmt/lints/tests/typos/locksall pass. A new test inironrdp-testsuite-coresets the handles to stale values, runs a connection that ends at once, and checks they readu32::MAXagain; it fails without the reset.