summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/src/meshbay_node/roster.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-30 22:17:30 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-30 22:17:30 +0200
commit07e6e4271ea3a45e9cd364eb6ec05801a653d9e8 (patch)
tree5d2dea4251ee2ecea32aeef80d09167d08085dd0 /packages/meshbay-node/src/meshbay_node/roster.py
parentbf56b60b95c5413d592f0199320d637978792756 (diff)
downloadmeshbay-07e6e4271ea3a45e9cd364eb6ec05801a653d9e8.tar.gz
feat: configurable STUN server fallbacks for WebRTC ICE
The WebRTC transport relied on a single Google STUN server — if it was unreachable, ICE gathering waited the full 4s timeout. Now four public servers are used by default (Google ×2, Cloudflare, Mozilla), configurable via node.toml, the Node page UI, and the CLI (meshbay-node stun list|add| remove|reset). Changes are hot-swapped on the live transport. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-node/src/meshbay_node/roster.py')
-rw-r--r--packages/meshbay-node/src/meshbay_node/roster.py11
1 files changed, 11 insertions, 0 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/roster.py b/packages/meshbay-node/src/meshbay_node/roster.py
index cf0d421..5bdb5ee 100644
--- a/packages/meshbay-node/src/meshbay_node/roster.py
+++ b/packages/meshbay-node/src/meshbay_node/roster.py
@@ -764,9 +764,11 @@ class Roster:
SETTING_DEVICE_TTL = "device_request_ttl_minutes"
SETTING_MAX_STREAMS = "max_concurrent_streams"
SETTING_TRANSCODE = "transcode_incompatible_video"
+ SETTING_STUN_SERVERS = "stun_servers"
async def node_settings(self, defaults: dict) -> dict:
"""Current effective settings: roster override if present, else config default."""
+ import json as _json
result = {}
for key, setting in [
("invite_ttl_hours", self.SETTING_INVITE_TTL),
@@ -783,6 +785,15 @@ class Roster:
result[key] = int(stored)
else:
result[key] = defaults.get(key)
+ stored = await self.get_setting(self.NODE_WIDE_GROUP_ID,
+ self.SETTING_STUN_SERVERS)
+ if stored is not None:
+ try:
+ result["stun_servers"] = _json.loads(stored)
+ except (ValueError, TypeError):
+ result["stun_servers"] = defaults.get("stun_servers", [])
+ else:
+ result["stun_servers"] = defaults.get("stun_servers", [])
return result
async def set_node_setting(self, key: str, value: str,