From d9895ff9cb4c77137fb05ce3161bcf7210177aef Mon Sep 17 00:00:00 2001 From: rustdesk Date: Mon, 21 Sep 2026 17:58:32 +0800 Subject: [PATCH] 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 Claude-Session: https://claude.ai/code/session_01EZ49AbZJYfm8NTp5yDPMab --- Cargo.toml | 4 ++-- src/websocket.rs | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fc53aa354..e8a722802 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/src/websocket.rs b/src/websocket.rs index 2e38c90ff..b2901e322 100644 --- a/src/websocket.rs +++ b/src/websocket.rs @@ -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| {