From 86a1c5e61336803e5cccee7c10f245a71f0517a8 Mon Sep 17 00:00:00 2001 From: foxxcn Date: Sun, 11 Oct 2026 18:38:59 +0800 Subject: [PATCH] webui: close the signaling WebSocket when a session ends The signaling socket's sender task waited on a queue whose senders (ping loop, ICE candidate callback) never went away, so the socket outlived its session: every reconnect, and every failed connect, left one more signaling connection open on the device. Keep the queue's sender in Peer and close it in Peer::close and on connect failure; the sender task then exits and closes the socket, and the ping loop stops once its sends fail. Co-Authored-By: Claude Opus 5.5 --- crates/rkvm-web/src/net/peer.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/crates/rkvm-web/src/net/peer.rs b/crates/rkvm-web/src/net/peer.rs index 57c1920..3ffbe4e 100644 --- a/crates/rkvm-web/src/net/peer.rs +++ b/crates/rkvm-web/src/net/peer.rs @@ -22,6 +22,9 @@ pub struct Peer { pub hidrpc: RtcDataChannel, pub hidrpc_unreliable_nonordered: RtcDataChannel, pub terminal: RtcDataChannel, + /// Outbound signaling queue. Closing it ends the sender task, which then + /// closes the signaling WebSocket. + signaling: mpsc::UnboundedSender, } impl Peer { @@ -30,6 +33,7 @@ impl Peer { ch.close(); } self.pc.close(); + self.signaling.close_channel(); } } @@ -149,6 +153,9 @@ pub async fn connect(video: &HtmlVideoElement) -> Result { break; } } + // Without this the socket outlives the session and every reconnect + // leaks one signaling connection on the device. + let _ = sink.close().await; }); { @@ -197,15 +204,26 @@ pub async fn connect(video: &HtmlVideoElement) -> Result { for _ in 0..240 { match pc.ice_connection_state() { RtcIceConnectionState::Failed | RtcIceConnectionState::Closed => { + pc.close(); + out_tx.close_channel(); return Err("ICE connection failed".to_string()); } _ => {} } if rpc.ready_state() == RtcDataChannelState::Open { - return Ok(Peer { pc, rpc, hidrpc, hidrpc_unreliable_nonordered, terminal }); + return Ok(Peer { + pc, + rpc, + hidrpc, + hidrpc_unreliable_nonordered, + terminal, + signaling: out_tx, + }); } TimeoutFuture::new(100).await; } + pc.close(); + out_tx.close_channel(); Err("timed out waiting for the data channel to open".to_string()) }