diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-08-14 03:13:29 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-08-14 03:13:29 +0200 |
| commit | 48124ac249b0bff42c84ab6aee9270cf7ee134d8 (patch) | |
| tree | 6fba6fbbad793d94206ad09e37771a8e259df808 /packages/meshbay-hub/src | |
| parent | 71df5857b213be893025c562977558ba79009c09 (diff) | |
| download | meshbay-48124ac249b0bff42c84ab6aee9270cf7ee134d8.tar.gz | |
fix(node): keep reading the hub socket while negotiating WebRTC
A node could be running, healthy in its own logs, and invisible to the hub with
nothing to say why. That is what "No nodes available" looked like from a browser,
and restarting the daemon was the only way out.
maintain_ws awaited the WebRTC offer handler inline, inside the loop that reads
the hub socket. One negotiation that did not finish — a client that closed its
tab mid-ICE is enough — stopped the node reading that socket at all: pings
unanswered, close frame never seen, later offers never served. The socket sat in
CLOSE-WAIT with the hub's goodbye unread in the receive queue, which is how this
was finally pinned down.
Offers are now answered in their own task, so the read loop keeps draining
whatever happens to any one peer. With that in place the existing reconnect logic
works: a hub restart is seen (1012), retried through the 502 while it comes back
up, and reconnected unattended — 19 seconds in the run that verified this.
Also:
- explicit ping_interval/ping_timeout. This connection is how a node stays
reachable, and a half-open socket looks exactly like a working one.
- a clean close ended `async for` without raising and reconnected in silence;
it now says so, because a node that stops being reachable should leave a trace.
- a failed negotiation logs the peer instead of taking the loop down with it.
Predates this branch (Phase 11), and independent of the invite work — surfaced
while testing it, because deploying the hub mid-session is exactly the trigger.
Tests: 232 node+common, plus the full QE/deploy/e2e.py run against the live
deployment after a deliberate hub restart.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/src')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/transport.js | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/transport.js b/packages/meshbay-hub/src/meshbay_hub/static/transport.js index 624c3c3..271d11f 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/transport.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/transport.js @@ -232,6 +232,20 @@ class MeshBayTransport { } } + if (!gekRaw && !this._sessionKeys) { + // No identity keys in this browser and none recoverable from the node: + // the keypair bundle is created where you register and only reaches a + // node after a first successful connection, so a brand-new member opening + // a second browser has nothing to sign or unwrap with. Say that, rather + // than blaming the GEK — a code prompt here would be useless, since a + // code proves who you are and we have no key to bind to. + const err = new Error( + 'This browser does not hold your keys. Open the group once from the ' + + 'browser where you registered — after that this one can recover them.'); + err.reason = 'no_keys'; + throw err; + } + if (!gekRaw) { throw this._joinError || new Error('Node requires GEK proof but no GEK available'); |