@streamr/sdk 103.3.1 → 103.7.0-rc.2
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/exports-umd.js +879 -121
- package/dist/exports-umd.js.map +1 -1
- package/dist/exports-umd.min.js +8 -2
- package/dist/exports-umd.min.js.map +1 -1
- package/package.json +6 -6
package/dist/exports-umd.js
CHANGED
|
@@ -41288,6 +41288,22 @@
|
|
|
41288
41288
|
cb();
|
|
41289
41289
|
}, ms);
|
|
41290
41290
|
};
|
|
41291
|
+
/**
|
|
41292
|
+
* setInterval with AbortSignal support. Aborting will simply clear
|
|
41293
|
+
* the interval silently.
|
|
41294
|
+
*/
|
|
41295
|
+
const setAbortableInterval = (cb, ms, abortSignal) => {
|
|
41296
|
+
if (abortSignal.aborted) {
|
|
41297
|
+
return;
|
|
41298
|
+
}
|
|
41299
|
+
const abortListener = () => {
|
|
41300
|
+
clearInterval(timeoutRef);
|
|
41301
|
+
};
|
|
41302
|
+
abortSignal.addEventListener('abort', abortListener, { once: true });
|
|
41303
|
+
const timeoutRef = setInterval(() => {
|
|
41304
|
+
cb();
|
|
41305
|
+
}, ms);
|
|
41306
|
+
};
|
|
41291
41307
|
|
|
41292
41308
|
const noopExecutor = () => { };
|
|
41293
41309
|
/**
|
|
@@ -73321,7 +73337,7 @@
|
|
|
73321
73337
|
}
|
|
73322
73338
|
}
|
|
73323
73339
|
|
|
73324
|
-
const logger$
|
|
73340
|
+
const logger$E = new Logger('LoggingJsonRpcProvider');
|
|
73325
73341
|
class LoggingJsonRpcProvider extends JsonRpcProvider {
|
|
73326
73342
|
urlConfig;
|
|
73327
73343
|
constructor(urlConfig, network, options) {
|
|
@@ -73340,20 +73356,20 @@
|
|
|
73340
73356
|
timeout: this.urlConfig.timeout
|
|
73341
73357
|
}
|
|
73342
73358
|
};
|
|
73343
|
-
logger$
|
|
73359
|
+
logger$E.debug('Send request', logContext);
|
|
73344
73360
|
let result;
|
|
73345
73361
|
try {
|
|
73346
73362
|
result = await super.send(method, params);
|
|
73347
73363
|
}
|
|
73348
73364
|
catch (err) {
|
|
73349
|
-
logger$
|
|
73365
|
+
logger$E.debug('Encountered error while requesting', {
|
|
73350
73366
|
...logContext,
|
|
73351
73367
|
err,
|
|
73352
73368
|
elapsedTime: Date.now() - startTime
|
|
73353
73369
|
});
|
|
73354
73370
|
throw err;
|
|
73355
73371
|
}
|
|
73356
|
-
logger$
|
|
73372
|
+
logger$E.debug('Received response', {
|
|
73357
73373
|
...logContext,
|
|
73358
73374
|
elapsedTime: Date.now() - startTime
|
|
73359
73375
|
});
|
|
@@ -80246,7 +80262,7 @@
|
|
|
80246
80262
|
this.deferredPromises.trailer.resolve({});
|
|
80247
80263
|
}
|
|
80248
80264
|
catch (err) {
|
|
80249
|
-
logger$
|
|
80265
|
+
logger$z.debug(`Could not parse response, received message is likely `);
|
|
80250
80266
|
const error = new FailedToParse(`Failed to parse received response, network protocol version likely is likely incompatible`, err);
|
|
80251
80267
|
this.rejectDeferredPromises(error, StatusCode.SERVER_ERROR);
|
|
80252
80268
|
}
|
|
@@ -80267,7 +80283,7 @@
|
|
|
80267
80283
|
return this.callContext;
|
|
80268
80284
|
}
|
|
80269
80285
|
}
|
|
80270
|
-
const logger$
|
|
80286
|
+
const logger$z = new Logger('RpcCommunicator');
|
|
80271
80287
|
class RpcCommunicator {
|
|
80272
80288
|
stopped = false;
|
|
80273
80289
|
rpcClientTransport;
|
|
@@ -80321,7 +80337,7 @@
|
|
|
80321
80337
|
if (deferredPromises && (!callContext || !callContext.notification)) {
|
|
80322
80338
|
this.registerRequest(rpcMessage.requestId, deferredPromises, callContext, requestOptions.timeout);
|
|
80323
80339
|
}
|
|
80324
|
-
logger$
|
|
80340
|
+
logger$z.trace(`onOutGoingMessage, messageId: ${rpcMessage.requestId}`);
|
|
80325
80341
|
if (this.outgoingMessageListener) {
|
|
80326
80342
|
this.outgoingMessageListener(rpcMessage, rpcMessage.requestId, callContext)
|
|
80327
80343
|
.catch((clientSideException) => {
|
|
@@ -80352,7 +80368,7 @@
|
|
|
80352
80368
|
}
|
|
80353
80369
|
}
|
|
80354
80370
|
async onIncomingMessage(rpcMessage, callContext) {
|
|
80355
|
-
logger$
|
|
80371
|
+
logger$z.trace(`onIncomingMessage, requestId: ${rpcMessage.requestId}`);
|
|
80356
80372
|
if (rpcMessage.header.response && this.ongoingRequests.has(rpcMessage.requestId)) {
|
|
80357
80373
|
if (rpcMessage.errorType !== undefined) {
|
|
80358
80374
|
this.rejectOngoingRequest(rpcMessage);
|
|
@@ -80414,7 +80430,7 @@
|
|
|
80414
80430
|
await this.rpcServerRegistry.handleNotification(rpcMessage, callContext);
|
|
80415
80431
|
}
|
|
80416
80432
|
catch (err) {
|
|
80417
|
-
logger$
|
|
80433
|
+
logger$z.debug('error', { err });
|
|
80418
80434
|
}
|
|
80419
80435
|
}
|
|
80420
80436
|
registerRequest(requestId, deferredPromises, callContext, timeout = this.rpcRequestTimeout) {
|
|
@@ -81601,6 +81617,355 @@
|
|
|
81601
81617
|
var ipaddrExports = requireIpaddr();
|
|
81602
81618
|
var ipaddr = /*@__PURE__*/getDefaultExportFromCjs$1(ipaddrExports);
|
|
81603
81619
|
|
|
81620
|
+
/**
|
|
81621
|
+
* @license
|
|
81622
|
+
* Copyright 2019 Google LLC
|
|
81623
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
81624
|
+
*/
|
|
81625
|
+
const proxyMarker = Symbol("Comlink.proxy");
|
|
81626
|
+
const createEndpoint = Symbol("Comlink.endpoint");
|
|
81627
|
+
const releaseProxy = Symbol("Comlink.releaseProxy");
|
|
81628
|
+
const finalizer = Symbol("Comlink.finalizer");
|
|
81629
|
+
const throwMarker = Symbol("Comlink.thrown");
|
|
81630
|
+
const isObject$1 = (val) => (typeof val === "object" && val !== null) || typeof val === "function";
|
|
81631
|
+
/**
|
|
81632
|
+
* Internal transfer handle to handle objects marked to proxy.
|
|
81633
|
+
*/
|
|
81634
|
+
const proxyTransferHandler = {
|
|
81635
|
+
canHandle: (val) => isObject$1(val) && val[proxyMarker],
|
|
81636
|
+
serialize(obj) {
|
|
81637
|
+
const { port1, port2 } = new MessageChannel();
|
|
81638
|
+
expose(obj, port1);
|
|
81639
|
+
return [port2, [port2]];
|
|
81640
|
+
},
|
|
81641
|
+
deserialize(port) {
|
|
81642
|
+
port.start();
|
|
81643
|
+
return wrap$1(port);
|
|
81644
|
+
},
|
|
81645
|
+
};
|
|
81646
|
+
/**
|
|
81647
|
+
* Internal transfer handler to handle thrown exceptions.
|
|
81648
|
+
*/
|
|
81649
|
+
const throwTransferHandler = {
|
|
81650
|
+
canHandle: (value) => isObject$1(value) && throwMarker in value,
|
|
81651
|
+
serialize({ value }) {
|
|
81652
|
+
let serialized;
|
|
81653
|
+
if (value instanceof Error) {
|
|
81654
|
+
serialized = {
|
|
81655
|
+
isError: true,
|
|
81656
|
+
value: {
|
|
81657
|
+
message: value.message,
|
|
81658
|
+
name: value.name,
|
|
81659
|
+
stack: value.stack,
|
|
81660
|
+
},
|
|
81661
|
+
};
|
|
81662
|
+
}
|
|
81663
|
+
else {
|
|
81664
|
+
serialized = { isError: false, value };
|
|
81665
|
+
}
|
|
81666
|
+
return [serialized, []];
|
|
81667
|
+
},
|
|
81668
|
+
deserialize(serialized) {
|
|
81669
|
+
if (serialized.isError) {
|
|
81670
|
+
throw Object.assign(new Error(serialized.value.message), serialized.value);
|
|
81671
|
+
}
|
|
81672
|
+
throw serialized.value;
|
|
81673
|
+
},
|
|
81674
|
+
};
|
|
81675
|
+
/**
|
|
81676
|
+
* Allows customizing the serialization of certain values.
|
|
81677
|
+
*/
|
|
81678
|
+
const transferHandlers = new Map([
|
|
81679
|
+
["proxy", proxyTransferHandler],
|
|
81680
|
+
["throw", throwTransferHandler],
|
|
81681
|
+
]);
|
|
81682
|
+
function isAllowedOrigin(allowedOrigins, origin) {
|
|
81683
|
+
for (const allowedOrigin of allowedOrigins) {
|
|
81684
|
+
if (origin === allowedOrigin || allowedOrigin === "*") {
|
|
81685
|
+
return true;
|
|
81686
|
+
}
|
|
81687
|
+
if (allowedOrigin instanceof RegExp && allowedOrigin.test(origin)) {
|
|
81688
|
+
return true;
|
|
81689
|
+
}
|
|
81690
|
+
}
|
|
81691
|
+
return false;
|
|
81692
|
+
}
|
|
81693
|
+
function expose(obj, ep = globalThis, allowedOrigins = ["*"]) {
|
|
81694
|
+
ep.addEventListener("message", function callback(ev) {
|
|
81695
|
+
if (!ev || !ev.data) {
|
|
81696
|
+
return;
|
|
81697
|
+
}
|
|
81698
|
+
if (!isAllowedOrigin(allowedOrigins, ev.origin)) {
|
|
81699
|
+
console.warn(`Invalid origin '${ev.origin}' for comlink proxy`);
|
|
81700
|
+
return;
|
|
81701
|
+
}
|
|
81702
|
+
const { id, type, path } = Object.assign({ path: [] }, ev.data);
|
|
81703
|
+
const argumentList = (ev.data.argumentList || []).map(fromWireValue);
|
|
81704
|
+
let returnValue;
|
|
81705
|
+
try {
|
|
81706
|
+
const parent = path.slice(0, -1).reduce((obj, prop) => obj[prop], obj);
|
|
81707
|
+
const rawValue = path.reduce((obj, prop) => obj[prop], obj);
|
|
81708
|
+
switch (type) {
|
|
81709
|
+
case "GET" /* MessageType.GET */:
|
|
81710
|
+
{
|
|
81711
|
+
returnValue = rawValue;
|
|
81712
|
+
}
|
|
81713
|
+
break;
|
|
81714
|
+
case "SET" /* MessageType.SET */:
|
|
81715
|
+
{
|
|
81716
|
+
parent[path.slice(-1)[0]] = fromWireValue(ev.data.value);
|
|
81717
|
+
returnValue = true;
|
|
81718
|
+
}
|
|
81719
|
+
break;
|
|
81720
|
+
case "APPLY" /* MessageType.APPLY */:
|
|
81721
|
+
{
|
|
81722
|
+
returnValue = rawValue.apply(parent, argumentList);
|
|
81723
|
+
}
|
|
81724
|
+
break;
|
|
81725
|
+
case "CONSTRUCT" /* MessageType.CONSTRUCT */:
|
|
81726
|
+
{
|
|
81727
|
+
const value = new rawValue(...argumentList);
|
|
81728
|
+
returnValue = proxy(value);
|
|
81729
|
+
}
|
|
81730
|
+
break;
|
|
81731
|
+
case "ENDPOINT" /* MessageType.ENDPOINT */:
|
|
81732
|
+
{
|
|
81733
|
+
const { port1, port2 } = new MessageChannel();
|
|
81734
|
+
expose(obj, port2);
|
|
81735
|
+
returnValue = transfer(port1, [port1]);
|
|
81736
|
+
}
|
|
81737
|
+
break;
|
|
81738
|
+
case "RELEASE" /* MessageType.RELEASE */:
|
|
81739
|
+
{
|
|
81740
|
+
returnValue = undefined;
|
|
81741
|
+
}
|
|
81742
|
+
break;
|
|
81743
|
+
default:
|
|
81744
|
+
return;
|
|
81745
|
+
}
|
|
81746
|
+
}
|
|
81747
|
+
catch (value) {
|
|
81748
|
+
returnValue = { value, [throwMarker]: 0 };
|
|
81749
|
+
}
|
|
81750
|
+
Promise.resolve(returnValue)
|
|
81751
|
+
.catch((value) => {
|
|
81752
|
+
return { value, [throwMarker]: 0 };
|
|
81753
|
+
})
|
|
81754
|
+
.then((returnValue) => {
|
|
81755
|
+
const [wireValue, transferables] = toWireValue(returnValue);
|
|
81756
|
+
ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
|
|
81757
|
+
if (type === "RELEASE" /* MessageType.RELEASE */) {
|
|
81758
|
+
// detach and deactive after sending release response above.
|
|
81759
|
+
ep.removeEventListener("message", callback);
|
|
81760
|
+
closeEndPoint(ep);
|
|
81761
|
+
if (finalizer in obj && typeof obj[finalizer] === "function") {
|
|
81762
|
+
obj[finalizer]();
|
|
81763
|
+
}
|
|
81764
|
+
}
|
|
81765
|
+
})
|
|
81766
|
+
.catch((error) => {
|
|
81767
|
+
// Send Serialization Error To Caller
|
|
81768
|
+
const [wireValue, transferables] = toWireValue({
|
|
81769
|
+
value: new TypeError("Unserializable return value"),
|
|
81770
|
+
[throwMarker]: 0,
|
|
81771
|
+
});
|
|
81772
|
+
ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
|
|
81773
|
+
});
|
|
81774
|
+
});
|
|
81775
|
+
if (ep.start) {
|
|
81776
|
+
ep.start();
|
|
81777
|
+
}
|
|
81778
|
+
}
|
|
81779
|
+
function isMessagePort(endpoint) {
|
|
81780
|
+
return endpoint.constructor.name === "MessagePort";
|
|
81781
|
+
}
|
|
81782
|
+
function closeEndPoint(endpoint) {
|
|
81783
|
+
if (isMessagePort(endpoint))
|
|
81784
|
+
endpoint.close();
|
|
81785
|
+
}
|
|
81786
|
+
function wrap$1(ep, target) {
|
|
81787
|
+
const pendingListeners = new Map();
|
|
81788
|
+
ep.addEventListener("message", function handleMessage(ev) {
|
|
81789
|
+
const { data } = ev;
|
|
81790
|
+
if (!data || !data.id) {
|
|
81791
|
+
return;
|
|
81792
|
+
}
|
|
81793
|
+
const resolver = pendingListeners.get(data.id);
|
|
81794
|
+
if (!resolver) {
|
|
81795
|
+
return;
|
|
81796
|
+
}
|
|
81797
|
+
try {
|
|
81798
|
+
resolver(data);
|
|
81799
|
+
}
|
|
81800
|
+
finally {
|
|
81801
|
+
pendingListeners.delete(data.id);
|
|
81802
|
+
}
|
|
81803
|
+
});
|
|
81804
|
+
return createProxy(ep, pendingListeners, [], target);
|
|
81805
|
+
}
|
|
81806
|
+
function throwIfProxyReleased(isReleased) {
|
|
81807
|
+
if (isReleased) {
|
|
81808
|
+
throw new Error("Proxy has been released and is not useable");
|
|
81809
|
+
}
|
|
81810
|
+
}
|
|
81811
|
+
function releaseEndpoint(ep) {
|
|
81812
|
+
return requestResponseMessage(ep, new Map(), {
|
|
81813
|
+
type: "RELEASE" /* MessageType.RELEASE */,
|
|
81814
|
+
}).then(() => {
|
|
81815
|
+
closeEndPoint(ep);
|
|
81816
|
+
});
|
|
81817
|
+
}
|
|
81818
|
+
const proxyCounter = new WeakMap();
|
|
81819
|
+
const proxyFinalizers = "FinalizationRegistry" in globalThis &&
|
|
81820
|
+
new FinalizationRegistry((ep) => {
|
|
81821
|
+
const newCount = (proxyCounter.get(ep) || 0) - 1;
|
|
81822
|
+
proxyCounter.set(ep, newCount);
|
|
81823
|
+
if (newCount === 0) {
|
|
81824
|
+
releaseEndpoint(ep);
|
|
81825
|
+
}
|
|
81826
|
+
});
|
|
81827
|
+
function registerProxy(proxy, ep) {
|
|
81828
|
+
const newCount = (proxyCounter.get(ep) || 0) + 1;
|
|
81829
|
+
proxyCounter.set(ep, newCount);
|
|
81830
|
+
if (proxyFinalizers) {
|
|
81831
|
+
proxyFinalizers.register(proxy, ep, proxy);
|
|
81832
|
+
}
|
|
81833
|
+
}
|
|
81834
|
+
function unregisterProxy(proxy) {
|
|
81835
|
+
if (proxyFinalizers) {
|
|
81836
|
+
proxyFinalizers.unregister(proxy);
|
|
81837
|
+
}
|
|
81838
|
+
}
|
|
81839
|
+
function createProxy(ep, pendingListeners, path = [], target = function () { }) {
|
|
81840
|
+
let isProxyReleased = false;
|
|
81841
|
+
const proxy = new Proxy(target, {
|
|
81842
|
+
get(_target, prop) {
|
|
81843
|
+
throwIfProxyReleased(isProxyReleased);
|
|
81844
|
+
if (prop === releaseProxy) {
|
|
81845
|
+
return () => {
|
|
81846
|
+
unregisterProxy(proxy);
|
|
81847
|
+
releaseEndpoint(ep);
|
|
81848
|
+
pendingListeners.clear();
|
|
81849
|
+
isProxyReleased = true;
|
|
81850
|
+
};
|
|
81851
|
+
}
|
|
81852
|
+
if (prop === "then") {
|
|
81853
|
+
if (path.length === 0) {
|
|
81854
|
+
return { then: () => proxy };
|
|
81855
|
+
}
|
|
81856
|
+
const r = requestResponseMessage(ep, pendingListeners, {
|
|
81857
|
+
type: "GET" /* MessageType.GET */,
|
|
81858
|
+
path: path.map((p) => p.toString()),
|
|
81859
|
+
}).then(fromWireValue);
|
|
81860
|
+
return r.then.bind(r);
|
|
81861
|
+
}
|
|
81862
|
+
return createProxy(ep, pendingListeners, [...path, prop]);
|
|
81863
|
+
},
|
|
81864
|
+
set(_target, prop, rawValue) {
|
|
81865
|
+
throwIfProxyReleased(isProxyReleased);
|
|
81866
|
+
// FIXME: ES6 Proxy Handler `set` methods are supposed to return a
|
|
81867
|
+
// boolean. To show good will, we return true asynchronously ¯\_(ツ)_/¯
|
|
81868
|
+
const [value, transferables] = toWireValue(rawValue);
|
|
81869
|
+
return requestResponseMessage(ep, pendingListeners, {
|
|
81870
|
+
type: "SET" /* MessageType.SET */,
|
|
81871
|
+
path: [...path, prop].map((p) => p.toString()),
|
|
81872
|
+
value,
|
|
81873
|
+
}, transferables).then(fromWireValue);
|
|
81874
|
+
},
|
|
81875
|
+
apply(_target, _thisArg, rawArgumentList) {
|
|
81876
|
+
throwIfProxyReleased(isProxyReleased);
|
|
81877
|
+
const last = path[path.length - 1];
|
|
81878
|
+
if (last === createEndpoint) {
|
|
81879
|
+
return requestResponseMessage(ep, pendingListeners, {
|
|
81880
|
+
type: "ENDPOINT" /* MessageType.ENDPOINT */,
|
|
81881
|
+
}).then(fromWireValue);
|
|
81882
|
+
}
|
|
81883
|
+
// We just pretend that `bind()` didn’t happen.
|
|
81884
|
+
if (last === "bind") {
|
|
81885
|
+
return createProxy(ep, pendingListeners, path.slice(0, -1));
|
|
81886
|
+
}
|
|
81887
|
+
const [argumentList, transferables] = processArguments(rawArgumentList);
|
|
81888
|
+
return requestResponseMessage(ep, pendingListeners, {
|
|
81889
|
+
type: "APPLY" /* MessageType.APPLY */,
|
|
81890
|
+
path: path.map((p) => p.toString()),
|
|
81891
|
+
argumentList,
|
|
81892
|
+
}, transferables).then(fromWireValue);
|
|
81893
|
+
},
|
|
81894
|
+
construct(_target, rawArgumentList) {
|
|
81895
|
+
throwIfProxyReleased(isProxyReleased);
|
|
81896
|
+
const [argumentList, transferables] = processArguments(rawArgumentList);
|
|
81897
|
+
return requestResponseMessage(ep, pendingListeners, {
|
|
81898
|
+
type: "CONSTRUCT" /* MessageType.CONSTRUCT */,
|
|
81899
|
+
path: path.map((p) => p.toString()),
|
|
81900
|
+
argumentList,
|
|
81901
|
+
}, transferables).then(fromWireValue);
|
|
81902
|
+
},
|
|
81903
|
+
});
|
|
81904
|
+
registerProxy(proxy, ep);
|
|
81905
|
+
return proxy;
|
|
81906
|
+
}
|
|
81907
|
+
function myFlat(arr) {
|
|
81908
|
+
return Array.prototype.concat.apply([], arr);
|
|
81909
|
+
}
|
|
81910
|
+
function processArguments(argumentList) {
|
|
81911
|
+
const processed = argumentList.map(toWireValue);
|
|
81912
|
+
return [processed.map((v) => v[0]), myFlat(processed.map((v) => v[1]))];
|
|
81913
|
+
}
|
|
81914
|
+
const transferCache = new WeakMap();
|
|
81915
|
+
function transfer(obj, transfers) {
|
|
81916
|
+
transferCache.set(obj, transfers);
|
|
81917
|
+
return obj;
|
|
81918
|
+
}
|
|
81919
|
+
function proxy(obj) {
|
|
81920
|
+
return Object.assign(obj, { [proxyMarker]: true });
|
|
81921
|
+
}
|
|
81922
|
+
function toWireValue(value) {
|
|
81923
|
+
for (const [name, handler] of transferHandlers) {
|
|
81924
|
+
if (handler.canHandle(value)) {
|
|
81925
|
+
const [serializedValue, transferables] = handler.serialize(value);
|
|
81926
|
+
return [
|
|
81927
|
+
{
|
|
81928
|
+
type: "HANDLER" /* WireValueType.HANDLER */,
|
|
81929
|
+
name,
|
|
81930
|
+
value: serializedValue,
|
|
81931
|
+
},
|
|
81932
|
+
transferables,
|
|
81933
|
+
];
|
|
81934
|
+
}
|
|
81935
|
+
}
|
|
81936
|
+
return [
|
|
81937
|
+
{
|
|
81938
|
+
type: "RAW" /* WireValueType.RAW */,
|
|
81939
|
+
value,
|
|
81940
|
+
},
|
|
81941
|
+
transferCache.get(value) || [],
|
|
81942
|
+
];
|
|
81943
|
+
}
|
|
81944
|
+
function fromWireValue(value) {
|
|
81945
|
+
switch (value.type) {
|
|
81946
|
+
case "HANDLER" /* WireValueType.HANDLER */:
|
|
81947
|
+
return transferHandlers.get(value.name).deserialize(value.value);
|
|
81948
|
+
case "RAW" /* WireValueType.RAW */:
|
|
81949
|
+
return value.value;
|
|
81950
|
+
}
|
|
81951
|
+
}
|
|
81952
|
+
function requestResponseMessage(ep, pendingListeners, msg, transfers) {
|
|
81953
|
+
return new Promise((resolve) => {
|
|
81954
|
+
const id = generateUUID();
|
|
81955
|
+
pendingListeners.set(id, resolve);
|
|
81956
|
+
if (ep.start) {
|
|
81957
|
+
ep.start();
|
|
81958
|
+
}
|
|
81959
|
+
ep.postMessage(Object.assign({ id }, msg), transfers);
|
|
81960
|
+
});
|
|
81961
|
+
}
|
|
81962
|
+
function generateUUID() {
|
|
81963
|
+
return new Array(4)
|
|
81964
|
+
.fill(0)
|
|
81965
|
+
.map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16))
|
|
81966
|
+
.join("-");
|
|
81967
|
+
}
|
|
81968
|
+
|
|
81604
81969
|
var global$1;
|
|
81605
81970
|
var hasRequiredGlobal;
|
|
81606
81971
|
|
|
@@ -85073,7 +85438,7 @@
|
|
|
85073
85438
|
};
|
|
85074
85439
|
|
|
85075
85440
|
const DEFAULT_MAX_CACHE_AGE = 1000 * 60 * 60; // 1 hour
|
|
85076
|
-
const logger$
|
|
85441
|
+
const logger$w = new Logger('getLocalRegion');
|
|
85077
85442
|
let cachedLocalRegion = undefined;
|
|
85078
85443
|
let cachedLocalRegionFetchTime = undefined;
|
|
85079
85444
|
const getLocalAirportCode = async () => {
|
|
@@ -85093,7 +85458,7 @@
|
|
|
85093
85458
|
// indicate that the region is random by adding 99, the convention is
|
|
85094
85459
|
// that random region numbers end with 99
|
|
85095
85460
|
const randomRegion = airportCodeToRegion[randomAirportCode][0] + 99;
|
|
85096
|
-
logger$
|
|
85461
|
+
logger$w.warn(`Could not get airport code, using random region: ${randomRegion}`);
|
|
85097
85462
|
return randomRegion;
|
|
85098
85463
|
};
|
|
85099
85464
|
const getLocalRegionWithCache = async (maxCacheAge = DEFAULT_MAX_CACHE_AGE) => {
|
|
@@ -85745,6 +86110,9 @@
|
|
|
85745
86110
|
class SendFailed extends Err {
|
|
85746
86111
|
constructor(message, originalError) { super(ErrorCode.SEND_FAILED, message, originalError); }
|
|
85747
86112
|
}
|
|
86113
|
+
function logGapDiagnosticSampled(layer, opts = {}) {
|
|
86114
|
+
return;
|
|
86115
|
+
}
|
|
85748
86116
|
|
|
85749
86117
|
// @generated message type with reflection information, may provide speed optimized methods
|
|
85750
86118
|
let Empty$Type$2 = class Empty$Type extends MessageType {
|
|
@@ -87288,7 +87656,7 @@
|
|
|
87288
87656
|
return v4();
|
|
87289
87657
|
};
|
|
87290
87658
|
|
|
87291
|
-
const logger$
|
|
87659
|
+
const logger$D = new Logger('ManagedConnection');
|
|
87292
87660
|
// ManagedConnection is a component used as a wrapper for IConnection after they have been successfully handshaked.
|
|
87293
87661
|
// Should only be used in the ConnectionManager.
|
|
87294
87662
|
class ManagedConnection extends EventEmitter {
|
|
@@ -87318,7 +87686,7 @@
|
|
|
87318
87686
|
this.remotePeerDescriptor = peerDescriptor;
|
|
87319
87687
|
}
|
|
87320
87688
|
onDisconnected(gracefulLeave) {
|
|
87321
|
-
logger$
|
|
87689
|
+
logger$D.trace(getNodeIdOrUnknownFromPeerDescriptor(this.remotePeerDescriptor) + ' onDisconnected() ' + gracefulLeave);
|
|
87322
87690
|
if (!this.replacedAsDuplicate) {
|
|
87323
87691
|
this.emit('disconnected', gracefulLeave);
|
|
87324
87692
|
}
|
|
@@ -87327,7 +87695,7 @@
|
|
|
87327
87695
|
// TODO: Can this be removed if ManagedConnections can never be duplicates?
|
|
87328
87696
|
// Handle duplicates in the ConncetorFacade and no longer have PendingConnections in ConnectionManager
|
|
87329
87697
|
replaceAsDuplicate() {
|
|
87330
|
-
logger$
|
|
87698
|
+
logger$D.trace(getNodeIdOrUnknownFromPeerDescriptor(this.remotePeerDescriptor) + ' replaceAsDuplicate');
|
|
87331
87699
|
this.replacedAsDuplicate = true;
|
|
87332
87700
|
}
|
|
87333
87701
|
send(data) {
|
|
@@ -87474,10 +87842,10 @@
|
|
|
87474
87842
|
}
|
|
87475
87843
|
}
|
|
87476
87844
|
|
|
87477
|
-
const logger$
|
|
87845
|
+
const logger$C = new Logger('ConnectionLockRpcRemote');
|
|
87478
87846
|
class ConnectionLockRpcRemote extends RpcRemote {
|
|
87479
87847
|
async lockRequest(lockId) {
|
|
87480
|
-
logger$
|
|
87848
|
+
logger$C.trace(`Requesting locked connection to ${toNodeId(this.getPeerDescriptor())}`);
|
|
87481
87849
|
const request = {
|
|
87482
87850
|
lockId
|
|
87483
87851
|
};
|
|
@@ -87487,12 +87855,12 @@
|
|
|
87487
87855
|
return res.accepted;
|
|
87488
87856
|
}
|
|
87489
87857
|
catch (err) {
|
|
87490
|
-
logger$
|
|
87858
|
+
logger$C.debug('Connection lock rejected', { err });
|
|
87491
87859
|
return false;
|
|
87492
87860
|
}
|
|
87493
87861
|
}
|
|
87494
87862
|
unlockRequest(lockId) {
|
|
87495
|
-
logger$
|
|
87863
|
+
logger$C.trace(`Requesting connection to be unlocked from ${toNodeId(this.getPeerDescriptor())}`);
|
|
87496
87864
|
const request = {
|
|
87497
87865
|
lockId
|
|
87498
87866
|
};
|
|
@@ -87500,11 +87868,11 @@
|
|
|
87500
87868
|
notification: true
|
|
87501
87869
|
});
|
|
87502
87870
|
this.getClient().unlockRequest(request, options).catch((_e) => {
|
|
87503
|
-
logger$
|
|
87871
|
+
logger$C.trace('failed to send unlockRequest');
|
|
87504
87872
|
});
|
|
87505
87873
|
}
|
|
87506
87874
|
async gracefulDisconnect(disconnectMode) {
|
|
87507
|
-
logger$
|
|
87875
|
+
logger$C.trace(`Notifying a graceful disconnect to ${toNodeId(this.getPeerDescriptor())}`);
|
|
87508
87876
|
const request = {
|
|
87509
87877
|
disconnectMode
|
|
87510
87878
|
};
|
|
@@ -87516,7 +87884,7 @@
|
|
|
87516
87884
|
await this.getClient().gracefulDisconnect(request, options);
|
|
87517
87885
|
}
|
|
87518
87886
|
async setPrivate(isPrivate) {
|
|
87519
|
-
logger$
|
|
87887
|
+
logger$C.trace(`Setting isPrivate: ${isPrivate} for ${toNodeId(this.getPeerDescriptor())}`);
|
|
87520
87888
|
const request = {
|
|
87521
87889
|
isPrivate
|
|
87522
87890
|
};
|
|
@@ -87528,7 +87896,7 @@
|
|
|
87528
87896
|
}
|
|
87529
87897
|
}
|
|
87530
87898
|
|
|
87531
|
-
const logger$
|
|
87899
|
+
const logger$B = new Logger('ConnectionLockRpcLocal');
|
|
87532
87900
|
class ConnectionLockRpcLocal {
|
|
87533
87901
|
options;
|
|
87534
87902
|
constructor(options) {
|
|
@@ -87557,7 +87925,7 @@
|
|
|
87557
87925
|
}
|
|
87558
87926
|
async gracefulDisconnect(disconnectNotice, context) {
|
|
87559
87927
|
const senderPeerDescriptor = context.incomingSourceDescriptor;
|
|
87560
|
-
logger$
|
|
87928
|
+
logger$B.trace(getNodeIdOrUnknownFromPeerDescriptor(senderPeerDescriptor) + ' received gracefulDisconnect notice');
|
|
87561
87929
|
if (disconnectNotice.disconnectMode === DisconnectMode$2.LEAVING) {
|
|
87562
87930
|
await this.options.closeConnection(senderPeerDescriptor, true, 'graceful leave notified');
|
|
87563
87931
|
}
|
|
@@ -87608,7 +87976,7 @@
|
|
|
87608
87976
|
NatType["OPEN_INTERNET"] = "open_internet";
|
|
87609
87977
|
NatType["UNKNOWN"] = "unknown";
|
|
87610
87978
|
})(NatType || (NatType = {}));
|
|
87611
|
-
const logger$
|
|
87979
|
+
const logger$A = new Logger('ConnectionManager');
|
|
87612
87980
|
var ConnectionManagerState;
|
|
87613
87981
|
(function (ConnectionManagerState) {
|
|
87614
87982
|
ConnectionManagerState["IDLE"] = "idle";
|
|
@@ -87658,7 +88026,7 @@
|
|
|
87658
88026
|
getLocalPeerDescriptor: () => this.getLocalPeerDescriptor(),
|
|
87659
88027
|
setPrivate: (id, isPrivate) => {
|
|
87660
88028
|
if (!this.options.allowIncomingPrivateConnections) {
|
|
87661
|
-
logger$
|
|
88029
|
+
logger$A.debug(`node ${id} attemted to set a connection as private, but it is not allowed`);
|
|
87662
88030
|
return;
|
|
87663
88031
|
}
|
|
87664
88032
|
if (isPrivate) {
|
|
@@ -87692,7 +88060,7 @@
|
|
|
87692
88060
|
const connection = endpoint.connection;
|
|
87693
88061
|
const nodeId = connection.getNodeId();
|
|
87694
88062
|
if (!this.locks.isLocked(nodeId) && !this.locks.isPrivate(nodeId) && Date.now() - connection.getLastUsedTimestamp() > maxIdleTime) {
|
|
87695
|
-
logger$
|
|
88063
|
+
logger$A.trace('disconnecting in timeout interval: ' + getNodeIdOrUnknownFromPeerDescriptor(connection.getPeerDescriptor()));
|
|
87696
88064
|
disconnectionCandidates.addContact(connection);
|
|
87697
88065
|
}
|
|
87698
88066
|
}
|
|
@@ -87700,7 +88068,7 @@
|
|
|
87700
88068
|
const disconnectables = disconnectionCandidates.getFurthestContacts(this.endpoints.size - maxConnections);
|
|
87701
88069
|
for (const disconnectable of disconnectables) {
|
|
87702
88070
|
const peerDescriptor = disconnectable.getPeerDescriptor();
|
|
87703
|
-
logger$
|
|
88071
|
+
logger$A.trace('garbageCollecting ' + toNodeId(peerDescriptor));
|
|
87704
88072
|
this.gracefullyDisconnectAsync(peerDescriptor, DisconnectMode$2.NORMAL).catch((_e) => { });
|
|
87705
88073
|
}
|
|
87706
88074
|
}
|
|
@@ -87709,11 +88077,11 @@
|
|
|
87709
88077
|
throw new CouldNotStart(`Cannot start already ${this.state} module`);
|
|
87710
88078
|
}
|
|
87711
88079
|
this.state = ConnectionManagerState.RUNNING;
|
|
87712
|
-
logger$
|
|
88080
|
+
logger$A.trace(`Starting ConnectionManager...`);
|
|
87713
88081
|
await this.connectorFacade.start((connection) => this.onNewConnection(connection), (nodeId) => this.hasConnection(nodeId), this);
|
|
87714
88082
|
// Garbage collection of connections
|
|
87715
88083
|
this.disconnectorIntervalRef = setInterval(() => {
|
|
87716
|
-
logger$
|
|
88084
|
+
logger$A.trace('disconnectorInterval');
|
|
87717
88085
|
const LAST_USED_LIMIT = 20000;
|
|
87718
88086
|
this.garbageCollectConnections(this.options.maxConnections ?? 80, LAST_USED_LIMIT);
|
|
87719
88087
|
}, 5000); // TODO use options option or named constant?
|
|
@@ -87723,7 +88091,7 @@
|
|
|
87723
88091
|
return;
|
|
87724
88092
|
}
|
|
87725
88093
|
this.state = ConnectionManagerState.STOPPING;
|
|
87726
|
-
logger$
|
|
88094
|
+
logger$A.trace(`Stopping ConnectionManager`);
|
|
87727
88095
|
if (this.disconnectorIntervalRef) {
|
|
87728
88096
|
clearInterval(this.disconnectorIntervalRef);
|
|
87729
88097
|
}
|
|
@@ -87733,23 +88101,23 @@
|
|
|
87733
88101
|
await this.gracefullyDisconnectAsync(endpoint.connection.getPeerDescriptor(), DisconnectMode$2.LEAVING);
|
|
87734
88102
|
}
|
|
87735
88103
|
catch (e) {
|
|
87736
|
-
logger$
|
|
88104
|
+
logger$A.error(e);
|
|
87737
88105
|
}
|
|
87738
88106
|
}
|
|
87739
88107
|
else {
|
|
87740
88108
|
const connection = endpoint.connection;
|
|
87741
|
-
logger$
|
|
88109
|
+
logger$A.trace('handshake of connection not completed, force-closing');
|
|
87742
88110
|
// TODO use options option or named constant?
|
|
87743
88111
|
const eventReceived = waitForEvent(connection, 'disconnected', 2000);
|
|
87744
88112
|
// TODO should we have some handling for this floating promise?
|
|
87745
88113
|
connection.close(true);
|
|
87746
88114
|
try {
|
|
87747
88115
|
await eventReceived;
|
|
87748
|
-
logger$
|
|
88116
|
+
logger$A.trace('resolving after receiving disconnected event from non-handshaked connection');
|
|
87749
88117
|
}
|
|
87750
88118
|
catch (e) {
|
|
87751
88119
|
endpoint.buffer.reject();
|
|
87752
|
-
logger$
|
|
88120
|
+
logger$A.trace('force-closing non-handshaked connection timed out ' + e);
|
|
87753
88121
|
}
|
|
87754
88122
|
}
|
|
87755
88123
|
}));
|
|
@@ -87778,7 +88146,7 @@
|
|
|
87778
88146
|
throw new CannotConnectToSelf('Cannot send to self');
|
|
87779
88147
|
}
|
|
87780
88148
|
const nodeId = toNodeId(peerDescriptor);
|
|
87781
|
-
logger$
|
|
88149
|
+
logger$A.trace(`Sending message to: ${nodeId}`);
|
|
87782
88150
|
message = {
|
|
87783
88151
|
...message,
|
|
87784
88152
|
sourceDescriptor: this.getLocalPeerDescriptor()
|
|
@@ -87833,13 +88201,13 @@
|
|
|
87833
88201
|
}
|
|
87834
88202
|
handleMessage(message) {
|
|
87835
88203
|
const messageType = message.body.oneofKind;
|
|
87836
|
-
logger$
|
|
88204
|
+
logger$A.trace('Received message of type ' + messageType);
|
|
87837
88205
|
if (messageType !== 'rpcMessage') {
|
|
87838
|
-
logger$
|
|
88206
|
+
logger$A.trace('Filtered out non-RPC message of type ' + messageType);
|
|
87839
88207
|
return;
|
|
87840
88208
|
}
|
|
87841
88209
|
if (this.duplicateMessageDetector.isMostLikelyDuplicate(message.messageId)) {
|
|
87842
|
-
logger$
|
|
88210
|
+
logger$A.trace('handleMessage filtered duplicate ' + toNodeId(message.sourceDescriptor)
|
|
87843
88211
|
+ ' ' + message.serviceId + ' ' + message.messageId);
|
|
87844
88212
|
return;
|
|
87845
88213
|
}
|
|
@@ -87848,7 +88216,7 @@
|
|
|
87848
88216
|
this.rpcCommunicator?.handleMessageFromPeer(message);
|
|
87849
88217
|
}
|
|
87850
88218
|
else {
|
|
87851
|
-
logger$
|
|
88219
|
+
logger$A.trace('emit "message" ' + toNodeId(message.sourceDescriptor)
|
|
87852
88220
|
+ ' ' + message.serviceId + ' ' + message.messageId);
|
|
87853
88221
|
this.emit('message', message);
|
|
87854
88222
|
}
|
|
@@ -87865,7 +88233,7 @@
|
|
|
87865
88233
|
}
|
|
87866
88234
|
catch (e) {
|
|
87867
88235
|
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
87868
|
-
logger$
|
|
88236
|
+
logger$A.debug(`Parsing incoming data into Message failed: ${e}`);
|
|
87869
88237
|
return;
|
|
87870
88238
|
}
|
|
87871
88239
|
message.sourceDescriptor = peerDescriptor;
|
|
@@ -87874,7 +88242,7 @@
|
|
|
87874
88242
|
}
|
|
87875
88243
|
catch (e) {
|
|
87876
88244
|
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
87877
|
-
logger$
|
|
88245
|
+
logger$A.debug(`Handling incoming data failed: ${e}`);
|
|
87878
88246
|
}
|
|
87879
88247
|
}
|
|
87880
88248
|
onConnected(peerDescriptor, connection) {
|
|
@@ -87887,7 +88255,7 @@
|
|
|
87887
88255
|
const pendingConnection = endpoint.connection;
|
|
87888
88256
|
const buffer = outputBuffer.getBuffer();
|
|
87889
88257
|
while (buffer.length > 0) {
|
|
87890
|
-
logger$
|
|
88258
|
+
logger$A.trace('emptying buffer');
|
|
87891
88259
|
managedConnection.send(buffer.shift());
|
|
87892
88260
|
}
|
|
87893
88261
|
outputBuffer.resolve();
|
|
@@ -87904,7 +88272,7 @@
|
|
|
87904
88272
|
}
|
|
87905
88273
|
onDisconnected(peerDescriptor, gracefulLeave) {
|
|
87906
88274
|
const nodeId = toNodeId(peerDescriptor);
|
|
87907
|
-
logger$
|
|
88275
|
+
logger$A.trace(nodeId + ' onDisconnected() gracefulLeave: ' + gracefulLeave);
|
|
87908
88276
|
const endpoint = this.endpoints.get(nodeId);
|
|
87909
88277
|
if (endpoint) {
|
|
87910
88278
|
this.locks.clearAllLocks(nodeId);
|
|
@@ -87912,7 +88280,7 @@
|
|
|
87912
88280
|
endpoint.buffer.reject();
|
|
87913
88281
|
}
|
|
87914
88282
|
this.endpoints.delete(nodeId);
|
|
87915
|
-
logger$
|
|
88283
|
+
logger$A.trace(nodeId + ' deleted connection in onDisconnected() gracefulLeave: ' + gracefulLeave);
|
|
87916
88284
|
this.emit('disconnected', peerDescriptor, gracefulLeave);
|
|
87917
88285
|
this.onConnectionCountChange();
|
|
87918
88286
|
}
|
|
@@ -87921,7 +88289,7 @@
|
|
|
87921
88289
|
if (this.state === ConnectionManagerState.STOPPED) {
|
|
87922
88290
|
return false;
|
|
87923
88291
|
}
|
|
87924
|
-
logger$
|
|
88292
|
+
logger$A.trace('onNewConnection()');
|
|
87925
88293
|
if (!this.acceptNewConnection(connection)) {
|
|
87926
88294
|
return false;
|
|
87927
88295
|
}
|
|
@@ -87931,7 +88299,7 @@
|
|
|
87931
88299
|
}
|
|
87932
88300
|
acceptNewConnection(newConnection) {
|
|
87933
88301
|
const nodeId = toNodeId(newConnection.getPeerDescriptor());
|
|
87934
|
-
logger$
|
|
88302
|
+
logger$A.trace(nodeId + ' acceptNewConnection()');
|
|
87935
88303
|
if (this.endpoints.has(nodeId)) {
|
|
87936
88304
|
if (getOfferer(toNodeId(this.getLocalPeerDescriptor()), nodeId) === 'remote') {
|
|
87937
88305
|
let buffer;
|
|
@@ -87940,14 +88308,14 @@
|
|
|
87940
88308
|
// Could be related to WS client connections not realizing that they have been disconnected.
|
|
87941
88309
|
// Makes refactoring duplicate connection handling to the connectors very difficult.
|
|
87942
88310
|
if (this.endpoints.get(nodeId).connected) {
|
|
87943
|
-
logger$
|
|
88311
|
+
logger$A.debug('replacing connected connection', { nodeId });
|
|
87944
88312
|
buffer = new OutputBuffer();
|
|
87945
88313
|
}
|
|
87946
88314
|
else {
|
|
87947
88315
|
buffer = endpoint.buffer;
|
|
87948
88316
|
}
|
|
87949
88317
|
const oldConnection = endpoint.connection;
|
|
87950
|
-
logger$
|
|
88318
|
+
logger$A.trace('replaced: ' + nodeId);
|
|
87951
88319
|
oldConnection.replaceAsDuplicate();
|
|
87952
88320
|
this.endpoints.set(nodeId, { connected: false, connection: newConnection, buffer: buffer });
|
|
87953
88321
|
return true;
|
|
@@ -87956,7 +88324,7 @@
|
|
|
87956
88324
|
return false;
|
|
87957
88325
|
}
|
|
87958
88326
|
}
|
|
87959
|
-
logger$
|
|
88327
|
+
logger$A.trace(nodeId + ' added to connections at acceptNewConnection');
|
|
87960
88328
|
this.endpoints.set(nodeId, {
|
|
87961
88329
|
connected: false,
|
|
87962
88330
|
buffer: new OutputBuffer(),
|
|
@@ -87966,14 +88334,14 @@
|
|
|
87966
88334
|
}
|
|
87967
88335
|
async closeConnection(peerDescriptor, gracefulLeave, reason) {
|
|
87968
88336
|
const nodeId = toNodeId(peerDescriptor);
|
|
87969
|
-
logger$
|
|
88337
|
+
logger$A.trace(nodeId + ' ' + 'closeConnection() ' + reason);
|
|
87970
88338
|
this.locks.clearAllLocks(nodeId);
|
|
87971
88339
|
if (this.endpoints.has(nodeId)) {
|
|
87972
88340
|
const connectionToClose = this.endpoints.get(nodeId).connection;
|
|
87973
88341
|
await connectionToClose.close(gracefulLeave);
|
|
87974
88342
|
}
|
|
87975
88343
|
else {
|
|
87976
|
-
logger$
|
|
88344
|
+
logger$A.trace(nodeId + ' ' + 'closeConnection() this.endpoints did not have the id');
|
|
87977
88345
|
this.emit('disconnected', peerDescriptor, false);
|
|
87978
88346
|
}
|
|
87979
88347
|
}
|
|
@@ -87985,8 +88353,8 @@
|
|
|
87985
88353
|
const rpcRemote = new ConnectionLockRpcRemote(this.getLocalPeerDescriptor(), targetDescriptor, this.rpcCommunicator, ConnectionLockRpcClient);
|
|
87986
88354
|
this.locks.addLocalLocked(nodeId, lockId);
|
|
87987
88355
|
rpcRemote.lockRequest(lockId)
|
|
87988
|
-
.then((_accepted) => logger$
|
|
87989
|
-
.catch((err) => { logger$
|
|
88356
|
+
.then((_accepted) => logger$A.trace('LockRequest successful'))
|
|
88357
|
+
.catch((err) => { logger$A.debug(err); });
|
|
87990
88358
|
}
|
|
87991
88359
|
unlockConnection(targetDescriptor, lockId) {
|
|
87992
88360
|
if (this.state === ConnectionManagerState.STOPPED || areEqualPeerDescriptors(targetDescriptor, this.getLocalPeerDescriptor())) {
|
|
@@ -88038,7 +88406,7 @@
|
|
|
88038
88406
|
async gracefullyDisconnectAsync(targetDescriptor, disconnectMode) {
|
|
88039
88407
|
const endpoint = this.endpoints.get(toNodeId(targetDescriptor));
|
|
88040
88408
|
if (!endpoint) {
|
|
88041
|
-
logger$
|
|
88409
|
+
logger$A.debug('gracefullyDisconnectedAsync() tried on a non-existing connection');
|
|
88042
88410
|
return;
|
|
88043
88411
|
}
|
|
88044
88412
|
if (endpoint.connected) {
|
|
@@ -88047,15 +88415,15 @@
|
|
|
88047
88415
|
// TODO use options option or named constant?
|
|
88048
88416
|
// eslint-disable-next-line promise/catch-or-return
|
|
88049
88417
|
waitForEvent(connection, 'disconnected', 2000).then(() => {
|
|
88050
|
-
logger$
|
|
88418
|
+
logger$A.trace('disconnected event received in gracefullyDisconnectAsync()');
|
|
88051
88419
|
})
|
|
88052
88420
|
.catch((e) => {
|
|
88053
|
-
logger$
|
|
88421
|
+
logger$A.trace('force-closing connection after timeout ' + e);
|
|
88054
88422
|
// TODO should we have some handling for this floating promise?
|
|
88055
88423
|
connection.close(true);
|
|
88056
88424
|
})
|
|
88057
88425
|
.finally(() => {
|
|
88058
|
-
logger$
|
|
88426
|
+
logger$A.trace('resolving after receiving disconnected event');
|
|
88059
88427
|
resolve();
|
|
88060
88428
|
});
|
|
88061
88429
|
});
|
|
@@ -88070,13 +88438,13 @@
|
|
|
88070
88438
|
}
|
|
88071
88439
|
async doGracefullyDisconnectAsync(targetDescriptor, disconnectMode) {
|
|
88072
88440
|
const nodeId = toNodeId(targetDescriptor);
|
|
88073
|
-
logger$
|
|
88441
|
+
logger$A.trace(nodeId + ' gracefullyDisconnectAsync()');
|
|
88074
88442
|
const rpcRemote = new ConnectionLockRpcRemote(this.getLocalPeerDescriptor(), targetDescriptor, this.rpcCommunicator, ConnectionLockRpcClient);
|
|
88075
88443
|
try {
|
|
88076
88444
|
await rpcRemote.gracefulDisconnect(disconnectMode);
|
|
88077
88445
|
}
|
|
88078
88446
|
catch (ex) {
|
|
88079
|
-
logger$
|
|
88447
|
+
logger$A.trace(nodeId + ' remote.gracefulDisconnect() failed' + ex);
|
|
88080
88448
|
}
|
|
88081
88449
|
}
|
|
88082
88450
|
getConnections() {
|
|
@@ -88136,9 +88504,9 @@
|
|
|
88136
88504
|
}
|
|
88137
88505
|
};
|
|
88138
88506
|
|
|
88139
|
-
var version$2 = "103.
|
|
88507
|
+
var version$2 = "103.7.0-rc.2";
|
|
88140
88508
|
|
|
88141
|
-
const logger$
|
|
88509
|
+
const logger$y = new Logger('Handshaker');
|
|
88142
88510
|
// Optimally the Outgoing and Incoming Handshakers could be their own separate classes
|
|
88143
88511
|
// However, in cases where the PeerDescriptor of the other end of the connection can be known
|
|
88144
88512
|
// only after a HandshakeRequest a base Handshaker class is needed as the IncomingHandshaker currently
|
|
@@ -88160,7 +88528,7 @@
|
|
|
88160
88528
|
}
|
|
88161
88529
|
};
|
|
88162
88530
|
const handshakeCompletedListener = (peerDescriptor) => {
|
|
88163
|
-
logger$
|
|
88531
|
+
logger$y.trace('handshake completed for outgoing connection, ' + toNodeId(peerDescriptor));
|
|
88164
88532
|
pendingConnection.onHandshakeCompleted(connection);
|
|
88165
88533
|
stopHandshaker();
|
|
88166
88534
|
};
|
|
@@ -88260,12 +88628,12 @@
|
|
|
88260
88628
|
try {
|
|
88261
88629
|
const message = Message$2.fromBinary(data);
|
|
88262
88630
|
if (message.body.oneofKind === 'handshakeRequest') {
|
|
88263
|
-
logger$
|
|
88631
|
+
logger$y.trace('handshake request received');
|
|
88264
88632
|
const handshake = message.body.handshakeRequest;
|
|
88265
88633
|
this.emit('handshakeRequest', handshake.sourcePeerDescriptor, handshake.protocolVersion, handshake.targetPeerDescriptor);
|
|
88266
88634
|
}
|
|
88267
88635
|
if (message.body.oneofKind === 'handshakeResponse') {
|
|
88268
|
-
logger$
|
|
88636
|
+
logger$y.trace('handshake response received');
|
|
88269
88637
|
const handshake = message.body.handshakeResponse;
|
|
88270
88638
|
const error = !isMaybeSupportedProtocolVersion(handshake.protocolVersion)
|
|
88271
88639
|
? HandshakeError$2.UNSUPPORTED_PROTOCOL_VERSION : handshake.error;
|
|
@@ -88278,18 +88646,18 @@
|
|
|
88278
88646
|
}
|
|
88279
88647
|
}
|
|
88280
88648
|
catch (err) {
|
|
88281
|
-
logger$
|
|
88649
|
+
logger$y.debug('error while parsing handshake message', err);
|
|
88282
88650
|
}
|
|
88283
88651
|
}
|
|
88284
88652
|
sendHandshakeRequest(remotePeerDescriptor) {
|
|
88285
88653
|
const msg = createHandshakeRequest(this.localPeerDescriptor, remotePeerDescriptor);
|
|
88286
88654
|
this.connection.send(Message$2.toBinary(msg));
|
|
88287
|
-
logger$
|
|
88655
|
+
logger$y.trace('handshake request sent');
|
|
88288
88656
|
}
|
|
88289
88657
|
sendHandshakeResponse(error) {
|
|
88290
88658
|
const msg = createHandshakeResponse(this.localPeerDescriptor, error);
|
|
88291
88659
|
this.connection.send(Message$2.toBinary(msg));
|
|
88292
|
-
logger$
|
|
88660
|
+
logger$y.trace('handshake response sent');
|
|
88293
88661
|
}
|
|
88294
88662
|
stop() {
|
|
88295
88663
|
this.connection.off('data', this.onDataListener);
|
|
@@ -88297,7 +88665,7 @@
|
|
|
88297
88665
|
}
|
|
88298
88666
|
};
|
|
88299
88667
|
|
|
88300
|
-
const logger$
|
|
88668
|
+
const logger$x = new Logger('PendingConnection');
|
|
88301
88669
|
// PendingConnection is used as a reference to a connection that should be opened and handshaked to a given PeerDescriptor
|
|
88302
88670
|
// It does not hold a connection internally. The public method onHandshakedCompleted should be called once a connection for the
|
|
88303
88671
|
// remotePeerDescriptor is opened and handshaked successfully.
|
|
@@ -88315,7 +88683,7 @@
|
|
|
88315
88683
|
}, timeout, this.connectingAbortController.signal);
|
|
88316
88684
|
}
|
|
88317
88685
|
replaceAsDuplicate() {
|
|
88318
|
-
logger$
|
|
88686
|
+
logger$x.trace(getNodeIdOrUnknownFromPeerDescriptor(this.remotePeerDescriptor) + ' replaceAsDuplicate');
|
|
88319
88687
|
this.replacedAsDuplicate = true;
|
|
88320
88688
|
}
|
|
88321
88689
|
onHandshakeCompleted(connection) {
|
|
@@ -88372,6 +88740,8 @@
|
|
|
88372
88740
|
}
|
|
88373
88741
|
}
|
|
88374
88742
|
|
|
88743
|
+
const isWorkerEnvironment = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope;
|
|
88744
|
+
|
|
88375
88745
|
var RtcDescription;
|
|
88376
88746
|
(function (RtcDescription) {
|
|
88377
88747
|
RtcDescription["OFFER"] = "offer";
|
|
@@ -88386,8 +88756,8 @@
|
|
|
88386
88756
|
DisconnectedRtcPeerConnectionStateEnum["FAILED"] = "failed";
|
|
88387
88757
|
DisconnectedRtcPeerConnectionStateEnum["CLOSED"] = "closed";
|
|
88388
88758
|
})(DisconnectedRtcPeerConnectionStateEnum || (DisconnectedRtcPeerConnectionStateEnum = {}));
|
|
88389
|
-
const logger$
|
|
88390
|
-
class
|
|
88759
|
+
const logger$v = new Logger('DirectWebrtcConnection (browser)');
|
|
88760
|
+
class DirectWebrtcConnection extends EventEmitter {
|
|
88391
88761
|
connectionId;
|
|
88392
88762
|
connectionType = ConnectionType.WEBRTC;
|
|
88393
88763
|
// We need to keep track of connection state ourselves because
|
|
@@ -88425,7 +88795,7 @@
|
|
|
88425
88795
|
}
|
|
88426
88796
|
};
|
|
88427
88797
|
this.peerConnection.onicegatheringstatechange = () => {
|
|
88428
|
-
logger$
|
|
88798
|
+
logger$v.trace(`conn.onGatheringStateChange: ${this.peerConnection?.iceGatheringState}`);
|
|
88429
88799
|
};
|
|
88430
88800
|
this.peerConnection.onconnectionstatechange = () => this.onStateChange();
|
|
88431
88801
|
if (isOffering) {
|
|
@@ -88436,7 +88806,7 @@
|
|
|
88436
88806
|
await this.peerConnection.setLocalDescription();
|
|
88437
88807
|
}
|
|
88438
88808
|
catch (err) {
|
|
88439
|
-
logger$
|
|
88809
|
+
logger$v.warn('Failed to set local description', { err });
|
|
88440
88810
|
}
|
|
88441
88811
|
if (this.peerConnection.localDescription !== null) {
|
|
88442
88812
|
this.emit('localDescription', this.peerConnection.localDescription?.sdp, this.peerConnection.localDescription?.type);
|
|
@@ -88464,14 +88834,14 @@
|
|
|
88464
88834
|
clearTimeout(this.earlyTimeout);
|
|
88465
88835
|
}
|
|
88466
88836
|
catch (err) {
|
|
88467
|
-
logger$
|
|
88837
|
+
logger$v.warn('Failed to set remote description', { err });
|
|
88468
88838
|
}
|
|
88469
88839
|
if ((type.toLowerCase() === RtcDescription.OFFER) && (this.peerConnection !== undefined)) {
|
|
88470
88840
|
try {
|
|
88471
88841
|
await this.peerConnection.setLocalDescription();
|
|
88472
88842
|
}
|
|
88473
88843
|
catch (err) {
|
|
88474
|
-
logger$
|
|
88844
|
+
logger$v.warn('Failed to set local description', { err });
|
|
88475
88845
|
}
|
|
88476
88846
|
if (this.peerConnection.localDescription !== null) {
|
|
88477
88847
|
this.emit('localDescription', this.peerConnection.localDescription.sdp, this.peerConnection.localDescription.type);
|
|
@@ -88481,7 +88851,7 @@
|
|
|
88481
88851
|
addRemoteCandidate(candidate, mid) {
|
|
88482
88852
|
this.peerConnection?.addIceCandidate({ candidate: candidate, sdpMid: mid })
|
|
88483
88853
|
.catch((err) => {
|
|
88484
|
-
logger$
|
|
88854
|
+
logger$v.warn('Failed to add ICE candidate', { err });
|
|
88485
88855
|
});
|
|
88486
88856
|
}
|
|
88487
88857
|
isOpen() {
|
|
@@ -88504,7 +88874,7 @@
|
|
|
88504
88874
|
this.dataChannel.close();
|
|
88505
88875
|
}
|
|
88506
88876
|
catch (err) {
|
|
88507
|
-
logger$
|
|
88877
|
+
logger$v.warn('Failed to close data channel', { err });
|
|
88508
88878
|
}
|
|
88509
88879
|
}
|
|
88510
88880
|
this.dataChannel = undefined;
|
|
@@ -88513,7 +88883,7 @@
|
|
|
88513
88883
|
this.peerConnection.close();
|
|
88514
88884
|
}
|
|
88515
88885
|
catch (err) {
|
|
88516
|
-
logger$
|
|
88886
|
+
logger$v.warn('Failed to close connection', { err });
|
|
88517
88887
|
}
|
|
88518
88888
|
}
|
|
88519
88889
|
this.peerConnection = undefined;
|
|
@@ -88525,6 +88895,9 @@
|
|
|
88525
88895
|
}
|
|
88526
88896
|
send(data) {
|
|
88527
88897
|
if (this.lastState === 'connected') {
|
|
88898
|
+
logGapDiagnosticSampled('dht.dc.send', {
|
|
88899
|
+
detail: { bufferedAmount: this.dataChannel.bufferedAmount, queueLen: this.messageQueue.length }
|
|
88900
|
+
});
|
|
88528
88901
|
if (this.dataChannel.bufferedAmount > this.bufferThresholdHigh) {
|
|
88529
88902
|
this.messageQueue.push(data);
|
|
88530
88903
|
}
|
|
@@ -88533,7 +88906,7 @@
|
|
|
88533
88906
|
}
|
|
88534
88907
|
}
|
|
88535
88908
|
else {
|
|
88536
|
-
logger$
|
|
88909
|
+
logger$v.warn('Tried to send on a connection with last state ' + this.lastState);
|
|
88537
88910
|
}
|
|
88538
88911
|
}
|
|
88539
88912
|
setupDataChannel(dataChannel) {
|
|
@@ -88541,22 +88914,22 @@
|
|
|
88541
88914
|
this.dataChannel.binaryType = 'arraybuffer';
|
|
88542
88915
|
this.dataChannel.bufferedAmountLowThreshold = this.bufferThresholdLow;
|
|
88543
88916
|
dataChannel.onopen = () => {
|
|
88544
|
-
logger$
|
|
88917
|
+
logger$v.trace('dc.onOpen');
|
|
88545
88918
|
this.onDataChannelOpen();
|
|
88546
88919
|
};
|
|
88547
88920
|
dataChannel.onclose = () => {
|
|
88548
|
-
logger$
|
|
88921
|
+
logger$v.trace('dc.onClosed');
|
|
88549
88922
|
this.doClose(false);
|
|
88550
88923
|
};
|
|
88551
88924
|
dataChannel.onerror = (err) => {
|
|
88552
|
-
logger$
|
|
88925
|
+
logger$v.warn('Data channel error', { err });
|
|
88553
88926
|
};
|
|
88554
88927
|
dataChannel.onmessage = (msg) => {
|
|
88555
|
-
logger$
|
|
88928
|
+
logger$v.trace('dc.onmessage');
|
|
88556
88929
|
this.emit('data', new Uint8Array(msg.data));
|
|
88557
88930
|
};
|
|
88558
88931
|
dataChannel.onbufferedamountlow = () => {
|
|
88559
|
-
logger$
|
|
88932
|
+
logger$v.trace('dc.onBufferedAmountLow');
|
|
88560
88933
|
while (this.messageQueue.length > 0 && this.dataChannel.bufferedAmount < this.bufferThresholdHigh) {
|
|
88561
88934
|
const data = this.messageQueue.shift();
|
|
88562
88935
|
this.dataChannel.send(data);
|
|
@@ -88595,6 +88968,292 @@
|
|
|
88595
88968
|
}
|
|
88596
88969
|
}
|
|
88597
88970
|
|
|
88971
|
+
/**
|
|
88972
|
+
* Call this function on the **main thread** before the worker starts using
|
|
88973
|
+
* WebRTC connections. It creates a dedicated `MessageChannel`, exposes a
|
|
88974
|
+
* {@link WebrtcBridge} instance on one port, and sends the other port to
|
|
88975
|
+
* the worker so that `WorkerWebrtcConnection` can reach the bridge.
|
|
88976
|
+
*
|
|
88977
|
+
* @example
|
|
88978
|
+
* ```ts
|
|
88979
|
+
* import { installWebrtcBridge } from '@streamr/dht'
|
|
88980
|
+
*
|
|
88981
|
+
* const worker = new Worker('./my-worker.ts', { type: 'module' })
|
|
88982
|
+
* installWebrtcBridge(worker)
|
|
88983
|
+
* ```
|
|
88984
|
+
*/
|
|
88985
|
+
const WEBRTC_BRIDGE_PORT_MESSAGE_TYPE = 'streamr-webrtc-bridge-port';
|
|
88986
|
+
|
|
88987
|
+
/**
|
|
88988
|
+
* WorkerWebrtcConnection — runs inside a **Web Worker**.
|
|
88989
|
+
*
|
|
88990
|
+
* Implements the same IWebrtcConnection + IConnection interfaces as
|
|
88991
|
+
* DirectWebrtcConnection, but delegates RTCPeerConnection management to
|
|
88992
|
+
* the main-thread {@link WebrtcBridge} via Comlink.
|
|
88993
|
+
*
|
|
88994
|
+
* The RTCDataChannel is **transferred** from the main thread and lives
|
|
88995
|
+
* entirely in the worker — all data events (onmessage, onopen, onclose,
|
|
88996
|
+
* onbufferedamountlow) fire in the worker's event loop. The main thread
|
|
88997
|
+
* is never involved in the data path.
|
|
88998
|
+
*/
|
|
88999
|
+
// ── Module-level bridge client (initialized once per worker) ────────
|
|
89000
|
+
let resolveBridgeProxy;
|
|
89001
|
+
const bridgeProxyPromise = new Promise((resolve) => {
|
|
89002
|
+
resolveBridgeProxy = resolve;
|
|
89003
|
+
});
|
|
89004
|
+
// Listen for the bridge port message from the main thread.
|
|
89005
|
+
// This is guarded so it only runs inside a worker context.
|
|
89006
|
+
if (isWorkerEnvironment) {
|
|
89007
|
+
const handler = (e) => {
|
|
89008
|
+
if (e.data?.type === WEBRTC_BRIDGE_PORT_MESSAGE_TYPE && e.data.port) {
|
|
89009
|
+
const proxy = wrap$1(e.data.port);
|
|
89010
|
+
resolveBridgeProxy(proxy);
|
|
89011
|
+
self.removeEventListener('message', handler);
|
|
89012
|
+
}
|
|
89013
|
+
};
|
|
89014
|
+
self.addEventListener('message', handler);
|
|
89015
|
+
}
|
|
89016
|
+
function getBridgeProxy() {
|
|
89017
|
+
return bridgeProxyPromise;
|
|
89018
|
+
}
|
|
89019
|
+
// ── Disconnection states ────────────────────────────────────────────
|
|
89020
|
+
var DisconnectedState;
|
|
89021
|
+
(function (DisconnectedState) {
|
|
89022
|
+
DisconnectedState["DISCONNECTED"] = "disconnected";
|
|
89023
|
+
DisconnectedState["FAILED"] = "failed";
|
|
89024
|
+
DisconnectedState["CLOSED"] = "closed";
|
|
89025
|
+
})(DisconnectedState || (DisconnectedState = {}));
|
|
89026
|
+
const logger$u = new Logger('WorkerWebrtcConnection');
|
|
89027
|
+
// ── WorkerWebrtcConnection ──────────────────────────────────────────
|
|
89028
|
+
class WorkerWebrtcConnection extends EventEmitter {
|
|
89029
|
+
connectionId;
|
|
89030
|
+
connectionType = ConnectionType.WEBRTC;
|
|
89031
|
+
iceServers;
|
|
89032
|
+
bufferThresholdHigh;
|
|
89033
|
+
bufferThresholdLow;
|
|
89034
|
+
dataChannel;
|
|
89035
|
+
bridge;
|
|
89036
|
+
closed = false;
|
|
89037
|
+
connected = false;
|
|
89038
|
+
earlyTimeout;
|
|
89039
|
+
messageQueue = [];
|
|
89040
|
+
startPromise;
|
|
89041
|
+
constructor(params) {
|
|
89042
|
+
super();
|
|
89043
|
+
this.connectionId = createRandomConnectionId();
|
|
89044
|
+
this.iceServers = params.iceServers ?? [];
|
|
89045
|
+
this.bufferThresholdHigh = params.bufferThresholdHigh ?? 2 ** 17;
|
|
89046
|
+
this.bufferThresholdLow = params.bufferThresholdLow ?? 2 ** 15;
|
|
89047
|
+
this.earlyTimeout = setTimeout(() => {
|
|
89048
|
+
this.doClose(false, 'timed out due to remote descriptor not being set');
|
|
89049
|
+
}, EARLY_TIMEOUT);
|
|
89050
|
+
}
|
|
89051
|
+
// ── IWebrtcConnection ───────────────────────────────────────
|
|
89052
|
+
start(isOffering) {
|
|
89053
|
+
this.startPromise = this.doStart(isOffering);
|
|
89054
|
+
this.startPromise.catch((err) => {
|
|
89055
|
+
logger$u.warn('Failed to start worker WebRTC connection', { err });
|
|
89056
|
+
this.doClose(false, 'Failed to start');
|
|
89057
|
+
});
|
|
89058
|
+
}
|
|
89059
|
+
async doStart(isOffering) {
|
|
89060
|
+
this.bridge = await getBridgeProxy();
|
|
89061
|
+
const iceServers = this.iceServers.map(({ url, port, username, password }) => ({
|
|
89062
|
+
urls: `${url}:${port}`,
|
|
89063
|
+
username,
|
|
89064
|
+
credential: password,
|
|
89065
|
+
}));
|
|
89066
|
+
await this.bridge.start(this.connectionId, iceServers, isOffering, proxy({
|
|
89067
|
+
onLocalCandidate: (candidate, mid) => {
|
|
89068
|
+
if (!this.closed) {
|
|
89069
|
+
this.emit('localCandidate', candidate, mid);
|
|
89070
|
+
}
|
|
89071
|
+
},
|
|
89072
|
+
onLocalDescription: (description, type) => {
|
|
89073
|
+
if (!this.closed) {
|
|
89074
|
+
this.emit('localDescription', description, type);
|
|
89075
|
+
}
|
|
89076
|
+
},
|
|
89077
|
+
onConnectionStateChange: (state) => {
|
|
89078
|
+
if (state === DisconnectedState.CLOSED ||
|
|
89079
|
+
state === DisconnectedState.DISCONNECTED ||
|
|
89080
|
+
state === DisconnectedState.FAILED) {
|
|
89081
|
+
this.doClose(false, `pcState=${state}`);
|
|
89082
|
+
}
|
|
89083
|
+
},
|
|
89084
|
+
onDataChannel: (channel) => {
|
|
89085
|
+
if (!this.closed) {
|
|
89086
|
+
this.setupDataChannel(channel);
|
|
89087
|
+
// If the channel was already open at transfer time
|
|
89088
|
+
if (channel.readyState === 'open') {
|
|
89089
|
+
this.onDataChannelOpen();
|
|
89090
|
+
}
|
|
89091
|
+
}
|
|
89092
|
+
},
|
|
89093
|
+
}));
|
|
89094
|
+
}
|
|
89095
|
+
async setRemoteDescription(description, type) {
|
|
89096
|
+
if (this.startPromise) {
|
|
89097
|
+
await this.startPromise;
|
|
89098
|
+
}
|
|
89099
|
+
if (!this.bridge || this.closed) {
|
|
89100
|
+
return;
|
|
89101
|
+
}
|
|
89102
|
+
const wasSet = await this.bridge.setRemoteDescription(this.connectionId, description, type);
|
|
89103
|
+
if (wasSet) {
|
|
89104
|
+
clearTimeout(this.earlyTimeout);
|
|
89105
|
+
}
|
|
89106
|
+
}
|
|
89107
|
+
addRemoteCandidate(candidate, mid) {
|
|
89108
|
+
this.doAddRemoteCandidate(candidate, mid).catch((err) => {
|
|
89109
|
+
logger$u.warn('Failed to add remote candidate via bridge', { err });
|
|
89110
|
+
});
|
|
89111
|
+
}
|
|
89112
|
+
async doAddRemoteCandidate(candidate, mid) {
|
|
89113
|
+
if (this.startPromise) {
|
|
89114
|
+
await this.startPromise;
|
|
89115
|
+
}
|
|
89116
|
+
if (!this.bridge || this.closed) {
|
|
89117
|
+
return;
|
|
89118
|
+
}
|
|
89119
|
+
await this.bridge.addRemoteCandidate(this.connectionId, candidate, mid);
|
|
89120
|
+
}
|
|
89121
|
+
isOpen() {
|
|
89122
|
+
return this.connected;
|
|
89123
|
+
}
|
|
89124
|
+
// ── IConnection ─────────────────────────────────────────────
|
|
89125
|
+
async close(gracefulLeave, reason) {
|
|
89126
|
+
this.doClose(gracefulLeave, reason);
|
|
89127
|
+
}
|
|
89128
|
+
destroy() {
|
|
89129
|
+
this.removeAllListeners();
|
|
89130
|
+
this.doClose(false);
|
|
89131
|
+
}
|
|
89132
|
+
send(data) {
|
|
89133
|
+
if (this.connected && this.dataChannel) {
|
|
89134
|
+
logGapDiagnosticSampled('dht.dc.send', {
|
|
89135
|
+
detail: { bufferedAmount: this.dataChannel.bufferedAmount, queueLen: this.messageQueue.length }
|
|
89136
|
+
});
|
|
89137
|
+
if (this.dataChannel.bufferedAmount > this.bufferThresholdHigh) {
|
|
89138
|
+
this.messageQueue.push(data);
|
|
89139
|
+
}
|
|
89140
|
+
else {
|
|
89141
|
+
this.dataChannel.send(data);
|
|
89142
|
+
}
|
|
89143
|
+
}
|
|
89144
|
+
else if (!this.closed) {
|
|
89145
|
+
this.messageQueue.push(data);
|
|
89146
|
+
}
|
|
89147
|
+
}
|
|
89148
|
+
setConnectionId(connectionId) {
|
|
89149
|
+
const oldId = this.connectionId;
|
|
89150
|
+
this.connectionId = connectionId;
|
|
89151
|
+
if (this.bridge && oldId !== connectionId) {
|
|
89152
|
+
this.bridge.renameConnection(oldId, connectionId).catch(() => { });
|
|
89153
|
+
}
|
|
89154
|
+
}
|
|
89155
|
+
// ── DataChannel handling (runs entirely in the worker) ──────
|
|
89156
|
+
setupDataChannel(dataChannel) {
|
|
89157
|
+
this.dataChannel = dataChannel;
|
|
89158
|
+
this.dataChannel.binaryType = 'arraybuffer';
|
|
89159
|
+
this.dataChannel.bufferedAmountLowThreshold = this.bufferThresholdLow;
|
|
89160
|
+
dataChannel.onopen = () => {
|
|
89161
|
+
logger$u.trace('dc.onOpen (worker)');
|
|
89162
|
+
this.onDataChannelOpen();
|
|
89163
|
+
};
|
|
89164
|
+
dataChannel.onclose = () => {
|
|
89165
|
+
logger$u.trace('dc.onClosed (worker)');
|
|
89166
|
+
this.doClose(false, 'dataChannel.onclose');
|
|
89167
|
+
};
|
|
89168
|
+
dataChannel.onerror = (err) => {
|
|
89169
|
+
logger$u.warn('Data channel error (worker)', { err });
|
|
89170
|
+
};
|
|
89171
|
+
dataChannel.onmessage = (msg) => {
|
|
89172
|
+
logger$u.trace('dc.onmessage (worker)');
|
|
89173
|
+
this.emit('data', new Uint8Array(msg.data));
|
|
89174
|
+
};
|
|
89175
|
+
dataChannel.onbufferedamountlow = () => {
|
|
89176
|
+
logger$u.trace('dc.onBufferedAmountLow (worker)');
|
|
89177
|
+
while (this.messageQueue.length > 0 &&
|
|
89178
|
+
this.dataChannel.bufferedAmount < this.bufferThresholdHigh) {
|
|
89179
|
+
const data = this.messageQueue.shift();
|
|
89180
|
+
this.dataChannel.send(data);
|
|
89181
|
+
}
|
|
89182
|
+
};
|
|
89183
|
+
}
|
|
89184
|
+
onDataChannelOpen() {
|
|
89185
|
+
this.connected = true;
|
|
89186
|
+
this.flushMessageQueue();
|
|
89187
|
+
this.emit('connected');
|
|
89188
|
+
}
|
|
89189
|
+
flushMessageQueue() {
|
|
89190
|
+
while (this.messageQueue.length > 0 &&
|
|
89191
|
+
this.dataChannel &&
|
|
89192
|
+
this.dataChannel.bufferedAmount < this.bufferThresholdHigh) {
|
|
89193
|
+
const data = this.messageQueue.shift();
|
|
89194
|
+
this.dataChannel.send(data);
|
|
89195
|
+
}
|
|
89196
|
+
}
|
|
89197
|
+
// ── Teardown ────────────────────────────────────────────────
|
|
89198
|
+
doClose(gracefulLeave, reason) {
|
|
89199
|
+
if (!this.closed) {
|
|
89200
|
+
this.closed = true;
|
|
89201
|
+
this.connected = false;
|
|
89202
|
+
this.messageQueue.length = 0;
|
|
89203
|
+
clearTimeout(this.earlyTimeout);
|
|
89204
|
+
this.stopListening();
|
|
89205
|
+
this.emit('disconnected', gracefulLeave, undefined, reason);
|
|
89206
|
+
this.removeAllListeners();
|
|
89207
|
+
if (this.dataChannel !== undefined) {
|
|
89208
|
+
try {
|
|
89209
|
+
this.dataChannel.close();
|
|
89210
|
+
}
|
|
89211
|
+
catch (err) {
|
|
89212
|
+
logger$u.warn('Failed to close data channel (worker)', { err });
|
|
89213
|
+
}
|
|
89214
|
+
}
|
|
89215
|
+
this.dataChannel = undefined;
|
|
89216
|
+
// Tell the main-thread bridge to tear down the RTCPeerConnection.
|
|
89217
|
+
// Fire-and-forget — we don't block on this.
|
|
89218
|
+
this.bridge
|
|
89219
|
+
?.close(this.connectionId)
|
|
89220
|
+
.catch(() => {
|
|
89221
|
+
// intentionally swallowed
|
|
89222
|
+
});
|
|
89223
|
+
}
|
|
89224
|
+
}
|
|
89225
|
+
stopListening() {
|
|
89226
|
+
if (this.dataChannel !== undefined) {
|
|
89227
|
+
this.dataChannel.onopen = null;
|
|
89228
|
+
this.dataChannel.onclose = null;
|
|
89229
|
+
this.dataChannel.onerror = null;
|
|
89230
|
+
this.dataChannel.onbufferedamountlow = null;
|
|
89231
|
+
this.dataChannel.onmessage = null;
|
|
89232
|
+
}
|
|
89233
|
+
}
|
|
89234
|
+
}
|
|
89235
|
+
|
|
89236
|
+
/**
|
|
89237
|
+
* Conditional re-export of the browser WebrtcConnection.
|
|
89238
|
+
*
|
|
89239
|
+
* At module-load time we detect whether we are running inside a Web Worker.
|
|
89240
|
+
* - **Main thread** → use {@link DirectWebrtcConnection} which owns the
|
|
89241
|
+
* `RTCPeerConnection` and `RTCDataChannel` directly.
|
|
89242
|
+
* - **Worker thread** → use {@link WorkerWebrtcConnection} which delegates
|
|
89243
|
+
* `RTCPeerConnection` signaling to the main thread via a Comlink bridge
|
|
89244
|
+
* and receives a transferred `RTCDataChannel` that lives entirely in the
|
|
89245
|
+
* worker.
|
|
89246
|
+
*
|
|
89247
|
+
* Both classes implement `IWebrtcConnection & IConnection` and expose the
|
|
89248
|
+
* same public API, so upstream code (WebrtcConnector, etc.) is unaffected.
|
|
89249
|
+
*/
|
|
89250
|
+
// The constructor — points to the right class based on the runtime
|
|
89251
|
+
// environment. The type assertion is safe because both implementations
|
|
89252
|
+
// share the same public interface surface.
|
|
89253
|
+
const WebrtcConnection = (isWorkerEnvironment
|
|
89254
|
+
? WorkerWebrtcConnection
|
|
89255
|
+
: DirectWebrtcConnection);
|
|
89256
|
+
|
|
88598
89257
|
const logger$t = new Logger('WebrtcConnectorRpcRemote');
|
|
88599
89258
|
class WebrtcConnectorRpcRemote extends RpcRemote {
|
|
88600
89259
|
requestConnection() {
|
|
@@ -90757,7 +91416,7 @@
|
|
|
90757
91416
|
logger$d$1.debug(`Ring join on ${this.options.serviceId} timed out`);
|
|
90758
91417
|
}
|
|
90759
91418
|
finally {
|
|
90760
|
-
sessions.forEach((session) => this.
|
|
91419
|
+
sessions.forEach((session) => this.ongoingRingDiscoverySessions.delete(session.id));
|
|
90761
91420
|
}
|
|
90762
91421
|
}
|
|
90763
91422
|
async rejoinDht(entryPoint, contactedPeers = new Set(), distantJoinContactPeers = new Set()) {
|
|
@@ -93073,7 +93732,7 @@
|
|
|
93073
93732
|
}
|
|
93074
93733
|
}
|
|
93075
93734
|
|
|
93076
|
-
var version$1 = "103.
|
|
93735
|
+
var version$1 = "103.7.0-rc.2";
|
|
93077
93736
|
|
|
93078
93737
|
// @generated message type with reflection information, may provide speed optimized methods
|
|
93079
93738
|
let Any$Type$1 = class Any$Type extends MessageType {
|
|
@@ -94720,6 +95379,18 @@
|
|
|
94720
95379
|
*/
|
|
94721
95380
|
const PauseNeighborRequest = new PauseNeighborRequest$Type();
|
|
94722
95381
|
// @generated message type with reflection information, may provide speed optimized methods
|
|
95382
|
+
class PauseNeighborResponse$Type extends MessageType {
|
|
95383
|
+
constructor() {
|
|
95384
|
+
super("PauseNeighborResponse", [
|
|
95385
|
+
{ no: 1, name: "accepted", kind: "scalar", T: 8 /*ScalarType.BOOL*/ }
|
|
95386
|
+
]);
|
|
95387
|
+
}
|
|
95388
|
+
}
|
|
95389
|
+
/**
|
|
95390
|
+
* @generated MessageType for protobuf message PauseNeighborResponse
|
|
95391
|
+
*/
|
|
95392
|
+
const PauseNeighborResponse = new PauseNeighborResponse$Type();
|
|
95393
|
+
// @generated message type with reflection information, may provide speed optimized methods
|
|
94723
95394
|
class ResumeNeighborRequest$Type extends MessageType {
|
|
94724
95395
|
constructor() {
|
|
94725
95396
|
super("ResumeNeighborRequest", [
|
|
@@ -94775,7 +95446,7 @@
|
|
|
94775
95446
|
* @generated ServiceType for protobuf service PlumtreeRpc
|
|
94776
95447
|
*/
|
|
94777
95448
|
const PlumtreeRpc = new ServiceType("PlumtreeRpc", [
|
|
94778
|
-
{ name: "pauseNeighbor", options: {}, I: PauseNeighborRequest, O:
|
|
95449
|
+
{ name: "pauseNeighbor", options: {}, I: PauseNeighborRequest, O: PauseNeighborResponse },
|
|
94779
95450
|
{ name: "resumeNeighbor", options: {}, I: ResumeNeighborRequest, O: Empty$1 },
|
|
94780
95451
|
{ name: "sendMetadata", options: {}, I: MessageID$1, O: Empty$1 }
|
|
94781
95452
|
]);
|
|
@@ -95802,6 +96473,7 @@
|
|
|
95802
96473
|
this.options.neighborFinder.stop();
|
|
95803
96474
|
this.options.neighborUpdateManager.stop();
|
|
95804
96475
|
this.options.inspector.stop();
|
|
96476
|
+
this.duplicateDetectors.clear();
|
|
95805
96477
|
}
|
|
95806
96478
|
broadcast(msg, previousNode) {
|
|
95807
96479
|
if (!previousNode) {
|
|
@@ -96377,14 +97049,17 @@
|
|
|
96377
97049
|
async pauseNeighbor(request, context) {
|
|
96378
97050
|
const sender = toNodeId(context.incomingSourceDescriptor);
|
|
96379
97051
|
if (this.neighbors.has(sender)) {
|
|
96380
|
-
this.pausedNodes.add(sender, request.messageChainId);
|
|
97052
|
+
const accepted = this.pausedNodes.add(sender, request.messageChainId);
|
|
97053
|
+
return { accepted };
|
|
96381
97054
|
}
|
|
96382
|
-
return
|
|
97055
|
+
return { accepted: false };
|
|
96383
97056
|
}
|
|
96384
97057
|
async resumeNeighbor(request, context) {
|
|
96385
97058
|
const sender = context.incomingSourceDescriptor;
|
|
96386
|
-
this.
|
|
96387
|
-
|
|
97059
|
+
if (this.neighbors.has(toNodeId(sender))) {
|
|
97060
|
+
this.pausedNodes.delete(toNodeId(sender), request.messageChainId);
|
|
97061
|
+
await this.sendBuffer(request.fromTimestamp, request.messageChainId, sender);
|
|
97062
|
+
}
|
|
96388
97063
|
return Empty$1;
|
|
96389
97064
|
}
|
|
96390
97065
|
}
|
|
@@ -96397,10 +97072,9 @@
|
|
|
96397
97072
|
await this.getClient().sendMetadata(msg, options);
|
|
96398
97073
|
}
|
|
96399
97074
|
async pauseNeighbor(messageChainId) {
|
|
96400
|
-
const options = this.formDhtRpcOptions(
|
|
96401
|
-
|
|
96402
|
-
|
|
96403
|
-
await this.getClient().pauseNeighbor({ messageChainId }, options);
|
|
97075
|
+
const options = this.formDhtRpcOptions();
|
|
97076
|
+
const response = await this.getClient().pauseNeighbor({ messageChainId }, options);
|
|
97077
|
+
return response.accepted;
|
|
96404
97078
|
}
|
|
96405
97079
|
async resumeNeighbor(fromTimestamp, messageChainId) {
|
|
96406
97080
|
const options = this.formDhtRpcOptions({
|
|
@@ -96422,9 +97096,10 @@
|
|
|
96422
97096
|
this.pausedNeighbors.set(msgChainId, new Set());
|
|
96423
97097
|
}
|
|
96424
97098
|
if (this.pausedNeighbors.get(msgChainId).size >= this.limit) {
|
|
96425
|
-
return;
|
|
97099
|
+
return false;
|
|
96426
97100
|
}
|
|
96427
97101
|
this.pausedNeighbors.get(msgChainId).add(node);
|
|
97102
|
+
return true;
|
|
96428
97103
|
}
|
|
96429
97104
|
delete(node, msgChainId) {
|
|
96430
97105
|
this.pausedNeighbors.get(msgChainId)?.delete(node);
|
|
@@ -96457,19 +97132,24 @@
|
|
|
96457
97132
|
}
|
|
96458
97133
|
|
|
96459
97134
|
const MAX_PAUSED_NEIGHBORS_DEFAULT = 3;
|
|
97135
|
+
const DEFAULT_RECOVERY_TIMEOUT = 500;
|
|
97136
|
+
const DEFAULT_RECOVERY_CHECK_INTERVAL = 200;
|
|
97137
|
+
const DEFAULT_RECOVERY_COOLDOWN = 2500;
|
|
96460
97138
|
const logger$4$1 = new Logger('PlumtreeManager');
|
|
96461
97139
|
class PlumtreeManager extends EventEmitter {
|
|
96462
97140
|
neighbors;
|
|
96463
97141
|
localPeerDescriptor;
|
|
96464
|
-
// We have paused sending real data to these neighbrs and only send metadata
|
|
96465
97142
|
localPausedNeighbors;
|
|
96466
|
-
// We have asked these nodes to pause sending real data to us, used to limit sending of pausing and resuming requests
|
|
96467
97143
|
remotePausedNeighbors;
|
|
96468
97144
|
rpcLocal;
|
|
96469
97145
|
latestMessages = new Map();
|
|
96470
97146
|
rpcCommunicator;
|
|
96471
|
-
metadataTimestampsAheadOfRealData = new Map();
|
|
96472
97147
|
maxPausedNeighbors;
|
|
97148
|
+
recoveryState = new Map();
|
|
97149
|
+
recoveryCooldownUntil = new Map();
|
|
97150
|
+
recoveryTimeout;
|
|
97151
|
+
recoveryCooldown;
|
|
97152
|
+
abortController = new AbortController();
|
|
96473
97153
|
constructor(options) {
|
|
96474
97154
|
super();
|
|
96475
97155
|
this.neighbors = options.neighbors;
|
|
@@ -96477,12 +97157,22 @@
|
|
|
96477
97157
|
this.localPeerDescriptor = options.localPeerDescriptor;
|
|
96478
97158
|
this.localPausedNeighbors = new PausedNeighbors(options.maxPausedNeighbors ?? MAX_PAUSED_NEIGHBORS_DEFAULT);
|
|
96479
97159
|
this.remotePausedNeighbors = new PausedNeighbors(options.maxPausedNeighbors ?? MAX_PAUSED_NEIGHBORS_DEFAULT);
|
|
97160
|
+
this.recoveryTimeout = options.recoveryTimeout ?? DEFAULT_RECOVERY_TIMEOUT;
|
|
97161
|
+
this.recoveryCooldown = options.recoveryCooldown ?? DEFAULT_RECOVERY_COOLDOWN;
|
|
96480
97162
|
this.rpcLocal = new PlumtreeRpcLocal(this.neighbors, this.localPausedNeighbors, (metadata, previousNode) => this.onMetadata(metadata, previousNode), (fromTimestamp, msgChainId, remotePeerDescriptor) => this.sendBuffer(fromTimestamp, msgChainId, remotePeerDescriptor));
|
|
96481
|
-
this.neighbors.on('nodeRemoved',
|
|
97163
|
+
this.neighbors.on('nodeRemoved', this.onNeighborRemoved);
|
|
96482
97164
|
this.rpcCommunicator = options.rpcCommunicator;
|
|
96483
97165
|
this.rpcCommunicator.registerRpcNotification(MessageID$1, 'sendMetadata', (msg, context) => this.rpcLocal.sendMetadata(msg, context));
|
|
96484
|
-
this.rpcCommunicator.
|
|
97166
|
+
this.rpcCommunicator.registerRpcMethod(PauseNeighborRequest, PauseNeighborResponse, 'pauseNeighbor', (msg, context) => this.rpcLocal.pauseNeighbor(msg, context));
|
|
96485
97167
|
this.rpcCommunicator.registerRpcNotification(ResumeNeighborRequest, 'resumeNeighbor', (msg, context) => this.rpcLocal.resumeNeighbor(msg, context));
|
|
97168
|
+
setAbortableInterval(() => {
|
|
97169
|
+
const now = performance.now();
|
|
97170
|
+
for (const [chainId, state] of this.recoveryState) {
|
|
97171
|
+
if (now - state.metadataAheadSince >= this.recoveryTimeout && !state.resumeInProgress) {
|
|
97172
|
+
this.attemptRecovery(chainId, state, this.getLatestMessageTimestamp(chainId));
|
|
97173
|
+
}
|
|
97174
|
+
}
|
|
97175
|
+
}, options.recoveryCheckInterval ?? DEFAULT_RECOVERY_CHECK_INTERVAL, this.abortController.signal);
|
|
96486
97176
|
}
|
|
96487
97177
|
async pauseNeighbor(node, msgChainId) {
|
|
96488
97178
|
if (this.neighbors.has(toNodeId(node))
|
|
@@ -96490,8 +97180,16 @@
|
|
|
96490
97180
|
&& this.remotePausedNeighbors.size(msgChainId) < this.maxPausedNeighbors) {
|
|
96491
97181
|
logger$4$1.debug(`Pausing neighbor ${toNodeId(node)}`);
|
|
96492
97182
|
this.remotePausedNeighbors.add(toNodeId(node), msgChainId);
|
|
96493
|
-
|
|
96494
|
-
|
|
97183
|
+
try {
|
|
97184
|
+
const remote = this.createRemote(node);
|
|
97185
|
+
const accepted = await remote.pauseNeighbor(msgChainId);
|
|
97186
|
+
if (!accepted) {
|
|
97187
|
+
this.remotePausedNeighbors.delete(toNodeId(node), msgChainId);
|
|
97188
|
+
}
|
|
97189
|
+
}
|
|
97190
|
+
catch (_e) {
|
|
97191
|
+
this.remotePausedNeighbors.delete(toNodeId(node), msgChainId);
|
|
97192
|
+
}
|
|
96495
97193
|
}
|
|
96496
97194
|
}
|
|
96497
97195
|
async resumeNeighbor(node, msgChainId, fromTimestamp) {
|
|
@@ -96502,9 +97200,15 @@
|
|
|
96502
97200
|
await remote.resumeNeighbor(fromTimestamp, msgChainId);
|
|
96503
97201
|
}
|
|
96504
97202
|
}
|
|
96505
|
-
onNeighborRemoved(nodeId) {
|
|
97203
|
+
onNeighborRemoved = (nodeId) => {
|
|
96506
97204
|
this.localPausedNeighbors.deleteAll(nodeId);
|
|
96507
97205
|
this.remotePausedNeighbors.deleteAll(nodeId);
|
|
97206
|
+
for (const [_chainId, state] of this.recoveryState) {
|
|
97207
|
+
state.candidates = state.candidates.filter((c) => toNodeId(c) !== nodeId);
|
|
97208
|
+
if (state.lastAttemptedNode !== null && toNodeId(state.lastAttemptedNode) === nodeId) {
|
|
97209
|
+
state.lastAttemptedNode = null;
|
|
97210
|
+
}
|
|
97211
|
+
}
|
|
96508
97212
|
if (this.neighbors.size() > 0) {
|
|
96509
97213
|
this.remotePausedNeighbors.forEach((pausedNeighbors, msgChainId) => {
|
|
96510
97214
|
if (pausedNeighbors.size >= this.neighbors.size()) {
|
|
@@ -96514,7 +97218,7 @@
|
|
|
96514
97218
|
}
|
|
96515
97219
|
});
|
|
96516
97220
|
}
|
|
96517
|
-
}
|
|
97221
|
+
};
|
|
96518
97222
|
getLatestMessageTimestamp(msgChainId) {
|
|
96519
97223
|
if (!this.latestMessages.has(msgChainId) || this.latestMessages.get(msgChainId).length === 0) {
|
|
96520
97224
|
return 0;
|
|
@@ -96524,22 +97228,61 @@
|
|
|
96524
97228
|
async sendBuffer(fromTimestamp, msgChainId, neighbor) {
|
|
96525
97229
|
const remote = new ContentDeliveryRpcRemote(this.localPeerDescriptor, neighbor, this.rpcCommunicator, ContentDeliveryRpcClient);
|
|
96526
97230
|
const messages = this.latestMessages.get(msgChainId)?.filter((msg) => msg.messageId.timestamp > fromTimestamp) ?? [];
|
|
96527
|
-
|
|
97231
|
+
for (const msg of messages) {
|
|
97232
|
+
await remote.sendStreamMessage(msg);
|
|
97233
|
+
}
|
|
96528
97234
|
}
|
|
96529
97235
|
async onMetadata(msg, previousNode) {
|
|
96530
|
-
|
|
96531
|
-
|
|
96532
|
-
|
|
96533
|
-
|
|
96534
|
-
|
|
96535
|
-
|
|
96536
|
-
|
|
96537
|
-
|
|
96538
|
-
|
|
96539
|
-
|
|
96540
|
-
|
|
96541
|
-
|
|
96542
|
-
|
|
97236
|
+
const latestTs = this.getLatestMessageTimestamp(msg.messageChainId);
|
|
97237
|
+
if (latestTs >= msg.timestamp) {
|
|
97238
|
+
return;
|
|
97239
|
+
}
|
|
97240
|
+
const chainId = msg.messageChainId;
|
|
97241
|
+
const cooldownUntil = this.recoveryCooldownUntil.get(chainId);
|
|
97242
|
+
if (cooldownUntil !== undefined && performance.now() < cooldownUntil) {
|
|
97243
|
+
return;
|
|
97244
|
+
}
|
|
97245
|
+
let state = this.recoveryState.get(chainId);
|
|
97246
|
+
if (!state) {
|
|
97247
|
+
state = {
|
|
97248
|
+
timestampsAhead: new Set(),
|
|
97249
|
+
metadataAheadSince: performance.now(),
|
|
97250
|
+
candidates: [],
|
|
97251
|
+
lastAttemptedNode: null,
|
|
97252
|
+
resumeInProgress: false
|
|
97253
|
+
};
|
|
97254
|
+
this.recoveryState.set(chainId, state);
|
|
97255
|
+
}
|
|
97256
|
+
state.timestampsAhead.add(msg.timestamp);
|
|
97257
|
+
const nodeId = toNodeId(previousNode);
|
|
97258
|
+
const isLastAttempted = state.lastAttemptedNode !== null && toNodeId(state.lastAttemptedNode) === nodeId;
|
|
97259
|
+
if (!isLastAttempted && !state.candidates.some((c) => toNodeId(c) === nodeId)) {
|
|
97260
|
+
state.candidates.push(previousNode);
|
|
97261
|
+
}
|
|
97262
|
+
if (state.timestampsAhead.size > 1 && !state.resumeInProgress) {
|
|
97263
|
+
await this.attemptRecovery(chainId, state, latestTs);
|
|
97264
|
+
}
|
|
97265
|
+
}
|
|
97266
|
+
async attemptRecovery(chainId, state, latestTs) {
|
|
97267
|
+
const candidate = state.candidates.shift();
|
|
97268
|
+
if (!candidate) {
|
|
97269
|
+
state.metadataAheadSince = performance.now();
|
|
97270
|
+
return;
|
|
97271
|
+
}
|
|
97272
|
+
state.resumeInProgress = true;
|
|
97273
|
+
state.lastAttemptedNode = candidate;
|
|
97274
|
+
state.candidates = [];
|
|
97275
|
+
state.timestampsAhead.clear();
|
|
97276
|
+
state.metadataAheadSince = performance.now();
|
|
97277
|
+
try {
|
|
97278
|
+
const remote = this.createRemote(candidate);
|
|
97279
|
+
await remote.resumeNeighbor(latestTs, chainId);
|
|
97280
|
+
}
|
|
97281
|
+
catch (_e) {
|
|
97282
|
+
logger$4$1.debug('Recovery resume failed, will retry with next candidate');
|
|
97283
|
+
}
|
|
97284
|
+
finally {
|
|
97285
|
+
state.resumeInProgress = false;
|
|
96543
97286
|
}
|
|
96544
97287
|
}
|
|
96545
97288
|
createRemote(neighbor) {
|
|
@@ -96557,8 +97300,13 @@
|
|
|
96557
97300
|
this.latestMessages.get(messageChainId).shift();
|
|
96558
97301
|
this.latestMessages.get(messageChainId).push(msg);
|
|
96559
97302
|
}
|
|
96560
|
-
|
|
96561
|
-
|
|
97303
|
+
const state = this.recoveryState.get(messageChainId);
|
|
97304
|
+
if (state) {
|
|
97305
|
+
if (state.lastAttemptedNode) {
|
|
97306
|
+
this.remotePausedNeighbors.delete(toNodeId(state.lastAttemptedNode), messageChainId);
|
|
97307
|
+
}
|
|
97308
|
+
this.recoveryState.delete(messageChainId);
|
|
97309
|
+
this.recoveryCooldownUntil.set(messageChainId, performance.now() + this.recoveryCooldown);
|
|
96562
97310
|
}
|
|
96563
97311
|
this.emit('message', msg);
|
|
96564
97312
|
const neighbors = this.neighbors.getAll().filter((neighbor) => toNodeId(neighbor.getPeerDescriptor()) !== previousNode);
|
|
@@ -96576,8 +97324,18 @@
|
|
|
96576
97324
|
return this.localPausedNeighbors.isPaused(toNodeId(node), msgChainId)
|
|
96577
97325
|
|| this.remotePausedNeighbors.isPaused(toNodeId(node), msgChainId);
|
|
96578
97326
|
}
|
|
97327
|
+
getLocalPausedNeighbors() {
|
|
97328
|
+
return this.localPausedNeighbors;
|
|
97329
|
+
}
|
|
97330
|
+
getRemotePausedNeighbors() {
|
|
97331
|
+
return this.remotePausedNeighbors;
|
|
97332
|
+
}
|
|
96579
97333
|
stop() {
|
|
97334
|
+
this.abortController.abort();
|
|
96580
97335
|
this.neighbors.off('nodeRemoved', this.onNeighborRemoved);
|
|
97336
|
+
this.latestMessages.clear();
|
|
97337
|
+
this.recoveryState.clear();
|
|
97338
|
+
this.recoveryCooldownUntil.clear();
|
|
96581
97339
|
}
|
|
96582
97340
|
}
|
|
96583
97341
|
|