@dxos/teleport 0.3.5-main.caaa612 → 0.3.5-main.d14658e
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/lib/browser/{chunk-PWWDYMDW.mjs → chunk-3PM5BABC.mjs} +62 -54
- package/dist/lib/browser/chunk-3PM5BABC.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1 -1
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +1 -1
- package/dist/lib/node/index.cjs +61 -53
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +61 -53
- package/dist/lib/node/testing/index.cjs.map +3 -3
- package/dist/types/src/muxing/muxer.d.ts +2 -2
- package/dist/types/src/muxing/muxer.d.ts.map +1 -1
- package/dist/types/src/muxing/rpc-port.d.ts +1 -1
- package/dist/types/src/muxing/rpc-port.d.ts.map +1 -1
- package/dist/types/src/teleport.d.ts.map +1 -1
- package/package.json +12 -12
- package/src/muxing/muxer.ts +20 -13
- package/src/muxing/rpc-port.ts +1 -1
- package/src/teleport.ts +7 -4
- package/dist/lib/browser/chunk-PWWDYMDW.mjs.map +0 -7
|
@@ -363,6 +363,8 @@ var decodeChunk = (data, withLength) => {
|
|
|
363
363
|
// packages/core/mesh/teleport/src/muxing/muxer.ts
|
|
364
364
|
var __dxlog_file3 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/muxing/muxer.ts";
|
|
365
365
|
var Command = schema.getCodecForType("dxos.mesh.muxer.Command");
|
|
366
|
+
var DEFAULT_SEND_COMMAND_TIMEOUT = 6e4;
|
|
367
|
+
var DESTROY_COMMAND_SEND_TIMEOUT = 5e3;
|
|
366
368
|
var STATS_INTERVAL = 1e3;
|
|
367
369
|
var MAX_SAFE_FRAME_SIZE = 1e6;
|
|
368
370
|
var SYSTEM_CHANNEL_ID = 0;
|
|
@@ -374,9 +376,9 @@ var Muxer = class {
|
|
|
374
376
|
this._channelsByTag = /* @__PURE__ */ new Map();
|
|
375
377
|
this._ctx = new Context();
|
|
376
378
|
this._nextId = 1;
|
|
377
|
-
this._destroyed = false;
|
|
378
|
-
this._destroying = false;
|
|
379
379
|
this._closing = false;
|
|
380
|
+
this._destroying = false;
|
|
381
|
+
this._disposed = false;
|
|
380
382
|
this._lastStats = void 0;
|
|
381
383
|
this._lastChannelStats = /* @__PURE__ */ new Map();
|
|
382
384
|
this.afterClosed = new Event3();
|
|
@@ -385,7 +387,6 @@ var Muxer = class {
|
|
|
385
387
|
this._balancer.incomingData.on(async (msg) => {
|
|
386
388
|
await this._handleCommand(Command.decode(msg));
|
|
387
389
|
});
|
|
388
|
-
scheduleTaskInterval(this._ctx, async () => this._emitStats(), STATS_INTERVAL);
|
|
389
390
|
}
|
|
390
391
|
/**
|
|
391
392
|
* Creates a duplex Node.js-style stream.
|
|
@@ -400,7 +401,7 @@ var Muxer = class {
|
|
|
400
401
|
});
|
|
401
402
|
invariant2(!channel.push, `Channel already open: ${tag}`, {
|
|
402
403
|
F: __dxlog_file3,
|
|
403
|
-
L:
|
|
404
|
+
L: 140,
|
|
404
405
|
S: this,
|
|
405
406
|
A: [
|
|
406
407
|
"!channel.push",
|
|
@@ -448,7 +449,7 @@ var Muxer = class {
|
|
|
448
449
|
});
|
|
449
450
|
invariant2(!channel.push, `Channel already open: ${tag}`, {
|
|
450
451
|
F: __dxlog_file3,
|
|
451
|
-
L:
|
|
452
|
+
L: 192,
|
|
452
453
|
S: this,
|
|
453
454
|
A: [
|
|
454
455
|
"!channel.push",
|
|
@@ -466,13 +467,13 @@ var Muxer = class {
|
|
|
466
467
|
}
|
|
467
468
|
};
|
|
468
469
|
const port = {
|
|
469
|
-
send: async (data) => {
|
|
470
|
-
await this._sendData(channel, data);
|
|
470
|
+
send: async (data, timeout) => {
|
|
471
|
+
await this._sendData(channel, data, timeout);
|
|
471
472
|
},
|
|
472
473
|
subscribe: (cb) => {
|
|
473
474
|
invariant2(!callback, "Only one subscriber is allowed", {
|
|
474
475
|
F: __dxlog_file3,
|
|
475
|
-
L:
|
|
476
|
+
L: 214,
|
|
476
477
|
S: this,
|
|
477
478
|
A: [
|
|
478
479
|
"!callback",
|
|
@@ -505,7 +506,7 @@ var Muxer = class {
|
|
|
505
506
|
if (this._destroying) {
|
|
506
507
|
log3("already destroying, ignoring graceful close request", void 0, {
|
|
507
508
|
F: __dxlog_file3,
|
|
508
|
-
L:
|
|
509
|
+
L: 247,
|
|
509
510
|
S: this,
|
|
510
511
|
C: (f, a) => f(...a)
|
|
511
512
|
});
|
|
@@ -514,7 +515,7 @@ var Muxer = class {
|
|
|
514
515
|
if (this._closing) {
|
|
515
516
|
log3("already closing, ignoring graceful close request", void 0, {
|
|
516
517
|
F: __dxlog_file3,
|
|
517
|
-
L:
|
|
518
|
+
L: 251,
|
|
518
519
|
S: this,
|
|
519
520
|
C: (f, a) => f(...a)
|
|
520
521
|
});
|
|
@@ -525,12 +526,12 @@ var Muxer = class {
|
|
|
525
526
|
close: {
|
|
526
527
|
error: err?.message
|
|
527
528
|
}
|
|
528
|
-
}, SYSTEM_CHANNEL_ID).catch(async (err2) => {
|
|
529
|
+
}, SYSTEM_CHANNEL_ID, DESTROY_COMMAND_SEND_TIMEOUT).catch(async (err2) => {
|
|
529
530
|
log3("error sending close command", {
|
|
530
531
|
err: err2
|
|
531
532
|
}, {
|
|
532
533
|
F: __dxlog_file3,
|
|
533
|
-
L:
|
|
534
|
+
L: 266,
|
|
534
535
|
S: this,
|
|
535
536
|
C: (f, a) => f(...a)
|
|
536
537
|
});
|
|
@@ -552,7 +553,7 @@ var Muxer = class {
|
|
|
552
553
|
if (this._destroying) {
|
|
553
554
|
log3("already destroying, ignoring destroy request", void 0, {
|
|
554
555
|
F: __dxlog_file3,
|
|
555
|
-
L:
|
|
556
|
+
L: 287,
|
|
556
557
|
S: this,
|
|
557
558
|
C: (f, a) => f(...a)
|
|
558
559
|
});
|
|
@@ -563,7 +564,7 @@ var Muxer = class {
|
|
|
563
564
|
if (this._closing) {
|
|
564
565
|
log3("destroy cancelling graceful close", void 0, {
|
|
565
566
|
F: __dxlog_file3,
|
|
566
|
-
L:
|
|
567
|
+
L: 293,
|
|
567
568
|
S: this,
|
|
568
569
|
C: (f, a) => f(...a)
|
|
569
570
|
});
|
|
@@ -578,7 +579,7 @@ var Muxer = class {
|
|
|
578
579
|
err: err2
|
|
579
580
|
}, {
|
|
580
581
|
F: __dxlog_file3,
|
|
581
|
-
L:
|
|
582
|
+
L: 306,
|
|
582
583
|
S: this,
|
|
583
584
|
C: (f, a) => f(...a)
|
|
584
585
|
});
|
|
@@ -589,7 +590,7 @@ var Muxer = class {
|
|
|
589
590
|
err: err2
|
|
590
591
|
}, {
|
|
591
592
|
F: __dxlog_file3,
|
|
592
|
-
L:
|
|
593
|
+
L: 311,
|
|
593
594
|
S: this,
|
|
594
595
|
C: (f, a) => f(...a)
|
|
595
596
|
});
|
|
@@ -597,10 +598,10 @@ var Muxer = class {
|
|
|
597
598
|
}
|
|
598
599
|
// complete the termination, graceful or otherwise
|
|
599
600
|
async dispose(err) {
|
|
600
|
-
if (this.
|
|
601
|
+
if (this._disposed) {
|
|
601
602
|
log3("already destroyed, ignoring dispose request", void 0, {
|
|
602
603
|
F: __dxlog_file3,
|
|
603
|
-
L:
|
|
604
|
+
L: 319,
|
|
604
605
|
S: this,
|
|
605
606
|
C: (f, a) => f(...a)
|
|
606
607
|
});
|
|
@@ -611,18 +612,18 @@ var Muxer = class {
|
|
|
611
612
|
for (const channel of this._channelsByTag.values()) {
|
|
612
613
|
channel.destroy?.(err);
|
|
613
614
|
}
|
|
614
|
-
this.
|
|
615
|
+
this._disposed = true;
|
|
615
616
|
this.afterClosed.emit(err);
|
|
616
617
|
this._channelsByLocalId.clear();
|
|
617
618
|
this._channelsByTag.clear();
|
|
618
619
|
}
|
|
619
620
|
async _handleCommand(cmd) {
|
|
620
|
-
if (this.
|
|
621
|
+
if (this._disposed) {
|
|
621
622
|
log3.warn("Received command after destroy", {
|
|
622
623
|
cmd
|
|
623
624
|
}, {
|
|
624
625
|
F: __dxlog_file3,
|
|
625
|
-
L:
|
|
626
|
+
L: 341,
|
|
626
627
|
S: this,
|
|
627
628
|
C: (f, a) => f(...a)
|
|
628
629
|
});
|
|
@@ -632,7 +633,7 @@ var Muxer = class {
|
|
|
632
633
|
if (!this._closing) {
|
|
633
634
|
log3("received peer close, initiating my own graceful close", void 0, {
|
|
634
635
|
F: __dxlog_file3,
|
|
635
|
-
L:
|
|
636
|
+
L: 347,
|
|
636
637
|
S: this,
|
|
637
638
|
C: (f, a) => f(...a)
|
|
638
639
|
});
|
|
@@ -640,7 +641,7 @@ var Muxer = class {
|
|
|
640
641
|
} else {
|
|
641
642
|
log3("received close from peer, already closing", void 0, {
|
|
642
643
|
F: __dxlog_file3,
|
|
643
|
-
L:
|
|
644
|
+
L: 350,
|
|
644
645
|
S: this,
|
|
645
646
|
C: (f, a) => f(...a)
|
|
646
647
|
});
|
|
@@ -669,7 +670,7 @@ var Muxer = class {
|
|
|
669
670
|
tag: stream.tag
|
|
670
671
|
}, {
|
|
671
672
|
F: __dxlog_file3,
|
|
672
|
-
L:
|
|
673
|
+
L: 379,
|
|
673
674
|
S: this,
|
|
674
675
|
C: (f, a) => f(...a)
|
|
675
676
|
});
|
|
@@ -678,16 +679,21 @@ var Muxer = class {
|
|
|
678
679
|
stream.push(cmd.data.data);
|
|
679
680
|
}
|
|
680
681
|
}
|
|
681
|
-
async _sendCommand(cmd, channelId = -1) {
|
|
682
|
+
async _sendCommand(cmd, channelId = -1, timeout = DEFAULT_SEND_COMMAND_TIMEOUT) {
|
|
682
683
|
try {
|
|
683
684
|
const trigger = new Trigger();
|
|
684
685
|
this._balancer.pushData(Command.encode(cmd), trigger, channelId);
|
|
685
|
-
await trigger.wait(
|
|
686
|
+
await trigger.wait({
|
|
687
|
+
timeout
|
|
688
|
+
});
|
|
686
689
|
} catch (err) {
|
|
687
690
|
await this.destroy(err);
|
|
688
691
|
}
|
|
689
692
|
}
|
|
690
693
|
_getOrCreateStream(params) {
|
|
694
|
+
if (this._channelsByTag.size === 0) {
|
|
695
|
+
scheduleTaskInterval(this._ctx, async () => this._emitStats(), STATS_INTERVAL);
|
|
696
|
+
}
|
|
691
697
|
let channel = this._channelsByTag.get(params.tag);
|
|
692
698
|
if (!channel) {
|
|
693
699
|
channel = {
|
|
@@ -709,14 +715,14 @@ var Muxer = class {
|
|
|
709
715
|
}
|
|
710
716
|
return channel;
|
|
711
717
|
}
|
|
712
|
-
async _sendData(channel, data) {
|
|
718
|
+
async _sendData(channel, data, timeout) {
|
|
713
719
|
if (data.length > MAX_SAFE_FRAME_SIZE) {
|
|
714
720
|
log3.warn("frame size exceeds maximum safe value", {
|
|
715
721
|
size: data.length,
|
|
716
722
|
threshold: MAX_SAFE_FRAME_SIZE
|
|
717
723
|
}, {
|
|
718
724
|
F: __dxlog_file3,
|
|
719
|
-
L:
|
|
725
|
+
L: 425,
|
|
720
726
|
S: this,
|
|
721
727
|
C: (f, a) => f(...a)
|
|
722
728
|
});
|
|
@@ -731,7 +737,7 @@ var Muxer = class {
|
|
|
731
737
|
channelId: channel.remoteId,
|
|
732
738
|
data
|
|
733
739
|
}
|
|
734
|
-
}, channel.id);
|
|
740
|
+
}, channel.id, timeout);
|
|
735
741
|
}
|
|
736
742
|
_destroyChannel(channel, err) {
|
|
737
743
|
if (channel.destroy) {
|
|
@@ -741,7 +747,7 @@ var Muxer = class {
|
|
|
741
747
|
this._channelsByTag.delete(channel.tag);
|
|
742
748
|
}
|
|
743
749
|
async _emitStats() {
|
|
744
|
-
if (this.
|
|
750
|
+
if (this._disposed || this._destroying) {
|
|
745
751
|
this._lastStats = void 0;
|
|
746
752
|
this._lastChannelStats.clear();
|
|
747
753
|
return;
|
|
@@ -794,6 +800,8 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
794
800
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
795
801
|
}
|
|
796
802
|
var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/core/mesh/teleport/src/teleport.ts";
|
|
803
|
+
var CONTROL_HEARTBEAT_INTERVAL = 1e4;
|
|
804
|
+
var CONTROL_HEARTBEAT_TIMEOUT = 6e4;
|
|
797
805
|
var Teleport = class {
|
|
798
806
|
constructor({ initiator, localPeerId, remotePeerId }) {
|
|
799
807
|
this._ctx = new Context2({
|
|
@@ -801,7 +809,7 @@ var Teleport = class {
|
|
|
801
809
|
void this.destroy(err).catch(() => {
|
|
802
810
|
log4.error("Error during destroy", err, {
|
|
803
811
|
F: __dxlog_file4,
|
|
804
|
-
L:
|
|
812
|
+
L: 47,
|
|
805
813
|
S: this,
|
|
806
814
|
C: (f, a) => f(...a)
|
|
807
815
|
});
|
|
@@ -810,21 +818,21 @@ var Teleport = class {
|
|
|
810
818
|
});
|
|
811
819
|
this._muxer = new Muxer();
|
|
812
820
|
this._control = new ControlExtension({
|
|
813
|
-
heartbeatInterval:
|
|
814
|
-
heartbeatTimeout:
|
|
821
|
+
heartbeatInterval: CONTROL_HEARTBEAT_INTERVAL,
|
|
822
|
+
heartbeatTimeout: CONTROL_HEARTBEAT_TIMEOUT,
|
|
815
823
|
onTimeout: () => {
|
|
816
824
|
if (this._destroying || this._aborting) {
|
|
817
825
|
return;
|
|
818
826
|
}
|
|
819
|
-
log4("
|
|
827
|
+
log4("abort teleport due to onTimeout in ControlExtension", void 0, {
|
|
820
828
|
F: __dxlog_file4,
|
|
821
|
-
L:
|
|
829
|
+
L: 62,
|
|
822
830
|
S: this,
|
|
823
831
|
C: (f, a) => f(...a)
|
|
824
832
|
});
|
|
825
|
-
this.
|
|
833
|
+
this.abort(new TimeoutError2("control extension")).catch((err) => log4.catch(err, void 0, {
|
|
826
834
|
F: __dxlog_file4,
|
|
827
|
-
L:
|
|
835
|
+
L: 63,
|
|
828
836
|
S: this,
|
|
829
837
|
C: (f, a) => f(...a)
|
|
830
838
|
}));
|
|
@@ -837,7 +845,7 @@ var Teleport = class {
|
|
|
837
845
|
this._aborting = false;
|
|
838
846
|
invariant3(typeof initiator === "boolean", void 0, {
|
|
839
847
|
F: __dxlog_file4,
|
|
840
|
-
L:
|
|
848
|
+
L: 75,
|
|
841
849
|
S: this,
|
|
842
850
|
A: [
|
|
843
851
|
"typeof initiator === 'boolean'",
|
|
@@ -846,7 +854,7 @@ var Teleport = class {
|
|
|
846
854
|
});
|
|
847
855
|
invariant3(PublicKey.isPublicKey(localPeerId), void 0, {
|
|
848
856
|
F: __dxlog_file4,
|
|
849
|
-
L:
|
|
857
|
+
L: 76,
|
|
850
858
|
S: this,
|
|
851
859
|
A: [
|
|
852
860
|
"PublicKey.isPublicKey(localPeerId)",
|
|
@@ -855,7 +863,7 @@ var Teleport = class {
|
|
|
855
863
|
});
|
|
856
864
|
invariant3(PublicKey.isPublicKey(remotePeerId), void 0, {
|
|
857
865
|
F: __dxlog_file4,
|
|
858
|
-
L:
|
|
866
|
+
L: 77,
|
|
859
867
|
S: this,
|
|
860
868
|
A: [
|
|
861
869
|
"PublicKey.isPublicKey(remotePeerId)",
|
|
@@ -870,13 +878,13 @@ var Teleport = class {
|
|
|
870
878
|
name
|
|
871
879
|
}, {
|
|
872
880
|
F: __dxlog_file4,
|
|
873
|
-
L:
|
|
881
|
+
L: 83,
|
|
874
882
|
S: this,
|
|
875
883
|
C: (f, a) => f(...a)
|
|
876
884
|
});
|
|
877
885
|
invariant3(!this._remoteExtensions.has(name), "Remote extension already exists", {
|
|
878
886
|
F: __dxlog_file4,
|
|
879
|
-
L:
|
|
887
|
+
L: 84,
|
|
880
888
|
S: this,
|
|
881
889
|
A: [
|
|
882
890
|
"!this._remoteExtensions.has(name)",
|
|
@@ -897,7 +905,7 @@ var Teleport = class {
|
|
|
897
905
|
if (this._destroying || this._aborting) {
|
|
898
906
|
log4("destroy teleport due to muxer stream close, skipping due to already destroying/aborting", void 0, {
|
|
899
907
|
F: __dxlog_file4,
|
|
900
|
-
L:
|
|
908
|
+
L: 100,
|
|
901
909
|
S: this,
|
|
902
910
|
C: (f, a) => f(...a)
|
|
903
911
|
});
|
|
@@ -920,7 +928,7 @@ var Teleport = class {
|
|
|
920
928
|
channels: stats.channels
|
|
921
929
|
}, {
|
|
922
930
|
F: __dxlog_file4,
|
|
923
|
-
L:
|
|
931
|
+
L: 113,
|
|
924
932
|
S: this,
|
|
925
933
|
C: (f, a) => f(...a)
|
|
926
934
|
});
|
|
@@ -958,7 +966,7 @@ var Teleport = class {
|
|
|
958
966
|
} catch (err2) {
|
|
959
967
|
log4.catch(err2, void 0, {
|
|
960
968
|
F: __dxlog_file4,
|
|
961
|
-
L:
|
|
969
|
+
L: 166,
|
|
962
970
|
S: this,
|
|
963
971
|
C: (f, a) => f(...a)
|
|
964
972
|
});
|
|
@@ -981,7 +989,7 @@ var Teleport = class {
|
|
|
981
989
|
} catch (err2) {
|
|
982
990
|
log4.catch(err2, void 0, {
|
|
983
991
|
F: __dxlog_file4,
|
|
984
|
-
L:
|
|
992
|
+
L: 190,
|
|
985
993
|
S: this,
|
|
986
994
|
C: (f, a) => f(...a)
|
|
987
995
|
});
|
|
@@ -997,7 +1005,7 @@ var Teleport = class {
|
|
|
997
1005
|
name
|
|
998
1006
|
}, {
|
|
999
1007
|
F: __dxlog_file4,
|
|
1000
|
-
L:
|
|
1008
|
+
L: 202,
|
|
1001
1009
|
S: this,
|
|
1002
1010
|
C: (f, a) => f(...a)
|
|
1003
1011
|
});
|
|
@@ -1021,7 +1029,7 @@ var Teleport = class {
|
|
|
1021
1029
|
_setExtension(extensionName, extension) {
|
|
1022
1030
|
invariant3(!extensionName.includes("/"), "Invalid extension name", {
|
|
1023
1031
|
F: __dxlog_file4,
|
|
1024
|
-
L:
|
|
1032
|
+
L: 226,
|
|
1025
1033
|
S: this,
|
|
1026
1034
|
A: [
|
|
1027
1035
|
"!extensionName.includes('/')",
|
|
@@ -1030,7 +1038,7 @@ var Teleport = class {
|
|
|
1030
1038
|
});
|
|
1031
1039
|
invariant3(!this._extensions.has(extensionName), "Extension already exists", {
|
|
1032
1040
|
F: __dxlog_file4,
|
|
1033
|
-
L:
|
|
1041
|
+
L: 227,
|
|
1034
1042
|
S: this,
|
|
1035
1043
|
A: [
|
|
1036
1044
|
"!this._extensions.has(extensionName)",
|
|
@@ -1044,7 +1052,7 @@ var Teleport = class {
|
|
|
1044
1052
|
extensionName
|
|
1045
1053
|
}, {
|
|
1046
1054
|
F: __dxlog_file4,
|
|
1047
|
-
L:
|
|
1055
|
+
L: 232,
|
|
1048
1056
|
S: this,
|
|
1049
1057
|
C: (f, a) => f(...a)
|
|
1050
1058
|
});
|
|
@@ -1056,7 +1064,7 @@ var Teleport = class {
|
|
|
1056
1064
|
createPort: async (channelName, opts) => {
|
|
1057
1065
|
invariant3(!channelName.includes("/"), "Invalid channel name", {
|
|
1058
1066
|
F: __dxlog_file4,
|
|
1059
|
-
L:
|
|
1067
|
+
L: 240,
|
|
1060
1068
|
S: this,
|
|
1061
1069
|
A: [
|
|
1062
1070
|
"!channelName.includes('/')",
|
|
@@ -1068,7 +1076,7 @@ var Teleport = class {
|
|
|
1068
1076
|
createStream: async (channelName, opts) => {
|
|
1069
1077
|
invariant3(!channelName.includes("/"), "Invalid channel name", {
|
|
1070
1078
|
F: __dxlog_file4,
|
|
1071
|
-
L:
|
|
1079
|
+
L: 244,
|
|
1072
1080
|
S: this,
|
|
1073
1081
|
A: [
|
|
1074
1082
|
"!channelName.includes('/')",
|
|
@@ -1088,7 +1096,7 @@ var Teleport = class {
|
|
|
1088
1096
|
extensionName
|
|
1089
1097
|
}, {
|
|
1090
1098
|
F: __dxlog_file4,
|
|
1091
|
-
L:
|
|
1099
|
+
L: 255,
|
|
1092
1100
|
S: this,
|
|
1093
1101
|
C: (f, a) => f(...a)
|
|
1094
1102
|
});
|
|
@@ -1735,4 +1743,4 @@ export {
|
|
|
1735
1743
|
TestExtension,
|
|
1736
1744
|
TestExtensionWithStreams
|
|
1737
1745
|
};
|
|
1738
|
-
//# sourceMappingURL=chunk-
|
|
1746
|
+
//# sourceMappingURL=chunk-3PM5BABC.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/testing/test-builder.ts", "../../../src/teleport.ts", "../../../src/muxing/framer.ts", "../../../src/muxing/muxer.ts", "../../../src/muxing/balancer.ts", "../../../src/testing/test-extension.ts", "../../../src/testing/test-extension-with-streams.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport { type Duplex, pipeline } from 'node:stream';\n\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\n\nimport { Teleport } from '../teleport';\n\ntype CreatePeerOpts<T extends TestPeer> = {\n factory: () => T;\n};\n\nexport class TestBuilder {\n private readonly _peers = new Set<TestPeer>();\n\n createPeer<T extends TestPeer>(opts: CreatePeerOpts<T>): T {\n const peer = opts.factory();\n this._peers.add(peer);\n return peer;\n }\n\n *createPeers<T extends TestPeer>(opts: CreatePeerOpts<T>): Generator<T> {\n while (true) {\n yield this.createPeer(opts);\n }\n }\n\n async destroy() {\n await Promise.all(Array.from(this._peers).map((agent) => agent.destroy()));\n }\n\n async connect(peer1: TestPeer, peer2: TestPeer) {\n invariant(peer1 !== peer2);\n invariant(this._peers.has(peer1));\n invariant(this._peers.has(peer1));\n\n const connection1 = peer1.createConnection({ initiator: true, remotePeerId: peer2.peerId });\n const connection2 = peer2.createConnection({ initiator: false, remotePeerId: peer1.peerId });\n\n pipeStreams(connection1.teleport.stream, connection2.teleport.stream);\n await Promise.all([peer1.openConnection(connection1), peer2.openConnection(connection2)]);\n\n return [connection1, connection2];\n }\n\n async disconnect(peer1: TestPeer, peer2: TestPeer) {\n invariant(peer1 !== peer2);\n invariant(this._peers.has(peer1));\n invariant(this._peers.has(peer1));\n\n const connection1 = Array.from(peer1.connections).find((connection) =>\n connection.remotePeerId.equals(peer2.peerId),\n );\n const connection2 = Array.from(peer2.connections).find((connection) =>\n connection.remotePeerId.equals(peer1.peerId),\n );\n\n invariant(connection1);\n invariant(connection2);\n\n await Promise.all([peer1.closeConnection(connection1), peer2.closeConnection(connection2)]);\n }\n}\n\nexport class TestPeer {\n public readonly connections = new Set<TestConnection>();\n\n constructor(public readonly peerId: PublicKey = PublicKey.random()) {}\n\n protected async onOpen(connection: TestConnection) {}\n protected async onClose(connection: TestConnection) {}\n\n createConnection({ initiator, remotePeerId }: { initiator: boolean; remotePeerId: PublicKey }) {\n const connection = new TestConnection(this.peerId, remotePeerId, initiator);\n this.connections.add(connection);\n return connection;\n }\n\n async openConnection(connection: TestConnection) {\n invariant(this.connections.has(connection));\n await connection.teleport.open();\n await this.onOpen(connection);\n }\n\n async closeConnection(connection: TestConnection) {\n invariant(this.connections.has(connection));\n await this.onClose(connection);\n await connection.teleport.close();\n this.connections.delete(connection);\n }\n\n async destroy() {\n for (const teleport of this.connections) {\n await this.closeConnection(teleport);\n }\n }\n}\n\nconst pipeStreams = (stream1: Duplex, stream2: Duplex) => {\n pipeline(stream1, stream2, (err) => {\n if (err && err.code !== 'ERR_STREAM_PREMATURE_CLOSE') {\n log.catch(err);\n }\n });\n pipeline(stream2, stream1, (err) => {\n if (err && err.code !== 'ERR_STREAM_PREMATURE_CLOSE') {\n log.catch(err);\n }\n });\n};\n\nexport class TestConnection {\n public teleport: Teleport;\n\n constructor(\n public readonly localPeerId: PublicKey,\n public readonly remotePeerId: PublicKey,\n public readonly initiator: boolean,\n ) {\n this.teleport = new Teleport({\n initiator,\n localPeerId,\n remotePeerId,\n });\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { type Duplex } from 'node:stream';\n\nimport {\n asyncTimeout,\n scheduleTaskInterval,\n runInContextAsync,\n synchronized,\n scheduleTask,\n type Event,\n} from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { failUndefined } from '@dxos/debug';\nimport { invariant } from '@dxos/invariant';\nimport { PublicKey } from '@dxos/keys';\nimport { log } from '@dxos/log';\nimport { schema, RpcClosedError, TimeoutError } from '@dxos/protocols';\nimport { type ControlService } from '@dxos/protocols/proto/dxos/mesh/teleport/control';\nimport { createProtoRpcPeer, type ProtoRpcPeer } from '@dxos/rpc';\nimport { Callback } from '@dxos/util';\n\nimport { type CreateChannelOpts, Muxer, type MuxerStats, type RpcPort } from './muxing';\n\nexport type TeleportParams = {\n initiator: boolean;\n localPeerId: PublicKey;\n remotePeerId: PublicKey;\n};\n\nconst CONTROL_HEARTBEAT_INTERVAL = 10_000;\nconst CONTROL_HEARTBEAT_TIMEOUT = 60_000;\n\n/**\n * TODO(burdon): Comment: what is this?\n */\nexport class Teleport {\n public readonly initiator: boolean;\n public readonly localPeerId: PublicKey;\n public readonly remotePeerId: PublicKey;\n\n private readonly _ctx = new Context({\n onError: (err) => {\n void this.destroy(err).catch(() => {\n log.error('Error during destroy', err);\n });\n },\n });\n\n private readonly _muxer = new Muxer();\n\n private readonly _control = new ControlExtension({\n heartbeatInterval: CONTROL_HEARTBEAT_INTERVAL,\n heartbeatTimeout: CONTROL_HEARTBEAT_TIMEOUT,\n onTimeout: () => {\n if (this._destroying || this._aborting) {\n return;\n }\n // TODO(egorgripasov): Evaluate use of abort instead of destroy.\n log('abort teleport due to onTimeout in ControlExtension');\n this.abort(new TimeoutError('control extension')).catch((err) => log.catch(err));\n },\n });\n\n private readonly _extensions = new Map<string, TeleportExtension>();\n private readonly _remoteExtensions = new Set<string>();\n\n private _open = false;\n private _destroying = false;\n private _aborting = false;\n\n constructor({ initiator, localPeerId, remotePeerId }: TeleportParams) {\n invariant(typeof initiator === 'boolean');\n invariant(PublicKey.isPublicKey(localPeerId));\n invariant(PublicKey.isPublicKey(remotePeerId));\n this.initiator = initiator;\n this.localPeerId = localPeerId;\n this.remotePeerId = remotePeerId;\n\n this._control.onExtensionRegistered.set(async (name) => {\n log('remote extension', { name });\n invariant(!this._remoteExtensions.has(name), 'Remote extension already exists');\n this._remoteExtensions.add(name);\n\n if (this._extensions.has(name)) {\n try {\n await this._openExtension(name);\n } catch (err: any) {\n await this.destroy(err);\n }\n }\n });\n\n {\n // Destroy Teleport when the stream is closed.\n this._muxer.stream.on('close', async () => {\n if (this._destroying || this._aborting) {\n log('destroy teleport due to muxer stream close, skipping due to already destroying/aborting');\n return;\n }\n await this.destroy();\n });\n\n this._muxer.stream.on('error', async (err) => {\n await this.destroy(err);\n });\n }\n\n // let last: MuxerStats | undefined;\n this._muxer.statsUpdated.on((stats) => {\n log.trace('dxos.mesh.teleport.stats', {\n localPeerId,\n remotePeerId,\n bytesSent: stats.bytesSent,\n bytesSentRate: stats.bytesSentRate,\n bytesReceived: stats.bytesReceived,\n bytesReceivedRate: stats.bytesReceivedRate,\n channels: stats.channels,\n });\n\n // last = stats;\n });\n }\n\n get stream(): Duplex {\n return this._muxer.stream;\n }\n\n get stats(): Event<MuxerStats> {\n return this._muxer.statsUpdated;\n }\n\n /**\n * Blocks until the handshake is complete.\n */\n async open() {\n this._setExtension('dxos.mesh.teleport.control', this._control);\n await this._openExtension('dxos.mesh.teleport.control');\n this._open = true;\n }\n\n async close(err?: Error) {\n // TODO(dmaretskyi): Try soft close.\n await this.destroy(err);\n }\n\n @synchronized\n async abort(err?: Error) {\n if (this._aborting || this._destroying) {\n return;\n }\n this._aborting = true;\n\n if (this._ctx.disposed) {\n return;\n }\n\n await this._ctx.dispose();\n\n for (const extension of this._extensions.values()) {\n try {\n await extension.onAbort(err);\n } catch (err: any) {\n log.catch(err);\n }\n }\n\n await this._muxer.destroy(err);\n }\n\n @synchronized\n // TODO(nf): analyze callers and consider abort instead\n async destroy(err?: Error) {\n if (this._destroying || this._aborting) {\n return;\n }\n this._destroying = true;\n if (this._ctx.disposed) {\n return;\n }\n\n await this._ctx.dispose();\n\n for (const extension of this._extensions.values()) {\n try {\n await extension.onClose(err);\n } catch (err: any) {\n log.catch(err);\n }\n }\n\n await this._muxer.close();\n }\n\n addExtension(name: string, extension: TeleportExtension) {\n if (!this._open) {\n throw new Error('Not open');\n }\n\n log('addExtension', { name });\n this._setExtension(name, extension);\n\n // Perform the registration in a separate tick as this might block while the remote side is opening the extension.\n scheduleTask(this._ctx, async () => {\n try {\n await this._control.registerExtension(name);\n } catch (err) {\n if (err instanceof RpcClosedError) {\n return;\n }\n throw err;\n }\n });\n\n if (this._remoteExtensions.has(name)) {\n // Open the extension in a separate tick.\n scheduleTask(this._ctx, async () => {\n await this._openExtension(name);\n });\n }\n }\n\n private _setExtension(extensionName: string, extension: TeleportExtension) {\n invariant(!extensionName.includes('/'), 'Invalid extension name');\n invariant(!this._extensions.has(extensionName), 'Extension already exists');\n this._extensions.set(extensionName, extension);\n }\n\n private async _openExtension(extensionName: string) {\n log('open extension', { extensionName });\n const extension = this._extensions.get(extensionName) ?? failUndefined();\n\n const context: ExtensionContext = {\n initiator: this.initiator,\n localPeerId: this.localPeerId,\n remotePeerId: this.remotePeerId,\n createPort: async (channelName: string, opts?: CreateChannelOpts) => {\n invariant(!channelName.includes('/'), 'Invalid channel name');\n return this._muxer.createPort(`${extensionName}/${channelName}`, opts);\n },\n createStream: async (channelName: string, opts?: CreateChannelOpts) => {\n invariant(!channelName.includes('/'), 'Invalid channel name');\n return this._muxer.createStream(`${extensionName}/${channelName}`, opts);\n },\n close: (err) => {\n void runInContextAsync(this._ctx, async () => {\n await this.close(err);\n });\n },\n };\n\n await extension.onOpen(context);\n log('extension opened', { extensionName });\n }\n}\n\nexport type ExtensionContext = {\n /**\n * One of the peers will be designated an initiator.\n */\n initiator: boolean;\n localPeerId: PublicKey;\n remotePeerId: PublicKey;\n createStream(tag: string, opts?: CreateChannelOpts): Promise<Duplex>;\n createPort(tag: string, opts?: CreateChannelOpts): Promise<RpcPort>;\n close(err?: Error): void;\n};\n\nexport interface TeleportExtension {\n onOpen(context: ExtensionContext): Promise<void>;\n onClose(err?: Error): Promise<void>;\n onAbort(err?: Error): Promise<void>;\n}\n\ntype ControlRpcBundle = {\n Control: ControlService;\n};\n\ntype ControlExtensionOpts = {\n heartbeatInterval: number;\n heartbeatTimeout: number;\n onTimeout: () => void;\n};\n\nclass ControlExtension implements TeleportExtension {\n private readonly _ctx = new Context({\n onError: (err) => {\n this._extensionContext.close(err);\n },\n });\n\n public readonly onExtensionRegistered = new Callback<(extensionName: string) => void>();\n\n private _extensionContext!: ExtensionContext;\n private _rpc!: ProtoRpcPeer<{ Control: ControlService }>;\n\n constructor(private readonly opts: ControlExtensionOpts) {}\n\n async registerExtension(name: string) {\n await this._rpc.rpc.Control.registerExtension({ name });\n }\n\n async onOpen(extensionContext: ExtensionContext): Promise<void> {\n this._extensionContext = extensionContext;\n\n // NOTE: Make sure that RPC timeout is greater than the heartbeat timeout.\n // TODO(dmaretskyi): Allow overwriting the timeout on individual RPC calls?\n this._rpc = createProtoRpcPeer<ControlRpcBundle, ControlRpcBundle>({\n requested: {\n Control: schema.getService('dxos.mesh.teleport.control.ControlService'),\n },\n exposed: {\n Control: schema.getService('dxos.mesh.teleport.control.ControlService'),\n },\n handlers: {\n Control: {\n registerExtension: async (request) => {\n this.onExtensionRegistered.call(request.name);\n },\n heartbeat: async (request) => {\n // Ok.\n },\n },\n },\n port: await extensionContext.createPort('rpc', {\n contentType: 'application/x-protobuf; messagType=\"dxos.rpc.Message\"',\n }),\n });\n\n await this._rpc.open();\n\n scheduleTaskInterval(\n this._ctx,\n async () => {\n try {\n await asyncTimeout(this._rpc.rpc.Control.heartbeat(), this.opts.heartbeatTimeout);\n } catch (err: any) {\n this.opts.onTimeout();\n }\n },\n this.opts.heartbeatInterval,\n );\n }\n\n async onClose(err?: Error): Promise<void> {\n await this._ctx.dispose();\n await this._rpc.close();\n }\n\n async onAbort(err?: Error | undefined): Promise<void> {\n await this._ctx.dispose();\n await this._rpc.abort();\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { Duplex } from 'node:stream';\n\nimport { Event } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\n\nimport { type RpcPort } from './rpc-port';\n\nconst FRAME_LENGTH_SIZE = 2;\n\n/**\n * Converts a stream of binary messages into a framed RpcPort.\n * Buffers are written prefixed by their length encoded as a varint.\n */\nexport class Framer {\n // private readonly _tagBuffer = Buffer.alloc(4)\n private _messageCb?: (msg: Uint8Array) => void = undefined;\n private _subscribeCb?: () => void = undefined;\n private _buffer?: Buffer = undefined; // The rest of the bytes from the previous write call.\n private _sendCallbacks: (() => void)[] = [];\n\n private _bytesSent = 0;\n private _bytesReceived = 0;\n\n private _writable = true;\n\n readonly drain = new Event();\n\n // TODO(egorgripasov): Consider using a Transform stream if it provides better backpressure handling.\n private readonly _stream = new Duplex({\n objectMode: false,\n read: () => {\n this._processResponseQueue();\n },\n write: (chunk, encoding, callback) => {\n invariant(!this._subscribeCb, 'Internal Framer bug. Concurrent writes detected.');\n\n this._bytesReceived += chunk.length;\n\n if (this._buffer && this._buffer.length > 0) {\n this._buffer = Buffer.concat([this._buffer, chunk]);\n } else {\n this._buffer = chunk;\n }\n\n if (this._messageCb) {\n this._popFrames();\n callback();\n } else {\n this._subscribeCb = () => {\n // Schedule the processing of the chunk after the peer subscribes to the messages.\n this._popFrames();\n this._subscribeCb = undefined;\n callback();\n };\n }\n },\n });\n\n public readonly port: RpcPort = {\n send: (message) => {\n // log('write', { len: message.length, frame: Buffer.from(message).toString('hex') })\n return new Promise<void>((resolve) => {\n const frame = encodeFrame(message);\n this._bytesSent += frame.length;\n this._writable = this._stream.push(frame);\n if (!this._writable) {\n this._sendCallbacks.push(resolve);\n } else {\n resolve();\n }\n });\n },\n subscribe: (callback) => {\n invariant(!this._messageCb, 'Rpc port already has a message listener.');\n this._messageCb = callback;\n this._subscribeCb?.();\n return () => {\n this._messageCb = undefined;\n };\n },\n };\n\n get stream(): Duplex {\n return this._stream;\n }\n\n get bytesSent() {\n return this._bytesSent;\n }\n\n get bytesReceived() {\n return this._bytesReceived;\n }\n\n get writable() {\n return this._writable;\n }\n\n private _processResponseQueue() {\n const responseQueue = this._sendCallbacks;\n this._sendCallbacks = [];\n this._writable = true;\n this.drain.emit();\n responseQueue.forEach((cb) => cb());\n }\n\n /**\n * Attempts to pop frames from the buffer and call the message callback.\n */\n private _popFrames() {\n let offset = 0;\n while (offset < this._buffer!.length) {\n const frame = decodeFrame(this._buffer!, offset);\n\n if (!frame) {\n break; // Couldn't read frame but there are still bytes left in the buffer.\n }\n offset += frame.bytesConsumed;\n // TODO(dmaretskyi): Possible bug if the peer unsubscribes while we're reading frames.\n // log('read', { len: frame.payload.length, frame: Buffer.from(frame.payload).toString('hex') })\n this._messageCb!(frame.payload);\n }\n\n if (offset < this._buffer!.length) {\n // Save the rest of the bytes for the next write call.\n this._buffer = this._buffer!.subarray(offset);\n } else {\n this._buffer = undefined;\n }\n }\n\n destroy() {\n // TODO(dmaretskyi): Call stream.end() instead?\n if (this._stream.readableLength > 0) {\n log.warn('framer destroyed while there are still read bytes in the buffer.');\n }\n if (this._stream.writableLength > 0) {\n log.warn('framer destroyed while there are still write bytes in the buffer.');\n }\n this._stream.destroy();\n }\n}\n\n/**\n * Attempts to read a frame from the input buffer.\n */\nexport const decodeFrame = (buffer: Buffer, offset: number): { payload: Buffer; bytesConsumed: number } | undefined => {\n if (buffer.length < offset + FRAME_LENGTH_SIZE) {\n // Not enough bytes to read the frame length.\n return undefined;\n }\n\n const frameLength = buffer.readUInt16BE(offset);\n const bytesConsumed = FRAME_LENGTH_SIZE + frameLength;\n\n if (buffer.length < offset + bytesConsumed) {\n // Not enough bytes to read the frame.\n return undefined;\n }\n\n const payload = buffer.subarray(offset + FRAME_LENGTH_SIZE, offset + bytesConsumed);\n\n return {\n payload,\n bytesConsumed,\n };\n};\n\nexport const encodeFrame = (payload: Uint8Array): Buffer => {\n const frame = Buffer.allocUnsafe(FRAME_LENGTH_SIZE + payload.length);\n frame.writeUInt16BE(payload.length, 0);\n frame.set(payload, FRAME_LENGTH_SIZE);\n return frame;\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { Duplex } from 'node:stream';\n\nimport { scheduleTaskInterval, Event, Trigger } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { failUndefined } from '@dxos/debug';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { schema, TimeoutError } from '@dxos/protocols';\nimport { type ConnectionInfo } from '@dxos/protocols/proto/dxos/devtools/swarm';\nimport { Command } from '@dxos/protocols/proto/dxos/mesh/muxer';\n\nimport { Balancer } from './balancer';\nimport { type RpcPort } from './rpc-port';\n\nconst Command = schema.getCodecForType('dxos.mesh.muxer.Command');\n\nconst DEFAULT_SEND_COMMAND_TIMEOUT = 60_000;\nconst DESTROY_COMMAND_SEND_TIMEOUT = 5_000;\n\nexport type CleanupCb = void | (() => void);\n\nexport type CreateChannelOpts = {\n /**\n * MIME type of the wire content.\n *\n * Examples:\n * - application/octet-stream\n * - application/x-protobuf; messageType=\"dxos.rpc.Message\"\n */\n contentType?: string;\n};\n\nexport type MuxerStats = {\n timestamp: number;\n channels: ConnectionInfo.StreamStats[];\n bytesSent: number;\n bytesReceived: number;\n bytesSentRate?: number;\n bytesReceivedRate?: number;\n readBufferSize?: number;\n writeBufferSize?: number;\n};\n\nconst STATS_INTERVAL = 1_000;\nconst MAX_SAFE_FRAME_SIZE = 1_000_000;\nconst SYSTEM_CHANNEL_ID = 0;\nconst GRACEFUL_CLOSE_TIMEOUT = 3_000;\n\ntype Channel = {\n /**\n * Our local channel ID.\n * Incoming Data commands will have this ID.\n */\n id: number;\n tag: string;\n\n /**\n * Remote id is set when we receive an OpenChannel command.\n * The originating Data commands should carry this id.\n */\n remoteId: null | number;\n\n contentType?: string;\n\n /**\n * Send buffer.\n */\n buffer: Uint8Array[];\n\n /**\n * Set when we initialize a NodeJS stream or an RPC port consuming the channel.\n */\n push: null | ((data: Uint8Array) => void);\n\n destroy: null | ((err?: Error) => void);\n\n stats: {\n bytesSent: number;\n bytesReceived: number;\n };\n};\n\ntype CreateChannelInternalParams = {\n tag: string;\n contentType?: string;\n};\n\n/**\n * Channel based multiplexer.\n *\n * Can be used to open a number of channels represented by streams or RPC ports.\n * Performs framing for RPC ports.\n * Will buffer data until the remote peer opens the channel.\n *\n * The API will not advertise channels that as they are opened by the remote peer.\n * A higher level API (could be build on top of this muxer) for channel discovery is required.\n */\nexport class Muxer {\n private readonly _balancer = new Balancer(SYSTEM_CHANNEL_ID);\n private readonly _channelsByLocalId = new Map<number, Channel>();\n private readonly _channelsByTag = new Map<string, Channel>();\n private readonly _ctx = new Context();\n\n private _nextId = 1;\n\n private _closing = false;\n private _destroying = false;\n private _disposed = false;\n\n private _lastStats?: MuxerStats = undefined;\n private readonly _lastChannelStats = new Map<number, Channel['stats']>();\n\n public afterClosed = new Event<Error | undefined>();\n public statsUpdated = new Event<MuxerStats>();\n\n public readonly stream = this._balancer.stream;\n\n constructor() {\n // Add a channel for control messages.\n this._balancer.incomingData.on(async (msg) => {\n await this._handleCommand(Command.decode(msg));\n });\n }\n\n /**\n * Creates a duplex Node.js-style stream.\n * The remote peer is expected to call `createStream` with the same tag.\n * The stream is immediately readable and writable.\n * NOTE: The data will be buffered until the stream is opened remotely with the same tag (may cause a memory leak).\n */\n async createStream(tag: string, opts: CreateChannelOpts = {}): Promise<Duplex> {\n const channel = this._getOrCreateStream({\n tag,\n contentType: opts.contentType,\n });\n invariant(!channel.push, `Channel already open: ${tag}`);\n\n const stream = new Duplex({\n write: (data, encoding, callback) => {\n this._sendData(channel, data)\n .then(() => callback())\n .catch(callback);\n // TODO(dmaretskyi): Should we error if sending data has errored?\n },\n read: () => {}, // No-op. We will push data when we receive it.\n });\n\n channel.push = (data) => {\n channel.stats.bytesReceived += data.length;\n stream.push(data);\n };\n channel.destroy = (err) => {\n // TODO(dmaretskyi): Call stream.end() instead?\n stream.destroy(err);\n };\n\n // NOTE: Make sure channel.push is set before sending the command.\n try {\n await this._sendCommand(\n {\n openChannel: {\n id: channel.id,\n tag: channel.tag,\n contentType: channel.contentType,\n },\n },\n SYSTEM_CHANNEL_ID,\n );\n } catch (err: any) {\n this._destroyChannel(channel, err);\n throw err;\n }\n\n return stream;\n }\n\n /**\n * Creates an RPC port.\n * The remote peer is expected to call `createPort` with the same tag.\n * The port is immediately usable.\n * NOTE: The data will be buffered until the stream is opened remotely with the same tag (may cause a memory leak).\n */\n async createPort(tag: string, opts: CreateChannelOpts = {}): Promise<RpcPort> {\n const channel = this._getOrCreateStream({\n tag,\n contentType: opts.contentType,\n });\n invariant(!channel.push, `Channel already open: ${tag}`);\n\n // We need to buffer incoming data until the port is subscribed to.\n let inboundBuffer: Uint8Array[] = [];\n let callback: ((data: Uint8Array) => void) | undefined;\n\n channel.push = (data) => {\n channel.stats.bytesReceived += data.length;\n if (callback) {\n callback(data);\n } else {\n inboundBuffer.push(data);\n }\n };\n\n const port: RpcPort = {\n send: async (data: Uint8Array, timeout?: number) => {\n await this._sendData(channel, data, timeout);\n // TODO(dmaretskyi): Debugging.\n // appendFileSync('log.json', JSON.stringify(schema.getCodecForType('dxos.rpc.RpcMessage').decode(data), null, 2) + '\\n')\n },\n subscribe: (cb: (data: Uint8Array) => void) => {\n invariant(!callback, 'Only one subscriber is allowed');\n callback = cb;\n for (const data of inboundBuffer) {\n cb(data);\n }\n inboundBuffer = [];\n },\n };\n\n // NOTE: Make sure channel.push is set before sending the command.\n try {\n await this._sendCommand(\n {\n openChannel: {\n id: channel.id,\n tag: channel.tag,\n contentType: channel.contentType,\n },\n },\n SYSTEM_CHANNEL_ID,\n );\n } catch (err: any) {\n this._destroyChannel(channel, err);\n throw err;\n }\n\n return port;\n }\n\n // initiate graceful close\n\n async close(err?: Error) {\n if (this._destroying) {\n log('already destroying, ignoring graceful close request');\n return;\n }\n if (this._closing) {\n log('already closing, ignoring graceful close request');\n return;\n }\n\n this._closing = true;\n\n await this._sendCommand(\n {\n close: {\n error: err?.message,\n },\n },\n SYSTEM_CHANNEL_ID,\n DESTROY_COMMAND_SEND_TIMEOUT,\n ).catch(async (err: any) => {\n log('error sending close command', { err });\n\n await this.dispose(err);\n });\n\n await Promise.race([\n new Promise((_resolve, reject) => {\n setTimeout(() => {\n reject(new TimeoutError('gracefully closing muxer'));\n }, GRACEFUL_CLOSE_TIMEOUT);\n }),\n (async () => {\n await this.dispose(err);\n })(),\n ]);\n }\n\n // force close without confirmation\n\n async destroy(err?: Error) {\n if (this._destroying) {\n log('already destroying, ignoring destroy request');\n return;\n }\n this._destroying = true;\n void this._ctx.dispose();\n if (this._closing) {\n log('destroy cancelling graceful close');\n this._closing = false;\n } else {\n // as a courtesy to the peer, send destroy command but ignore errors sending\n\n await this._sendCommand(\n {\n close: {\n error: err?.message,\n },\n },\n SYSTEM_CHANNEL_ID,\n ).catch(async (err: any) => {\n log('error sending courtesy close command', { err });\n });\n }\n\n this.dispose(err).catch((err) => {\n log('error disposing after destroy', { err });\n });\n }\n\n // complete the termination, graceful or otherwise\n\n async dispose(err?: Error) {\n if (this._disposed) {\n log('already destroyed, ignoring dispose request');\n return;\n }\n\n void this._ctx.dispose();\n\n await this._balancer.destroy();\n\n for (const channel of this._channelsByTag.values()) {\n channel.destroy?.(err);\n }\n this._disposed = true;\n\n this.afterClosed.emit(err);\n\n // Make it easy for GC.\n this._channelsByLocalId.clear();\n this._channelsByTag.clear();\n }\n\n private async _handleCommand(cmd: Command) {\n if (this._disposed) {\n log.warn('Received command after destroy', { cmd });\n return;\n }\n\n if (cmd.close) {\n if (!this._closing) {\n log('received peer close, initiating my own graceful close');\n await this.close();\n } else {\n log('received close from peer, already closing');\n }\n\n return;\n }\n\n if (cmd.openChannel) {\n const channel = this._getOrCreateStream({\n tag: cmd.openChannel.tag,\n contentType: cmd.openChannel.contentType,\n });\n channel.remoteId = cmd.openChannel.id;\n\n // Flush any buffered data.\n for (const data of channel.buffer) {\n await this._sendCommand(\n {\n data: {\n channelId: channel.remoteId!,\n data,\n },\n },\n channel.id,\n );\n }\n channel.buffer = [];\n } else if (cmd.data) {\n const stream = this._channelsByLocalId.get(cmd.data.channelId) ?? failUndefined();\n if (!stream.push) {\n log.warn('Received data for channel before it was opened', { tag: stream.tag });\n return;\n }\n stream.push(cmd.data.data);\n }\n }\n\n private async _sendCommand(cmd: Command, channelId = -1, timeout = DEFAULT_SEND_COMMAND_TIMEOUT) {\n try {\n const trigger = new Trigger<void>();\n this._balancer.pushData(Command.encode(cmd), trigger, channelId);\n await trigger.wait({ timeout });\n } catch (err: any) {\n await this.destroy(err);\n }\n }\n\n private _getOrCreateStream(params: CreateChannelInternalParams): Channel {\n if (this._channelsByTag.size === 0) {\n scheduleTaskInterval(this._ctx, async () => this._emitStats(), STATS_INTERVAL);\n }\n let channel = this._channelsByTag.get(params.tag);\n if (!channel) {\n channel = {\n id: this._nextId++,\n remoteId: null,\n tag: params.tag,\n contentType: params.contentType,\n buffer: [],\n push: null,\n destroy: null,\n stats: {\n bytesSent: 0,\n bytesReceived: 0,\n },\n };\n this._channelsByTag.set(channel.tag, channel);\n this._channelsByLocalId.set(channel.id, channel);\n this._balancer.addChannel(channel.id);\n }\n\n return channel;\n }\n\n private async _sendData(channel: Channel, data: Uint8Array, timeout?: number): Promise<void> {\n if (data.length > MAX_SAFE_FRAME_SIZE) {\n log.warn('frame size exceeds maximum safe value', { size: data.length, threshold: MAX_SAFE_FRAME_SIZE });\n }\n\n channel.stats.bytesSent += data.length;\n if (channel.remoteId === null) {\n // Remote side has not opened the channel yet.\n channel.buffer.push(data);\n return;\n }\n await this._sendCommand(\n {\n data: {\n channelId: channel.remoteId,\n data,\n },\n },\n channel.id,\n timeout,\n );\n }\n\n private _destroyChannel(channel: Channel, err?: Error) {\n if (channel.destroy) {\n channel.destroy(err);\n }\n\n this._channelsByLocalId.delete(channel.id);\n this._channelsByTag.delete(channel.tag);\n }\n\n private async _emitStats() {\n if (this._disposed || this._destroying) {\n this._lastStats = undefined;\n this._lastChannelStats.clear();\n return;\n }\n\n const bytesSent = this._balancer.bytesSent;\n const bytesReceived = this._balancer.bytesReceived;\n\n const now = Date.now();\n const interval = this._lastStats ? (now - this._lastStats.timestamp) / 1_000 : 0;\n const calculateThroughput = (current: Channel['stats'], last: Channel['stats'] | undefined) =>\n last\n ? {\n bytesSentRate: interval ? (current.bytesSent - last.bytesSent) / interval : undefined,\n bytesReceivedRate: interval ? (current.bytesReceived - last.bytesReceived) / interval : undefined,\n }\n : {};\n\n this._lastStats = {\n timestamp: now,\n channels: Array.from(this._channelsByTag.values()).map((channel) => {\n const stats: ConnectionInfo.StreamStats = {\n id: channel.id,\n tag: channel.tag,\n contentType: channel.contentType,\n writeBufferSize: channel.buffer.length,\n bytesSent: channel.stats.bytesSent,\n bytesReceived: channel.stats.bytesReceived,\n ...calculateThroughput(channel.stats, this._lastChannelStats.get(channel.id)),\n };\n\n this._lastChannelStats.set(channel.id, stats);\n return stats;\n }),\n bytesSent,\n bytesReceived,\n ...calculateThroughput({ bytesSent, bytesReceived }, this._lastStats),\n readBufferSize: this._balancer.stream.readableLength,\n writeBufferSize: this._balancer.stream.writableLength,\n };\n\n this.statsUpdated.emit(this._lastStats);\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport * as varint from 'varint';\n\nimport { type Trigger, Event } from '@dxos/async';\nimport { log } from '@dxos/log';\n\nimport { Framer } from './framer';\n\nconst MAX_CHUNK_SIZE = 8192;\n\ntype Chunk = {\n chunk: Uint8Array;\n channelId: number;\n dataLength?: number;\n};\n\ntype ChunkEnvelope = {\n msg: Buffer;\n trigger?: Trigger;\n};\n\ntype ChannelBuffer = {\n buffer: Buffer;\n msgLength: number;\n};\n\n/**\n * Load balancer for handling asynchronous calls from multiple channels.\n *\n * Manages a queue of calls from different channels and ensures that the calls\n * are processed in a balanced manner in a round-robin fashion.\n */\nexport class Balancer {\n private _lastCallerIndex = 0;\n private _channels: number[] = [];\n\n private readonly _framer = new Framer();\n // TODO(egorgripasov): Will cause a memory leak if channels do not appreciate the backpressure.\n private readonly _sendBuffers: Map<number, ChunkEnvelope[]> = new Map();\n private readonly _receiveBuffers = new Map<number, ChannelBuffer>();\n\n public incomingData = new Event<Uint8Array>();\n public readonly stream = this._framer.stream;\n\n constructor(private readonly _sysChannelId: number) {\n this._channels.push(_sysChannelId);\n\n // Handle incoming messages.\n this._framer.port.subscribe(this._processIncomingMessage.bind(this));\n }\n\n get bytesSent() {\n return this._framer.bytesSent;\n }\n\n get bytesReceived() {\n return this._framer.bytesReceived;\n }\n\n get buffersCount() {\n return this._sendBuffers.size;\n }\n\n addChannel(channel: number) {\n this._channels.push(channel);\n }\n\n pushData(data: Uint8Array, trigger: Trigger, channelId: number) {\n const noCalls = this._sendBuffers.size === 0;\n\n if (!this._channels.includes(channelId)) {\n throw new Error(`Unknown channel ${channelId}`);\n }\n\n if (!this._sendBuffers.has(channelId)) {\n this._sendBuffers.set(channelId, []);\n }\n\n const sendBuffer = this._sendBuffers.get(channelId)!;\n\n const chunks = [];\n for (let idx = 0; idx < data.length; idx += MAX_CHUNK_SIZE) {\n chunks.push(data.subarray(idx, idx + MAX_CHUNK_SIZE));\n }\n\n chunks.forEach((chunk, index) => {\n const msg = encodeChunk({\n chunk,\n channelId,\n dataLength: index === 0 ? data.length : undefined,\n });\n sendBuffer.push({ msg, trigger: index === chunks.length - 1 ? trigger : undefined });\n });\n\n // Start processing calls if this is the first call.\n if (noCalls) {\n this._sendChunk().catch((err) => log.catch(err));\n }\n }\n\n destroy() {\n if (this._sendBuffers.size !== 0) {\n log.warn('destroying balancer with pending calls');\n }\n this._sendBuffers.clear();\n this._framer.destroy();\n }\n\n private _processIncomingMessage(msg: Uint8Array) {\n const { channelId, dataLength, chunk } = decodeChunk(msg, (channelId) => !this._receiveBuffers.has(channelId));\n if (!this._receiveBuffers.has(channelId)) {\n if (chunk.length < dataLength!) {\n this._receiveBuffers.set(channelId, {\n buffer: Buffer.from(chunk),\n msgLength: dataLength!,\n });\n } else {\n this.incomingData.emit(chunk);\n }\n } else {\n const channelBuffer = this._receiveBuffers.get(channelId)!;\n channelBuffer.buffer = Buffer.concat([channelBuffer.buffer, chunk]);\n if (channelBuffer.buffer.length < channelBuffer.msgLength) {\n return;\n }\n const msg = channelBuffer.buffer;\n this._receiveBuffers.delete(channelId);\n this.incomingData.emit(msg);\n }\n }\n\n private _getNextCallerId() {\n if (this._sendBuffers.has(this._sysChannelId)) {\n return this._sysChannelId;\n }\n\n const index = this._lastCallerIndex;\n this._lastCallerIndex = (this._lastCallerIndex + 1) % this._channels.length;\n\n return this._channels[index];\n }\n\n private _getNextChunk(): ChunkEnvelope {\n let chunk;\n while (!chunk) {\n const channelId = this._getNextCallerId();\n const sendBuffer = this._sendBuffers.get(channelId);\n if (!sendBuffer) {\n continue;\n }\n\n chunk = sendBuffer.shift();\n if (sendBuffer.length === 0) {\n this._sendBuffers.delete(channelId);\n }\n }\n return chunk;\n }\n\n private async _sendChunk() {\n if (this._sendBuffers.size === 0) {\n return;\n }\n\n if (!this._framer.writable) {\n await this._framer.drain.waitForCount(1);\n }\n\n const chunk = this._getNextChunk();\n\n try {\n await this._framer.port.send(chunk.msg);\n chunk.trigger?.wake();\n } catch (err: any) {\n chunk.trigger?.throw(err);\n }\n\n await this._sendChunk();\n }\n}\n\nexport const encodeChunk = ({ channelId, dataLength, chunk }: Chunk): Buffer => {\n const channelTagLength = varint.encodingLength(channelId);\n const dataLengthLength = dataLength ? varint.encodingLength(dataLength) : 0;\n const message = Buffer.allocUnsafe(channelTagLength + dataLengthLength + chunk.length);\n varint.encode(channelId, message);\n if (dataLength) {\n varint.encode(dataLength, message, channelTagLength);\n }\n message.set(chunk, channelTagLength + dataLengthLength);\n return message;\n};\n\nexport const decodeChunk = (data: Uint8Array, withLength: (channelId: number) => boolean): Chunk => {\n const channelId = varint.decode(data);\n let dataLength: number | undefined;\n let offset = varint.decode.bytes;\n\n if (withLength(channelId)) {\n dataLength = varint.decode(data, offset);\n offset += varint.decode.bytes;\n }\n\n const chunk = data.subarray(offset);\n\n return { channelId, dataLength, chunk };\n};\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { asyncTimeout, Trigger } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { schema } from '@dxos/protocols';\nimport { type TestService } from '@dxos/protocols/proto/example/testing/rpc';\nimport { createProtoRpcPeer, type ProtoRpcPeer } from '@dxos/rpc';\n\nimport { type ExtensionContext, type TeleportExtension } from '../teleport';\n\ninterface TestExtensionCallbacks {\n onOpen?: () => Promise<void>;\n onClose?: () => Promise<void>;\n onAbort?: () => Promise<void>;\n}\n\nexport class TestExtension implements TeleportExtension {\n public readonly open = new Trigger();\n public readonly closed = new Trigger();\n public readonly aborted = new Trigger();\n public extensionContext: ExtensionContext | undefined;\n private _rpc!: ProtoRpcPeer<{ TestService: TestService }>;\n\n constructor(public readonly callbacks: TestExtensionCallbacks = {}) {}\n\n get remotePeerId() {\n return this.extensionContext?.remotePeerId;\n }\n\n async onOpen(context: ExtensionContext) {\n log('onOpen', { localPeerId: context.localPeerId, remotePeerId: context.remotePeerId });\n this.extensionContext = context;\n this._rpc = createProtoRpcPeer<{ TestService: TestService }, { TestService: TestService }>({\n port: await context.createPort('rpc', {\n contentType: 'application/x-protobuf; messageType=\"dxos.rpc.Message\"',\n }),\n requested: {\n TestService: schema.getService('example.testing.rpc.TestService'),\n },\n exposed: {\n TestService: schema.getService('example.testing.rpc.TestService'),\n },\n handlers: {\n TestService: {\n voidCall: async (request) => {\n // Ok.\n },\n testCall: async (request) => {\n return {\n data: request.data,\n };\n },\n },\n },\n timeout: 2000,\n });\n\n await this._rpc.open();\n await this.callbacks.onOpen?.();\n\n this.open.wake();\n }\n\n async onClose(err?: Error) {\n log('onClose', { err });\n await this.callbacks.onClose?.();\n this.closed.wake();\n await this._rpc?.close();\n }\n\n async onAbort(err?: Error) {\n log('onAbort', { err });\n await this.callbacks.onAbort?.();\n this.aborted.wake();\n await this._rpc?.abort();\n }\n\n async test(message = 'test') {\n await this.open.wait({ timeout: 1500 });\n const res = await asyncTimeout(this._rpc.rpc.TestService.testCall({ data: message }), 1500);\n invariant(res.data === message);\n }\n\n /**\n * Force-close the connection.\n */\n async closeConnection(err?: Error) {\n this.extensionContext?.close(err);\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport { randomBytes } from 'node:crypto';\nimport { type Duplex } from 'node:stream';\n\nimport { Trigger } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { schema } from '@dxos/protocols';\nimport { type TestServiceWithStreams } from '@dxos/protocols/proto/example/testing/rpc';\nimport { createProtoRpcPeer, type ProtoRpcPeer } from '@dxos/rpc';\n\nimport { type ExtensionContext, type TeleportExtension } from '../teleport';\n\ninterface TestExtensionWithStreamsCallbacks {\n onOpen?: () => Promise<void>;\n onClose?: () => Promise<void>;\n onAbort?: () => Promise<void>;\n}\n\nexport class TestExtensionWithStreams implements TeleportExtension {\n public readonly open = new Trigger();\n public readonly closed = new Trigger();\n public readonly aborted = new Trigger();\n private readonly _streams = new Map<string, TestStream>();\n\n public extensionContext: ExtensionContext | undefined;\n private _rpc!: ProtoRpcPeer<{ TestServiceWithStreams: TestServiceWithStreams }>;\n\n constructor(public readonly callbacks: TestExtensionWithStreamsCallbacks = {}) {}\n\n get remotePeerId() {\n return this.extensionContext?.remotePeerId;\n }\n\n private async _openStream(streamTag: string, interval = 5, chunkSize = 2048) {\n invariant(!this._streams.has(streamTag), `Stream already exists: ${streamTag}`);\n\n const networkStream = await this.extensionContext!.createStream(streamTag, {\n contentType: 'application/x-test-stream',\n });\n\n const streamEntry: TestStream = {\n networkStream,\n bytesSent: 0,\n bytesReceived: 0,\n sendErrors: 0,\n receiveErrors: 0,\n startTimestamp: Date.now(),\n };\n\n const pushChunk = () => {\n streamEntry.timer = setTimeout(() => {\n const chunk = randomBytes(chunkSize);\n\n if (\n !networkStream.write(chunk, 'binary', (err) => {\n if (!err) {\n streamEntry.bytesSent += chunk.length;\n } else {\n streamEntry.sendErrors += 1;\n }\n })\n ) {\n networkStream.once('drain', pushChunk);\n } else {\n process.nextTick(pushChunk);\n }\n }, interval);\n };\n\n pushChunk();\n\n this._streams.set(streamTag, streamEntry);\n\n networkStream.on('data', (data) => {\n streamEntry.bytesReceived += data.length;\n });\n\n networkStream.on('error', (err) => {\n streamEntry.receiveErrors += 1;\n });\n\n networkStream.on('close', () => {\n networkStream.removeAllListeners();\n });\n\n streamEntry.reportingTimer = setInterval(() => {\n const { bytesSent, bytesReceived, sendErrors, receiveErrors } = streamEntry;\n // log.info('stream stats', { streamTag, bytesSent, bytesReceived, sendErrors, receiveErrors });\n log.trace('dxos.test.stream-stats', {\n streamTag,\n bytesSent,\n bytesReceived,\n sendErrors,\n receiveErrors,\n from: this.extensionContext?.localPeerId,\n to: this.extensionContext?.remotePeerId,\n });\n }, 100);\n }\n\n private _closeStream(streamTag: string): Stats {\n invariant(this._streams.has(streamTag), `Stream does not exist: ${streamTag}`);\n\n const stream = this._streams.get(streamTag)!;\n\n clearTimeout(stream.timer);\n clearTimeout(stream.reportingTimer);\n\n const { bytesSent, bytesReceived, sendErrors, receiveErrors, startTimestamp } = stream;\n\n stream.networkStream.destroy();\n this._streams.delete(streamTag);\n\n return {\n bytesSent,\n bytesReceived,\n sendErrors,\n receiveErrors,\n runningTime: Date.now() - (startTimestamp ?? 0),\n };\n }\n\n async onOpen(context: ExtensionContext) {\n log('onOpen', { localPeerId: context.localPeerId, remotePeerId: context.remotePeerId });\n this.extensionContext = context;\n this._rpc = createProtoRpcPeer<\n { TestServiceWithStreams: TestServiceWithStreams },\n { TestServiceWithStreams: TestServiceWithStreams }\n >({\n port: await context.createPort('rpc', {\n contentType: 'application/x-protobuf; messageType=\"dxos.rpc.Message\"',\n }),\n requested: {\n TestServiceWithStreams: schema.getService('example.testing.rpc.TestServiceWithStreams'),\n },\n exposed: {\n TestServiceWithStreams: schema.getService('example.testing.rpc.TestServiceWithStreams'),\n },\n handlers: {\n TestServiceWithStreams: {\n requestTestStream: async (request) => {\n const { data: streamTag, streamLoadInterval, streamLoadChunkSize } = request;\n\n await this._openStream(streamTag, streamLoadInterval, streamLoadChunkSize);\n\n return {\n data: streamTag,\n };\n },\n closeTestStream: async (request) => {\n const streamTag = request.data;\n const { bytesSent, bytesReceived, sendErrors, receiveErrors, runningTime } = this._closeStream(streamTag);\n\n return {\n data: streamTag,\n bytesSent,\n bytesReceived,\n sendErrors,\n receiveErrors,\n runningTime,\n };\n },\n },\n },\n timeout: 2000,\n });\n\n await this._rpc.open();\n await this.callbacks.onOpen?.();\n\n this.open.wake();\n }\n\n async onClose(err?: Error) {\n log('onClose', { err });\n await this.callbacks.onClose?.();\n this.closed.wake();\n for (const [streamTag, stream] of Object.entries(this._streams)) {\n log('closing stream', { streamTag });\n clearTimeout(stream.interval);\n stream.networkStream.destroy();\n }\n await this._rpc?.close();\n }\n\n async onAbort(err?: Error) {\n log('onAbort', { err });\n await this.callbacks.onAbort?.();\n this.aborted.wake();\n await this._rpc?.abort();\n }\n\n async addNewStream(streamLoadInterval: number, streamLoadChunkSize: number, streamTag?: string): Promise<string> {\n await this.open.wait({ timeout: 1500 });\n if (!streamTag) {\n streamTag = `stream-${randomBytes(4).toString('hex')}`;\n }\n const { data } = await this._rpc.rpc.TestServiceWithStreams.requestTestStream({\n data: streamTag,\n streamLoadInterval,\n streamLoadChunkSize,\n });\n invariant(data === streamTag);\n\n await this._openStream(streamTag, streamLoadInterval, streamLoadChunkSize);\n return streamTag;\n }\n\n async closeStream(streamTag: string): Promise<TestStreamStats> {\n await this.open.wait({ timeout: 1500 });\n const { data, bytesSent, bytesReceived, sendErrors, receiveErrors, runningTime } =\n await this._rpc.rpc.TestServiceWithStreams.closeTestStream({\n data: streamTag,\n });\n\n invariant(data === streamTag);\n\n const local = this._closeStream(streamTag);\n\n return {\n streamTag,\n stats: {\n local,\n remote: {\n bytesSent,\n bytesReceived,\n sendErrors,\n receiveErrors,\n runningTime,\n },\n },\n };\n }\n\n /**\n * Force-close the connection.\n */\n async closeConnection(err?: Error) {\n this.extensionContext?.close(err);\n }\n}\n\ntype Stats = {\n bytesSent: number;\n bytesReceived: number;\n sendErrors: number;\n receiveErrors: number;\n runningTime: number;\n};\n\nexport type TestStreamStats = {\n streamTag: string;\n stats: {\n local: Stats;\n remote: Stats;\n };\n};\n\ntype TestStream = {\n networkStream: Duplex;\n bytesSent: number;\n bytesReceived: number;\n sendErrors: number;\n receiveErrors: number;\n timer?: NodeJS.Timer;\n startTimestamp?: number;\n reportingTimer?: NodeJS.Timer;\n};\n"],
|
|
5
|
+
"mappings": ";;;AAIA,SAAsBA,gBAAgB;AAEtC,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,OAAAA,YAAW;;;ACFpB,SACEC,cACAC,wBAAAA,uBACAC,mBACAC,cACAC,oBAEK;AACP,SAASC,WAAAA,gBAAe;AACxB,SAASC,iBAAAA,sBAAqB;AAC9B,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,iBAAiB;AAC1B,SAASC,OAAAA,YAAW;AACpB,SAASC,UAAAA,SAAQC,gBAAgBC,gBAAAA,qBAAoB;AAErD,SAASC,0BAA6C;AACtD,SAASC,gBAAgB;;;AClBzB,SAASC,cAAc;AAEvB,SAASC,aAAa;AACtB,SAASC,iBAAiB;AAC1B,SAASC,WAAW;;AAIpB,IAAMC,oBAAoB;AAMnB,IAAMC,SAAN,MAAMA;EAAN;AAEGC;sBAAyCC;AACzCC,wBAA4BD;AAC5BE,mBAAmBF;AACnBG,0BAAiC,CAAA;AAEjCC,sBAAa;AACbC,0BAAiB;AAEjBC,qBAAY;AAEXC,iBAAQ,IAAIb,MAAAA;AAGJc;mBAAU,IAAIf,OAAO;MACpCgB,YAAY;MACZC,MAAM,MAAA;AACJ,aAAKC,sBAAqB;MAC5B;MACAC,OAAO,CAACC,OAAOC,UAAUC,aAAAA;AACvBpB,kBAAU,CAAC,KAAKM,cAAc,oDAAA;;;;;;;;;AAE9B,aAAKI,kBAAkBQ,MAAMG;AAE7B,YAAI,KAAKd,WAAW,KAAKA,QAAQc,SAAS,GAAG;AAC3C,eAAKd,UAAUe,OAAOC,OAAO;YAAC,KAAKhB;YAASW;WAAM;QACpD,OAAO;AACL,eAAKX,UAAUW;QACjB;AAEA,YAAI,KAAKd,YAAY;AACnB,eAAKoB,WAAU;AACfJ,mBAAAA;QACF,OAAO;AACL,eAAKd,eAAe,MAAA;AAElB,iBAAKkB,WAAU;AACf,iBAAKlB,eAAeD;AACpBe,qBAAAA;UACF;QACF;MACF;IACF,CAAA;AAEgBK,gBAAgB;MAC9BC,MAAM,CAACC,YAAAA;AAEL,eAAO,IAAIC,QAAc,CAACC,YAAAA;AACxB,gBAAMC,QAAQC,YAAYJ,OAAAA;AAC1B,eAAKlB,cAAcqB,MAAMT;AACzB,eAAKV,YAAY,KAAKE,QAAQmB,KAAKF,KAAAA;AACnC,cAAI,CAAC,KAAKnB,WAAW;AACnB,iBAAKH,eAAewB,KAAKH,OAAAA;UAC3B,OAAO;AACLA,oBAAAA;UACF;QACF,CAAA;MACF;MACAI,WAAW,CAACb,aAAAA;AACVpB,kBAAU,CAAC,KAAKI,YAAY,4CAAA;;;;;;;;;AAC5B,aAAKA,aAAagB;AAClB,aAAKd,eAAY;AACjB,eAAO,MAAA;AACL,eAAKF,aAAaC;QACpB;MACF;IACF;;EAEA,IAAI6B,SAAiB;AACnB,WAAO,KAAKrB;EACd;EAEA,IAAIsB,YAAY;AACd,WAAO,KAAK1B;EACd;EAEA,IAAI2B,gBAAgB;AAClB,WAAO,KAAK1B;EACd;EAEA,IAAI2B,WAAW;AACb,WAAO,KAAK1B;EACd;EAEQK,wBAAwB;AAC9B,UAAMsB,gBAAgB,KAAK9B;AAC3B,SAAKA,iBAAiB,CAAA;AACtB,SAAKG,YAAY;AACjB,SAAKC,MAAM2B,KAAI;AACfD,kBAAcE,QAAQ,CAACC,OAAOA,GAAAA,CAAAA;EAChC;;;;EAKQjB,aAAa;AACnB,QAAIkB,SAAS;AACb,WAAOA,SAAS,KAAKnC,QAASc,QAAQ;AACpC,YAAMS,QAAQa,YAAY,KAAKpC,SAAUmC,MAAAA;AAEzC,UAAI,CAACZ,OAAO;AACV;MACF;AACAY,gBAAUZ,MAAMc;AAGhB,WAAKxC,WAAY0B,MAAMe,OAAO;IAChC;AAEA,QAAIH,SAAS,KAAKnC,QAASc,QAAQ;AAEjC,WAAKd,UAAU,KAAKA,QAASuC,SAASJ,MAAAA;IACxC,OAAO;AACL,WAAKnC,UAAUF;IACjB;EACF;EAEA0C,UAAU;AAER,QAAI,KAAKlC,QAAQmC,iBAAiB,GAAG;AACnC/C,UAAIgD,KAAK,oEAAA,QAAA;;;;;;IACX;AACA,QAAI,KAAKpC,QAAQqC,iBAAiB,GAAG;AACnCjD,UAAIgD,KAAK,qEAAA,QAAA;;;;;;IACX;AACA,SAAKpC,QAAQkC,QAAO;EACtB;AACF;AAKO,IAAMJ,cAAc,CAACQ,QAAgBT,WAAAA;AAC1C,MAAIS,OAAO9B,SAASqB,SAASxC,mBAAmB;AAE9C,WAAOG;EACT;AAEA,QAAM+C,cAAcD,OAAOE,aAAaX,MAAAA;AACxC,QAAME,gBAAgB1C,oBAAoBkD;AAE1C,MAAID,OAAO9B,SAASqB,SAASE,eAAe;AAE1C,WAAOvC;EACT;AAEA,QAAMwC,UAAUM,OAAOL,SAASJ,SAASxC,mBAAmBwC,SAASE,aAAAA;AAErE,SAAO;IACLC;IACAD;EACF;AACF;AAEO,IAAMb,cAAc,CAACc,YAAAA;AAC1B,QAAMf,QAAQR,OAAOgC,YAAYpD,oBAAoB2C,QAAQxB,MAAM;AACnES,QAAMyB,cAAcV,QAAQxB,QAAQ,CAAA;AACpCS,QAAM0B,IAAIX,SAAS3C,iBAAAA;AACnB,SAAO4B;AACT;;;AC9KA,SAAS2B,UAAAA,eAAc;AAEvB,SAASC,sBAAsBC,SAAAA,QAAOC,eAAe;AACrD,SAASC,eAAe;AACxB,SAASC,qBAAqB;AAC9B,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,OAAAA,YAAW;AACpB,SAASC,QAAQC,oBAAoB;;;ACPrC,YAAYC,YAAY;AAExB,SAAuBC,SAAAA,cAAa;AACpC,SAASC,OAAAA,YAAW;;AAIpB,IAAMC,iBAAiB;AAwBhB,IAAMC,WAAN,MAAMA;EAYXC,YAA6BC,eAAuB;yBAAvBA;SAXrBC,mBAAmB;SACnBC,YAAsB,CAAA;SAEbC,UAAU,IAAIC,OAAAA;SAEdC,eAA6C,oBAAIC,IAAAA;SACjDC,kBAAkB,oBAAID,IAAAA;SAEhCE,eAAe,IAAIC,OAAAA;SACVC,SAAS,KAAKP,QAAQO;AAGpC,SAAKR,UAAUS,KAAKX,aAAAA;AAGpB,SAAKG,QAAQS,KAAKC,UAAU,KAAKC,wBAAwBC,KAAK,IAAI,CAAA;EACpE;EAEA,IAAIC,YAAY;AACd,WAAO,KAAKb,QAAQa;EACtB;EAEA,IAAIC,gBAAgB;AAClB,WAAO,KAAKd,QAAQc;EACtB;EAEA,IAAIC,eAAe;AACjB,WAAO,KAAKb,aAAac;EAC3B;EAEAC,WAAWC,SAAiB;AAC1B,SAAKnB,UAAUS,KAAKU,OAAAA;EACtB;EAEAC,SAASC,MAAkBC,SAAkBC,WAAmB;AAC9D,UAAMC,UAAU,KAAKrB,aAAac,SAAS;AAE3C,QAAI,CAAC,KAAKjB,UAAUyB,SAASF,SAAAA,GAAY;AACvC,YAAM,IAAIG,MAAM,mBAAmBH,SAAAA,EAAW;IAChD;AAEA,QAAI,CAAC,KAAKpB,aAAawB,IAAIJ,SAAAA,GAAY;AACrC,WAAKpB,aAAayB,IAAIL,WAAW,CAAA,CAAE;IACrC;AAEA,UAAMM,aAAa,KAAK1B,aAAa2B,IAAIP,SAAAA;AAEzC,UAAMQ,SAAS,CAAA;AACf,aAASC,MAAM,GAAGA,MAAMX,KAAKY,QAAQD,OAAOrC,gBAAgB;AAC1DoC,aAAOtB,KAAKY,KAAKa,SAASF,KAAKA,MAAMrC,cAAAA,CAAAA;IACvC;AAEAoC,WAAOI,QAAQ,CAACC,OAAOC,UAAAA;AACrB,YAAMC,MAAMC,YAAY;QACtBH;QACAb;QACAiB,YAAYH,UAAU,IAAIhB,KAAKY,SAASQ;MAC1C,CAAA;AACAZ,iBAAWpB,KAAK;QAAE6B;QAAKhB,SAASe,UAAUN,OAAOE,SAAS,IAAIX,UAAUmB;MAAU,CAAA;IACpF,CAAA;AAGA,QAAIjB,SAAS;AACX,WAAKkB,WAAU,EAAGC,MAAM,CAACC,QAAQC,KAAIF,MAAMC,KAAAA,QAAAA;;;;;;IAC7C;EACF;EAEAE,UAAU;AACR,QAAI,KAAK3C,aAAac,SAAS,GAAG;AAChC4B,MAAAA,KAAIE,KAAK,0CAAA,QAAA;;;;;;IACX;AACA,SAAK5C,aAAa6C,MAAK;AACvB,SAAK/C,QAAQ6C,QAAO;EACtB;EAEQlC,wBAAwB0B,KAAiB;AAC/C,UAAM,EAAEf,WAAWiB,YAAYJ,MAAK,IAAKa,YAAYX,KAAK,CAACf,eAAc,CAAC,KAAKlB,gBAAgBsB,IAAIJ,UAAAA,CAAAA;AACnG,QAAI,CAAC,KAAKlB,gBAAgBsB,IAAIJ,SAAAA,GAAY;AACxC,UAAIa,MAAMH,SAASO,YAAa;AAC9B,aAAKnC,gBAAgBuB,IAAIL,WAAW;UAClC2B,QAAQC,OAAOC,KAAKhB,KAAAA;UACpBiB,WAAWb;QACb,CAAA;MACF,OAAO;AACL,aAAKlC,aAAagD,KAAKlB,KAAAA;MACzB;IACF,OAAO;AACL,YAAMmB,gBAAgB,KAAKlD,gBAAgByB,IAAIP,SAAAA;AAC/CgC,oBAAcL,SAASC,OAAOK,OAAO;QAACD,cAAcL;QAAQd;OAAM;AAClE,UAAImB,cAAcL,OAAOjB,SAASsB,cAAcF,WAAW;AACzD;MACF;AACA,YAAMf,OAAMiB,cAAcL;AAC1B,WAAK7C,gBAAgBoD,OAAOlC,SAAAA;AAC5B,WAAKjB,aAAagD,KAAKhB,IAAAA;IACzB;EACF;EAEQoB,mBAAmB;AACzB,QAAI,KAAKvD,aAAawB,IAAI,KAAK7B,aAAa,GAAG;AAC7C,aAAO,KAAKA;IACd;AAEA,UAAMuC,QAAQ,KAAKtC;AACnB,SAAKA,oBAAoB,KAAKA,mBAAmB,KAAK,KAAKC,UAAUiC;AAErE,WAAO,KAAKjC,UAAUqC,KAAAA;EACxB;EAEQsB,gBAA+B;AACrC,QAAIvB;AACJ,WAAO,CAACA,OAAO;AACb,YAAMb,YAAY,KAAKmC,iBAAgB;AACvC,YAAM7B,aAAa,KAAK1B,aAAa2B,IAAIP,SAAAA;AACzC,UAAI,CAACM,YAAY;AACf;MACF;AAEAO,cAAQP,WAAW+B,MAAK;AACxB,UAAI/B,WAAWI,WAAW,GAAG;AAC3B,aAAK9B,aAAasD,OAAOlC,SAAAA;MAC3B;IACF;AACA,WAAOa;EACT;EAEA,MAAcM,aAAa;AACzB,QAAI,KAAKvC,aAAac,SAAS,GAAG;AAChC;IACF;AAEA,QAAI,CAAC,KAAKhB,QAAQ4D,UAAU;AAC1B,YAAM,KAAK5D,QAAQ6D,MAAMC,aAAa,CAAA;IACxC;AAEA,UAAM3B,QAAQ,KAAKuB,cAAa;AAEhC,QAAI;AACF,YAAM,KAAK1D,QAAQS,KAAKsD,KAAK5B,MAAME,GAAG;AACtCF,YAAMd,SAAS2C,KAAAA;IACjB,SAASrB,KAAU;AACjBR,YAAMd,SAAS4C,MAAMtB,GAAAA;IACvB;AAEA,UAAM,KAAKF,WAAU;EACvB;AACF;AAEO,IAAMH,cAAc,CAAC,EAAEhB,WAAWiB,YAAYJ,MAAK,MAAS;AACjE,QAAM+B,mBAA0BC,sBAAe7C,SAAAA;AAC/C,QAAM8C,mBAAmB7B,aAAoB4B,sBAAe5B,UAAAA,IAAc;AAC1E,QAAM8B,UAAUnB,OAAOoB,YAAYJ,mBAAmBE,mBAAmBjC,MAAMH,MAAM;AACrFuC,EAAOC,cAAOlD,WAAW+C,OAAAA;AACzB,MAAI9B,YAAY;AACdgC,IAAOC,cAAOjC,YAAY8B,SAASH,gBAAAA;EACrC;AACAG,UAAQ1C,IAAIQ,OAAO+B,mBAAmBE,gBAAAA;AACtC,SAAOC;AACT;AAEO,IAAMrB,cAAc,CAAC5B,MAAkBqD,eAAAA;AAC5C,QAAMnD,YAAmBoD,cAAOtD,IAAAA;AAChC,MAAImB;AACJ,MAAIoC,SAAgBD,cAAOE;AAE3B,MAAIH,WAAWnD,SAAAA,GAAY;AACzBiB,iBAAoBmC,cAAOtD,MAAMuD,MAAAA;AACjCA,cAAiBD,cAAOE;EAC1B;AAEA,QAAMzC,QAAQf,KAAKa,SAAS0C,MAAAA;AAE5B,SAAO;IAAErD;IAAWiB;IAAYJ;EAAM;AACxC;;;;AD/LA,IAAM0C,UAAUC,OAAOC,gBAAgB,yBAAA;AAEvC,IAAMC,+BAA+B;AACrC,IAAMC,+BAA+B;AA0BrC,IAAMC,iBAAiB;AACvB,IAAMC,sBAAsB;AAC5B,IAAMC,oBAAoB;AAC1B,IAAMC,yBAAyB;AAmDxB,IAAMC,QAAN,MAAMA;EAoBXC,cAAc;AAnBGC,qBAAY,IAAIC,SAASL,iBAAAA;AACzBM,8BAAqB,oBAAIC,IAAAA;AACzBC,0BAAiB,oBAAID,IAAAA;AACrBE,gBAAO,IAAIC,QAAAA;AAEpBC,mBAAU;AAEVC,oBAAW;AACXC,uBAAc;AACdC,qBAAY;AAEZC,sBAA0BC;AACjBC,6BAAoB,oBAAIV,IAAAA;AAElCW,uBAAc,IAAIC,OAAAA;AAClBC,wBAAe,IAAID,OAAAA;AAEVE,kBAAS,KAAKjB,UAAUiB;AAItC,SAAKjB,UAAUkB,aAAaC,GAAG,OAAOC,QAAAA;AACpC,YAAM,KAAKC,eAAehC,QAAQiC,OAAOF,GAAAA,CAAAA;IAC3C,CAAA;EACF;;;;;;;EAQA,MAAMG,aAAaC,KAAaC,OAA0B,CAAC,GAAoB;AAC7E,UAAMC,UAAU,KAAKC,mBAAmB;MACtCH;MACAI,aAAaH,KAAKG;IACpB,CAAA;AACAC,IAAAA,WAAU,CAACH,QAAQI,MAAM,yBAAyBN,GAAAA,IAAK;;;;;;;;;AAEvD,UAAMP,SAAS,IAAIc,QAAO;MACxBC,OAAO,CAACC,MAAMC,UAAUC,aAAAA;AACtB,aAAKC,UAAUV,SAASO,IAAAA,EACrBI,KAAK,MAAMF,SAAAA,CAAAA,EACXG,MAAMH,QAAAA;MAEX;MACAI,MAAM,MAAA;MAAO;IACf,CAAA;AAEAb,YAAQI,OAAO,CAACG,SAAAA;AACdP,cAAQc,MAAMC,iBAAiBR,KAAKS;AACpCzB,aAAOa,KAAKG,IAAAA;IACd;AACAP,YAAQiB,UAAU,CAACC,QAAAA;AAEjB3B,aAAO0B,QAAQC,GAAAA;IACjB;AAGA,QAAI;AACF,YAAM,KAAKC,aACT;QACEC,aAAa;UACXC,IAAIrB,QAAQqB;UACZvB,KAAKE,QAAQF;UACbI,aAAaF,QAAQE;QACvB;MACF,GACAhC,iBAAAA;IAEJ,SAASgD,KAAU;AACjB,WAAKI,gBAAgBtB,SAASkB,GAAAA;AAC9B,YAAMA;IACR;AAEA,WAAO3B;EACT;;;;;;;EAQA,MAAMgC,WAAWzB,KAAaC,OAA0B,CAAC,GAAqB;AAC5E,UAAMC,UAAU,KAAKC,mBAAmB;MACtCH;MACAI,aAAaH,KAAKG;IACpB,CAAA;AACAC,IAAAA,WAAU,CAACH,QAAQI,MAAM,yBAAyBN,GAAAA,IAAK;;;;;;;;;AAGvD,QAAI0B,gBAA8B,CAAA;AAClC,QAAIf;AAEJT,YAAQI,OAAO,CAACG,SAAAA;AACdP,cAAQc,MAAMC,iBAAiBR,KAAKS;AACpC,UAAIP,UAAU;AACZA,iBAASF,IAAAA;MACX,OAAO;AACLiB,sBAAcpB,KAAKG,IAAAA;MACrB;IACF;AAEA,UAAMkB,OAAgB;MACpBC,MAAM,OAAOnB,MAAkBoB,YAAAA;AAC7B,cAAM,KAAKjB,UAAUV,SAASO,MAAMoB,OAAAA;MAGtC;MACAC,WAAW,CAACC,OAAAA;AACV1B,QAAAA,WAAU,CAACM,UAAU,kCAAA;;;;;;;;;AACrBA,mBAAWoB;AACX,mBAAWtB,QAAQiB,eAAe;AAChCK,aAAGtB,IAAAA;QACL;AACAiB,wBAAgB,CAAA;MAClB;IACF;AAGA,QAAI;AACF,YAAM,KAAKL,aACT;QACEC,aAAa;UACXC,IAAIrB,QAAQqB;UACZvB,KAAKE,QAAQF;UACbI,aAAaF,QAAQE;QACvB;MACF,GACAhC,iBAAAA;IAEJ,SAASgD,KAAU;AACjB,WAAKI,gBAAgBtB,SAASkB,GAAAA;AAC9B,YAAMA;IACR;AAEA,WAAOO;EACT;;EAIA,MAAMK,MAAMZ,KAAa;AACvB,QAAI,KAAKnC,aAAa;AACpBgD,MAAAA,KAAI,uDAAA,QAAA;;;;;;AACJ;IACF;AACA,QAAI,KAAKjD,UAAU;AACjBiD,MAAAA,KAAI,oDAAA,QAAA;;;;;;AACJ;IACF;AAEA,SAAKjD,WAAW;AAEhB,UAAM,KAAKqC,aACT;MACEW,OAAO;QACLE,OAAOd,KAAKe;MACd;IACF,GACA/D,mBACAH,4BAAAA,EACA6C,MAAM,OAAOM,SAAAA;AACba,MAAAA,KAAI,+BAA+B;QAAEb,KAAAA;MAAI,GAAA;;;;;;AAEzC,YAAM,KAAKgB,QAAQhB,IAAAA;IACrB,CAAA;AAEA,UAAMiB,QAAQC,KAAK;MACjB,IAAID,QAAQ,CAACE,UAAUC,WAAAA;AACrBC,mBAAW,MAAA;AACTD,iBAAO,IAAIE,aAAa,0BAAA,CAAA;QAC1B,GAAGrE,sBAAAA;MACL,CAAA;OACC,YAAA;AACC,cAAM,KAAK+D,QAAQhB,GAAAA;MACrB,GAAA;KACD;EACH;;EAIA,MAAMD,QAAQC,KAAa;AACzB,QAAI,KAAKnC,aAAa;AACpBgD,MAAAA,KAAI,gDAAA,QAAA;;;;;;AACJ;IACF;AACA,SAAKhD,cAAc;AACnB,SAAK,KAAKJ,KAAKuD,QAAO;AACtB,QAAI,KAAKpD,UAAU;AACjBiD,MAAAA,KAAI,qCAAA,QAAA;;;;;;AACJ,WAAKjD,WAAW;IAClB,OAAO;AAGL,YAAM,KAAKqC,aACT;QACEW,OAAO;UACLE,OAAOd,KAAKe;QACd;MACF,GACA/D,iBAAAA,EACA0C,MAAM,OAAOM,SAAAA;AACba,QAAAA,KAAI,wCAAwC;UAAEb,KAAAA;QAAI,GAAA;;;;;;MACpD,CAAA;IACF;AAEA,SAAKgB,QAAQhB,GAAAA,EAAKN,MAAM,CAACM,SAAAA;AACvBa,MAAAA,KAAI,iCAAiC;QAAEb,KAAAA;MAAI,GAAA;;;;;;IAC7C,CAAA;EACF;;EAIA,MAAMgB,QAAQhB,KAAa;AACzB,QAAI,KAAKlC,WAAW;AAClB+C,MAAAA,KAAI,+CAAA,QAAA;;;;;;AACJ;IACF;AAEA,SAAK,KAAKpD,KAAKuD,QAAO;AAEtB,UAAM,KAAK5D,UAAU2C,QAAO;AAE5B,eAAWjB,WAAW,KAAKtB,eAAe+D,OAAM,GAAI;AAClDzC,cAAQiB,UAAUC,GAAAA;IACpB;AACA,SAAKlC,YAAY;AAEjB,SAAKI,YAAYsD,KAAKxB,GAAAA;AAGtB,SAAK1C,mBAAmBmE,MAAK;AAC7B,SAAKjE,eAAeiE,MAAK;EAC3B;EAEA,MAAchD,eAAeiD,KAAc;AACzC,QAAI,KAAK5D,WAAW;AAClB+C,MAAAA,KAAIc,KAAK,kCAAkC;QAAED;MAAI,GAAA;;;;;;AACjD;IACF;AAEA,QAAIA,IAAId,OAAO;AACb,UAAI,CAAC,KAAKhD,UAAU;AAClBiD,QAAAA,KAAI,yDAAA,QAAA;;;;;;AACJ,cAAM,KAAKD,MAAK;MAClB,OAAO;AACLC,QAAAA,KAAI,6CAAA,QAAA;;;;;;MACN;AAEA;IACF;AAEA,QAAIa,IAAIxB,aAAa;AACnB,YAAMpB,UAAU,KAAKC,mBAAmB;QACtCH,KAAK8C,IAAIxB,YAAYtB;QACrBI,aAAa0C,IAAIxB,YAAYlB;MAC/B,CAAA;AACAF,cAAQ8C,WAAWF,IAAIxB,YAAYC;AAGnC,iBAAWd,QAAQP,QAAQ+C,QAAQ;AACjC,cAAM,KAAK5B,aACT;UACEZ,MAAM;YACJyC,WAAWhD,QAAQ8C;YACnBvC;UACF;QACF,GACAP,QAAQqB,EAAE;MAEd;AACArB,cAAQ+C,SAAS,CAAA;IACnB,WAAWH,IAAIrC,MAAM;AACnB,YAAMhB,SAAS,KAAKf,mBAAmByE,IAAIL,IAAIrC,KAAKyC,SAAS,KAAKE,cAAAA;AAClE,UAAI,CAAC3D,OAAOa,MAAM;AAChB2B,QAAAA,KAAIc,KAAK,kDAAkD;UAAE/C,KAAKP,OAAOO;QAAI,GAAA;;;;;;AAC7E;MACF;AACAP,aAAOa,KAAKwC,IAAIrC,KAAKA,IAAI;IAC3B;EACF;EAEA,MAAcY,aAAayB,KAAcI,YAAY,IAAIrB,UAAU7D,8BAA8B;AAC/F,QAAI;AACF,YAAMqF,UAAU,IAAIC,QAAAA;AACpB,WAAK9E,UAAU+E,SAAS1F,QAAQ2F,OAAOV,GAAAA,GAAMO,SAASH,SAAAA;AACtD,YAAMG,QAAQI,KAAK;QAAE5B;MAAQ,CAAA;IAC/B,SAAST,KAAU;AACjB,YAAM,KAAKD,QAAQC,GAAAA;IACrB;EACF;EAEQjB,mBAAmBuD,QAA8C;AACvE,QAAI,KAAK9E,eAAe+E,SAAS,GAAG;AAClCC,2BAAqB,KAAK/E,MAAM,YAAY,KAAKgF,WAAU,GAAI3F,cAAAA;IACjE;AACA,QAAIgC,UAAU,KAAKtB,eAAeuE,IAAIO,OAAO1D,GAAG;AAChD,QAAI,CAACE,SAAS;AACZA,gBAAU;QACRqB,IAAI,KAAKxC;QACTiE,UAAU;QACVhD,KAAK0D,OAAO1D;QACZI,aAAasD,OAAOtD;QACpB6C,QAAQ,CAAA;QACR3C,MAAM;QACNa,SAAS;QACTH,OAAO;UACL8C,WAAW;UACX7C,eAAe;QACjB;MACF;AACA,WAAKrC,eAAemF,IAAI7D,QAAQF,KAAKE,OAAAA;AACrC,WAAKxB,mBAAmBqF,IAAI7D,QAAQqB,IAAIrB,OAAAA;AACxC,WAAK1B,UAAUwF,WAAW9D,QAAQqB,EAAE;IACtC;AAEA,WAAOrB;EACT;EAEA,MAAcU,UAAUV,SAAkBO,MAAkBoB,SAAiC;AAC3F,QAAIpB,KAAKS,SAAS/C,qBAAqB;AACrC8D,MAAAA,KAAIc,KAAK,yCAAyC;QAAEY,MAAMlD,KAAKS;QAAQ+C,WAAW9F;MAAoB,GAAA;;;;;;IACxG;AAEA+B,YAAQc,MAAM8C,aAAarD,KAAKS;AAChC,QAAIhB,QAAQ8C,aAAa,MAAM;AAE7B9C,cAAQ+C,OAAO3C,KAAKG,IAAAA;AACpB;IACF;AACA,UAAM,KAAKY,aACT;MACEZ,MAAM;QACJyC,WAAWhD,QAAQ8C;QACnBvC;MACF;IACF,GACAP,QAAQqB,IACRM,OAAAA;EAEJ;EAEQL,gBAAgBtB,SAAkBkB,KAAa;AACrD,QAAIlB,QAAQiB,SAAS;AACnBjB,cAAQiB,QAAQC,GAAAA;IAClB;AAEA,SAAK1C,mBAAmBwF,OAAOhE,QAAQqB,EAAE;AACzC,SAAK3C,eAAesF,OAAOhE,QAAQF,GAAG;EACxC;EAEA,MAAc6D,aAAa;AACzB,QAAI,KAAK3E,aAAa,KAAKD,aAAa;AACtC,WAAKE,aAAaC;AAClB,WAAKC,kBAAkBwD,MAAK;AAC5B;IACF;AAEA,UAAMiB,YAAY,KAAKtF,UAAUsF;AACjC,UAAM7C,gBAAgB,KAAKzC,UAAUyC;AAErC,UAAMkD,MAAMC,KAAKD,IAAG;AACpB,UAAME,WAAW,KAAKlF,cAAcgF,MAAM,KAAKhF,WAAWmF,aAAa,MAAQ;AAC/E,UAAMC,sBAAsB,CAACC,SAA2BC,SACtDA,OACI;MACEC,eAAeL,YAAYG,QAAQV,YAAYW,KAAKX,aAAaO,WAAWjF;MAC5EuF,mBAAmBN,YAAYG,QAAQvD,gBAAgBwD,KAAKxD,iBAAiBoD,WAAWjF;IAC1F,IACA,CAAC;AAEP,SAAKD,aAAa;MAChBmF,WAAWH;MACXS,UAAUC,MAAMC,KAAK,KAAKlG,eAAe+D,OAAM,CAAA,EAAIoC,IAAI,CAAC7E,YAAAA;AACtD,cAAMc,QAAoC;UACxCO,IAAIrB,QAAQqB;UACZvB,KAAKE,QAAQF;UACbI,aAAaF,QAAQE;UACrB4E,iBAAiB9E,QAAQ+C,OAAO/B;UAChC4C,WAAW5D,QAAQc,MAAM8C;UACzB7C,eAAef,QAAQc,MAAMC;UAC7B,GAAGsD,oBAAoBrE,QAAQc,OAAO,KAAK3B,kBAAkB8D,IAAIjD,QAAQqB,EAAE,CAAA;QAC7E;AAEA,aAAKlC,kBAAkB0E,IAAI7D,QAAQqB,IAAIP,KAAAA;AACvC,eAAOA;MACT,CAAA;MACA8C;MACA7C;MACA,GAAGsD,oBAAoB;QAAET;QAAW7C;MAAc,GAAG,KAAK9B,UAAU;MACpE8F,gBAAgB,KAAKzG,UAAUiB,OAAOyF;MACtCF,iBAAiB,KAAKxG,UAAUiB,OAAO0F;IACzC;AAEA,SAAK3F,aAAaoD,KAAK,KAAKzD,UAAU;EACxC;AACF;;;;;;;;;;;;;;AFndA,IAAMiG,6BAA6B;AACnC,IAAMC,4BAA4B;AAK3B,IAAMC,WAAN,MAAMA;EAmCXC,YAAY,EAAEC,WAAWC,aAAaC,aAAY,GAAoB;AA9BrDC,gBAAO,IAAIC,SAAQ;MAClCC,SAAS,CAACC,QAAAA;AACR,aAAK,KAAKC,QAAQD,GAAAA,EAAKE,MAAM,MAAA;AAC3BC,UAAAA,KAAIC,MAAM,wBAAwBJ,KAAAA;;;;;;QACpC,CAAA;MACF;IACF,CAAA;AAEiBK,kBAAS,IAAIC,MAAAA;AAEbC,oBAAW,IAAIC,iBAAiB;MAC/CC,mBAAmBnB;MACnBoB,kBAAkBnB;MAClBoB,WAAW,MAAA;AACT,YAAI,KAAKC,eAAe,KAAKC,WAAW;AACtC;QACF;AAEAV,QAAAA,KAAI,uDAAA,QAAA;;;;;;AACJ,aAAKW,MAAM,IAAIC,cAAa,mBAAA,CAAA,EAAsBb,MAAM,CAACF,QAAQG,KAAID,MAAMF,KAAAA,QAAAA;;;;;;MAC7E;IACF,CAAA;AAEiBgB,uBAAc,oBAAIC,IAAAA;AAClBC,6BAAoB,oBAAIC,IAAAA;AAEjCC,iBAAQ;AACRR,uBAAc;AACdC,qBAAY;AAGlBQ,IAAAA,WAAU,OAAO3B,cAAc,WAAA,QAAA;;;;;;;;;AAC/B2B,IAAAA,WAAUC,UAAUC,YAAY5B,WAAAA,GAAAA,QAAAA;;;;;;;;;AAChC0B,IAAAA,WAAUC,UAAUC,YAAY3B,YAAAA,GAAAA,QAAAA;;;;;;;;;AAChC,SAAKF,YAAYA;AACjB,SAAKC,cAAcA;AACnB,SAAKC,eAAeA;AAEpB,SAAKW,SAASiB,sBAAsBC,IAAI,OAAOC,SAAAA;AAC7CvB,MAAAA,KAAI,oBAAoB;QAAEuB;MAAK,GAAA;;;;;;AAC/BL,MAAAA,WAAU,CAAC,KAAKH,kBAAkBS,IAAID,IAAAA,GAAO,mCAAA;;;;;;;;;AAC7C,WAAKR,kBAAkBU,IAAIF,IAAAA;AAE3B,UAAI,KAAKV,YAAYW,IAAID,IAAAA,GAAO;AAC9B,YAAI;AACF,gBAAM,KAAKG,eAAeH,IAAAA;QAC5B,SAAS1B,KAAU;AACjB,gBAAM,KAAKC,QAAQD,GAAAA;QACrB;MACF;IACF,CAAA;AAEA;AAEE,WAAKK,OAAOyB,OAAOC,GAAG,SAAS,YAAA;AAC7B,YAAI,KAAKnB,eAAe,KAAKC,WAAW;AACtCV,UAAAA,KAAI,2FAAA,QAAA;;;;;;AACJ;QACF;AACA,cAAM,KAAKF,QAAO;MACpB,CAAA;AAEA,WAAKI,OAAOyB,OAAOC,GAAG,SAAS,OAAO/B,QAAAA;AACpC,cAAM,KAAKC,QAAQD,GAAAA;MACrB,CAAA;IACF;AAGA,SAAKK,OAAO2B,aAAaD,GAAG,CAACE,UAAAA;AAC3B9B,MAAAA,KAAI+B,MAAM,4BAA4B;QACpCvC;QACAC;QACAuC,WAAWF,MAAME;QACjBC,eAAeH,MAAMG;QACrBC,eAAeJ,MAAMI;QACrBC,mBAAmBL,MAAMK;QACzBC,UAAUN,MAAMM;MAClB,GAAA;;;;;;IAGF,CAAA;EACF;EAEA,IAAIT,SAAiB;AACnB,WAAO,KAAKzB,OAAOyB;EACrB;EAEA,IAAIG,QAA2B;AAC7B,WAAO,KAAK5B,OAAO2B;EACrB;;;;EAKA,MAAMQ,OAAO;AACX,SAAKC,cAAc,8BAA8B,KAAKlC,QAAQ;AAC9D,UAAM,KAAKsB,eAAe,4BAAA;AAC1B,SAAKT,QAAQ;EACf;EAEA,MAAMsB,MAAM1C,KAAa;AAEvB,UAAM,KAAKC,QAAQD,GAAAA;EACrB;EAEA,MACMc,MAAMd,KAAa;AACvB,QAAI,KAAKa,aAAa,KAAKD,aAAa;AACtC;IACF;AACA,SAAKC,YAAY;AAEjB,QAAI,KAAKhB,KAAK8C,UAAU;AACtB;IACF;AAEA,UAAM,KAAK9C,KAAK+C,QAAO;AAEvB,eAAWC,aAAa,KAAK7B,YAAY8B,OAAM,GAAI;AACjD,UAAI;AACF,cAAMD,UAAUE,QAAQ/C,GAAAA;MAC1B,SAASA,MAAU;AACjBG,QAAAA,KAAID,MAAMF,MAAAA,QAAAA;;;;;;MACZ;IACF;AAEA,UAAM,KAAKK,OAAOJ,QAAQD,GAAAA;EAC5B;EAEA,MAEMC,QAAQD,KAAa;AACzB,QAAI,KAAKY,eAAe,KAAKC,WAAW;AACtC;IACF;AACA,SAAKD,cAAc;AACnB,QAAI,KAAKf,KAAK8C,UAAU;AACtB;IACF;AAEA,UAAM,KAAK9C,KAAK+C,QAAO;AAEvB,eAAWC,aAAa,KAAK7B,YAAY8B,OAAM,GAAI;AACjD,UAAI;AACF,cAAMD,UAAUG,QAAQhD,GAAAA;MAC1B,SAASA,MAAU;AACjBG,QAAAA,KAAID,MAAMF,MAAAA,QAAAA;;;;;;MACZ;IACF;AAEA,UAAM,KAAKK,OAAOqC,MAAK;EACzB;EAEAO,aAAavB,MAAcmB,WAA8B;AACvD,QAAI,CAAC,KAAKzB,OAAO;AACf,YAAM,IAAI8B,MAAM,UAAA;IAClB;AAEA/C,IAAAA,KAAI,gBAAgB;MAAEuB;IAAK,GAAA;;;;;;AAC3B,SAAKe,cAAcf,MAAMmB,SAAAA;AAGzBM,iBAAa,KAAKtD,MAAM,YAAA;AACtB,UAAI;AACF,cAAM,KAAKU,SAAS6C,kBAAkB1B,IAAAA;MACxC,SAAS1B,KAAK;AACZ,YAAIA,eAAeqD,gBAAgB;AACjC;QACF;AACA,cAAMrD;MACR;IACF,CAAA;AAEA,QAAI,KAAKkB,kBAAkBS,IAAID,IAAAA,GAAO;AAEpCyB,mBAAa,KAAKtD,MAAM,YAAA;AACtB,cAAM,KAAKgC,eAAeH,IAAAA;MAC5B,CAAA;IACF;EACF;EAEQe,cAAca,eAAuBT,WAA8B;AACzExB,IAAAA,WAAU,CAACiC,cAAcC,SAAS,GAAA,GAAM,0BAAA;;;;;;;;;AACxClC,IAAAA,WAAU,CAAC,KAAKL,YAAYW,IAAI2B,aAAAA,GAAgB,4BAAA;;;;;;;;;AAChD,SAAKtC,YAAYS,IAAI6B,eAAeT,SAAAA;EACtC;EAEA,MAAchB,eAAeyB,eAAuB;AAClDnD,IAAAA,KAAI,kBAAkB;MAAEmD;IAAc,GAAA;;;;;;AACtC,UAAMT,YAAY,KAAK7B,YAAYwC,IAAIF,aAAAA,KAAkBG,eAAAA;AAEzD,UAAMC,UAA4B;MAChChE,WAAW,KAAKA;MAChBC,aAAa,KAAKA;MAClBC,cAAc,KAAKA;MACnB+D,YAAY,OAAOC,aAAqBC,SAAAA;AACtCxC,QAAAA,WAAU,CAACuC,YAAYL,SAAS,GAAA,GAAM,wBAAA;;;;;;;;;AACtC,eAAO,KAAKlD,OAAOsD,WAAW,GAAGL,aAAAA,IAAiBM,WAAAA,IAAeC,IAAAA;MACnE;MACAC,cAAc,OAAOF,aAAqBC,SAAAA;AACxCxC,QAAAA,WAAU,CAACuC,YAAYL,SAAS,GAAA,GAAM,wBAAA;;;;;;;;;AACtC,eAAO,KAAKlD,OAAOyD,aAAa,GAAGR,aAAAA,IAAiBM,WAAAA,IAAeC,IAAAA;MACrE;MACAnB,OAAO,CAAC1C,QAAAA;AACN,aAAK+D,kBAAkB,KAAKlE,MAAM,YAAA;AAChC,gBAAM,KAAK6C,MAAM1C,GAAAA;QACnB,CAAA;MACF;IACF;AAEA,UAAM6C,UAAUmB,OAAON,OAAAA;AACvBvD,IAAAA,KAAI,oBAAoB;MAAEmD;IAAc,GAAA;;;;;;EAC1C;AACF;;EA5GGW;GA9GUzE,SAAAA,WAAAA,SAAAA,IAAAA;;EAsIVyE;GAtIUzE,SAAAA,WAAAA,WAAAA,IAAAA;AAwPb,IAAMgB,mBAAN,MAAMA;EAYJf,YAA6BoE,MAA4B;gBAA5BA;SAXZhE,OAAO,IAAIC,SAAQ;MAClCC,SAAS,CAACC,QAAAA;AACR,aAAKkE,kBAAkBxB,MAAM1C,GAAAA;MAC/B;IACF,CAAA;SAEgBwB,wBAAwB,IAAI2C,SAAAA;EAKc;EAE1D,MAAMf,kBAAkB1B,MAAc;AACpC,UAAM,KAAK0C,KAAKC,IAAIC,QAAQlB,kBAAkB;MAAE1B;IAAK,CAAA;EACvD;EAEA,MAAMsC,OAAOO,kBAAmD;AAC9D,SAAKL,oBAAoBK;AAIzB,SAAKH,OAAOI,mBAAuD;MACjEC,WAAW;QACTH,SAASI,QAAOC,WAAW,2CAAA;MAC7B;MACAC,SAAS;QACPN,SAASI,QAAOC,WAAW,2CAAA;MAC7B;MACAE,UAAU;QACRP,SAAS;UACPlB,mBAAmB,OAAO0B,YAAAA;AACxB,iBAAKtD,sBAAsBuD,KAAKD,QAAQpD,IAAI;UAC9C;UACAsD,WAAW,OAAOF,YAAAA;UAElB;QACF;MACF;MACAG,MAAM,MAAMV,iBAAiBZ,WAAW,OAAO;QAC7CuB,aAAa;MACf,CAAA;IACF,CAAA;AAEA,UAAM,KAAKd,KAAK5B,KAAI;AAEpB2C,IAAAA,sBACE,KAAKtF,MACL,YAAA;AACE,UAAI;AACF,cAAMuF,aAAa,KAAKhB,KAAKC,IAAIC,QAAQU,UAAS,GAAI,KAAKnB,KAAKnD,gBAAgB;MAClF,SAASV,KAAU;AACjB,aAAK6D,KAAKlD,UAAS;MACrB;IACF,GACA,KAAKkD,KAAKpD,iBAAiB;EAE/B;EAEA,MAAMuC,QAAQhD,KAA4B;AACxC,UAAM,KAAKH,KAAK+C,QAAO;AACvB,UAAM,KAAKwB,KAAK1B,MAAK;EACvB;EAEA,MAAMK,QAAQ/C,KAAwC;AACpD,UAAM,KAAKH,KAAK+C,QAAO;AACvB,UAAM,KAAKwB,KAAKtD,MAAK;EACvB;AACF;;;;ADnVO,IAAMuE,cAAN,MAAMA;EAAN;AACYC,kBAAS,oBAAIC,IAAAA;;EAE9BC,WAA+BC,MAA4B;AACzD,UAAMC,OAAOD,KAAKE,QAAO;AACzB,SAAKL,OAAOM,IAAIF,IAAAA;AAChB,WAAOA;EACT;EAEA,CAACG,YAAgCJ,MAAuC;AACtE,WAAO,MAAM;AACX,YAAM,KAAKD,WAAWC,IAAAA;IACxB;EACF;EAEA,MAAMK,UAAU;AACd,UAAMC,QAAQC,IAAIC,MAAMC,KAAK,KAAKZ,MAAM,EAAEa,IAAI,CAACC,UAAUA,MAAMN,QAAO,CAAA,CAAA;EACxE;EAEA,MAAMO,QAAQC,OAAiBC,OAAiB;AAC9CC,IAAAA,WAAUF,UAAUC,OAAAA,QAAAA;;;;;;;;;AACpBC,IAAAA,WAAU,KAAKlB,OAAOmB,IAAIH,KAAAA,GAAAA,QAAAA;;;;;;;;;AAC1BE,IAAAA,WAAU,KAAKlB,OAAOmB,IAAIH,KAAAA,GAAAA,QAAAA;;;;;;;;;AAE1B,UAAMI,cAAcJ,MAAMK,iBAAiB;MAAEC,WAAW;MAAMC,cAAcN,MAAMO;IAAO,CAAA;AACzF,UAAMC,cAAcR,MAAMI,iBAAiB;MAAEC,WAAW;MAAOC,cAAcP,MAAMQ;IAAO,CAAA;AAE1FE,gBAAYN,YAAYO,SAASC,QAAQH,YAAYE,SAASC,MAAM;AACpE,UAAMnB,QAAQC,IAAI;MAACM,MAAMa,eAAeT,WAAAA;MAAcH,MAAMY,eAAeJ,WAAAA;KAAa;AAExF,WAAO;MAACL;MAAaK;;EACvB;EAEA,MAAMK,WAAWd,OAAiBC,OAAiB;AACjDC,IAAAA,WAAUF,UAAUC,OAAAA,QAAAA;;;;;;;;;AACpBC,IAAAA,WAAU,KAAKlB,OAAOmB,IAAIH,KAAAA,GAAAA,QAAAA;;;;;;;;;AAC1BE,IAAAA,WAAU,KAAKlB,OAAOmB,IAAIH,KAAAA,GAAAA,QAAAA;;;;;;;;;AAE1B,UAAMI,cAAcT,MAAMC,KAAKI,MAAMe,WAAW,EAAEC,KAAK,CAACC,eACtDA,WAAWV,aAAaW,OAAOjB,MAAMO,MAAM,CAAA;AAE7C,UAAMC,cAAcd,MAAMC,KAAKK,MAAMc,WAAW,EAAEC,KAAK,CAACC,eACtDA,WAAWV,aAAaW,OAAOlB,MAAMQ,MAAM,CAAA;AAG7CN,IAAAA,WAAUE,aAAAA,QAAAA;;;;;;;;;AACVF,IAAAA,WAAUO,aAAAA,QAAAA;;;;;;;;;AAEV,UAAMhB,QAAQC,IAAI;MAACM,MAAMmB,gBAAgBf,WAAAA;MAAcH,MAAMkB,gBAAgBV,WAAAA;KAAa;EAC5F;AACF;AAEO,IAAMW,WAAN,MAAMA;EAGXC,YAA4Bb,SAAoBc,WAAUC,OAAM,GAAI;kBAAxCf;SAFZO,cAAc,oBAAI9B,IAAAA;EAEmC;EAErE,MAAgBuC,OAAOP,YAA4B;EAAC;EACpD,MAAgBQ,QAAQR,YAA4B;EAAC;EAErDZ,iBAAiB,EAAEC,WAAWC,aAAY,GAAqD;AAC7F,UAAMU,aAAa,IAAIS,eAAe,KAAKlB,QAAQD,cAAcD,SAAAA;AACjE,SAAKS,YAAYzB,IAAI2B,UAAAA;AACrB,WAAOA;EACT;EAEA,MAAMJ,eAAeI,YAA4B;AAC/Cf,IAAAA,WAAU,KAAKa,YAAYZ,IAAIc,UAAAA,GAAAA,QAAAA;;;;;;;;;AAC/B,UAAMA,WAAWN,SAASgB,KAAI;AAC9B,UAAM,KAAKH,OAAOP,UAAAA;EACpB;EAEA,MAAME,gBAAgBF,YAA4B;AAChDf,IAAAA,WAAU,KAAKa,YAAYZ,IAAIc,UAAAA,GAAAA,QAAAA;;;;;;;;;AAC/B,UAAM,KAAKQ,QAAQR,UAAAA;AACnB,UAAMA,WAAWN,SAASiB,MAAK;AAC/B,SAAKb,YAAYc,OAAOZ,UAAAA;EAC1B;EAEA,MAAMzB,UAAU;AACd,eAAWmB,YAAY,KAAKI,aAAa;AACvC,YAAM,KAAKI,gBAAgBR,QAAAA;IAC7B;EACF;AACF;AAEA,IAAMD,cAAc,CAACoB,SAAiBC,YAAAA;AACpCC,WAASF,SAASC,SAAS,CAACE,QAAAA;AAC1B,QAAIA,OAAOA,IAAIC,SAAS,8BAA8B;AACpDC,MAAAA,KAAIC,MAAMH,KAAAA,QAAAA;;;;;;IACZ;EACF,CAAA;AACAD,WAASD,SAASD,SAAS,CAACG,QAAAA;AAC1B,QAAIA,OAAOA,IAAIC,SAAS,8BAA8B;AACpDC,MAAAA,KAAIC,MAAMH,KAAAA,QAAAA;;;;;;IACZ;EACF,CAAA;AACF;AAEO,IAAMP,iBAAN,MAAMA;EAGXL,YACkBgB,aACA9B,cACAD,WAChB;uBAHgB+B;wBACA9B;qBACAD;AAEhB,SAAKK,WAAW,IAAI2B,SAAS;MAC3BhC;MACA+B;MACA9B;IACF,CAAA;EACF;AACF;;;AK7HA,SAASgC,gBAAAA,eAAcC,WAAAA,gBAAe;AACtC,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,OAAAA,YAAW;AACpB,SAASC,UAAAA,eAAc;AAEvB,SAASC,sBAAAA,2BAA6C;;AAU/C,IAAMC,gBAAN,MAAMA;EAOXC,YAA4BC,YAAoC,CAAC,GAAG;qBAAxCA;SANZC,OAAO,IAAIR,SAAAA;SACXS,SAAS,IAAIT,SAAAA;SACbU,UAAU,IAAIV,SAAAA;EAIuC;EAErE,IAAIW,eAAe;AACjB,WAAO,KAAKC,kBAAkBD;EAChC;EAEA,MAAME,OAAOC,SAA2B;AACtCZ,IAAAA,KAAI,UAAU;MAAEa,aAAaD,QAAQC;MAAaJ,cAAcG,QAAQH;IAAa,GAAA;;;;;;AACrF,SAAKC,mBAAmBE;AACxB,SAAKE,OAAOZ,oBAA+E;MACzFa,MAAM,MAAMH,QAAQI,WAAW,OAAO;QACpCC,aAAa;MACf,CAAA;MACAC,WAAW;QACTC,aAAalB,QAAOmB,WAAW,iCAAA;MACjC;MACAC,SAAS;QACPF,aAAalB,QAAOmB,WAAW,iCAAA;MACjC;MACAE,UAAU;QACRH,aAAa;UACXI,UAAU,OAAOC,YAAAA;UAEjB;UACAC,UAAU,OAAOD,YAAAA;AACf,mBAAO;cACLE,MAAMF,QAAQE;YAChB;UACF;QACF;MACF;MACAC,SAAS;IACX,CAAA;AAEA,UAAM,KAAKb,KAAKR,KAAI;AACpB,UAAM,KAAKD,UAAUM,SAAM;AAE3B,SAAKL,KAAKsB,KAAI;EAChB;EAEA,MAAMC,QAAQC,KAAa;AACzB9B,IAAAA,KAAI,WAAW;MAAE8B;IAAI,GAAA;;;;;;AACrB,UAAM,KAAKzB,UAAUwB,UAAO;AAC5B,SAAKtB,OAAOqB,KAAI;AAChB,UAAM,KAAKd,MAAMiB,MAAAA;EACnB;EAEA,MAAMC,QAAQF,KAAa;AACzB9B,IAAAA,KAAI,WAAW;MAAE8B;IAAI,GAAA;;;;;;AACrB,UAAM,KAAKzB,UAAU2B,UAAO;AAC5B,SAAKxB,QAAQoB,KAAI;AACjB,UAAM,KAAKd,MAAMmB,MAAAA;EACnB;EAEA,MAAMC,KAAKC,UAAU,QAAQ;AAC3B,UAAM,KAAK7B,KAAK8B,KAAK;MAAET,SAAS;IAAK,CAAA;AACrC,UAAMU,MAAM,MAAMxC,cAAa,KAAKiB,KAAKwB,IAAInB,YAAYM,SAAS;MAAEC,MAAMS;IAAQ,CAAA,GAAI,IAAA;AACtFpC,IAAAA,WAAUsC,IAAIX,SAASS,SAAAA,QAAAA;;;;;;;;;EACzB;;;;EAKA,MAAMI,gBAAgBT,KAAa;AACjC,SAAKpB,kBAAkBqB,MAAMD,GAAAA;EAC/B;AACF;;;ACxFA,SAASU,mBAAmB;AAG5B,SAASC,WAAAA,gBAAe;AACxB,SAASC,aAAAA,kBAAiB;AAC1B,SAASC,OAAAA,YAAW;AACpB,SAASC,UAAAA,eAAc;AAEvB,SAASC,sBAAAA,2BAA6C;;AAU/C,IAAMC,2BAAN,MAAMA;EASXC,YAA4BC,YAA+C,CAAC,GAAG;qBAAnDA;SARZC,OAAO,IAAIR,SAAAA;SACXS,SAAS,IAAIT,SAAAA;SACbU,UAAU,IAAIV,SAAAA;SACbW,WAAW,oBAAIC,IAAAA;EAKgD;EAEhF,IAAIC,eAAe;AACjB,WAAO,KAAKC,kBAAkBD;EAChC;EAEA,MAAcE,YAAYC,WAAmBC,WAAW,GAAGC,YAAY,MAAM;AAC3EjB,IAAAA,WAAU,CAAC,KAAKU,SAASQ,IAAIH,SAAAA,GAAY,0BAA0BA,SAAAA,IAAW;;;;;;;;;AAE9E,UAAMI,gBAAgB,MAAM,KAAKN,iBAAkBO,aAAaL,WAAW;MACzEM,aAAa;IACf,CAAA;AAEA,UAAMC,cAA0B;MAC9BH;MACAI,WAAW;MACXC,eAAe;MACfC,YAAY;MACZC,eAAe;MACfC,gBAAgBC,KAAKC,IAAG;IAC1B;AAEA,UAAMC,YAAY,MAAA;AAChBR,kBAAYS,QAAQC,WAAW,MAAA;AAC7B,cAAMC,QAAQnC,YAAYmB,SAAAA;AAE1B,YACE,CAACE,cAAce,MAAMD,OAAO,UAAU,CAACE,QAAAA;AACrC,cAAI,CAACA,KAAK;AACRb,wBAAYC,aAAaU,MAAMG;UACjC,OAAO;AACLd,wBAAYG,cAAc;UAC5B;QACF,CAAA,GACA;AACAN,wBAAckB,KAAK,SAASP,SAAAA;QAC9B,OAAO;AACLQ,kBAAQC,SAAST,SAAAA;QACnB;MACF,GAAGd,QAAAA;IACL;AAEAc,cAAAA;AAEA,SAAKpB,SAAS8B,IAAIzB,WAAWO,WAAAA;AAE7BH,kBAAcsB,GAAG,QAAQ,CAACC,SAAAA;AACxBpB,kBAAYE,iBAAiBkB,KAAKN;IACpC,CAAA;AAEAjB,kBAAcsB,GAAG,SAAS,CAACN,QAAAA;AACzBb,kBAAYI,iBAAiB;IAC/B,CAAA;AAEAP,kBAAcsB,GAAG,SAAS,MAAA;AACxBtB,oBAAcwB,mBAAkB;IAClC,CAAA;AAEArB,gBAAYsB,iBAAiBC,YAAY,MAAA;AACvC,YAAM,EAAEtB,WAAWC,eAAeC,YAAYC,cAAa,IAAKJ;AAEhErB,MAAAA,KAAI6C,MAAM,0BAA0B;QAClC/B;QACAQ;QACAC;QACAC;QACAC;QACAqB,MAAM,KAAKlC,kBAAkBmC;QAC7BC,IAAI,KAAKpC,kBAAkBD;MAC7B,GAAA;;;;;;IACF,GAAG,GAAA;EACL;EAEQsC,aAAanC,WAA0B;AAC7Cf,IAAAA,WAAU,KAAKU,SAASQ,IAAIH,SAAAA,GAAY,0BAA0BA,SAAAA,IAAW;;;;;;;;;AAE7E,UAAMoC,SAAS,KAAKzC,SAAS0C,IAAIrC,SAAAA;AAEjCsC,iBAAaF,OAAOpB,KAAK;AACzBsB,iBAAaF,OAAOP,cAAc;AAElC,UAAM,EAAErB,WAAWC,eAAeC,YAAYC,eAAeC,eAAc,IAAKwB;AAEhFA,WAAOhC,cAAcmC,QAAO;AAC5B,SAAK5C,SAAS6C,OAAOxC,SAAAA;AAErB,WAAO;MACLQ;MACAC;MACAC;MACAC;MACA8B,aAAa5B,KAAKC,IAAG,KAAMF,kBAAkB;IAC/C;EACF;EAEA,MAAM8B,OAAOC,SAA2B;AACtCzD,IAAAA,KAAI,UAAU;MAAE+C,aAAaU,QAAQV;MAAapC,cAAc8C,QAAQ9C;IAAa,GAAA;;;;;;AACrF,SAAKC,mBAAmB6C;AACxB,SAAKC,OAAOxD,oBAGV;MACAyD,MAAM,MAAMF,QAAQG,WAAW,OAAO;QACpCxC,aAAa;MACf,CAAA;MACAyC,WAAW;QACTC,wBAAwB7D,QAAO8D,WAAW,4CAAA;MAC5C;MACAC,SAAS;QACPF,wBAAwB7D,QAAO8D,WAAW,4CAAA;MAC5C;MACAE,UAAU;QACRH,wBAAwB;UACtBI,mBAAmB,OAAOC,YAAAA;AACxB,kBAAM,EAAE1B,MAAM3B,WAAWsD,oBAAoBC,oBAAmB,IAAKF;AAErE,kBAAM,KAAKtD,YAAYC,WAAWsD,oBAAoBC,mBAAAA;AAEtD,mBAAO;cACL5B,MAAM3B;YACR;UACF;UACAwD,iBAAiB,OAAOH,YAAAA;AACtB,kBAAMrD,YAAYqD,QAAQ1B;AAC1B,kBAAM,EAAEnB,WAAWC,eAAeC,YAAYC,eAAe8B,YAAW,IAAK,KAAKN,aAAanC,SAAAA;AAE/F,mBAAO;cACL2B,MAAM3B;cACNQ;cACAC;cACAC;cACAC;cACA8B;YACF;UACF;QACF;MACF;MACAgB,SAAS;IACX,CAAA;AAEA,UAAM,KAAKb,KAAKpD,KAAI;AACpB,UAAM,KAAKD,UAAUmD,SAAM;AAE3B,SAAKlD,KAAKkE,KAAI;EAChB;EAEA,MAAMC,QAAQvC,KAAa;AACzBlC,IAAAA,KAAI,WAAW;MAAEkC;IAAI,GAAA;;;;;;AACrB,UAAM,KAAK7B,UAAUoE,UAAO;AAC5B,SAAKlE,OAAOiE,KAAI;AAChB,eAAW,CAAC1D,WAAWoC,MAAAA,KAAWwB,OAAOC,QAAQ,KAAKlE,QAAQ,GAAG;AAC/DT,MAAAA,KAAI,kBAAkB;QAAEc;MAAU,GAAA;;;;;;AAClCsC,mBAAaF,OAAOnC,QAAQ;AAC5BmC,aAAOhC,cAAcmC,QAAO;IAC9B;AACA,UAAM,KAAKK,MAAMkB,MAAAA;EACnB;EAEA,MAAMC,QAAQ3C,KAAa;AACzBlC,IAAAA,KAAI,WAAW;MAAEkC;IAAI,GAAA;;;;;;AACrB,UAAM,KAAK7B,UAAUwE,UAAO;AAC5B,SAAKrE,QAAQgE,KAAI;AACjB,UAAM,KAAKd,MAAMoB,MAAAA;EACnB;EAEA,MAAMC,aAAaX,oBAA4BC,qBAA6BvD,WAAqC;AAC/G,UAAM,KAAKR,KAAK0E,KAAK;MAAET,SAAS;IAAK,CAAA;AACrC,QAAI,CAACzD,WAAW;AACdA,kBAAY,UAAUjB,YAAY,CAAA,EAAGoF,SAAS,KAAA,CAAA;IAChD;AACA,UAAM,EAAExC,KAAI,IAAK,MAAM,KAAKiB,KAAKwB,IAAIpB,uBAAuBI,kBAAkB;MAC5EzB,MAAM3B;MACNsD;MACAC;IACF,CAAA;AACAtE,IAAAA,WAAU0C,SAAS3B,WAAAA,QAAAA;;;;;;;;;AAEnB,UAAM,KAAKD,YAAYC,WAAWsD,oBAAoBC,mBAAAA;AACtD,WAAOvD;EACT;EAEA,MAAMqE,YAAYrE,WAA6C;AAC7D,UAAM,KAAKR,KAAK0E,KAAK;MAAET,SAAS;IAAK,CAAA;AACrC,UAAM,EAAE9B,MAAMnB,WAAWC,eAAeC,YAAYC,eAAe8B,YAAW,IAC5E,MAAM,KAAKG,KAAKwB,IAAIpB,uBAAuBQ,gBAAgB;MACzD7B,MAAM3B;IACR,CAAA;AAEFf,IAAAA,WAAU0C,SAAS3B,WAAAA,QAAAA;;;;;;;;;AAEnB,UAAMsE,QAAQ,KAAKnC,aAAanC,SAAAA;AAEhC,WAAO;MACLA;MACAuE,OAAO;QACLD;QACAE,QAAQ;UACNhE;UACAC;UACAC;UACAC;UACA8B;QACF;MACF;IACF;EACF;;;;EAKA,MAAMgC,gBAAgBrD,KAAa;AACjC,SAAKtB,kBAAkBgE,MAAM1C,GAAAA;EAC/B;AACF;",
|
|
6
|
+
"names": ["pipeline", "invariant", "PublicKey", "log", "asyncTimeout", "scheduleTaskInterval", "runInContextAsync", "synchronized", "scheduleTask", "Context", "failUndefined", "invariant", "PublicKey", "log", "schema", "RpcClosedError", "TimeoutError", "createProtoRpcPeer", "Callback", "Duplex", "Event", "invariant", "log", "FRAME_LENGTH_SIZE", "Framer", "_messageCb", "undefined", "_subscribeCb", "_buffer", "_sendCallbacks", "_bytesSent", "_bytesReceived", "_writable", "drain", "_stream", "objectMode", "read", "_processResponseQueue", "write", "chunk", "encoding", "callback", "length", "Buffer", "concat", "_popFrames", "port", "send", "message", "Promise", "resolve", "frame", "encodeFrame", "push", "subscribe", "stream", "bytesSent", "bytesReceived", "writable", "responseQueue", "emit", "forEach", "cb", "offset", "decodeFrame", "bytesConsumed", "payload", "subarray", "destroy", "readableLength", "warn", "writableLength", "buffer", "frameLength", "readUInt16BE", "allocUnsafe", "writeUInt16BE", "set", "Duplex", "scheduleTaskInterval", "Event", "Trigger", "Context", "failUndefined", "invariant", "log", "schema", "TimeoutError", "varint", "Event", "log", "MAX_CHUNK_SIZE", "Balancer", "constructor", "_sysChannelId", "_lastCallerIndex", "_channels", "_framer", "Framer", "_sendBuffers", "Map", "_receiveBuffers", "incomingData", "Event", "stream", "push", "port", "subscribe", "_processIncomingMessage", "bind", "bytesSent", "bytesReceived", "buffersCount", "size", "addChannel", "channel", "pushData", "data", "trigger", "channelId", "noCalls", "includes", "Error", "has", "set", "sendBuffer", "get", "chunks", "idx", "length", "subarray", "forEach", "chunk", "index", "msg", "encodeChunk", "dataLength", "undefined", "_sendChunk", "catch", "err", "log", "destroy", "warn", "clear", "decodeChunk", "buffer", "Buffer", "from", "msgLength", "emit", "channelBuffer", "concat", "delete", "_getNextCallerId", "_getNextChunk", "shift", "writable", "drain", "waitForCount", "send", "wake", "throw", "channelTagLength", "encodingLength", "dataLengthLength", "message", "allocUnsafe", "varint", "encode", "withLength", "decode", "offset", "bytes", "Command", "schema", "getCodecForType", "DEFAULT_SEND_COMMAND_TIMEOUT", "DESTROY_COMMAND_SEND_TIMEOUT", "STATS_INTERVAL", "MAX_SAFE_FRAME_SIZE", "SYSTEM_CHANNEL_ID", "GRACEFUL_CLOSE_TIMEOUT", "Muxer", "constructor", "_balancer", "Balancer", "_channelsByLocalId", "Map", "_channelsByTag", "_ctx", "Context", "_nextId", "_closing", "_destroying", "_disposed", "_lastStats", "undefined", "_lastChannelStats", "afterClosed", "Event", "statsUpdated", "stream", "incomingData", "on", "msg", "_handleCommand", "decode", "createStream", "tag", "opts", "channel", "_getOrCreateStream", "contentType", "invariant", "push", "Duplex", "write", "data", "encoding", "callback", "_sendData", "then", "catch", "read", "stats", "bytesReceived", "length", "destroy", "err", "_sendCommand", "openChannel", "id", "_destroyChannel", "createPort", "inboundBuffer", "port", "send", "timeout", "subscribe", "cb", "close", "log", "error", "message", "dispose", "Promise", "race", "_resolve", "reject", "setTimeout", "TimeoutError", "values", "emit", "clear", "cmd", "warn", "remoteId", "buffer", "channelId", "get", "failUndefined", "trigger", "Trigger", "pushData", "encode", "wait", "params", "size", "scheduleTaskInterval", "_emitStats", "bytesSent", "set", "addChannel", "threshold", "delete", "now", "Date", "interval", "timestamp", "calculateThroughput", "current", "last", "bytesSentRate", "bytesReceivedRate", "channels", "Array", "from", "map", "writeBufferSize", "readBufferSize", "readableLength", "writableLength", "CONTROL_HEARTBEAT_INTERVAL", "CONTROL_HEARTBEAT_TIMEOUT", "Teleport", "constructor", "initiator", "localPeerId", "remotePeerId", "_ctx", "Context", "onError", "err", "destroy", "catch", "log", "error", "_muxer", "Muxer", "_control", "ControlExtension", "heartbeatInterval", "heartbeatTimeout", "onTimeout", "_destroying", "_aborting", "abort", "TimeoutError", "_extensions", "Map", "_remoteExtensions", "Set", "_open", "invariant", "PublicKey", "isPublicKey", "onExtensionRegistered", "set", "name", "has", "add", "_openExtension", "stream", "on", "statsUpdated", "stats", "trace", "bytesSent", "bytesSentRate", "bytesReceived", "bytesReceivedRate", "channels", "open", "_setExtension", "close", "disposed", "dispose", "extension", "values", "onAbort", "onClose", "addExtension", "Error", "scheduleTask", "registerExtension", "RpcClosedError", "extensionName", "includes", "get", "failUndefined", "context", "createPort", "channelName", "opts", "createStream", "runInContextAsync", "onOpen", "synchronized", "_extensionContext", "Callback", "_rpc", "rpc", "Control", "extensionContext", "createProtoRpcPeer", "requested", "schema", "getService", "exposed", "handlers", "request", "call", "heartbeat", "port", "contentType", "scheduleTaskInterval", "asyncTimeout", "TestBuilder", "_peers", "Set", "createPeer", "opts", "peer", "factory", "add", "createPeers", "destroy", "Promise", "all", "Array", "from", "map", "agent", "connect", "peer1", "peer2", "invariant", "has", "connection1", "createConnection", "initiator", "remotePeerId", "peerId", "connection2", "pipeStreams", "teleport", "stream", "openConnection", "disconnect", "connections", "find", "connection", "equals", "closeConnection", "TestPeer", "constructor", "PublicKey", "random", "onOpen", "onClose", "TestConnection", "open", "close", "delete", "stream1", "stream2", "pipeline", "err", "code", "log", "catch", "localPeerId", "Teleport", "asyncTimeout", "Trigger", "invariant", "log", "schema", "createProtoRpcPeer", "TestExtension", "constructor", "callbacks", "open", "closed", "aborted", "remotePeerId", "extensionContext", "onOpen", "context", "localPeerId", "_rpc", "port", "createPort", "contentType", "requested", "TestService", "getService", "exposed", "handlers", "voidCall", "request", "testCall", "data", "timeout", "wake", "onClose", "err", "close", "onAbort", "abort", "test", "message", "wait", "res", "rpc", "closeConnection", "randomBytes", "Trigger", "invariant", "log", "schema", "createProtoRpcPeer", "TestExtensionWithStreams", "constructor", "callbacks", "open", "closed", "aborted", "_streams", "Map", "remotePeerId", "extensionContext", "_openStream", "streamTag", "interval", "chunkSize", "has", "networkStream", "createStream", "contentType", "streamEntry", "bytesSent", "bytesReceived", "sendErrors", "receiveErrors", "startTimestamp", "Date", "now", "pushChunk", "timer", "setTimeout", "chunk", "write", "err", "length", "once", "process", "nextTick", "set", "on", "data", "removeAllListeners", "reportingTimer", "setInterval", "trace", "from", "localPeerId", "to", "_closeStream", "stream", "get", "clearTimeout", "destroy", "delete", "runningTime", "onOpen", "context", "_rpc", "port", "createPort", "requested", "TestServiceWithStreams", "getService", "exposed", "handlers", "requestTestStream", "request", "streamLoadInterval", "streamLoadChunkSize", "closeTestStream", "timeout", "wake", "onClose", "Object", "entries", "close", "onAbort", "abort", "addNewStream", "wait", "toString", "rpc", "closeStream", "local", "stats", "remote", "closeConnection"]
|
|
7
|
+
}
|