@muhkoo/connect 0.10.2-alpha.0 → 0.10.4-alpha.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/dist/browser/index.js +45 -5
- package/dist/browser/index.js.map +1 -1
- package/dist/connect.d.ts +7 -0
- package/dist/server/index.js +45 -5
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/dist/connect.d.ts
CHANGED
|
@@ -5591,6 +5591,8 @@ interface WebRtcTransportOptions {
|
|
|
5591
5591
|
iceServers?: RTCIceServer[];
|
|
5592
5592
|
/** Cap on simultaneous peer connections (mesh size). Default 8. */
|
|
5593
5593
|
maxPeers?: number;
|
|
5594
|
+
/** Log ICE/connection state transitions for diagnosing peer connectivity. */
|
|
5595
|
+
debug?: boolean;
|
|
5594
5596
|
}
|
|
5595
5597
|
declare class WebRtcTransport implements PeerTransport {
|
|
5596
5598
|
private readonly signaler;
|
|
@@ -5601,8 +5603,10 @@ declare class WebRtcTransport implements PeerTransport {
|
|
|
5601
5603
|
private readonly offSignal;
|
|
5602
5604
|
private readonly iceServers;
|
|
5603
5605
|
private readonly maxPeers;
|
|
5606
|
+
private readonly debug;
|
|
5604
5607
|
private nextMsgId;
|
|
5605
5608
|
constructor(signaler: SpaceSignaler, myId: PeerId, opts?: WebRtcTransportOptions);
|
|
5609
|
+
private log;
|
|
5606
5610
|
peers(): PeerId[];
|
|
5607
5611
|
/** Dial a peer (no-op unless we're the deterministic initiator for the pair). */
|
|
5608
5612
|
connectTo(peerId: PeerId): void;
|
|
@@ -5612,6 +5616,9 @@ declare class WebRtcTransport implements PeerTransport {
|
|
|
5612
5616
|
onPeerChange(cb: (peers: PeerId[]) => void): () => void;
|
|
5613
5617
|
close(): void;
|
|
5614
5618
|
private newPc;
|
|
5619
|
+
/** Mark a peer's remote description as set and apply any ICE candidates that
|
|
5620
|
+
* arrived before it (dropping them, the old behavior, breaks LAN dials). */
|
|
5621
|
+
private markRemoteSet;
|
|
5615
5622
|
private initiate;
|
|
5616
5623
|
private bindChannel;
|
|
5617
5624
|
private onSignal;
|
package/dist/server/index.js
CHANGED
|
@@ -2976,7 +2976,7 @@ function base64UrlDecode(s) {
|
|
|
2976
2976
|
* expect (and isn't serving a stale cached bundle). Keep this in sync with
|
|
2977
2977
|
* `package.json` `version`.
|
|
2978
2978
|
*/
|
|
2979
|
-
const VERSION = "0.10.
|
|
2979
|
+
const VERSION = "0.10.4-alpha.0";
|
|
2980
2980
|
|
|
2981
2981
|
/**
|
|
2982
2982
|
* `HttpClient` — the one place the unified {@link Client} talks to the
|
|
@@ -8543,14 +8543,20 @@ class WebRtcTransport {
|
|
|
8543
8543
|
offSignal;
|
|
8544
8544
|
iceServers;
|
|
8545
8545
|
maxPeers;
|
|
8546
|
+
debug;
|
|
8546
8547
|
nextMsgId = 1;
|
|
8547
8548
|
constructor(signaler, myId, opts = {}) {
|
|
8548
8549
|
this.signaler = signaler;
|
|
8549
8550
|
this.myId = myId;
|
|
8550
8551
|
this.iceServers = opts.iceServers ?? DEFAULT_ICE;
|
|
8551
8552
|
this.maxPeers = opts.maxPeers ?? 8;
|
|
8553
|
+
this.debug = opts.debug ?? false;
|
|
8552
8554
|
this.offSignal = this.signaler.onSignal((from, kind, data) => this.onSignal(from, kind, data));
|
|
8553
8555
|
}
|
|
8556
|
+
log(...a) {
|
|
8557
|
+
if (this.debug)
|
|
8558
|
+
console.info("[muhkoo:p2p]", ...a);
|
|
8559
|
+
}
|
|
8554
8560
|
peers() {
|
|
8555
8561
|
return [...this.conns].filter(([, c]) => c.dc?.readyState === "open").map(([id]) => id);
|
|
8556
8562
|
}
|
|
@@ -8601,19 +8607,42 @@ class WebRtcTransport {
|
|
|
8601
8607
|
// -- internals -----------------------------------------------------------
|
|
8602
8608
|
newPc(peerId) {
|
|
8603
8609
|
const pc = new RTCPeerConnection({ iceServers: this.iceServers });
|
|
8604
|
-
const conn = { pc, reasm: new Map() };
|
|
8610
|
+
const conn = { pc, reasm: new Map(), remoteSet: false, pendingIce: [] };
|
|
8605
8611
|
this.conns.set(peerId, conn);
|
|
8612
|
+
const short = String(peerId).slice(0, 8);
|
|
8606
8613
|
pc.onicecandidate = (e) => {
|
|
8607
|
-
if (e.candidate)
|
|
8614
|
+
if (e.candidate) {
|
|
8615
|
+
this.log(`${short} local candidate ${e.candidate.type ?? "?"} ${(e.candidate.address ?? e.candidate.candidate).toString().slice(0, 40)}`);
|
|
8608
8616
|
this.signaler.send(peerId, "ice", e.candidate.toJSON());
|
|
8617
|
+
}
|
|
8609
8618
|
};
|
|
8610
8619
|
pc.onconnectionstatechange = () => {
|
|
8620
|
+
this.log(`${short} connection=${pc.connectionState}`);
|
|
8611
8621
|
if (["failed", "closed", "disconnected"].includes(pc.connectionState))
|
|
8612
8622
|
this.drop(peerId);
|
|
8613
8623
|
};
|
|
8624
|
+
if (this.debug) {
|
|
8625
|
+
pc.oniceconnectionstatechange = () => this.log(`${short} ice=${pc.iceConnectionState}`);
|
|
8626
|
+
pc.onicegatheringstatechange = () => this.log(`${short} gathering=${pc.iceGatheringState}`);
|
|
8627
|
+
}
|
|
8614
8628
|
pc.ondatachannel = (e) => this.bindChannel(peerId, conn, e.channel);
|
|
8615
8629
|
return conn;
|
|
8616
8630
|
}
|
|
8631
|
+
/** Mark a peer's remote description as set and apply any ICE candidates that
|
|
8632
|
+
* arrived before it (dropping them, the old behavior, breaks LAN dials). */
|
|
8633
|
+
async markRemoteSet(conn) {
|
|
8634
|
+
conn.remoteSet = true;
|
|
8635
|
+
const pending = conn.pendingIce;
|
|
8636
|
+
conn.pendingIce = [];
|
|
8637
|
+
for (const cand of pending) {
|
|
8638
|
+
try {
|
|
8639
|
+
await conn.pc.addIceCandidate(cand);
|
|
8640
|
+
}
|
|
8641
|
+
catch { /* stale/duplicate */ }
|
|
8642
|
+
}
|
|
8643
|
+
if (pending.length)
|
|
8644
|
+
this.log(`flushed ${pending.length} queued ICE candidate(s)`);
|
|
8645
|
+
}
|
|
8617
8646
|
async initiate(peerId) {
|
|
8618
8647
|
const conn = this.newPc(peerId);
|
|
8619
8648
|
const dc = conn.pc.createDataChannel("blocks");
|
|
@@ -8635,22 +8664,32 @@ class WebRtcTransport {
|
|
|
8635
8664
|
return; // mesh cap
|
|
8636
8665
|
const conn = this.conns.get(from) ?? this.newPc(from);
|
|
8637
8666
|
await conn.pc.setRemoteDescription(data);
|
|
8667
|
+
await this.markRemoteSet(conn);
|
|
8638
8668
|
const answer = await conn.pc.createAnswer();
|
|
8639
8669
|
await conn.pc.setLocalDescription(answer);
|
|
8640
8670
|
this.signaler.send(from, "answer", answer);
|
|
8641
8671
|
}
|
|
8642
8672
|
else if (kind === "answer") {
|
|
8643
8673
|
const conn = this.conns.get(from);
|
|
8644
|
-
if (conn)
|
|
8674
|
+
if (conn) {
|
|
8645
8675
|
await conn.pc.setRemoteDescription(data);
|
|
8676
|
+
await this.markRemoteSet(conn);
|
|
8677
|
+
}
|
|
8646
8678
|
}
|
|
8647
8679
|
else if (kind === "ice") {
|
|
8648
8680
|
const conn = this.conns.get(from);
|
|
8649
8681
|
if (conn && data) {
|
|
8682
|
+
// Queue candidates that arrive before setRemoteDescription — adding
|
|
8683
|
+
// them early throws and (previously) dropped them, which killed the
|
|
8684
|
+
// connection on fast LANs where ICE beats the SDP answer.
|
|
8685
|
+
if (!conn.remoteSet) {
|
|
8686
|
+
conn.pendingIce.push(data);
|
|
8687
|
+
return;
|
|
8688
|
+
}
|
|
8650
8689
|
try {
|
|
8651
8690
|
await conn.pc.addIceCandidate(data);
|
|
8652
8691
|
}
|
|
8653
|
-
catch { /*
|
|
8692
|
+
catch { /* stale */ }
|
|
8654
8693
|
}
|
|
8655
8694
|
}
|
|
8656
8695
|
else if (kind === "bye") {
|
|
@@ -9119,6 +9158,7 @@ class PeerNetwork {
|
|
|
9119
9158
|
new WebRtcTransport(this.signaler, opts.myId, {
|
|
9120
9159
|
iceServers: opts.iceServers,
|
|
9121
9160
|
maxPeers: opts.maxPeers,
|
|
9161
|
+
debug: opts.debug,
|
|
9122
9162
|
});
|
|
9123
9163
|
this.host = buildEngineHost(opts);
|
|
9124
9164
|
// Wire transport ⇄ engine, demuxing block (engine) from gossip (app).
|