From b3b48a43a33f936be18a3daa22d307c144b60e22 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Tue, 1 Sep 2026 01:13:43 +0200 Subject: fix(node): make WebRTC STUN fallback actually use every configured server aiortc's connection_kwargs() keeps only the first STUN URI from RTCConfiguration.iceServers ("only a single STUN server is supported"), and aioice.ice.Connection has a single stun_server field. So the node's four default STUN servers -- and anything added on the Node page or with `meshbay-node stun add` -- collapsed to stun:stun.l.google.com:19302. When that one server was slow or unreachable from the node, ICE gathering (get_component_candidates, timeout=5) burned its full 5 s with no server-reflexive candidate, adding seconds to every browser connection. The multi-server fallback of draft-v6 s2.12 was configuration only. transport/stun_multi patches aioice.ice.server_reflexive_candidate (same monkey-patch technique ice_filter.py uses on get_host_addresses) so a single ICE gather races the STUN binding request against every configured server on the one bound socket and takes the first answer. One reachable server anywhere in the list now yields a reflexive candidate in one RTT. - daemon: install_stun_multi() alongside install_ice_filter() - ops.set_node_settings: push the list to stun_multi.set_servers() so the CLI / Node-page hot-swap takes effect without a restart - webrtc_server.handle_offer: log ICE gather time and srflx count - test_stun_multi.py: fan-out, first-answer-wins, all-fail, empty-list fallback, DNS failure Verified end to end with a real RTCPeerConnection: with a black-hole STUN server first in the list, gathering still completes in ~0.07 s with full srflx candidates (previously a 5 s stall). Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01BSsQhfxEAhwi4nqc4hASmq --- packages/meshbay-node/src/meshbay_node/config.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'packages/meshbay-node/src/meshbay_node/config.py') diff --git a/packages/meshbay-node/src/meshbay_node/config.py b/packages/meshbay-node/src/meshbay_node/config.py index b94d03a..0355615 100644 --- a/packages/meshbay-node/src/meshbay_node/config.py +++ b/packages/meshbay-node/src/meshbay_node/config.py @@ -65,7 +65,9 @@ transcode_incompatible_video = true # ice_interfaces = ["wlp0s20f3", "eth0"] # STUN servers for WebRTC ICE candidate gathering (NAT traversal). By default -# four public servers are used; set this to override. +# four public servers are used; set this to override. Every server in the list +# is queried in parallel each gather and the first answer wins, so one slow or +# blocked server no longer stalls the WebRTC answer. # stun_servers = ["stun:stun.l.google.com:19302", "stun:stun.cloudflare.com:3478"] # Browser and native clients reach this node over WebRTC DataChannel via hub -- cgit v1.2.3