summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/transport.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/transport.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/transport.js35
1 files changed, 35 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 844a201..df2abb0 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/transport.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/transport.js
@@ -562,6 +562,18 @@ class MeshBayTransport {
}
/**
+ * Nobody is watching any more.
+ *
+ * Closing the viewer used to say nothing to the node, which went on
+ * transcoding and holding one of its two slots until the credit timeout — so
+ * the next video answered "server busy".
+ */
+ stopStream() {
+ if (!this._connected) return;
+ try { this._send({ type: 'stream_stop', v: '0.1' }); } catch { /* gone */ }
+ }
+
+ /**
* Push a whole file, several chunks in flight at once.
*
* One chunk per round trip is 48 KB of throughput per RTT no matter how much
@@ -778,6 +790,11 @@ class MeshBayTransport {
}, 30000);
this._pending.set(id, {
_reqType: obj.type,
+ // Chunks are the one request that runs several at a time and can be
+ // interleaved with anything else on the channel. Matching them by
+ // arrival order was only ever true by luck; this makes it true.
+ _key: obj.type === 'file_req'
+ ? `chunk:${obj.file_id}:${obj.chunk_index}` : null,
resolve: (msg) => { clearTimeout(timeout); this._pending.delete(id); resolve(msg); },
reject: (err) => { clearTimeout(timeout); this._pending.delete(id); reject(err); },
});
@@ -857,6 +874,24 @@ class MeshBayTransport {
return;
}
+ if (msg.type === 'file_chunk') {
+ const key = `chunk:${msg.file_id}:${msg.chunk_index}`;
+ for (const [, handler] of this._pending) {
+ // A node from before the reply carried a file_id: fall back to the
+ // index, which is still better than the oldest pending request.
+ const match = msg.file_id
+ ? handler._key === key
+ : handler._key && handler._key.endsWith(`:${msg.chunk_index}`);
+ if (match) {
+ handler.resolve(msg);
+ return;
+ }
+ }
+ // Nobody asked for it any more — a cancelled download, most likely. It
+ // must not be handed to whatever request happens to be waiting.
+ return;
+ }
+
const oldest = this._pending.entries().next();
if (!oldest.done) {
const [, handler] = oldest.value;