@fairfox/polly 0.55.0 → 0.56.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/src/mesh.d.ts +1 -1
- package/dist/src/mesh.js +110 -17
- package/dist/src/mesh.js.map +5 -5
- package/dist/src/shared/lib/mesh-webrtc-adapter.d.ts +185 -2
- package/package.json +1 -1
package/dist/src/mesh.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ export type { MeshSignalingClientOptions, SignalingMessage as MeshSignalingMessa
|
|
|
29
29
|
export { MeshSignalingClient } from "./shared/lib/mesh-signaling-client";
|
|
30
30
|
export type { MeshStateOptions } from "./shared/lib/mesh-state";
|
|
31
31
|
export { $meshCounter, $meshList, $meshState, $meshText, configureMeshState, resetMeshState, } from "./shared/lib/mesh-state";
|
|
32
|
-
export type { MeshWebRTCAdapterOptions } from "./shared/lib/mesh-webrtc-adapter";
|
|
32
|
+
export type { InFlightSyncSnapshot, MeshWebRTCAdapterOptions, SlotInitiationDecision, SlotInitiationRejectionReason, SweepSnapshot, SyncHandshakeAttemptSnapshot, SyncProgressEvent, TransportSnapshot, } from "./shared/lib/mesh-webrtc-adapter";
|
|
33
33
|
export { DEFAULT_ICE_SERVERS, MeshWebRTCAdapter } from "./shared/lib/mesh-webrtc-adapter";
|
|
34
34
|
export type { CreatePairingTokenOptions, PairingToken, } from "./shared/lib/pairing";
|
|
35
35
|
export { applyPairingToken, createPairingToken, createPairingTokenWithFreshIdentity, DEFAULT_PAIRING_TTL_MS, decodePairingToken, encodePairingToken, isPairingTokenExpired, PAIRING_NONCE_BYTES, PAIRING_TOKEN_VERSION, PairingError, parsePairingToken, serialisePairingToken, } from "./shared/lib/pairing";
|
package/dist/src/mesh.js
CHANGED
|
@@ -2044,7 +2044,16 @@ function serialiseSlotView(slot) {
|
|
|
2044
2044
|
transport: slot.transport ? {
|
|
2045
2045
|
...slot.transport,
|
|
2046
2046
|
selectedCandidatePair: slot.transport.selectedCandidatePair ? { ...slot.transport.selectedCandidatePair } : undefined
|
|
2047
|
-
} : undefined
|
|
2047
|
+
} : undefined,
|
|
2048
|
+
lastSyncHandshakeAttempt: { ...slot.lastSyncHandshakeAttempt }
|
|
2049
|
+
};
|
|
2050
|
+
}
|
|
2051
|
+
function emptySyncHandshakeAttempt() {
|
|
2052
|
+
return {
|
|
2053
|
+
dataChannelOpenedAt: undefined,
|
|
2054
|
+
peerCandidateEmittedAt: undefined,
|
|
2055
|
+
firstOutboundSendAt: undefined,
|
|
2056
|
+
firstInboundMessageAt: undefined
|
|
2048
2057
|
};
|
|
2049
2058
|
}
|
|
2050
2059
|
function buildCandidatePairView(pair, localCands, remoteCands) {
|
|
@@ -2082,6 +2091,9 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2082
2091
|
slots = new Map;
|
|
2083
2092
|
ready = false;
|
|
2084
2093
|
readyResolver;
|
|
2094
|
+
lastSlotInitiationDecisions = new Map;
|
|
2095
|
+
sweepRunCount = 0;
|
|
2096
|
+
lastSweepAt;
|
|
2085
2097
|
get knownPeerIds() {
|
|
2086
2098
|
if (this.keyringSource !== undefined) {
|
|
2087
2099
|
return [...this.keyringSource().knownPeers.keys()].filter((id) => id !== this.localPeerId);
|
|
@@ -2134,10 +2146,13 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2134
2146
|
const peers = [];
|
|
2135
2147
|
for (const peerId of allPeers) {
|
|
2136
2148
|
const slot = this.slots.get(peerId);
|
|
2149
|
+
const decision = this.snapshotInitiationDecision(peerId);
|
|
2137
2150
|
peers.push({
|
|
2138
2151
|
peerId,
|
|
2139
2152
|
knownInKeyring: knownPeerSet.has(peerId),
|
|
2140
2153
|
presentInSignalling: this.presentPeers.has(peerId),
|
|
2154
|
+
slotInitiationRejectionReason: decision.reason,
|
|
2155
|
+
slotInitiationDecision: decision,
|
|
2141
2156
|
slot: slot ? serialiseSlotView(slot) : undefined
|
|
2142
2157
|
});
|
|
2143
2158
|
}
|
|
@@ -2145,6 +2160,12 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2145
2160
|
localPeerId: this.localPeerId,
|
|
2146
2161
|
knownPeerIds,
|
|
2147
2162
|
presentPeerIds,
|
|
2163
|
+
sweep: {
|
|
2164
|
+
enabled: this.knownPeersRefreshTimer !== undefined,
|
|
2165
|
+
intervalMs: this.knownPeersRefreshIntervalMs,
|
|
2166
|
+
runCount: this.sweepRunCount,
|
|
2167
|
+
lastRunAt: this.lastSweepAt
|
|
2168
|
+
},
|
|
2148
2169
|
peers
|
|
2149
2170
|
};
|
|
2150
2171
|
}
|
|
@@ -2152,14 +2173,27 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2152
2173
|
this.presentPeers.add(remotePeerId);
|
|
2153
2174
|
if (!this.shouldInitiateTo(remotePeerId))
|
|
2154
2175
|
return;
|
|
2155
|
-
this.
|
|
2176
|
+
this.tryCreateInitiatingSlot(remotePeerId);
|
|
2156
2177
|
}
|
|
2157
2178
|
handlePeersPresent(peerIds) {
|
|
2158
2179
|
for (const remotePeerId of peerIds) {
|
|
2159
2180
|
this.presentPeers.add(remotePeerId);
|
|
2160
2181
|
if (!this.shouldInitiateTo(remotePeerId))
|
|
2161
2182
|
continue;
|
|
2183
|
+
this.tryCreateInitiatingSlot(remotePeerId);
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
tryCreateInitiatingSlot(remotePeerId) {
|
|
2187
|
+
try {
|
|
2162
2188
|
this.createInitiatingSlot(remotePeerId);
|
|
2189
|
+
} catch (err) {
|
|
2190
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2191
|
+
this.lastSlotInitiationDecisions.set(remotePeerId, {
|
|
2192
|
+
decision: "rejected",
|
|
2193
|
+
reason: "fatal-error",
|
|
2194
|
+
error: message,
|
|
2195
|
+
at: performance.now()
|
|
2196
|
+
});
|
|
2163
2197
|
}
|
|
2164
2198
|
}
|
|
2165
2199
|
handlePeerLeft(remotePeerId) {
|
|
@@ -2183,25 +2217,49 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2183
2217
|
return;
|
|
2184
2218
|
if (!this.shouldInitiateTo(remotePeerId))
|
|
2185
2219
|
return;
|
|
2186
|
-
this.
|
|
2220
|
+
this.tryCreateInitiatingSlot(remotePeerId);
|
|
2187
2221
|
}
|
|
2188
2222
|
refreshKnownPeers() {
|
|
2189
2223
|
for (const remotePeerId of this.presentPeers) {
|
|
2190
2224
|
if (!this.shouldInitiateTo(remotePeerId))
|
|
2191
2225
|
continue;
|
|
2192
|
-
this.
|
|
2226
|
+
this.tryCreateInitiatingSlot(remotePeerId);
|
|
2193
2227
|
}
|
|
2194
2228
|
}
|
|
2195
2229
|
shouldInitiateTo(remotePeerId) {
|
|
2230
|
+
const reason = this.evaluateInitiation(remotePeerId);
|
|
2231
|
+
this.lastSlotInitiationDecisions.set(remotePeerId, {
|
|
2232
|
+
decision: reason === undefined ? "accepted" : "rejected",
|
|
2233
|
+
reason,
|
|
2234
|
+
error: undefined,
|
|
2235
|
+
at: performance.now()
|
|
2236
|
+
});
|
|
2237
|
+
return reason === undefined;
|
|
2238
|
+
}
|
|
2239
|
+
evaluateInitiation(remotePeerId) {
|
|
2196
2240
|
if (remotePeerId === this.localPeerId)
|
|
2197
|
-
return
|
|
2241
|
+
return "self";
|
|
2198
2242
|
if (!this.hasKnownPeer(remotePeerId))
|
|
2199
|
-
return
|
|
2243
|
+
return "not-in-keyring";
|
|
2244
|
+
if (!this.presentPeers.has(remotePeerId))
|
|
2245
|
+
return "not-present";
|
|
2200
2246
|
if (this.slots.has(remotePeerId))
|
|
2201
|
-
return
|
|
2247
|
+
return "slot-already-exists";
|
|
2202
2248
|
if (this.localPeerId <= remotePeerId)
|
|
2203
|
-
return
|
|
2204
|
-
return
|
|
2249
|
+
return "tie-break-other-side";
|
|
2250
|
+
return;
|
|
2251
|
+
}
|
|
2252
|
+
snapshotInitiationDecision(remotePeerId) {
|
|
2253
|
+
const cached = this.lastSlotInitiationDecisions.get(remotePeerId);
|
|
2254
|
+
if (cached?.reason === "fatal-error")
|
|
2255
|
+
return cached;
|
|
2256
|
+
const reason = this.evaluateInitiation(remotePeerId);
|
|
2257
|
+
return {
|
|
2258
|
+
decision: reason === undefined ? "accepted" : "rejected",
|
|
2259
|
+
reason,
|
|
2260
|
+
error: undefined,
|
|
2261
|
+
at: performance.now()
|
|
2262
|
+
};
|
|
2205
2263
|
}
|
|
2206
2264
|
whenReady() {
|
|
2207
2265
|
if (this.ready)
|
|
@@ -2238,7 +2296,11 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2238
2296
|
if (this.knownPeersRefreshTimer !== undefined)
|
|
2239
2297
|
return;
|
|
2240
2298
|
this.knownPeersRefreshTimer = setInterval(() => {
|
|
2241
|
-
this.
|
|
2299
|
+
this.sweepRunCount += 1;
|
|
2300
|
+
this.lastSweepAt = performance.now();
|
|
2301
|
+
try {
|
|
2302
|
+
this.refreshKnownPeers();
|
|
2303
|
+
} catch {}
|
|
2242
2304
|
}, this.knownPeersRefreshIntervalMs);
|
|
2243
2305
|
}
|
|
2244
2306
|
stopKnownPeersSweep() {
|
|
@@ -2254,6 +2316,9 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2254
2316
|
if (!slot) {
|
|
2255
2317
|
slot = this.createInitiatingSlot(targetId);
|
|
2256
2318
|
}
|
|
2319
|
+
if (slot.lastSyncHandshakeAttempt.firstOutboundSendAt === undefined) {
|
|
2320
|
+
slot.lastSyncHandshakeAttempt.firstOutboundSendAt = performance.now();
|
|
2321
|
+
}
|
|
2257
2322
|
if (slot.channel && slot.channel.readyState === "open") {
|
|
2258
2323
|
this.sendBytesMaybeFragmented(slot.channel, bytes);
|
|
2259
2324
|
} else {
|
|
@@ -2366,7 +2431,8 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2366
2431
|
pendingRemoteIce: [],
|
|
2367
2432
|
inFlightSync: undefined,
|
|
2368
2433
|
transport: undefined,
|
|
2369
|
-
lastDataChannelError: undefined
|
|
2434
|
+
lastDataChannelError: undefined,
|
|
2435
|
+
lastSyncHandshakeAttempt: emptySyncHandshakeAttempt()
|
|
2370
2436
|
};
|
|
2371
2437
|
this.slots.set(targetId, slot);
|
|
2372
2438
|
this.wireConnection(targetId, connection);
|
|
@@ -2407,7 +2473,8 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2407
2473
|
pendingRemoteIce: [],
|
|
2408
2474
|
inFlightSync: undefined,
|
|
2409
2475
|
transport: undefined,
|
|
2410
|
-
lastDataChannelError: undefined
|
|
2476
|
+
lastDataChannelError: undefined,
|
|
2477
|
+
lastSyncHandshakeAttempt: emptySyncHandshakeAttempt()
|
|
2411
2478
|
};
|
|
2412
2479
|
this.slots.set(fromPeerId, slot);
|
|
2413
2480
|
this.wireConnection(fromPeerId, connection);
|
|
@@ -2477,21 +2544,32 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2477
2544
|
connection.onconnectionstatechange = () => {
|
|
2478
2545
|
const state = connection.connectionState;
|
|
2479
2546
|
if (state === "connected") {
|
|
2480
|
-
this.
|
|
2481
|
-
peerId,
|
|
2482
|
-
peerMetadata: {}
|
|
2483
|
-
});
|
|
2547
|
+
this.emitPeerCandidateOnce(peerId);
|
|
2484
2548
|
} else if (state === "disconnected" || state === "failed" || state === "closed") {
|
|
2485
2549
|
this.slots.delete(peerId);
|
|
2486
2550
|
this.emit("peer-disconnected", { peerId });
|
|
2487
2551
|
}
|
|
2488
2552
|
};
|
|
2489
2553
|
}
|
|
2554
|
+
emitPeerCandidateOnce(peerId) {
|
|
2555
|
+
const slot = this.slots.get(peerId);
|
|
2556
|
+
if (!slot)
|
|
2557
|
+
return;
|
|
2558
|
+
if (slot.lastSyncHandshakeAttempt.peerCandidateEmittedAt !== undefined)
|
|
2559
|
+
return;
|
|
2560
|
+
slot.lastSyncHandshakeAttempt.peerCandidateEmittedAt = performance.now();
|
|
2561
|
+
this.emit("peer-candidate", {
|
|
2562
|
+
peerId,
|
|
2563
|
+
peerMetadata: {}
|
|
2564
|
+
});
|
|
2565
|
+
}
|
|
2490
2566
|
wireDataChannel(peerId, channel) {
|
|
2491
2567
|
channel.onopen = () => {
|
|
2492
2568
|
const slot = this.slots.get(peerId);
|
|
2493
2569
|
if (!slot)
|
|
2494
2570
|
return;
|
|
2571
|
+
slot.lastSyncHandshakeAttempt.dataChannelOpenedAt = performance.now();
|
|
2572
|
+
this.emitPeerCandidateOnce(peerId);
|
|
2495
2573
|
for (const bytes of slot.pendingSends) {
|
|
2496
2574
|
this.sendBytesMaybeFragmented(channel, bytes);
|
|
2497
2575
|
}
|
|
@@ -2559,6 +2637,7 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2559
2637
|
} catch {}
|
|
2560
2638
|
}
|
|
2561
2639
|
scheduleEmitMessage(fromPeerId, message, viaFragmentPath) {
|
|
2640
|
+
this.stampFirstInboundMessage(fromPeerId);
|
|
2562
2641
|
if (!this.syncYieldEnabled) {
|
|
2563
2642
|
this.emit("message", message);
|
|
2564
2643
|
if (viaFragmentPath) {
|
|
@@ -2582,6 +2661,14 @@ class MeshWebRTCAdapter extends NetworkAdapter2 {
|
|
|
2582
2661
|
}
|
|
2583
2662
|
}, 0);
|
|
2584
2663
|
}
|
|
2664
|
+
stampFirstInboundMessage(fromPeerId) {
|
|
2665
|
+
const slot = this.slots.get(fromPeerId);
|
|
2666
|
+
if (!slot)
|
|
2667
|
+
return;
|
|
2668
|
+
if (slot.lastSyncHandshakeAttempt.firstInboundMessageAt !== undefined)
|
|
2669
|
+
return;
|
|
2670
|
+
slot.lastSyncHandshakeAttempt.firstInboundMessageAt = performance.now();
|
|
2671
|
+
}
|
|
2585
2672
|
finishInFlightSyncApply(fromPeerId) {
|
|
2586
2673
|
const slot = this.slots.get(fromPeerId);
|
|
2587
2674
|
if (!slot?.inFlightSync)
|
|
@@ -2813,6 +2900,12 @@ async function createMeshClient(options) {
|
|
|
2813
2900
|
localPeerId: options.signaling.peerId,
|
|
2814
2901
|
knownPeerIds: [],
|
|
2815
2902
|
presentPeerIds: [],
|
|
2903
|
+
sweep: {
|
|
2904
|
+
enabled: false,
|
|
2905
|
+
intervalMs: 0,
|
|
2906
|
+
runCount: 0,
|
|
2907
|
+
lastRunAt: undefined
|
|
2908
|
+
},
|
|
2816
2909
|
peers: []
|
|
2817
2910
|
};
|
|
2818
2911
|
}
|
|
@@ -3237,4 +3330,4 @@ export {
|
|
|
3237
3330
|
$meshCounter
|
|
3238
3331
|
};
|
|
3239
3332
|
|
|
3240
|
-
//# debugId=
|
|
3333
|
+
//# debugId=27D9577FC215E14564756E2164756E21
|