@leofcoin/peernet 1.1.97 → 1.1.99
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.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { L as LittlePubSub } from './peernet-
|
|
1
|
+
import { L as LittlePubSub } from './peernet-BQUef8u4.js';
|
|
2
2
|
import './identity-Cn0iQbY3.js';
|
|
3
3
|
import './value-C3vAp-wb.js';
|
|
4
4
|
|
|
@@ -132,10 +132,9 @@ class Api {
|
|
|
132
132
|
throw e;
|
|
133
133
|
}
|
|
134
134
|
},
|
|
135
|
-
peers: async (
|
|
135
|
+
peers: async () => {
|
|
136
136
|
try {
|
|
137
|
-
params
|
|
138
|
-
const requested = { url: 'peernet', params };
|
|
137
|
+
const requested = { url: 'peernet', params: { peers: true } };
|
|
139
138
|
const { result, id, handler } = await this.request(client, requested);
|
|
140
139
|
this.unsubscribe(id, handler);
|
|
141
140
|
return result;
|
|
@@ -206,7 +205,7 @@ class SocketRequestClient {
|
|
|
206
205
|
clientConnection;
|
|
207
206
|
#tries = 0;
|
|
208
207
|
#retry = false;
|
|
209
|
-
#timeout =
|
|
208
|
+
#timeout = 10_000;
|
|
210
209
|
#times = 10;
|
|
211
210
|
#options;
|
|
212
211
|
#protocol;
|
|
@@ -342,16 +341,16 @@ class Peer extends SimplePeer {
|
|
|
342
341
|
channelName;
|
|
343
342
|
version;
|
|
344
343
|
bw = { up: 0, down: 0 };
|
|
345
|
-
get connected() {
|
|
346
|
-
return super.connected;
|
|
347
|
-
}
|
|
348
344
|
constructor(options) {
|
|
349
|
-
const { from, to,
|
|
350
|
-
|
|
345
|
+
const { from, to, trickle, config, version } = options;
|
|
346
|
+
// Canonical initiator and channel label based on sorted IDs
|
|
347
|
+
const [a, b] = [from, to].sort();
|
|
348
|
+
const channelName = `${a}:${b}`;
|
|
349
|
+
const initiator = from === a;
|
|
351
350
|
super({
|
|
352
351
|
channelName,
|
|
353
352
|
initiator,
|
|
354
|
-
trickle: trickle
|
|
353
|
+
trickle: trickle ?? true,
|
|
355
354
|
config: { iceServers, ...config },
|
|
356
355
|
wrtc: globalThis.wrtc
|
|
357
356
|
});
|
|
@@ -428,7 +427,11 @@ class Client {
|
|
|
428
427
|
#peerId;
|
|
429
428
|
#connections = {};
|
|
430
429
|
#stars = {};
|
|
430
|
+
#starListeners = {};
|
|
431
|
+
#handlersSetup = false;
|
|
432
|
+
#reinitLock = null;
|
|
431
433
|
#connectEvent = 'peer:connected';
|
|
434
|
+
#retryOptions = { retries: 5, factor: 2, minTimeout: 1000, maxTimeout: 30000 };
|
|
432
435
|
id;
|
|
433
436
|
networkVersion;
|
|
434
437
|
starsConfig;
|
|
@@ -467,21 +470,80 @@ class Client {
|
|
|
467
470
|
this.version = version;
|
|
468
471
|
this.#connectEvent = connectEvent;
|
|
469
472
|
this.starsConfig = stars;
|
|
473
|
+
if (options?.retry)
|
|
474
|
+
this.#retryOptions = { ...this.#retryOptions, ...options.retry };
|
|
470
475
|
this._init();
|
|
471
476
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
+
/**
|
|
478
|
+
* Safely reinitialize the client (used after system resume/sleep).
|
|
479
|
+
* It closes existing connections and reconnects to configured stars.
|
|
480
|
+
*/
|
|
481
|
+
async reinit() {
|
|
482
|
+
// avoid concurrent reinit runs
|
|
483
|
+
if (this.#reinitLock)
|
|
484
|
+
return this.#reinitLock;
|
|
485
|
+
this.#reinitLock = (async () => {
|
|
486
|
+
debug('reinit: start');
|
|
487
|
+
try {
|
|
488
|
+
await this.close();
|
|
489
|
+
// clear internal maps so setupStar starts fresh
|
|
490
|
+
this.#stars = {};
|
|
491
|
+
this.#connections = {};
|
|
492
|
+
for (const star of this.starsConfig) {
|
|
493
|
+
try {
|
|
494
|
+
await this.setupStar(star);
|
|
495
|
+
}
|
|
496
|
+
catch (e) {
|
|
497
|
+
// If last star fails and none connected, surface error
|
|
498
|
+
if (this.starsConfig.indexOf(star) === this.starsConfig.length - 1 &&
|
|
499
|
+
Object.keys(this.#stars).length === 0)
|
|
500
|
+
throw new Error(`No star available to connect`);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
finally {
|
|
505
|
+
debug('reinit: done');
|
|
506
|
+
this.#reinitLock = null;
|
|
507
|
+
}
|
|
508
|
+
})();
|
|
509
|
+
return this.#reinitLock;
|
|
510
|
+
}
|
|
511
|
+
async setupStar(star) {
|
|
512
|
+
const { retries, factor, minTimeout, maxTimeout } = this.#retryOptions;
|
|
513
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
514
|
+
let attempt = 0;
|
|
515
|
+
let lastErr;
|
|
516
|
+
while (attempt <= retries) {
|
|
477
517
|
try {
|
|
478
518
|
const client = new SocketRequestClient(star, this.networkVersion);
|
|
479
519
|
this.#stars[star] = await client.init();
|
|
480
|
-
this.setupStarListeners(this.#stars[star]);
|
|
520
|
+
this.setupStarListeners(this.#stars[star], star);
|
|
481
521
|
this.#stars[star].send({
|
|
482
522
|
url: 'join',
|
|
483
523
|
params: { version: this.version, peerId: this.peerId }
|
|
484
524
|
});
|
|
525
|
+
return this.#stars[star];
|
|
526
|
+
}
|
|
527
|
+
catch (e) {
|
|
528
|
+
lastErr = e;
|
|
529
|
+
attempt += 1;
|
|
530
|
+
if (attempt > retries)
|
|
531
|
+
break;
|
|
532
|
+
const delay = Math.min(maxTimeout, Math.round(minTimeout * Math.pow(factor, attempt - 1)));
|
|
533
|
+
debug(`setupStar ${star} failed, retrying in ${delay}ms (attempt ${attempt})`);
|
|
534
|
+
// eslint-disable-next-line no-await-in-loop
|
|
535
|
+
await sleep(delay);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
throw lastErr;
|
|
539
|
+
}
|
|
540
|
+
async _init() {
|
|
541
|
+
// reconnectJob()
|
|
542
|
+
if (!globalThis.RTCPeerConnection)
|
|
543
|
+
globalThis.wrtc = (await import('./browser-Cjcx-T47.js').then(function (n) { return n.b; })).default;
|
|
544
|
+
for (const star of this.starsConfig) {
|
|
545
|
+
try {
|
|
546
|
+
await this.setupStar(star);
|
|
485
547
|
}
|
|
486
548
|
catch (e) {
|
|
487
549
|
if (this.starsConfig.indexOf(star) === this.starsConfig.length - 1 &&
|
|
@@ -499,13 +561,68 @@ class Client {
|
|
|
499
561
|
else {
|
|
500
562
|
globalThis.addEventListener('beforeunload', this.close.bind(this));
|
|
501
563
|
}
|
|
564
|
+
// Setup resume/sleep detection so we can reinit connections after wake
|
|
565
|
+
this._setupResumeHandler();
|
|
566
|
+
}
|
|
567
|
+
setupStarListeners(starConnection, starId) {
|
|
568
|
+
// create stable references to handlers so we can unsubscribe later
|
|
569
|
+
const onPeerJoined = (id) => this.#peerJoined(id, starConnection);
|
|
570
|
+
const onPeerLeft = (id) => this.#peerLeft(id, starConnection);
|
|
571
|
+
const onStarJoined = this.#starJoined;
|
|
572
|
+
const onStarLeft = this.#starLeft;
|
|
573
|
+
const onSignal = (message) => this.#inComingSignal(message, starConnection);
|
|
574
|
+
starConnection.pubsub.subscribe('peer:joined', onPeerJoined);
|
|
575
|
+
starConnection.pubsub.subscribe('peer:left', onPeerLeft);
|
|
576
|
+
starConnection.pubsub.subscribe('star:joined', onStarJoined);
|
|
577
|
+
starConnection.pubsub.subscribe('star:left', onStarLeft);
|
|
578
|
+
starConnection.pubsub.subscribe('signal', onSignal);
|
|
579
|
+
this.#starListeners[starId] = [
|
|
580
|
+
{ topic: 'peer:joined', handler: onPeerJoined },
|
|
581
|
+
{ topic: 'peer:left', handler: onPeerLeft },
|
|
582
|
+
{ topic: 'star:joined', handler: onStarJoined },
|
|
583
|
+
{ topic: 'star:left', handler: onStarLeft },
|
|
584
|
+
{ topic: 'signal', handler: onSignal }
|
|
585
|
+
];
|
|
502
586
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
587
|
+
_setupResumeHandler() {
|
|
588
|
+
if (this.#handlersSetup)
|
|
589
|
+
return;
|
|
590
|
+
this.#handlersSetup = true;
|
|
591
|
+
const THRESHOLD = 10 * 1000; // 10s gap indicates sleep/wake
|
|
592
|
+
let last = Date.now();
|
|
593
|
+
const check = () => {
|
|
594
|
+
const now = Date.now();
|
|
595
|
+
const delta = now - last;
|
|
596
|
+
last = now;
|
|
597
|
+
if (delta > THRESHOLD) {
|
|
598
|
+
debug(`resume detected (gap ${delta}ms)`);
|
|
599
|
+
this.reinit().catch((e) => debug('reinit error', e));
|
|
600
|
+
}
|
|
601
|
+
};
|
|
602
|
+
// Start interval checker
|
|
603
|
+
const iv = setInterval(check, 2000);
|
|
604
|
+
// Browser specific events
|
|
605
|
+
if (typeof document !== 'undefined' && document.addEventListener) {
|
|
606
|
+
document.addEventListener('visibilitychange', () => {
|
|
607
|
+
if (document.visibilityState === 'visible') {
|
|
608
|
+
// small delay to let timers update
|
|
609
|
+
setTimeout(() => check(), 50);
|
|
610
|
+
}
|
|
611
|
+
});
|
|
612
|
+
window.addEventListener('online', () => setTimeout(() => check(), 50));
|
|
613
|
+
}
|
|
614
|
+
// Node: listen for SIGCONT (process continued) as well
|
|
615
|
+
if (globalThis.process?.on) {
|
|
616
|
+
try {
|
|
617
|
+
process.on('SIGCONT', () => setTimeout(() => check(), 50));
|
|
618
|
+
}
|
|
619
|
+
catch (e) {
|
|
620
|
+
// ignore
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
// keep reference so it can be cleared on close
|
|
624
|
+
// @ts-ignore
|
|
625
|
+
this._resumeInterval = iv;
|
|
509
626
|
}
|
|
510
627
|
#starJoined = (id) => {
|
|
511
628
|
if (this.#stars[id]) {
|
|
@@ -519,20 +636,16 @@ class Client {
|
|
|
519
636
|
this.#stars[id].close(0);
|
|
520
637
|
delete this.#stars[id];
|
|
521
638
|
}
|
|
639
|
+
// if we lost all stars, try to reconnect to configured stars with backoff
|
|
522
640
|
if (Object.keys(this.#stars).length === 0) {
|
|
523
641
|
for (const star of this.starsConfig) {
|
|
524
642
|
try {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
this.#stars[star] = socketClient;
|
|
529
|
-
this.#stars[star].send({
|
|
530
|
-
url: 'join',
|
|
531
|
-
params: { peerId: this.peerId, version: this.version }
|
|
532
|
-
});
|
|
533
|
-
this.setupStarListeners(socketClient);
|
|
643
|
+
await this.setupStar(star);
|
|
644
|
+
// stop at first success
|
|
645
|
+
return;
|
|
534
646
|
}
|
|
535
647
|
catch (e) {
|
|
648
|
+
debug(`reconnect star ${star} failed: ${e.message || e}`);
|
|
536
649
|
if (this.starsConfig.indexOf(star) === this.starsConfig.length - 1)
|
|
537
650
|
throw new Error(`No star available to connect`);
|
|
538
651
|
}
|
|
@@ -548,7 +661,7 @@ class Client {
|
|
|
548
661
|
}
|
|
549
662
|
debug(`peer ${id} left`);
|
|
550
663
|
};
|
|
551
|
-
connect(peerId, star
|
|
664
|
+
connect(peerId, star) {
|
|
552
665
|
if (this.#connections[peerId]) {
|
|
553
666
|
debug(`peer ${peerId} already connected`);
|
|
554
667
|
return;
|
|
@@ -557,16 +670,15 @@ class Client {
|
|
|
557
670
|
console.warn(`Star ${star} is not connected, cannot reconnect to peer ${peerId}`);
|
|
558
671
|
return;
|
|
559
672
|
}
|
|
560
|
-
this.#createRTCPeerConnection(peerId, star, this.version
|
|
673
|
+
this.#createRTCPeerConnection(peerId, star, this.version);
|
|
561
674
|
}
|
|
562
|
-
reconnect(peerId, star
|
|
675
|
+
reconnect(peerId, star) {
|
|
563
676
|
delete this.#connections[peerId];
|
|
564
677
|
debug(`reconnecting to peer ${peerId}`);
|
|
565
|
-
return this.connect(peerId, star
|
|
678
|
+
return this.connect(peerId, star);
|
|
566
679
|
}
|
|
567
|
-
#createRTCPeerConnection = (peerId, star, version
|
|
680
|
+
#createRTCPeerConnection = (peerId, star, version) => {
|
|
568
681
|
const peer = new Peer({
|
|
569
|
-
initiator: initiator,
|
|
570
682
|
from: this.peerId,
|
|
571
683
|
to: peerId,
|
|
572
684
|
version
|
|
@@ -585,7 +697,7 @@ class Client {
|
|
|
585
697
|
delete this.#connections[peerId];
|
|
586
698
|
}
|
|
587
699
|
if (this.peerId !== peerId)
|
|
588
|
-
this.#createRTCPeerConnection(peerId, star, version
|
|
700
|
+
this.#createRTCPeerConnection(peerId, star, version);
|
|
589
701
|
debug(`peer ${peerId} joined`);
|
|
590
702
|
};
|
|
591
703
|
#inComingSignal = async ({ from, signal, channelName, version }, star) => {
|
|
@@ -611,9 +723,10 @@ class Client {
|
|
|
611
723
|
// Destroy the existing peer connection
|
|
612
724
|
// peer.destroy()
|
|
613
725
|
// delete this.#connections[from]
|
|
614
|
-
// // Create a new peer connection with the correct configuration
|
|
726
|
+
// // // Create a new peer connection with the correct configuration
|
|
615
727
|
// this.#createRTCPeerConnection(from, star, version, false)
|
|
616
728
|
// peer = this.#connections[from]
|
|
729
|
+
return;
|
|
617
730
|
}
|
|
618
731
|
peer.signal(signal);
|
|
619
732
|
};
|
|
@@ -685,15 +798,53 @@ class Client {
|
|
|
685
798
|
peer.destroy();
|
|
686
799
|
};
|
|
687
800
|
async close() {
|
|
801
|
+
// clear resume interval if set
|
|
802
|
+
// @ts-ignore
|
|
803
|
+
if (this._resumeInterval) {
|
|
804
|
+
// @ts-ignore
|
|
805
|
+
clearInterval(this._resumeInterval);
|
|
806
|
+
// @ts-ignore
|
|
807
|
+
this._resumeInterval = null;
|
|
808
|
+
}
|
|
688
809
|
for (const star in this.#stars) {
|
|
689
|
-
if (this.#stars[star].connectionState() === 'open')
|
|
810
|
+
if (this.#stars[star].connectionState() === 'open') {
|
|
690
811
|
await this.#stars[star].send({ url: 'leave', params: this.peerId });
|
|
812
|
+
// unsubscribe handlers we registered earlier
|
|
813
|
+
const listeners = this.#starListeners[star];
|
|
814
|
+
if (listeners && listeners.length) {
|
|
815
|
+
for (const { topic, handler } of listeners) {
|
|
816
|
+
try {
|
|
817
|
+
this.#stars[star].pubsub.unsubscribe(topic, handler);
|
|
818
|
+
}
|
|
819
|
+
catch (e) {
|
|
820
|
+
// ignore
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
}
|
|
691
825
|
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
826
|
+
// Ensure we wait for all peer and star close/destroy operations.
|
|
827
|
+
// Previous code passed an array of arrays to Promise.allSettled which
|
|
828
|
+
// resolves immediately; flatten into a single array of promises (or
|
|
829
|
+
// values) so we actually wait for async close operations.
|
|
830
|
+
const peerClosers = Object.values(this.#connections).map((connection) => {
|
|
831
|
+
try {
|
|
832
|
+
// destroy() may be sync or return a promise
|
|
833
|
+
return connection.destroy();
|
|
834
|
+
}
|
|
835
|
+
catch (e) {
|
|
836
|
+
return undefined;
|
|
837
|
+
}
|
|
838
|
+
});
|
|
839
|
+
const starClosers = Object.values(this.#stars).map((connection) => {
|
|
840
|
+
try {
|
|
841
|
+
return connection.close(0);
|
|
842
|
+
}
|
|
843
|
+
catch (e) {
|
|
844
|
+
return undefined;
|
|
845
|
+
}
|
|
846
|
+
});
|
|
847
|
+
return Promise.allSettled([...peerClosers, ...starClosers]);
|
|
697
848
|
}
|
|
698
849
|
}
|
|
699
850
|
|
|
@@ -8367,7 +8367,7 @@ class Peernet {
|
|
|
8367
8367
|
this.root = options.root;
|
|
8368
8368
|
const { RequestMessage, ResponseMessage, PeerMessage, PeerMessageResponse, PeernetMessage, DHTMessage, DHTMessageResponse, DataMessage, DataMessageResponse, PsMessage, ChatMessage, PeernetFile
|
|
8369
8369
|
// FolderMessageResponse
|
|
8370
|
-
} = await import(/* webpackChunkName: "messages" */ './messages-
|
|
8370
|
+
} = await import(/* webpackChunkName: "messages" */ './messages-B2WVXv2a.js');
|
|
8371
8371
|
/**
|
|
8372
8372
|
* proto Object containing protos
|
|
8373
8373
|
* @type {Object}
|
|
@@ -8461,7 +8461,7 @@ class Peernet {
|
|
|
8461
8461
|
if (this.#starting || this.#started)
|
|
8462
8462
|
return;
|
|
8463
8463
|
this.#starting = true;
|
|
8464
|
-
const importee = await import('./client-
|
|
8464
|
+
const importee = await import('./client-BfWOZz0W.js');
|
|
8465
8465
|
/**
|
|
8466
8466
|
* @access public
|
|
8467
8467
|
* @type {PeernetClient}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leofcoin/peernet",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.99",
|
|
4
4
|
"description": "",
|
|
5
5
|
"browser": "./exports/browser/peernet.js",
|
|
6
6
|
"exports": {
|
|
@@ -37,34 +37,34 @@
|
|
|
37
37
|
"@leofcoin/identity-utils": "^1.0.2",
|
|
38
38
|
"@leofcoin/multi-wallet": "^3.1.8",
|
|
39
39
|
"@leofcoin/storage": "^3.5.38",
|
|
40
|
-
"@netpeer/swarm": "^0.8.
|
|
40
|
+
"@netpeer/swarm": "^0.8.29",
|
|
41
41
|
"@vandeurenglenn/base32": "^1.2.4",
|
|
42
42
|
"@vandeurenglenn/base58": "^1.1.9",
|
|
43
43
|
"@vandeurenglenn/debug": "^1.2.6",
|
|
44
44
|
"@vandeurenglenn/is-hex": "^1.1.1",
|
|
45
45
|
"@vandeurenglenn/little-pubsub": "^1.5.1",
|
|
46
|
-
"inquirer": "^12.
|
|
46
|
+
"inquirer": "^12.10.0",
|
|
47
47
|
"multi-signature": "^1.3.1",
|
|
48
48
|
"qr-scanner": "^1.4.2",
|
|
49
49
|
"qrcode": "^1.5.4",
|
|
50
|
-
"socket-request-client": "^2.1.
|
|
51
|
-
"socket-request-server": "^1.7.
|
|
50
|
+
"socket-request-client": "^2.1.2",
|
|
51
|
+
"socket-request-server": "^1.7.2"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@jest/globals": "^30.0
|
|
55
|
-
"@rollup/plugin-commonjs": "^28.0.
|
|
54
|
+
"@jest/globals": "^30.2.0",
|
|
55
|
+
"@rollup/plugin-commonjs": "^28.0.8",
|
|
56
56
|
"@rollup/plugin-json": "^6.1.0",
|
|
57
|
-
"@rollup/plugin-node-resolve": "^16.0.
|
|
57
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
58
58
|
"@rollup/plugin-typescript": "^12.1.4",
|
|
59
59
|
"@rollup/plugin-wasm": "^6.2.2",
|
|
60
|
-
"@types/bs58check": "^
|
|
61
|
-
"@types/node": "^24.1
|
|
60
|
+
"@types/bs58check": "^3.0.1",
|
|
61
|
+
"@types/node": "^24.9.1",
|
|
62
62
|
"@types/qrcode": "^1.5.5",
|
|
63
|
-
"@types/secp256k1": "^4.0.
|
|
63
|
+
"@types/secp256k1": "^4.0.7",
|
|
64
64
|
"@types/varint": "^6.0.3",
|
|
65
|
-
"chai": "^
|
|
66
|
-
"cross-env": "^10.
|
|
67
|
-
"rollup": "^4.
|
|
65
|
+
"chai": "^6.2.0",
|
|
66
|
+
"cross-env": "^10.1.0",
|
|
67
|
+
"rollup": "^4.52.5",
|
|
68
68
|
"sinon": "^21.0.0"
|
|
69
69
|
}
|
|
70
70
|
}
|