diff options
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/connection-pool.js')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/connection-pool.js | 49 |
1 files changed, 34 insertions, 15 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/connection-pool.js b/packages/meshbay-hub/src/meshbay_hub/static/connection-pool.js index 8a616c2a..2961420b 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/connection-pool.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/connection-pool.js @@ -61,11 +61,15 @@ const SEARCH_MAX_MS = 30000; * * So does a node this device refuses to reach on the local network (Android * 17, Chrome 155: transport.js localNetworkRefused): another node of the group - * may be elsewhere. Search gives up long before connect() would name it, so it - * is read from the connection when giving up, and it is what is thrown when - * no node answered: the page says what to change rather than "unreachable". + * may be elsewhere. connect() names it only once ICE gives up, about thirty + * seconds, and until then Chrome lists the refused address like any other, + * its checks "sent": measured on a Pixel, nothing tells it from a node that + * does not answer when search gives up. So a connection given up on is left + * to reach its own verdict, out of the walk and its places, and + * `onLateRefusal` hears the refusal when it comes. */ -async function connectToGroup(hubBase, groupId, token, bundleKey, username, userId) { +async function connectToGroup(hubBase, groupId, token, bundleKey, username, userId, + onLateRefusal = null) { const nodesData = await hubFetch(`/v1/groups/${groupId}/nodes`, { token }); if (!nodesData.nodes || !nodesData.nodes.length) return null; @@ -81,11 +85,12 @@ async function connectToGroup(hubBase, groupId, token, bundleKey, username, user clearTimeout(capTimer); transport.onConnectProgress = null; }; + const connecting = transport.connect( + n.node_id, live, groupId, null, null, bundleKey, + username, userId, null, undefined, undefined, n.pk_node); try { const ack = await Promise.race([ - transport.connect( - n.node_id, live, groupId, null, null, bundleKey, - username, userId, null, undefined, undefined, n.pk_node), + connecting, new Promise((_, reject) => { const giveUp = () => reject(new Error('Connection timeout')); stallTimer = setTimeout(giveUp, SEARCH_STALL_MS); @@ -103,13 +108,23 @@ async function connectToGroup(hubBase, groupId, token, bundleKey, username, user } catch (e) { stopTimers(); lastErr = e; - if (!e.reason && await transport.localNetworkRefused()) { - lastErr = new Error('This device refused to reach the local network'); - lastErr.reason = 'local_network_blocked'; + if (e.reason === 'local_network_blocked') lanErr = e; + if (e.reason) { + try { transport.close(); } catch {} + } else { + // Given up on by search, not by the connection: closed once it ends. + connecting.then(() => { + try { transport.close(); } catch {} + }, (err) => { + try { transport.close(); } catch {} + if (err && err.reason === 'local_network_blocked' && onLateRefusal) { + onLateRefusal(groupId); + } + }); + } + if (e.reason && e.reason !== 'not_hosted' && e.reason !== 'local_network_blocked') { + throw e; } - try { transport.close(); } catch {} - if (lastErr.reason === 'local_network_blocked') { lanErr = lastErr; continue; } - if (e.reason && e.reason !== 'not_hosted') throw e; } } throw (lanErr || lastErr || new Error('no node served this group')); @@ -128,7 +143,7 @@ async function connectToGroup(hubBase, groupId, token, bundleKey, username, user * phone ran into the hub's per-account ceilings with five groups. */ class ConnectionPool { - constructor(hubBase, onEvict) { + constructor(hubBase, onEvict, onLanRefused) { this._hubBase = hubBase; this._connections = new Map(); this._connecting = new Map(); @@ -136,6 +151,9 @@ class ConnectionPool { // (eviction, close or closeAll). SearchPage uses it to drop its own record // so it never hands a tile a `_tRef` pointing at a transport closed here. this._onEvict = onEvict || (() => {}); + // Called with a groupId when a node search gave up on turns out to be one + // this device refuses on the local network (connectToGroup). + this._onLanRefused = onLanRefused || (() => {}); // Negotiations under way, and those waiting for one of the places. this._active = 0; this._waiting = []; @@ -233,7 +251,8 @@ class ConnectionPool { async _doConnect(groupId, token, bundleKey, username, userId) { const found = await connectToGroup( - this._hubBase, groupId, token, bundleKey, username, userId); + this._hubBase, groupId, token, bundleKey, username, userId, + (id) => { if (!this._closed) this._onLanRefused(id); }); if (!found) throw new Error('offline'); const { transport, ack } = found; |