onelobby 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/direct/hub-host.js +23 -0
- package/dist/direct/hub-host.js.map +1 -1
- package/dist/direct/portmap.d.ts +19 -1
- package/dist/direct/portmap.js +79 -14
- package/dist/direct/portmap.js.map +1 -1
- package/dist/lobby.d.ts +2 -0
- package/dist/lobby.js +25 -6
- package/dist/lobby.js.map +1 -1
- package/dist/onelobby.bundle.mjs +5 -5
- package/dist/onelobby.bundle.mjs.map +3 -3
- package/dist/onelobby.d.ts +1 -1
- package/dist/onelobby.global.js +59 -9
- package/dist/onelobby.global.js.map +2 -2
- package/dist/onelobby.global.min.js +5 -5
- package/dist/onelobby.global.min.js.map +3 -3
- package/dist/onelobby.js +1 -1
- package/dist/onelobby.js.map +1 -1
- package/dist/signaling.d.ts +5 -1
- package/dist/signaling.js +17 -2
- package/dist/signaling.js.map +1 -1
- package/dist/webrtc.d.ts +12 -0
- package/dist/webrtc.js +30 -1
- package/dist/webrtc.js.map +1 -1
- package/package.json +1 -1
package/dist/onelobby.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { type LobbySummary } from "./signaling.js";
|
|
|
5
5
|
import { type LinkFactory, type SocketFactory } from "./transport.js";
|
|
6
6
|
import type { VoiceCodec, FrameSource, AudioSink } from "./voice-types.js";
|
|
7
7
|
export declare const LIB_NAME = "onelobby";
|
|
8
|
-
export declare const LIB_VERSION = "0.
|
|
8
|
+
export declare const LIB_VERSION = "0.3.0";
|
|
9
9
|
/** Where `rememberSeat` keeps the resume token: the subset of the Web Storage API it uses. */
|
|
10
10
|
export interface SeatStorage {
|
|
11
11
|
getItem(key: string): string | null;
|
package/dist/onelobby.global.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! onelobby 0.
|
|
1
|
+
/*! onelobby 0.3.0 | MIT license */
|
|
2
2
|
"use strict";
|
|
3
3
|
var OneLobby = (() => {
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -1146,8 +1146,19 @@ var OneLobby = (() => {
|
|
|
1146
1146
|
cancelPing = null;
|
|
1147
1147
|
pingN = 0;
|
|
1148
1148
|
closed = false;
|
|
1149
|
-
|
|
1149
|
+
handler = null;
|
|
1150
|
+
// Messages with no waiter and no handler yet. The reply that resolves join/create can arrive in the same socket
|
|
1151
|
+
// read as the host's first offer; both are dispatched before the awaiting code builds its Lobby and sets a handler.
|
|
1152
|
+
backlog = [];
|
|
1150
1153
|
onClose = null;
|
|
1154
|
+
get onMessage() {
|
|
1155
|
+
return this.handler;
|
|
1156
|
+
}
|
|
1157
|
+
/** Setting a handler first delivers, in order, what arrived while there was none. */
|
|
1158
|
+
set onMessage(h) {
|
|
1159
|
+
this.handler = h;
|
|
1160
|
+
while (h && this.handler === h && this.backlog.length) h(this.backlog.shift());
|
|
1161
|
+
}
|
|
1151
1162
|
connect() {
|
|
1152
1163
|
return new Promise((resolve, reject) => {
|
|
1153
1164
|
let s;
|
|
@@ -1187,7 +1198,8 @@ var OneLobby = (() => {
|
|
|
1187
1198
|
else w.resolve(m);
|
|
1188
1199
|
return;
|
|
1189
1200
|
}
|
|
1190
|
-
this.
|
|
1201
|
+
if (this.handler) this.handler(m);
|
|
1202
|
+
else if (this.backlog.length < 256) this.backlog.push(m);
|
|
1191
1203
|
};
|
|
1192
1204
|
s.onclose = () => {
|
|
1193
1205
|
if (!this.lastRx) reject(new OneLobbyError("connect_failed", `cannot reach ${this.url}`));
|
|
@@ -1798,6 +1810,8 @@ var OneLobby = (() => {
|
|
|
1798
1810
|
cfg;
|
|
1799
1811
|
roster = /* @__PURE__ */ new Map();
|
|
1800
1812
|
links = /* @__PURE__ */ new Map();
|
|
1813
|
+
/** ICE from a peer that has no link yet: its candidates can overtake its offer (node-datachannel). */
|
|
1814
|
+
earlyIce = /* @__PURE__ */ new Map();
|
|
1801
1815
|
connected = /* @__PURE__ */ new Set();
|
|
1802
1816
|
// host: peers that said hi
|
|
1803
1817
|
hiSentTo = /* @__PURE__ */ new Set();
|
|
@@ -2393,13 +2407,25 @@ var OneLobby = (() => {
|
|
|
2393
2407
|
}
|
|
2394
2408
|
async onSignal(from, s) {
|
|
2395
2409
|
let link = this.links.get(from);
|
|
2396
|
-
if (s.sdp?.type === "offer") {
|
|
2397
|
-
link = this.makeLink(from);
|
|
2398
|
-
}
|
|
2399
|
-
if (!link) return;
|
|
2400
2410
|
const payload = {};
|
|
2401
2411
|
if (s.sdp) payload.sdp = s.sdp;
|
|
2402
2412
|
if (s.ice) payload.ice = s.ice;
|
|
2413
|
+
if (s.sdp?.type === "offer") {
|
|
2414
|
+
link = this.makeLink(from);
|
|
2415
|
+
const early = this.earlyIce.get(from) ?? [];
|
|
2416
|
+
this.earlyIce.delete(from);
|
|
2417
|
+
const done = link.handleSignal(payload);
|
|
2418
|
+
for (const e of early) void link.handleSignal(e);
|
|
2419
|
+
await done;
|
|
2420
|
+
return;
|
|
2421
|
+
}
|
|
2422
|
+
if (!link) {
|
|
2423
|
+
if (!payload.ice || this.ended || !this.roster.has(from)) return;
|
|
2424
|
+
const q = this.earlyIce.get(from) ?? [];
|
|
2425
|
+
if (q.length < 64) q.push(payload);
|
|
2426
|
+
this.earlyIce.set(from, q);
|
|
2427
|
+
return;
|
|
2428
|
+
}
|
|
2403
2429
|
await link.handleSignal(payload);
|
|
2404
2430
|
}
|
|
2405
2431
|
/**
|
|
@@ -2414,6 +2440,7 @@ var OneLobby = (() => {
|
|
|
2414
2440
|
return;
|
|
2415
2441
|
}
|
|
2416
2442
|
if (peer) this.roster.delete(peerId);
|
|
2443
|
+
this.earlyIce.delete(peerId);
|
|
2417
2444
|
const link = this.links.get(peerId);
|
|
2418
2445
|
if (link && peerId !== this.hostPeerId) {
|
|
2419
2446
|
link.onMessage = null;
|
|
@@ -2518,6 +2545,7 @@ var OneLobby = (() => {
|
|
|
2518
2545
|
l.close();
|
|
2519
2546
|
}
|
|
2520
2547
|
this.links.clear();
|
|
2548
|
+
this.earlyIce.clear();
|
|
2521
2549
|
this.lingering.clear();
|
|
2522
2550
|
this.signaling.onClose = null;
|
|
2523
2551
|
this.signaling.onMessage = null;
|
|
@@ -2691,8 +2719,14 @@ registerProcessor('onelobby-capture', OneLobbyCapture);
|
|
|
2691
2719
|
pc;
|
|
2692
2720
|
channels = {};
|
|
2693
2721
|
pendingIce = [];
|
|
2722
|
+
/**
|
|
2723
|
+
* Set once setRemoteDescription resolves. Not `pc.remoteDescription`: node-datachannel's polyfill returns an object
|
|
2724
|
+
* there before any is set, and its addIceCandidate throws until one is.
|
|
2725
|
+
*/
|
|
2726
|
+
haveRemote = false;
|
|
2694
2727
|
closed = false;
|
|
2695
2728
|
opened = 0;
|
|
2729
|
+
early = [];
|
|
2696
2730
|
extra;
|
|
2697
2731
|
/** `rtc`: the RTCPeerConnection class to use (default the global one; in Node, node-datachannel's polyfill). */
|
|
2698
2732
|
constructor(opts, rtc = globalThis.RTCPeerConnection) {
|
|
@@ -2718,6 +2752,14 @@ registerProcessor('onelobby-capture', OneLobbyCapture);
|
|
|
2718
2752
|
else this.fail(s);
|
|
2719
2753
|
}
|
|
2720
2754
|
};
|
|
2755
|
+
}
|
|
2756
|
+
/**
|
|
2757
|
+
* The offerer creates the channels just before its offer, the answerer once the remote offer is set. Creating them
|
|
2758
|
+
* any earlier makes libdatachannel (node-datachannel) start an offer of its own on the answering side, which then
|
|
2759
|
+
* collides with the real one (both ICE agents controlling, the link never opens).
|
|
2760
|
+
*/
|
|
2761
|
+
openChannels() {
|
|
2762
|
+
if (this.channels.reliable) return;
|
|
2721
2763
|
for (const name of ["reliable", "fast", "voice"]) {
|
|
2722
2764
|
const ch = this.pc.createDataChannel(name, CHANNEL_INIT[name]);
|
|
2723
2765
|
ch.binaryType = "arraybuffer";
|
|
@@ -2725,6 +2767,7 @@ registerProcessor('onelobby-capture', OneLobbyCapture);
|
|
|
2725
2767
|
if (++this.opened === 3 && !this.closed) {
|
|
2726
2768
|
this.isOpen = true;
|
|
2727
2769
|
this.onOpen?.();
|
|
2770
|
+
for (const [n, data] of this.early.splice(0)) if (!this.closed) this.onMessage?.(n, data);
|
|
2728
2771
|
void this.reportPath();
|
|
2729
2772
|
}
|
|
2730
2773
|
};
|
|
@@ -2732,6 +2775,10 @@ registerProcessor('onelobby-capture', OneLobbyCapture);
|
|
|
2732
2775
|
ch.onmessage = (e) => {
|
|
2733
2776
|
const d = e.data;
|
|
2734
2777
|
const data = d instanceof ArrayBuffer ? new Uint8Array(d) : ArrayBuffer.isView(d) ? new Uint8Array(d.buffer, d.byteOffset, d.byteLength) : new Uint8Array(d);
|
|
2778
|
+
if (!this.isOpen) {
|
|
2779
|
+
if (this.early.length < 1e3) this.early.push([name, data]);
|
|
2780
|
+
return;
|
|
2781
|
+
}
|
|
2735
2782
|
this.onMessage?.(name, data);
|
|
2736
2783
|
};
|
|
2737
2784
|
this.channels[name] = ch;
|
|
@@ -2740,6 +2787,7 @@ registerProcessor('onelobby-capture', OneLobbyCapture);
|
|
|
2740
2787
|
startOffer() {
|
|
2741
2788
|
void (async () => {
|
|
2742
2789
|
try {
|
|
2790
|
+
this.openChannels();
|
|
2743
2791
|
const offer = await this.pc.createOffer();
|
|
2744
2792
|
await this.pc.setLocalDescription(offer);
|
|
2745
2793
|
this.onSignal?.({ sdp: { type: "offer", sdp: offer.sdp ?? "" } });
|
|
@@ -2752,19 +2800,21 @@ registerProcessor('onelobby-capture', OneLobbyCapture);
|
|
|
2752
2800
|
try {
|
|
2753
2801
|
if (s.sdp) {
|
|
2754
2802
|
await this.pc.setRemoteDescription({ type: s.sdp.type, sdp: s.sdp.sdp });
|
|
2803
|
+
this.haveRemote = true;
|
|
2755
2804
|
for (const c of this.pendingIce.splice(0)) await this.pc.addIceCandidate(c);
|
|
2756
2805
|
if (this.extra.length) {
|
|
2757
2806
|
const mid = /^a=mid:(\S+)/m.exec(s.sdp.sdp)?.[1] ?? "0";
|
|
2758
2807
|
for (const candidate of this.extra.splice(0)) await this.pc.addIceCandidate({ candidate, sdpMid: mid, sdpMLineIndex: 0 });
|
|
2759
2808
|
}
|
|
2760
2809
|
if (s.sdp.type === "offer") {
|
|
2810
|
+
this.openChannels();
|
|
2761
2811
|
const answer = await this.pc.createAnswer();
|
|
2762
2812
|
await this.pc.setLocalDescription(answer);
|
|
2763
2813
|
this.onSignal?.({ sdp: { type: "answer", sdp: answer.sdp ?? "" } });
|
|
2764
2814
|
}
|
|
2765
2815
|
}
|
|
2766
2816
|
if (s.ice) {
|
|
2767
|
-
if (this.
|
|
2817
|
+
if (this.haveRemote) await this.pc.addIceCandidate(s.ice);
|
|
2768
2818
|
else this.pendingIce.push(s.ice);
|
|
2769
2819
|
}
|
|
2770
2820
|
} catch (e) {
|
|
@@ -2930,7 +2980,7 @@ registerProcessor('onelobby-capture', OneLobbyCapture);
|
|
|
2930
2980
|
|
|
2931
2981
|
// src/onelobby.ts
|
|
2932
2982
|
var LIB_NAME = "onelobby";
|
|
2933
|
-
var LIB_VERSION = "0.
|
|
2983
|
+
var LIB_VERSION = "0.3.0";
|
|
2934
2984
|
var DEFAULT_READY_TIMEOUT_MS = 15e3;
|
|
2935
2985
|
function hasMic() {
|
|
2936
2986
|
return typeof navigator !== "undefined" && !!navigator.mediaDevices?.getUserMedia && typeof AudioWorkletNode !== "undefined";
|