websocket: tungstenite 0.29 from rustdesk-org, read buffer grown as bytes arrive

Upstream reserves a frame's whole declared length the moment its header
is in, bounded only by max_frame_size, so a header alone buys the
allocation it names: 128 KiB before a session is authorized and 16 MiB
after. The rustdesk-org tungstenite-rs fork on rustdesk-patches-0.29,
upstream v0.29.0, grows the read buffer one read_buffer_size chunk at a
time as the bytes actually arrive instead, and tokio-tungstenite moves to
its rustdesk-patches-0.29 branch to match, still one commit for
set_config. 0.27's read chunking comes with the move, so a large frame no
longer clears its whole grown buffer on every read.

No source change: Bytes payloads and the non-exhaustive config arrived in
0.26 and 0.25 and were already in use here, and 0.28's boxing of
Error::Http derefs at its one use. The read buffer keeps tungstenite's
128 KiB default, this side reading video frames and file blocks over a
handful of connections rather than small messages over thousands. The
workspace root patches tungstenite to the fork, where cargo reads
[patch], so this crate's copy and tokio-tungstenite's resolve to one.

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-21 17:58:32 +08:00
co-authored by Claude Fable 5.1
parent 7dc56d69e0
commit d9895ff9cb
2 changed files with 6 additions and 5 deletions
+2 -2
View File
@@ -60,8 +60,8 @@ tokio-native-tls = "0.3"
# Fork of v0.26.2: upstream's WebSocketStream exposes get_config but no set_config, so a
# message cap lowered before authorization could never be lifted again. One commit on top of
# the tag; pinned by rev, not branch, because a fork branch can be rewritten under the lockfile.
tokio-tungstenite = { git = "https://github.com/rustdesk-org/tokio-tungstenite", rev = "9c320de8e7c546cb654b017b7f4cbb4a5cc09cd9", version = "0.26", features = ["native-tls", "rustls-tls-native-roots", "rustls-tls-webpki-roots"] }
tungstenite = { version = "0.26", features = ["native-tls", "rustls-tls-native-roots", "rustls-tls-webpki-roots"] }
tokio-tungstenite = { git = "https://github.com/rustdesk-org/tokio-tungstenite", rev = "c241b11b03de4881faf1ecd2fe6e867c92f3013b", version = "0.29", features = ["native-tls", "rustls-tls-native-roots", "rustls-tls-webpki-roots"] }
tungstenite = { version = "0.29", features = ["native-tls", "rustls-tls-native-roots", "rustls-tls-webpki-roots"] }
rustls-platform-verifier = "0.6"
rustls-pki-types = "1.11"
rustls-native-certs = "0.8"
+4 -3
View File
@@ -216,9 +216,10 @@ impl WsFramedStream {
self.encrypt = None;
}
/// Both bounds, not just the message one: tungstenite reserves the whole declared payload of a
/// frame as soon as it passes `max_frame_size` (`protocol/frame/mod.rs`), so that is what keeps
/// a frame header from buying an allocation, while `max_message_size` bounds reassembly.
/// Both bounds, not just the message one: `max_frame_size` refuses an oversized frame on its
/// header, before any of it is buffered, while `max_message_size` bounds reassembly across a
/// fragmented one. What a header on its own can allocate is `read_buffer_size`, the patched
/// fork growing the read buffer a chunk at a time rather than to the length a frame declares.
#[inline]
pub fn set_max_packet_length(&mut self, n: usize) {
self.stream.set_config(|c| {