Keep live TUI output raw under retransmit pressure
ci / test (push) Has been cancelled
ci / fuzz-smoke (push) Has been cancelled
ci / windows-client (push) Has been cancelled
ci / package-release (linux-x86_64, ubuntu-latest) (push) Has been cancelled
ci / package-release (macos-aarch64, macos-14) (push) Has been cancelled
ci / package-release (macos-x86_64, macos-13) (push) Has been cancelled
ci / package-release (windows-x86_64, windows-latest) (push) Has been cancelled
ci / remote-bench (push) Has been cancelled

This commit is contained in:
DuProcess
2026-07-02 19:21:43 -04:00
parent 601510687e
commit c40f5459ba
5 changed files with 91 additions and 17 deletions
+10 -15
View File
@@ -3336,7 +3336,7 @@ async fn broadcast_output(
let sends = {
let mut locked = state.lock().expect("server state poisoned");
let scrollback = locked.config.scrollback;
let retransmit_window = locked.config.retransmit_window;
let retransmit_window = locked.config.retransmit_window.max(1);
let session = locked
.sessions
.get_mut(&output.session)
@@ -3374,20 +3374,18 @@ async fn broadcast_output(
client.send_seq += 1;
// Count traffic toward the packet-count rekey trigger (spec §11).
client.epoch_packets = client.epoch_packets.saturating_add(1);
// Only materialize a screen snapshot when this client has fallen too
// far behind; the common case sends the raw output bytes and must not
// clone the whole vt100 grid per client per packet.
let (bytes, snapshot) = if client.pending.len() >= retransmit_window {
client.pending.clear();
(screen_snapshot(session.parser.screen()), true)
} else {
(output.bytes.clone(), false)
};
// Live terminal bytes are never rewritten into vt100 snapshots. A
// snapshot is useful for attach/resume, but substituting it during a
// running TUI can lose graph/background-cell details that apps like
// btop rely on. If retransmit history is full, prune only history.
while client.pending.len() >= retransmit_window {
client.pending.pop_front();
}
let frame = Frame {
session: output.session.clone(),
output_seq,
bytes,
snapshot,
bytes: output.bytes.clone(),
snapshot: false,
closed: false,
};
let body = protocol::to_body(&frame)?;
@@ -3400,9 +3398,6 @@ async fn broadcast_output(
SERVER_TO_CLIENT,
&body,
)?;
while client.pending.len() >= retransmit_window {
client.pending.pop_front();
}
client.pending.push_back(PendingFrame {
output_seq,
packet: packet.clone(),