server: admit only INITIAL_WINDOW on a channel before opened

The demultiplexer accepted CHANNEL_WINDOW into a pending channel's
unbounded queue, four times the bound the channel task enforces once
it polls. The window now starts at INITIAL_WINDOW and is widened right
before `opened` advertises the rest.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZ49AbZJYfm8NTp5yDPMab
This commit is contained in:
rustdesk
2026-09-04 16:41:30 +08:00
parent c755464f9b
commit adda994a42
2 changed files with 43 additions and 1 deletions

View File

@@ -66,6 +66,16 @@ impl RecvWindow {
}
}
/// Widens the window without advertising: the grant travels in `opened`.
pub fn grant(&mut self, n: u32) {
self.remaining = self.remaining.saturating_add(n);
}
#[cfg(test)]
pub fn remaining(&self) -> u32 {
self.remaining
}
/// Returns the amount to advertise in a `window_update` once enough has
/// been drained; the same amount is credited back.
pub fn drained(&mut self, n: usize) -> Option<u32> {
@@ -781,6 +791,16 @@ mod tests {
}
}
#[test]
fn grant_extends_a_window_that_has_been_used_up() {
let mut w = RecvWindow::new(INITIAL_WINDOW);
assert!(w.accept(INITIAL_WINDOW as usize));
assert!(!w.accept(1));
w.grant(CHANNEL_WINDOW - INITIAL_WINDOW);
assert!(w.accept((CHANNEL_WINDOW - INITIAL_WINDOW) as usize));
assert!(!w.accept(1));
}
#[test]
fn send_credit_blocks_at_zero_and_resumes_on_add() {
rt().block_on(async {