From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id EF1B67C800 for ; Fri, 5 Nov 2021 14:04:34 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id E2274BCAB for ; Fri, 5 Nov 2021 14:04:04 +0100 (CET) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 423BCBC3E for ; Fri, 5 Nov 2021 14:04:03 +0100 (CET) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 1AB4546A78 for ; Fri, 5 Nov 2021 14:04:03 +0100 (CET) From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= To: pve-devel@lists.proxmox.com Date: Fri, 5 Nov 2021 14:03:38 +0100 Message-Id: <20211105130359.40803-2-f.gruenbichler@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211105130359.40803-1-f.gruenbichler@proxmox.com> References: <20211105130359.40803-1-f.gruenbichler@proxmox.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.322 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pve-devel] [PATCH proxmox 1/1] websocket: adapt for client connection X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 05 Nov 2021 13:04:35 -0000 previously, this was only used for the server side handling of web sockets. by making the mask part of the WebSocket struct and making some of the fns associated, we can re-use this for client-side connections such as in proxmox-websocket-tunnel. Signed-off-by: Fabian Grünbichler --- Notes: v2: - adapt to changes in proxmox(-http) proxmox-http/src/websocket/mod.rs | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/proxmox-http/src/websocket/mod.rs b/proxmox-http/src/websocket/mod.rs index 2c53d01..d72c550 100644 --- a/proxmox-http/src/websocket/mod.rs +++ b/proxmox-http/src/websocket/mod.rs @@ -650,7 +650,9 @@ impl AsyncRead for WebSocketReader { pub const MAGIC_WEBSOCKET_GUID: &str = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; /// Provides methods for connecting a WebSocket endpoint with another -pub struct WebSocket; +pub struct WebSocket { + pub mask: Option<[u8; 4]>, +} impl WebSocket { /// Returns a new WebSocket instance and the generates the correct @@ -702,10 +704,13 @@ impl WebSocket { let response = response.body(Body::empty())?; - Ok((Self, response)) + let mask = None; + + Ok((Self { mask }, response)) } - async fn handle_channel_message( + pub async fn handle_channel_message( + &self, result: WebSocketReadResult, writer: &mut WebSocketWriter, ) -> Result @@ -714,11 +719,11 @@ impl WebSocket { { match result { Ok((OpCode::Ping, msg)) => { - writer.send_control_frame(None, OpCode::Pong, &msg).await?; + writer.send_control_frame(self.mask, OpCode::Pong, &msg).await?; Ok(OpCode::Pong) } Ok((OpCode::Close, msg)) => { - writer.send_control_frame(None, OpCode::Close, &msg).await?; + writer.send_control_frame(self.mask, OpCode::Close, &msg).await?; Ok(OpCode::Close) } Ok((opcode, _)) => { @@ -727,7 +732,7 @@ impl WebSocket { } Err(err) => { writer - .send_control_frame(None, OpCode::Close, &err.generate_frame_payload()) + .send_control_frame(self.mask, OpCode::Close, &err.generate_frame_payload()) .await?; Err(Error::from(err)) } @@ -735,6 +740,7 @@ impl WebSocket { } async fn copy_to_websocket( + &self, mut reader: &mut R, mut writer: &mut WebSocketWriter, receiver: &mut mpsc::UnboundedReceiver, @@ -743,7 +749,7 @@ impl WebSocket { R: AsyncRead + Unpin + Send, W: AsyncWrite + Unpin + Send, { - let mut buf = ByteBuffer::new(); + let mut buf = ByteBuffer::with_capacity(16*1024); let mut eof = false; loop { if !buf.is_full() { @@ -751,7 +757,7 @@ impl WebSocket { res = buf.read_from_async(&mut reader).fuse() => res?, res = receiver.recv().fuse() => { let res = res.ok_or_else(|| format_err!("control channel closed"))?; - match Self::handle_channel_message(res, &mut writer).await? { + match self.handle_channel_message(res, &mut writer).await? { OpCode::Close => return Ok(true), _ => { continue; }, } @@ -771,6 +777,7 @@ impl WebSocket { } if eof && buf.is_empty() { + writer.flush().await?; return Ok(false); } } @@ -791,10 +798,10 @@ impl WebSocket { let (tx, mut rx) = mpsc::unbounded_channel(); let mut wsreader = WebSocketReader::new(usreader, tx); - let mut wswriter = WebSocketWriter::new(None, uswriter); + let mut wswriter = WebSocketWriter::new(self.mask, uswriter); let ws_future = tokio::io::copy(&mut wsreader, &mut dswriter); - let term_future = Self::copy_to_websocket(&mut dsreader, &mut wswriter, &mut rx); + let term_future = self.copy_to_websocket(&mut dsreader, &mut wswriter, &mut rx); let res = select! { res = ws_future.fuse() => match res { @@ -804,7 +811,7 @@ impl WebSocket { res = term_future.fuse() => match res { Ok(sent_close) if !sent_close => { // status code 1000 => 0x03E8 - wswriter.send_control_frame(None, OpCode::Close, &WebSocketErrorKind::Normal.to_be_bytes()).await?; + wswriter.send_control_frame(self.mask, OpCode::Close, &WebSocketErrorKind::Normal.to_be_bytes()).await?; Ok(()) } Ok(_) => Ok(()), -- 2.30.2