diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-04 01:47:45 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-04 01:47:45 +0200 |
| commit | 5022f2be149e40ac5bdd5fc362e926f3edcf44f0 (patch) | |
| tree | d202f7a557e6d5ac5a6e8409ab1c8cadac39be05 /packages/meshbay-client/src/main.js | |
| parent | 2e819f7c5e0fb6352908ca88ff09b3465023767c (diff) | |
| download | meshbay-5022f2be149e40ac5bdd5fc362e926f3edcf44f0.tar.gz | |
fix(client): resolve STUN hostnames in the main process
Chromium's P2P socket manager failed every STUN hostname with
ERR_NAME_NOT_RESOLVED in a restricted-resolver environment (a Windows KVM
guest), even though its own general network stack, the OS resolver and
Node's resolver all resolved the same names -- and mapping the names to IPs
with --host-resolver-rules changed nothing, so it is not ordinary
resolution. WebRTC was left with no server-reflexive candidate.
The desktop client now resolves the STUN hostnames in the main process
(`ice:resolve-stun`, Node's dns.resolve4) and hands `transport.js` the
IP form; a name that will not resolve (the decommissioned Mozilla host) is
dropped. In a browser there is no `meshbay` bridge and the hostnames are
used unchanged -- a browser resolves them fine, so that path is untouched.
Falls back to the hostname form if the bridge call throws.
Also, scoped to win32: disable WebRtcHideLocalIpsWithMdns, so the client
publishes its real local IP instead of a `.local` name the node's ICE stack
cannot resolve across the KVM bridge. Changes nothing on Linux/macOS.
Test-env workaround, revisit before release.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-client/src/main.js')
| -rw-r--r-- | packages/meshbay-client/src/main.js | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/packages/meshbay-client/src/main.js b/packages/meshbay-client/src/main.js index 2a97246..9c27cfe 100644 --- a/packages/meshbay-client/src/main.js +++ b/packages/meshbay-client/src/main.js @@ -40,6 +40,17 @@ const { pathToFileURL } = require('node:url'); // runs (`electron .`) consistent with it. app.commandLine.appendSwitch('class', 'MeshBay'); +// TEST-ENV WORKAROUND (Windows libvirt/KVM guest) — REVISIT BEFORE RELEASE. +// In that guest Chromium hides the host candidate behind a random `.local` +// mDNS name that the node's ICE stack cannot resolve across the KVM bridge, +// so the one working candidate pair is present on some attempts and missing +// on others (60 s ICE timeouts, "2nd connection hangs"). Publishing the real +// local IP removes the dependency. Scoped to win32 so it changes nothing on +// Linux/macOS, where mDNS concealment works and should stay on. +if (process.platform === 'win32') { + app.commandLine.appendSwitch('disable-features', 'WebRtcHideLocalIpsWithMdns'); +} + const UI_DIR = path.join(__dirname, '..', 'ui'); const SCHEME = 'app'; @@ -497,6 +508,23 @@ function registerBridge() { }; }); + ipcMain.handle('ice:resolve-stun', async (_e, urls) => { + const dns = require('node:dns').promises; + const list = Array.isArray(urls) ? urls : []; + const out = []; + for (const u of list) { + const m = /^(stuns?):(\[?[^\]]+\]?|[^:]+):(\d+)$/.exec(String(u)); + if (!m) { out.push(String(u)); continue; } + const [, scheme, host, port] = m; + if (/^[\d.]+$/.test(host) || host.includes(':')) { out.push(String(u)); continue; } + try { + const [ip] = await dns.resolve4(host); + if (ip) out.push(`${scheme}:${ip}:${port}`); + } catch { /* unresolvable (e.g. a decommissioned host) — drop it */ } + } + return out; + }); + ipcMain.handle('hub:probe', async (_e, url) => { const target = String(url || config.hubBase || '').replace(/\/+$/, ''); if (!target) return null; |