@replit/river 0.26.0 → 0.26.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-KP4UB5NW.js → chunk-AWCUCZY4.js} +2 -2
- package/dist/{chunk-5S64PXTU.js → chunk-IV27BICV.js} +36 -9
- package/dist/chunk-IV27BICV.js.map +1 -0
- package/dist/{chunk-5FDAIAQ5.js → chunk-M5X4JTU3.js} +5 -5
- package/dist/chunk-M5X4JTU3.js.map +1 -0
- package/dist/{chunk-CCUYKR5C.js → chunk-M75K5TJS.js} +2 -2
- package/dist/{chunk-CCUYKR5C.js.map → chunk-M75K5TJS.js.map} +1 -1
- package/dist/{chunk-BNNELZM4.js → chunk-MREEJE3X.js} +2 -2
- package/dist/{chunk-JSU2KACV.js → chunk-NC54BC47.js} +98 -35
- package/dist/chunk-NC54BC47.js.map +1 -0
- package/dist/{chunk-7ETNUCOL.js → chunk-YQABPD3C.js} +29 -14
- package/dist/chunk-YQABPD3C.js.map +1 -0
- package/dist/{client-162c509c.d.ts → client-654098be.d.ts} +2 -4
- package/dist/{connection-6a404bb8.d.ts → connection-bc2454dc.d.ts} +1 -1
- package/dist/{handshake-3342bb94.d.ts → handshake-1a86f06d.d.ts} +60 -42
- package/dist/logging/index.d.cts +1 -1
- package/dist/logging/index.d.ts +1 -1
- package/dist/{message-1a434848.d.ts → message-57296605.d.ts} +2 -1
- package/dist/router/index.cjs +1 -1
- package/dist/router/index.cjs.map +1 -1
- package/dist/router/index.d.cts +8 -8
- package/dist/router/index.d.ts +8 -8
- package/dist/router/index.js +2 -2
- package/dist/{server-1b695374.d.ts → server-9a6b5a8e.d.ts} +12 -4
- package/dist/{services-c17f7eff.d.ts → services-7daa60a0.d.ts} +3 -3
- package/dist/transport/impls/ws/client.cjs +131 -41
- package/dist/transport/impls/ws/client.cjs.map +1 -1
- package/dist/transport/impls/ws/client.d.cts +4 -4
- package/dist/transport/impls/ws/client.d.ts +4 -4
- package/dist/transport/impls/ws/client.js +5 -5
- package/dist/transport/impls/ws/server.cjs +124 -46
- package/dist/transport/impls/ws/server.cjs.map +1 -1
- package/dist/transport/impls/ws/server.d.cts +4 -4
- package/dist/transport/impls/ws/server.d.ts +4 -4
- package/dist/transport/impls/ws/server.js +5 -5
- package/dist/transport/index.cjs +156 -51
- package/dist/transport/index.cjs.map +1 -1
- package/dist/transport/index.d.cts +4 -4
- package/dist/transport/index.d.ts +4 -4
- package/dist/transport/index.js +5 -5
- package/dist/util/testHelpers.cjs +97 -34
- package/dist/util/testHelpers.cjs.map +1 -1
- package/dist/util/testHelpers.d.cts +4 -4
- package/dist/util/testHelpers.d.ts +4 -4
- package/dist/util/testHelpers.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-5FDAIAQ5.js.map +0 -1
- package/dist/chunk-5S64PXTU.js.map +0 -1
- package/dist/chunk-7ETNUCOL.js.map +0 -1
- package/dist/chunk-JSU2KACV.js.map +0 -1
- /package/dist/{chunk-KP4UB5NW.js.map → chunk-AWCUCZY4.js.map} +0 -0
- /package/dist/{chunk-BNNELZM4.js.map → chunk-MREEJE3X.js.map} +0 -0
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
createSessionTelemetryInfo,
|
|
4
4
|
generateId,
|
|
5
5
|
isAck
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-M75K5TJS.js";
|
|
7
7
|
import {
|
|
8
8
|
NaiveJsonCodec
|
|
9
9
|
} from "./chunk-4PVU7J25.js";
|
|
@@ -15,6 +15,7 @@ var defaultTransportOptions = {
|
|
|
15
15
|
sessionDisconnectGraceMs: 5e3,
|
|
16
16
|
connectionTimeoutMs: 2e3,
|
|
17
17
|
handshakeTimeoutMs: 1e3,
|
|
18
|
+
enableTransparentSessionReconnects: true,
|
|
18
19
|
codec: NaiveJsonCodec
|
|
19
20
|
};
|
|
20
21
|
var defaultConnectionRetryOptions = {
|
|
@@ -185,9 +186,32 @@ var IdentifiedSession = class extends CommonSession {
|
|
|
185
186
|
this.telemetry.span.end();
|
|
186
187
|
}
|
|
187
188
|
};
|
|
189
|
+
var IdentifiedSessionWithGracePeriod = class extends IdentifiedSession {
|
|
190
|
+
graceExpiryTime;
|
|
191
|
+
gracePeriodTimeout;
|
|
192
|
+
listeners;
|
|
193
|
+
constructor(props) {
|
|
194
|
+
super(props);
|
|
195
|
+
this.listeners = props.listeners;
|
|
196
|
+
this.graceExpiryTime = props.graceExpiryTime;
|
|
197
|
+
this.gracePeriodTimeout = setTimeout(() => {
|
|
198
|
+
this.listeners.onSessionGracePeriodElapsed();
|
|
199
|
+
}, this.graceExpiryTime - Date.now());
|
|
200
|
+
}
|
|
201
|
+
_handleStateExit() {
|
|
202
|
+
super._handleStateExit();
|
|
203
|
+
if (this.gracePeriodTimeout) {
|
|
204
|
+
clearTimeout(this.gracePeriodTimeout);
|
|
205
|
+
this.gracePeriodTimeout = void 0;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
_handleClose() {
|
|
209
|
+
super._handleClose();
|
|
210
|
+
}
|
|
211
|
+
};
|
|
188
212
|
|
|
189
213
|
// transport/sessionStateMachine/SessionConnecting.ts
|
|
190
|
-
var SessionConnecting = class extends
|
|
214
|
+
var SessionConnecting = class extends IdentifiedSessionWithGracePeriod {
|
|
191
215
|
state = "Connecting" /* Connecting */;
|
|
192
216
|
connPromise;
|
|
193
217
|
listeners;
|
|
@@ -220,8 +244,10 @@ var SessionConnecting = class extends IdentifiedSession {
|
|
|
220
244
|
}
|
|
221
245
|
_handleStateExit() {
|
|
222
246
|
super._handleStateExit();
|
|
223
|
-
|
|
224
|
-
|
|
247
|
+
if (this.connectionTimeout) {
|
|
248
|
+
clearTimeout(this.connectionTimeout);
|
|
249
|
+
this.connectionTimeout = void 0;
|
|
250
|
+
}
|
|
225
251
|
}
|
|
226
252
|
_handleClose() {
|
|
227
253
|
this.bestEffortClose();
|
|
@@ -230,26 +256,13 @@ var SessionConnecting = class extends IdentifiedSession {
|
|
|
230
256
|
};
|
|
231
257
|
|
|
232
258
|
// transport/sessionStateMachine/SessionNoConnection.ts
|
|
233
|
-
var SessionNoConnection = class extends
|
|
259
|
+
var SessionNoConnection = class extends IdentifiedSessionWithGracePeriod {
|
|
234
260
|
state = "NoConnection" /* NoConnection */;
|
|
235
|
-
listeners;
|
|
236
|
-
gracePeriodTimeout;
|
|
237
|
-
constructor(props) {
|
|
238
|
-
super(props);
|
|
239
|
-
this.listeners = props.listeners;
|
|
240
|
-
this.gracePeriodTimeout = setTimeout(() => {
|
|
241
|
-
this.listeners.onSessionGracePeriodElapsed();
|
|
242
|
-
}, this.options.sessionDisconnectGraceMs);
|
|
243
|
-
}
|
|
244
261
|
_handleClose() {
|
|
245
262
|
super._handleClose();
|
|
246
263
|
}
|
|
247
264
|
_handleStateExit() {
|
|
248
265
|
super._handleStateExit();
|
|
249
|
-
if (this.gracePeriodTimeout) {
|
|
250
|
-
clearTimeout(this.gracePeriodTimeout);
|
|
251
|
-
this.gracePeriodTimeout = void 0;
|
|
252
|
-
}
|
|
253
266
|
}
|
|
254
267
|
};
|
|
255
268
|
|
|
@@ -273,7 +286,10 @@ var SessionWaitingForHandshake = class extends CommonSession {
|
|
|
273
286
|
onHandshakeData = (msg) => {
|
|
274
287
|
const parsedMsg = this.parseMsg(msg);
|
|
275
288
|
if (parsedMsg === null) {
|
|
276
|
-
this.listeners.onInvalidHandshake(
|
|
289
|
+
this.listeners.onInvalidHandshake(
|
|
290
|
+
"could not parse message",
|
|
291
|
+
"MALFORMED_HANDSHAKE"
|
|
292
|
+
);
|
|
277
293
|
return;
|
|
278
294
|
}
|
|
279
295
|
this.listeners.onHandshake(parsedMsg);
|
|
@@ -300,7 +316,7 @@ var SessionWaitingForHandshake = class extends CommonSession {
|
|
|
300
316
|
};
|
|
301
317
|
|
|
302
318
|
// transport/sessionStateMachine/SessionHandshaking.ts
|
|
303
|
-
var SessionHandshaking = class extends
|
|
319
|
+
var SessionHandshaking = class extends IdentifiedSessionWithGracePeriod {
|
|
304
320
|
state = "Handshaking" /* Handshaking */;
|
|
305
321
|
conn;
|
|
306
322
|
listeners;
|
|
@@ -319,7 +335,10 @@ var SessionHandshaking = class extends IdentifiedSession {
|
|
|
319
335
|
onHandshakeData = (msg) => {
|
|
320
336
|
const parsedMsg = this.parseMsg(msg);
|
|
321
337
|
if (parsedMsg === null) {
|
|
322
|
-
this.listeners.onInvalidHandshake(
|
|
338
|
+
this.listeners.onInvalidHandshake(
|
|
339
|
+
"could not parse message",
|
|
340
|
+
"MALFORMED_HANDSHAKE"
|
|
341
|
+
);
|
|
323
342
|
return;
|
|
324
343
|
}
|
|
325
344
|
this.listeners.onHandshake(parsedMsg);
|
|
@@ -332,7 +351,10 @@ var SessionHandshaking = class extends IdentifiedSession {
|
|
|
332
351
|
this.conn.removeDataListener(this.onHandshakeData);
|
|
333
352
|
this.conn.removeErrorListener(this.listeners.onConnectionErrored);
|
|
334
353
|
this.conn.removeCloseListener(this.listeners.onConnectionClosed);
|
|
335
|
-
|
|
354
|
+
if (this.handshakeTimeout) {
|
|
355
|
+
clearTimeout(this.handshakeTimeout);
|
|
356
|
+
this.handshakeTimeout = void 0;
|
|
357
|
+
}
|
|
336
358
|
}
|
|
337
359
|
_handleClose() {
|
|
338
360
|
super._handleClose();
|
|
@@ -412,8 +434,10 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
412
434
|
}
|
|
413
435
|
onMessageData = (msg) => {
|
|
414
436
|
const parsedMsg = this.parseMsg(msg);
|
|
415
|
-
if (parsedMsg === null)
|
|
437
|
+
if (parsedMsg === null) {
|
|
438
|
+
this.listeners.onInvalidMessage("could not parse message");
|
|
416
439
|
return;
|
|
440
|
+
}
|
|
417
441
|
if (parsedMsg.seq !== this.ack) {
|
|
418
442
|
if (parsedMsg.seq < this.ack) {
|
|
419
443
|
this.log?.debug(
|
|
@@ -470,7 +494,7 @@ var SessionConnected = class extends IdentifiedSession {
|
|
|
470
494
|
};
|
|
471
495
|
|
|
472
496
|
// transport/sessionStateMachine/SessionBackingOff.ts
|
|
473
|
-
var SessionBackingOff = class extends
|
|
497
|
+
var SessionBackingOff = class extends IdentifiedSessionWithGracePeriod {
|
|
474
498
|
state = "BackingOff" /* BackingOff */;
|
|
475
499
|
listeners;
|
|
476
500
|
backoffTimeout;
|
|
@@ -507,6 +531,12 @@ function inheritSharedSession(session) {
|
|
|
507
531
|
log: session.log
|
|
508
532
|
};
|
|
509
533
|
}
|
|
534
|
+
function inheritSharedSessionWithGrace(session) {
|
|
535
|
+
return {
|
|
536
|
+
...inheritSharedSession(session),
|
|
537
|
+
graceExpiryTime: session.graceExpiryTime
|
|
538
|
+
};
|
|
539
|
+
}
|
|
510
540
|
var SessionStateGraph = {
|
|
511
541
|
entrypoints: {
|
|
512
542
|
NoConnection: (to, from, listeners, options, log) => {
|
|
@@ -520,6 +550,7 @@ var SessionStateGraph = {
|
|
|
520
550
|
to,
|
|
521
551
|
seq: 0,
|
|
522
552
|
ack: 0,
|
|
553
|
+
graceExpiryTime: Date.now() + options.sessionDisconnectGraceMs,
|
|
523
554
|
sendBuffer,
|
|
524
555
|
telemetry,
|
|
525
556
|
options,
|
|
@@ -551,7 +582,7 @@ var SessionStateGraph = {
|
|
|
551
582
|
transition: {
|
|
552
583
|
// happy path transitions
|
|
553
584
|
NoConnectionToBackingOff: (oldSession, backoffMs, listeners) => {
|
|
554
|
-
const carriedState =
|
|
585
|
+
const carriedState = inheritSharedSessionWithGrace(oldSession);
|
|
555
586
|
oldSession._handleStateExit();
|
|
556
587
|
const session = new SessionBackingOff({
|
|
557
588
|
backoffMs,
|
|
@@ -568,7 +599,7 @@ var SessionStateGraph = {
|
|
|
568
599
|
return session;
|
|
569
600
|
},
|
|
570
601
|
BackingOffToConnecting: (oldSession, connPromise, listeners) => {
|
|
571
|
-
const carriedState =
|
|
602
|
+
const carriedState = inheritSharedSessionWithGrace(oldSession);
|
|
572
603
|
oldSession._handleStateExit();
|
|
573
604
|
const session = new SessionConnecting({
|
|
574
605
|
connPromise,
|
|
@@ -585,7 +616,7 @@ var SessionStateGraph = {
|
|
|
585
616
|
return session;
|
|
586
617
|
},
|
|
587
618
|
ConnectingToHandshaking: (oldSession, conn, listeners) => {
|
|
588
|
-
const carriedState =
|
|
619
|
+
const carriedState = inheritSharedSessionWithGrace(oldSession);
|
|
589
620
|
oldSession._handleStateExit();
|
|
590
621
|
const session = new SessionHandshaking({
|
|
591
622
|
conn,
|
|
@@ -662,9 +693,12 @@ var SessionStateGraph = {
|
|
|
662
693
|
},
|
|
663
694
|
// disconnect paths
|
|
664
695
|
BackingOffToNoConnection: (oldSession, listeners) => {
|
|
665
|
-
const carriedState =
|
|
696
|
+
const carriedState = inheritSharedSessionWithGrace(oldSession);
|
|
666
697
|
oldSession._handleStateExit();
|
|
667
|
-
const session = new SessionNoConnection({
|
|
698
|
+
const session = new SessionNoConnection({
|
|
699
|
+
listeners,
|
|
700
|
+
...carriedState
|
|
701
|
+
});
|
|
668
702
|
session.log?.info(
|
|
669
703
|
`session ${session.id} transition from BackingOff to NoConnection`,
|
|
670
704
|
{
|
|
@@ -675,10 +709,13 @@ var SessionStateGraph = {
|
|
|
675
709
|
return session;
|
|
676
710
|
},
|
|
677
711
|
ConnectingToNoConnection: (oldSession, listeners) => {
|
|
678
|
-
const carriedState =
|
|
712
|
+
const carriedState = inheritSharedSessionWithGrace(oldSession);
|
|
679
713
|
oldSession.bestEffortClose();
|
|
680
714
|
oldSession._handleStateExit();
|
|
681
|
-
const session = new SessionNoConnection({
|
|
715
|
+
const session = new SessionNoConnection({
|
|
716
|
+
listeners,
|
|
717
|
+
...carriedState
|
|
718
|
+
});
|
|
682
719
|
session.log?.info(
|
|
683
720
|
`session ${session.id} transition from Connecting to NoConnection`,
|
|
684
721
|
{
|
|
@@ -689,10 +726,13 @@ var SessionStateGraph = {
|
|
|
689
726
|
return session;
|
|
690
727
|
},
|
|
691
728
|
HandshakingToNoConnection: (oldSession, listeners) => {
|
|
692
|
-
const carriedState =
|
|
729
|
+
const carriedState = inheritSharedSessionWithGrace(oldSession);
|
|
693
730
|
oldSession.conn.close();
|
|
694
731
|
oldSession._handleStateExit();
|
|
695
|
-
const session = new SessionNoConnection({
|
|
732
|
+
const session = new SessionNoConnection({
|
|
733
|
+
listeners,
|
|
734
|
+
...carriedState
|
|
735
|
+
});
|
|
696
736
|
session.log?.info(
|
|
697
737
|
`session ${session.id} transition from Handshaking to NoConnection`,
|
|
698
738
|
{
|
|
@@ -704,9 +744,14 @@ var SessionStateGraph = {
|
|
|
704
744
|
},
|
|
705
745
|
ConnectedToNoConnection: (oldSession, listeners) => {
|
|
706
746
|
const carriedState = inheritSharedSession(oldSession);
|
|
747
|
+
const graceExpiryTime = Date.now() + oldSession.options.sessionDisconnectGraceMs;
|
|
707
748
|
oldSession.conn.close();
|
|
708
749
|
oldSession._handleStateExit();
|
|
709
|
-
const session = new SessionNoConnection({
|
|
750
|
+
const session = new SessionNoConnection({
|
|
751
|
+
listeners,
|
|
752
|
+
graceExpiryTime,
|
|
753
|
+
...carriedState
|
|
754
|
+
});
|
|
710
755
|
session.log?.info(
|
|
711
756
|
`session ${session.id} transition from Connected to NoConnection`,
|
|
712
757
|
{
|
|
@@ -723,24 +768,42 @@ var ClientSessionStateGraph = {
|
|
|
723
768
|
entrypoint: SessionStateGraph.entrypoints.NoConnection,
|
|
724
769
|
transition: {
|
|
725
770
|
// happy paths
|
|
771
|
+
// NoConnection -> BackingOff: attempt to connect
|
|
726
772
|
NoConnectionToBackingOff: transitions.NoConnectionToBackingOff,
|
|
773
|
+
// BackingOff -> Connecting: backoff period elapsed, start connection
|
|
727
774
|
BackingOffToConnecting: transitions.BackingOffToConnecting,
|
|
775
|
+
// Connecting -> Handshaking: connection established, start handshake
|
|
728
776
|
ConnectingToHandshaking: transitions.ConnectingToHandshaking,
|
|
777
|
+
// Handshaking -> Connected: handshake complete, session ready
|
|
729
778
|
HandshakingToConnected: transitions.HandshakingToConnected,
|
|
730
779
|
// disconnect paths
|
|
780
|
+
// BackingOff -> NoConnection: unused
|
|
731
781
|
BackingOffToNoConnection: transitions.BackingOffToNoConnection,
|
|
782
|
+
// Connecting -> NoConnection: connection failed or connection timeout
|
|
732
783
|
ConnectingToNoConnection: transitions.ConnectingToNoConnection,
|
|
784
|
+
// Handshaking -> NoConnection: connection closed or handshake timeout
|
|
733
785
|
HandshakingToNoConnection: transitions.HandshakingToNoConnection,
|
|
786
|
+
// Connected -> NoConnection: connection closed
|
|
734
787
|
ConnectedToNoConnection: transitions.ConnectedToNoConnection
|
|
788
|
+
// destroy/close paths
|
|
789
|
+
// NoConnection -> x: grace period elapsed
|
|
790
|
+
// BackingOff -> x: grace period elapsed
|
|
791
|
+
// Connecting -> x: grace period elapsed
|
|
792
|
+
// Handshaking -> x: grace period elapsed or invalid handshake message or handshake rejection
|
|
793
|
+
// Connected -> x: grace period elapsed or invalid message
|
|
735
794
|
}
|
|
736
795
|
};
|
|
737
796
|
var ServerSessionStateGraph = {
|
|
738
797
|
entrypoint: SessionStateGraph.entrypoints.WaitingForHandshake,
|
|
739
798
|
transition: {
|
|
740
799
|
// happy paths
|
|
800
|
+
// WaitingForHandshake -> Connected: handshake complete, session ready
|
|
741
801
|
WaitingForHandshakeToConnected: transitions.WaitingForHandshakeToConnected,
|
|
742
802
|
// disconnect paths
|
|
803
|
+
// Connected -> NoConnection: connection closed
|
|
743
804
|
ConnectedToNoConnection: transitions.ConnectedToNoConnection
|
|
805
|
+
// destroy/close paths
|
|
806
|
+
// WaitingForHandshake -> x: handshake timeout elapsed or invalid handshake message or handshake rejection or connection closed
|
|
744
807
|
}
|
|
745
808
|
};
|
|
746
809
|
|
|
@@ -753,4 +816,4 @@ export {
|
|
|
753
816
|
ClientSessionStateGraph,
|
|
754
817
|
ServerSessionStateGraph
|
|
755
818
|
};
|
|
756
|
-
//# sourceMappingURL=chunk-
|
|
819
|
+
//# sourceMappingURL=chunk-NC54BC47.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../transport/options.ts","../transport/sessionStateMachine/common.ts","../transport/sessionStateMachine/SessionConnecting.ts","../transport/sessionStateMachine/SessionNoConnection.ts","../transport/sessionStateMachine/SessionWaitingForHandshake.ts","../transport/sessionStateMachine/SessionHandshaking.ts","../transport/sessionStateMachine/SessionConnected.ts","../transport/sessionStateMachine/SessionBackingOff.ts","../transport/sessionStateMachine/transitions.ts"],"sourcesContent":["import { NaiveJsonCodec } from '../codec/json';\nimport { ConnectionRetryOptions } from './rateLimit';\nimport { SessionOptions } from './sessionStateMachine/common';\n\nexport type TransportOptions = SessionOptions;\n\nexport type ProvidedTransportOptions = Partial<TransportOptions>;\n\nexport const defaultTransportOptions: TransportOptions = {\n heartbeatIntervalMs: 1_000,\n heartbeatsUntilDead: 2,\n sessionDisconnectGraceMs: 5_000,\n connectionTimeoutMs: 2_000,\n handshakeTimeoutMs: 1_000,\n enableTransparentSessionReconnects: true,\n codec: NaiveJsonCodec,\n};\n\nexport type ClientTransportOptions = TransportOptions & ConnectionRetryOptions;\n\nexport type ProvidedClientTransportOptions = Partial<ClientTransportOptions>;\n\nconst defaultConnectionRetryOptions: ConnectionRetryOptions = {\n baseIntervalMs: 150,\n maxJitterMs: 200,\n maxBackoffMs: 32_000,\n attemptBudgetCapacity: 5,\n budgetRestoreIntervalMs: 200,\n};\n\nexport const defaultClientTransportOptions: ClientTransportOptions = {\n ...defaultTransportOptions,\n ...defaultConnectionRetryOptions,\n};\n\nexport type ServerTransportOptions = TransportOptions;\n\nexport type ProvidedServerTransportOptions = Partial<ServerTransportOptions>;\n\nexport const defaultServerTransportOptions: ServerTransportOptions = {\n ...defaultTransportOptions,\n};\n","import { Logger, MessageMetadata } from '../../logging';\nimport { TelemetryInfo } from '../../tracing';\nimport {\n OpaqueTransportMessage,\n OpaqueTransportMessageSchema,\n PartialTransportMessage,\n TransportClientId,\n TransportMessage,\n} from '../message';\nimport { Value } from '@sinclair/typebox/value';\nimport { Codec } from '../../codec';\nimport { generateId } from '../id';\n\nexport const enum SessionState {\n NoConnection = 'NoConnection',\n BackingOff = 'BackingOff',\n Connecting = 'Connecting',\n Handshaking = 'Handshaking',\n Connected = 'Connected',\n WaitingForHandshake = 'WaitingForHandshake',\n}\n\nexport const ERR_CONSUMED = `session state has been consumed and is no longer valid`;\n\nabstract class StateMachineState {\n abstract readonly state: SessionState;\n\n /*\n * Whether this state has been consumed\n * and we've moved on to another state\n */\n _isConsumed: boolean;\n\n // called when we're transitioning to another state\n // note that this is internal and should not be called directly\n // by consumers, the proxy will call this when the state is consumed\n // and we're transitioning to another state\n abstract _handleStateExit(): void;\n\n // called when we exit the state machine entirely\n // note that this is internal and should not be called directly\n // by consumers, the proxy will call this when .close is closed\n abstract _handleClose(): void;\n\n close(): void {\n this._handleClose();\n }\n\n constructor() {\n this._isConsumed = false;\n\n // proxy helps us prevent access to properties after the state has been consumed\n // e.g. if we hold a reference to a state and try to access it after it's been consumed\n // we intercept the access and throw an error to help catch bugs\n return new Proxy(this, {\n get(target, prop) {\n // always allow access to _isConsumed, id, and state\n if (prop === '_isConsumed' || prop === 'id' || prop === 'state') {\n return Reflect.get(target, prop);\n }\n\n // modify _handleStateExit\n if (prop === '_handleStateExit') {\n return () => {\n target._isConsumed = true;\n target._handleStateExit();\n };\n }\n\n // modify _handleClose\n if (prop === '_handleClose') {\n return () => {\n target._handleStateExit();\n target._handleClose();\n };\n }\n\n if (target._isConsumed) {\n throw new Error(\n `${ERR_CONSUMED}: getting ${prop.toString()} on consumed state`,\n );\n }\n\n return Reflect.get(target, prop);\n },\n set(target, prop, value) {\n if (target._isConsumed) {\n throw new Error(\n `${ERR_CONSUMED}: setting ${prop.toString()} on consumed state`,\n );\n }\n\n return Reflect.set(target, prop, value);\n },\n });\n }\n}\n\nexport interface SessionOptions {\n /**\n * Frequency at which to send heartbeat acknowledgements\n */\n heartbeatIntervalMs: number;\n /**\n * Number of elapsed heartbeats without a response message before we consider\n * the connection dead.\n */\n heartbeatsUntilDead: number;\n /**\n * Max duration that a session can be without a connection before we consider\n * it dead. This deadline is carried between states and is used to determine\n * when to consider the session a lost cause and delete it entirely.\n * Generally, this should be strictly greater than the sum of\n * {@link connectionTimeoutMs} and {@link handshakeTimeoutMs}.\n */\n sessionDisconnectGraceMs: number;\n /**\n * Connection timeout in milliseconds\n */\n connectionTimeoutMs: number;\n /**\n * Handshake timeout in milliseconds\n */\n handshakeTimeoutMs: number;\n /**\n * Whether to enable transparent session reconnects\n */\n enableTransparentSessionReconnects: boolean;\n /**\n * The codec to use for encoding/decoding messages over the wire\n */\n codec: Codec;\n}\n\n// all session states have a from and options\nexport interface CommonSessionProps {\n from: TransportClientId;\n options: SessionOptions;\n log: Logger | undefined;\n}\n\nexport abstract class CommonSession extends StateMachineState {\n readonly from: TransportClientId;\n readonly options: SessionOptions;\n\n log?: Logger;\n abstract get loggingMetadata(): MessageMetadata;\n\n constructor({ from, options, log }: CommonSessionProps) {\n super();\n this.from = from;\n this.options = options;\n this.log = log;\n }\n\n parseMsg(msg: Uint8Array): OpaqueTransportMessage | null {\n const parsedMsg = this.options.codec.fromBuffer(msg);\n\n if (parsedMsg === null) {\n const decodedBuffer = new TextDecoder().decode(Buffer.from(msg));\n this.log?.error(\n `received malformed msg: ${decodedBuffer}`,\n this.loggingMetadata,\n );\n return null;\n }\n\n if (!Value.Check(OpaqueTransportMessageSchema, parsedMsg)) {\n this.log?.error(`received invalid msg: ${JSON.stringify(parsedMsg)}`, {\n ...this.loggingMetadata,\n validationErrors: [\n ...Value.Errors(OpaqueTransportMessageSchema, parsedMsg),\n ],\n });\n\n return null;\n }\n\n return parsedMsg;\n }\n}\n\nexport type InheritedProperties = Pick<\n IdentifiedSession,\n 'id' | 'from' | 'to' | 'seq' | 'ack' | 'sendBuffer' | 'telemetry' | 'options'\n>;\n\nexport type SessionId = string;\n\n// all sessions where we know the other side's client id\nexport interface IdentifiedSessionProps extends CommonSessionProps {\n id: SessionId;\n to: TransportClientId;\n seq: number;\n ack: number;\n sendBuffer: Array<OpaqueTransportMessage>;\n telemetry: TelemetryInfo;\n}\n\nexport abstract class IdentifiedSession extends CommonSession {\n readonly id: SessionId;\n readonly telemetry: TelemetryInfo;\n readonly to: TransportClientId;\n\n /**\n * Index of the message we will send next (excluding handshake)\n */\n seq: number;\n\n /**\n * Number of unique messages we've received this session (excluding handshake)\n */\n ack: number;\n sendBuffer: Array<OpaqueTransportMessage>;\n\n constructor(props: IdentifiedSessionProps) {\n const { id, to, seq, ack, sendBuffer, telemetry, log } = props;\n super(props);\n this.id = id;\n this.to = to;\n this.seq = seq;\n this.ack = ack;\n this.sendBuffer = sendBuffer;\n this.telemetry = telemetry;\n this.log = log;\n }\n\n get loggingMetadata(): MessageMetadata {\n const spanContext = this.telemetry.span.spanContext();\n\n return {\n clientId: this.from,\n connectedTo: this.to,\n sessionId: this.id,\n telemetry: {\n traceId: spanContext.traceId,\n spanId: spanContext.spanId,\n },\n };\n }\n\n constructMsg<Payload>(\n partialMsg: PartialTransportMessage<Payload>,\n ): TransportMessage<Payload> {\n const msg = {\n ...partialMsg,\n id: generateId(),\n to: this.to,\n from: this.from,\n seq: this.seq,\n ack: this.ack,\n };\n\n this.seq++;\n return msg;\n }\n\n nextSeq(): number {\n return this.sendBuffer.length > 0 ? this.sendBuffer[0].seq : this.seq;\n }\n\n send(msg: PartialTransportMessage): string {\n const constructedMsg = this.constructMsg(msg);\n this.sendBuffer.push(constructedMsg);\n return constructedMsg.id;\n }\n\n _handleStateExit(): void {\n // noop\n }\n\n _handleClose(): void {\n // zero out the buffer\n this.sendBuffer.length = 0;\n this.telemetry.span.end();\n }\n}\n\nexport interface IdentifiedSessionWithGracePeriodListeners {\n onSessionGracePeriodElapsed: () => void;\n}\n\nexport interface IdentifiedSessionWithGracePeriodProps\n extends IdentifiedSessionProps {\n graceExpiryTime: number;\n listeners: IdentifiedSessionWithGracePeriodListeners;\n}\n\nexport abstract class IdentifiedSessionWithGracePeriod extends IdentifiedSession {\n graceExpiryTime: number;\n protected gracePeriodTimeout?: ReturnType<typeof setTimeout>;\n\n listeners: IdentifiedSessionWithGracePeriodListeners;\n\n constructor(props: IdentifiedSessionWithGracePeriodProps) {\n super(props);\n this.listeners = props.listeners;\n\n this.graceExpiryTime = props.graceExpiryTime;\n this.gracePeriodTimeout = setTimeout(() => {\n this.listeners.onSessionGracePeriodElapsed();\n }, this.graceExpiryTime - Date.now());\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n\n if (this.gracePeriodTimeout) {\n clearTimeout(this.gracePeriodTimeout);\n this.gracePeriodTimeout = undefined;\n }\n }\n\n _handleClose(): void {\n super._handleClose();\n }\n}\n","import { Connection } from '../connection';\nimport {\n IdentifiedSessionWithGracePeriod,\n IdentifiedSessionWithGracePeriodListeners,\n IdentifiedSessionWithGracePeriodProps,\n SessionState,\n} from './common';\n\nexport interface SessionConnectingListeners\n extends IdentifiedSessionWithGracePeriodListeners {\n onConnectionEstablished: (conn: Connection) => void;\n onConnectionFailed: (err: unknown) => void;\n\n // timeout related\n onConnectionTimeout: () => void;\n}\n\nexport interface SessionConnectingProps<ConnType extends Connection>\n extends IdentifiedSessionWithGracePeriodProps {\n connPromise: Promise<ConnType>;\n listeners: SessionConnectingListeners;\n}\n\n/*\n * A session that is connecting but we don't have access to the raw connection yet.\n * See transitions.ts for valid transitions.\n */\nexport class SessionConnecting<\n ConnType extends Connection,\n> extends IdentifiedSessionWithGracePeriod {\n readonly state = SessionState.Connecting as const;\n connPromise: Promise<ConnType>;\n listeners: SessionConnectingListeners;\n\n connectionTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(props: SessionConnectingProps<ConnType>) {\n super(props);\n this.connPromise = props.connPromise;\n this.listeners = props.listeners;\n\n this.connectionTimeout = setTimeout(() => {\n this.listeners.onConnectionTimeout();\n }, this.options.connectionTimeoutMs);\n\n this.connPromise.then(\n (conn) => {\n if (this._isConsumed) return;\n this.listeners.onConnectionEstablished(conn);\n },\n (err) => {\n if (this._isConsumed) return;\n this.listeners.onConnectionFailed(err);\n },\n );\n }\n\n // close a pending connection if it resolves, ignore errors if the promise\n // ends up rejected anyways\n bestEffortClose() {\n void this.connPromise\n .then((conn) => conn.close())\n .catch(() => {\n // ignore errors\n });\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n\n if (this.connectionTimeout) {\n clearTimeout(this.connectionTimeout);\n this.connectionTimeout = undefined;\n }\n }\n\n _handleClose(): void {\n // close the pending connection if it resolves\n this.bestEffortClose();\n super._handleClose();\n }\n}\n","import {\n IdentifiedSessionWithGracePeriod,\n IdentifiedSessionWithGracePeriodListeners,\n IdentifiedSessionWithGracePeriodProps,\n SessionState,\n} from './common';\n\nexport type SessionNoConnectionListeners =\n IdentifiedSessionWithGracePeriodListeners;\n\nexport type SessionNoConnectionProps = IdentifiedSessionWithGracePeriodProps;\n\n/*\n * A session that is not connected and cannot send or receive messages.\n * See transitions.ts for valid transitions.\n */\nexport class SessionNoConnection extends IdentifiedSessionWithGracePeriod {\n readonly state = SessionState.NoConnection as const;\n\n _handleClose(): void {\n super._handleClose();\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n }\n}\n","import { Static } from '@sinclair/typebox';\nimport { MessageMetadata } from '../../logging';\nimport { Connection } from '../connection';\nimport {\n HandshakeErrorResponseCodes,\n OpaqueTransportMessage,\n TransportMessage,\n} from '../message';\nimport { CommonSession, CommonSessionProps, SessionState } from './common';\n\nexport interface SessionWaitingForHandshakeListeners {\n onConnectionErrored: (err: unknown) => void;\n onConnectionClosed: () => void;\n onHandshake: (msg: OpaqueTransportMessage) => void;\n onInvalidHandshake: (\n reason: string,\n code: Static<typeof HandshakeErrorResponseCodes>,\n ) => void;\n\n // timeout related\n onHandshakeTimeout: () => void;\n}\n\nexport interface SessionWaitingForHandshakeProps<ConnType extends Connection>\n extends CommonSessionProps {\n conn: ConnType;\n listeners: SessionWaitingForHandshakeListeners;\n}\n\n/*\n * Server-side session that has a connection but is waiting for the client to identify itself.\n * See transitions.ts for valid transitions.\n */\nexport class SessionWaitingForHandshake<\n ConnType extends Connection,\n> extends CommonSession {\n readonly state = SessionState.WaitingForHandshake as const;\n conn: ConnType;\n listeners: SessionWaitingForHandshakeListeners;\n\n handshakeTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(props: SessionWaitingForHandshakeProps<ConnType>) {\n super(props);\n this.conn = props.conn;\n this.listeners = props.listeners;\n\n this.handshakeTimeout = setTimeout(() => {\n this.listeners.onHandshakeTimeout();\n }, this.options.handshakeTimeoutMs);\n\n this.conn.addDataListener(this.onHandshakeData);\n this.conn.addErrorListener(this.listeners.onConnectionErrored);\n this.conn.addCloseListener(this.listeners.onConnectionClosed);\n }\n\n onHandshakeData = (msg: Uint8Array) => {\n const parsedMsg = this.parseMsg(msg);\n if (parsedMsg === null) {\n this.listeners.onInvalidHandshake(\n 'could not parse message',\n 'MALFORMED_HANDSHAKE',\n );\n return;\n }\n\n // after this fires, the listener is responsible for transitioning the session\n // and thus removing the handshake timeout\n this.listeners.onHandshake(parsedMsg);\n };\n\n get loggingMetadata(): MessageMetadata {\n return {\n clientId: this.from,\n connId: this.conn.id,\n };\n }\n\n sendHandshake(msg: TransportMessage): boolean {\n return this.conn.send(this.options.codec.toBuffer(msg));\n }\n\n _handleStateExit(): void {\n this.conn.removeDataListener(this.onHandshakeData);\n this.conn.removeErrorListener(this.listeners.onConnectionErrored);\n this.conn.removeCloseListener(this.listeners.onConnectionClosed);\n clearTimeout(this.handshakeTimeout);\n this.handshakeTimeout = undefined;\n }\n\n _handleClose(): void {\n this.conn.close();\n }\n}\n","import { Static } from '@sinclair/typebox';\nimport { Connection } from '../connection';\nimport {\n OpaqueTransportMessage,\n TransportMessage,\n HandshakeErrorResponseCodes,\n} from '../message';\nimport {\n IdentifiedSessionWithGracePeriod,\n IdentifiedSessionWithGracePeriodListeners,\n IdentifiedSessionWithGracePeriodProps,\n SessionState,\n} from './common';\n\nexport interface SessionHandshakingListeners\n extends IdentifiedSessionWithGracePeriodListeners {\n onConnectionErrored: (err: unknown) => void;\n onConnectionClosed: () => void;\n onHandshake: (msg: OpaqueTransportMessage) => void;\n onInvalidHandshake: (\n reason: string,\n code: Static<typeof HandshakeErrorResponseCodes>,\n ) => void;\n\n // timeout related\n onHandshakeTimeout: () => void;\n}\n\nexport interface SessionHandshakingProps<ConnType extends Connection>\n extends IdentifiedSessionWithGracePeriodProps {\n conn: ConnType;\n listeners: SessionHandshakingListeners;\n}\n\n/*\n * A session that is handshaking and waiting for the other side to identify itself.\n * See transitions.ts for valid transitions.\n */\nexport class SessionHandshaking<\n ConnType extends Connection,\n> extends IdentifiedSessionWithGracePeriod {\n readonly state = SessionState.Handshaking as const;\n conn: ConnType;\n listeners: SessionHandshakingListeners;\n\n handshakeTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(props: SessionHandshakingProps<ConnType>) {\n super(props);\n this.conn = props.conn;\n this.listeners = props.listeners;\n\n this.handshakeTimeout = setTimeout(() => {\n this.listeners.onHandshakeTimeout();\n }, this.options.handshakeTimeoutMs);\n\n this.conn.addDataListener(this.onHandshakeData);\n this.conn.addErrorListener(this.listeners.onConnectionErrored);\n this.conn.addCloseListener(this.listeners.onConnectionClosed);\n }\n\n onHandshakeData = (msg: Uint8Array) => {\n const parsedMsg = this.parseMsg(msg);\n if (parsedMsg === null) {\n this.listeners.onInvalidHandshake(\n 'could not parse message',\n 'MALFORMED_HANDSHAKE',\n );\n return;\n }\n\n this.listeners.onHandshake(parsedMsg);\n };\n\n sendHandshake(msg: TransportMessage): boolean {\n return this.conn.send(this.options.codec.toBuffer(msg));\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n this.conn.removeDataListener(this.onHandshakeData);\n this.conn.removeErrorListener(this.listeners.onConnectionErrored);\n this.conn.removeCloseListener(this.listeners.onConnectionClosed);\n\n if (this.handshakeTimeout) {\n clearTimeout(this.handshakeTimeout);\n this.handshakeTimeout = undefined;\n }\n }\n\n _handleClose(): void {\n super._handleClose();\n this.conn.close();\n }\n}\n","import { Static } from '@sinclair/typebox';\nimport {\n ControlFlags,\n ControlMessageAckSchema,\n OpaqueTransportMessage,\n PartialTransportMessage,\n isAck,\n} from '../message';\nimport {\n IdentifiedSession,\n IdentifiedSessionProps,\n SessionState,\n} from './common';\nimport { Connection } from '../connection';\nimport { SpanStatusCode } from '@opentelemetry/api';\n\nexport interface SessionConnectedListeners {\n onConnectionErrored: (err: unknown) => void;\n onConnectionClosed: () => void;\n onMessage: (msg: OpaqueTransportMessage) => void;\n onInvalidMessage: (reason: string) => void;\n}\n\nexport interface SessionConnectedProps<ConnType extends Connection>\n extends IdentifiedSessionProps {\n conn: ConnType;\n listeners: SessionConnectedListeners;\n}\n\n/*\n * A session that is connected and can send and receive messages.\n * See transitions.ts for valid transitions.\n */\nexport class SessionConnected<\n ConnType extends Connection,\n> extends IdentifiedSession {\n readonly state = SessionState.Connected as const;\n conn: ConnType;\n listeners: SessionConnectedListeners;\n\n private heartbeatHandle?: ReturnType<typeof setInterval> | undefined;\n private heartbeatMisses = 0;\n isActivelyHeartbeating: boolean;\n\n updateBookkeeping(ack: number, seq: number) {\n this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);\n this.ack = seq + 1;\n this.heartbeatMisses = 0;\n }\n\n send(msg: PartialTransportMessage): string {\n const constructedMsg = this.constructMsg(msg);\n this.sendBuffer.push(constructedMsg);\n this.conn.send(this.options.codec.toBuffer(constructedMsg));\n return constructedMsg.id;\n }\n\n constructor(props: SessionConnectedProps<ConnType>) {\n super(props);\n this.conn = props.conn;\n this.listeners = props.listeners;\n\n this.conn.addDataListener(this.onMessageData);\n this.conn.addCloseListener(this.listeners.onConnectionClosed);\n this.conn.addErrorListener(this.listeners.onConnectionErrored);\n\n // send any buffered messages\n if (this.sendBuffer.length > 0) {\n this.log?.debug(\n `sending ${this.sendBuffer.length} buffered messages`,\n this.loggingMetadata,\n );\n }\n\n for (const msg of this.sendBuffer) {\n this.conn.send(this.options.codec.toBuffer(msg));\n }\n\n // dont explicity clear the buffer, we'll just filter out old messages\n // when we receive an ack\n\n // setup heartbeat\n this.isActivelyHeartbeating = false;\n this.heartbeatHandle = setInterval(() => {\n const misses = this.heartbeatMisses;\n const missDuration = misses * this.options.heartbeatIntervalMs;\n if (misses >= this.options.heartbeatsUntilDead) {\n this.log?.info(\n `closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,\n this.loggingMetadata,\n );\n this.telemetry.span.addEvent('closing connection due to inactivity');\n\n // it is OK to close this even on the client when we can't trust the client timer\n // due to browser throttling or hibernation\n // at worst, this interval will fire later than what the server expects and the server\n // will have already closed the connection\n // this just helps us in cases where we have a proxying setup where the server has closed\n // the connection but the proxy hasn't synchronized the server-side close to the client so\n // the client isn't stuck with a pseudo-dead connection forever\n this.conn.close();\n clearInterval(this.heartbeatHandle);\n this.heartbeatHandle = undefined;\n return;\n }\n\n if (this.isActivelyHeartbeating) {\n this.sendHeartbeat();\n }\n\n this.heartbeatMisses++;\n }, this.options.heartbeatIntervalMs);\n }\n\n startActiveHeartbeat() {\n this.isActivelyHeartbeating = true;\n }\n\n private sendHeartbeat() {\n this.log?.debug('sending heartbeat', this.loggingMetadata);\n this.send({\n streamId: 'heartbeat',\n controlFlags: ControlFlags.AckBit,\n payload: {\n type: 'ACK',\n } satisfies Static<typeof ControlMessageAckSchema>,\n });\n }\n\n onMessageData = (msg: Uint8Array) => {\n const parsedMsg = this.parseMsg(msg);\n if (parsedMsg === null) {\n this.listeners.onInvalidMessage('could not parse message');\n return;\n }\n\n // check message ordering here\n if (parsedMsg.seq !== this.ack) {\n if (parsedMsg.seq < this.ack) {\n this.log?.debug(\n `received duplicate msg (got seq: ${parsedMsg.seq}, wanted seq: ${this.ack}), discarding`,\n {\n ...this.loggingMetadata,\n transportMessage: parsedMsg,\n },\n );\n } else {\n const reason = `received out-of-order msg (got seq: ${parsedMsg.seq}, wanted seq: ${this.ack})`;\n this.log?.error(reason, {\n ...this.loggingMetadata,\n transportMessage: parsedMsg,\n tags: ['invariant-violation'],\n });\n this.telemetry.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: reason,\n });\n\n this.listeners.onInvalidMessage(reason);\n }\n\n return;\n }\n\n // message is ok to update bookkeeping with\n this.log?.debug(`received msg`, {\n ...this.loggingMetadata,\n transportMessage: parsedMsg,\n });\n\n this.updateBookkeeping(parsedMsg.ack, parsedMsg.seq);\n\n // dispatch directly if its not an explicit ack\n if (!isAck(parsedMsg.controlFlags)) {\n this.listeners.onMessage(parsedMsg);\n return;\n }\n\n // discard acks (unless we aren't heartbeating in which case just respond)\n this.log?.debug(`discarding msg (ack bit set)`, {\n ...this.loggingMetadata,\n transportMessage: parsedMsg,\n });\n\n // if we are not actively heartbeating, we are in passive\n // heartbeat mode and should send a response to the ack\n if (!this.isActivelyHeartbeating) {\n this.sendHeartbeat();\n }\n };\n\n _handleStateExit(): void {\n super._handleStateExit();\n this.conn.removeDataListener(this.onMessageData);\n this.conn.removeCloseListener(this.listeners.onConnectionClosed);\n this.conn.removeErrorListener(this.listeners.onConnectionErrored);\n clearInterval(this.heartbeatHandle);\n this.heartbeatHandle = undefined;\n }\n\n _handleClose(): void {\n super._handleClose();\n this.conn.close();\n }\n}\n","import {\n IdentifiedSessionWithGracePeriod,\n IdentifiedSessionWithGracePeriodListeners,\n IdentifiedSessionWithGracePeriodProps,\n SessionState,\n} from './common';\n\nexport interface SessionBackingOffListeners\n extends IdentifiedSessionWithGracePeriodListeners {\n onBackoffFinished: () => void;\n}\n\nexport interface SessionBackingOffProps\n extends IdentifiedSessionWithGracePeriodProps {\n backoffMs: number;\n listeners: SessionBackingOffListeners;\n}\n\n/*\n * A session that is backing off before attempting to connect.\n * See transitions.ts for valid transitions.\n */\nexport class SessionBackingOff extends IdentifiedSessionWithGracePeriod {\n readonly state = SessionState.BackingOff as const;\n listeners: SessionBackingOffListeners;\n\n backoffTimeout?: ReturnType<typeof setTimeout>;\n\n constructor(props: SessionBackingOffProps) {\n super(props);\n this.listeners = props.listeners;\n\n this.backoffTimeout = setTimeout(() => {\n this.listeners.onBackoffFinished();\n }, props.backoffMs);\n }\n\n _handleClose(): void {\n super._handleClose();\n }\n\n _handleStateExit(): void {\n super._handleStateExit();\n\n if (this.backoffTimeout) {\n clearTimeout(this.backoffTimeout);\n this.backoffTimeout = undefined;\n }\n }\n}\n","import { OpaqueTransportMessage, TransportClientId } from '..';\nimport {\n SessionConnecting,\n SessionConnectingListeners,\n} from './SessionConnecting';\nimport {\n SessionNoConnection,\n SessionNoConnectionListeners,\n} from './SessionNoConnection';\nimport {\n IdentifiedSession,\n IdentifiedSessionProps,\n IdentifiedSessionWithGracePeriod,\n IdentifiedSessionWithGracePeriodProps,\n SessionOptions,\n} from './common';\nimport { PropagationContext, createSessionTelemetryInfo } from '../../tracing';\nimport {\n SessionWaitingForHandshake,\n SessionWaitingForHandshakeListeners,\n} from './SessionWaitingForHandshake';\nimport {\n SessionHandshaking,\n SessionHandshakingListeners,\n} from './SessionHandshaking';\nimport {\n SessionConnected,\n SessionConnectedListeners,\n} from './SessionConnected';\nimport { generateId } from '../id';\nimport { Connection } from '../connection';\nimport { Logger } from '../../logging';\nimport {\n SessionBackingOff,\n SessionBackingOffListeners,\n} from './SessionBackingOff';\n\nfunction inheritSharedSession(\n session: IdentifiedSession,\n): IdentifiedSessionProps {\n return {\n id: session.id,\n from: session.from,\n to: session.to,\n seq: session.seq,\n ack: session.ack,\n sendBuffer: session.sendBuffer,\n telemetry: session.telemetry,\n options: session.options,\n log: session.log,\n };\n}\n\nfunction inheritSharedSessionWithGrace(\n session: IdentifiedSessionWithGracePeriod,\n): Omit<IdentifiedSessionWithGracePeriodProps, 'listeners'> {\n return {\n ...inheritSharedSession(session),\n graceExpiryTime: session.graceExpiryTime,\n };\n}\n\nexport const SessionStateGraph = {\n entrypoints: {\n NoConnection: (\n to: TransportClientId,\n from: TransportClientId,\n listeners: SessionNoConnectionListeners,\n options: SessionOptions,\n log?: Logger,\n ) => {\n const id = `session-${generateId()}`;\n const telemetry = createSessionTelemetryInfo(id, to, from);\n const sendBuffer: Array<OpaqueTransportMessage> = [];\n\n const session = new SessionNoConnection({\n listeners,\n id,\n from,\n to,\n seq: 0,\n ack: 0,\n graceExpiryTime: Date.now() + options.sessionDisconnectGraceMs,\n sendBuffer,\n telemetry,\n options,\n log,\n });\n\n session.log?.info(`session ${session.id} created in NoConnection state`, {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n });\n\n return session;\n },\n WaitingForHandshake: <ConnType extends Connection>(\n from: TransportClientId,\n conn: ConnType,\n listeners: SessionWaitingForHandshakeListeners,\n options: SessionOptions,\n log?: Logger,\n ): SessionWaitingForHandshake<ConnType> => {\n const session = new SessionWaitingForHandshake({\n conn,\n listeners,\n from,\n options,\n log,\n });\n\n session.log?.info(`session created in WaitingForHandshake state`, {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n });\n\n return session;\n },\n },\n // All of the transitions 'move'/'consume' the old session and return a new one.\n // After a session is transitioned, any usage of the old session will throw.\n transition: {\n // happy path transitions\n NoConnectionToBackingOff: (\n oldSession: SessionNoConnection,\n backoffMs: number,\n listeners: SessionBackingOffListeners,\n ): SessionBackingOff => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession._handleStateExit();\n\n const session = new SessionBackingOff({\n backoffMs,\n listeners,\n ...carriedState,\n });\n\n session.log?.info(\n `session ${session.id} transition from NoConnection to BackingOff`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n return session;\n },\n BackingOffToConnecting: <ConnType extends Connection>(\n oldSession: SessionBackingOff,\n connPromise: Promise<ConnType>,\n listeners: SessionConnectingListeners,\n ): SessionConnecting<ConnType> => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession._handleStateExit();\n\n const session = new SessionConnecting({\n connPromise,\n listeners,\n ...carriedState,\n });\n\n session.log?.info(\n `session ${session.id} transition from BackingOff to Connecting`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n return session;\n },\n ConnectingToHandshaking: <ConnType extends Connection>(\n oldSession: SessionConnecting<ConnType>,\n conn: ConnType,\n listeners: SessionHandshakingListeners,\n ): SessionHandshaking<ConnType> => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession._handleStateExit();\n\n const session = new SessionHandshaking({\n conn,\n listeners,\n ...carriedState,\n });\n\n session.log?.info(\n `session ${session.id} transition from Connecting to Handshaking`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n HandshakingToConnected: <ConnType extends Connection>(\n oldSession: SessionHandshaking<ConnType>,\n listeners: SessionConnectedListeners,\n ): SessionConnected<ConnType> => {\n const carriedState = inheritSharedSession(oldSession);\n const conn = oldSession.conn;\n oldSession._handleStateExit();\n\n const session = new SessionConnected({\n conn,\n listeners,\n ...carriedState,\n });\n\n session.log?.info(\n `session ${session.id} transition from Handshaking to Connected`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n WaitingForHandshakeToConnected: <ConnType extends Connection>(\n pendingSession: SessionWaitingForHandshake<ConnType>,\n oldSession: SessionNoConnection | undefined,\n sessionId: string,\n to: TransportClientId,\n propagationCtx: PropagationContext | undefined,\n listeners: SessionConnectedListeners,\n ): SessionConnected<ConnType> => {\n const conn = pendingSession.conn;\n const { from, options } = pendingSession;\n const carriedState: IdentifiedSessionProps = oldSession\n ? // old session exists, inherit state\n inheritSharedSession(oldSession)\n : // old session does not exist, create new state\n {\n id: sessionId,\n from,\n to,\n seq: 0,\n ack: 0,\n sendBuffer: [],\n telemetry: createSessionTelemetryInfo(\n sessionId,\n to,\n from,\n propagationCtx,\n ),\n options,\n log: pendingSession.log,\n };\n\n pendingSession._handleStateExit();\n oldSession?._handleStateExit();\n\n const session = new SessionConnected({\n conn,\n listeners,\n ...carriedState,\n });\n session.log?.info(\n `session ${session.id} transition from WaitingForHandshake to Connected`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n // disconnect paths\n BackingOffToNoConnection: (\n oldSession: SessionBackingOff,\n listeners: SessionNoConnectionListeners,\n ): SessionNoConnection => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection({\n listeners,\n ...carriedState,\n });\n session.log?.info(\n `session ${session.id} transition from BackingOff to NoConnection`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n ConnectingToNoConnection: <ConnType extends Connection>(\n oldSession: SessionConnecting<ConnType>,\n listeners: SessionNoConnectionListeners,\n ): SessionNoConnection => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession.bestEffortClose();\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection({\n listeners,\n ...carriedState,\n });\n session.log?.info(\n `session ${session.id} transition from Connecting to NoConnection`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n HandshakingToNoConnection: <ConnType extends Connection>(\n oldSession: SessionHandshaking<ConnType>,\n listeners: SessionNoConnectionListeners,\n ): SessionNoConnection => {\n const carriedState = inheritSharedSessionWithGrace(oldSession);\n oldSession.conn.close();\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection({\n listeners,\n ...carriedState,\n });\n session.log?.info(\n `session ${session.id} transition from Handshaking to NoConnection`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n ConnectedToNoConnection: <ConnType extends Connection>(\n oldSession: SessionConnected<ConnType>,\n listeners: SessionNoConnectionListeners,\n ): SessionNoConnection => {\n const carriedState = inheritSharedSession(oldSession);\n const graceExpiryTime =\n Date.now() + oldSession.options.sessionDisconnectGraceMs;\n oldSession.conn.close();\n oldSession._handleStateExit();\n\n const session = new SessionNoConnection({\n listeners,\n graceExpiryTime,\n ...carriedState,\n });\n session.log?.info(\n `session ${session.id} transition from Connected to NoConnection`,\n {\n ...session.loggingMetadata,\n tags: ['state-transition'],\n },\n );\n\n return session;\n },\n },\n} as const;\n\nconst transitions = SessionStateGraph.transition;\n\nexport const ClientSessionStateGraph = {\n entrypoint: SessionStateGraph.entrypoints.NoConnection,\n transition: {\n // happy paths\n // NoConnection -> BackingOff: attempt to connect\n NoConnectionToBackingOff: transitions.NoConnectionToBackingOff,\n // BackingOff -> Connecting: backoff period elapsed, start connection\n BackingOffToConnecting: transitions.BackingOffToConnecting,\n // Connecting -> Handshaking: connection established, start handshake\n ConnectingToHandshaking: transitions.ConnectingToHandshaking,\n // Handshaking -> Connected: handshake complete, session ready\n HandshakingToConnected: transitions.HandshakingToConnected,\n\n // disconnect paths\n // BackingOff -> NoConnection: unused\n BackingOffToNoConnection: transitions.BackingOffToNoConnection,\n // Connecting -> NoConnection: connection failed or connection timeout\n ConnectingToNoConnection: transitions.ConnectingToNoConnection,\n // Handshaking -> NoConnection: connection closed or handshake timeout\n HandshakingToNoConnection: transitions.HandshakingToNoConnection,\n // Connected -> NoConnection: connection closed\n ConnectedToNoConnection: transitions.ConnectedToNoConnection,\n\n // destroy/close paths\n // NoConnection -> x: grace period elapsed\n // BackingOff -> x: grace period elapsed\n // Connecting -> x: grace period elapsed\n // Handshaking -> x: grace period elapsed or invalid handshake message or handshake rejection\n // Connected -> x: grace period elapsed or invalid message\n },\n};\n\nexport type ClientSession<ConnType extends Connection> =\n | SessionNoConnection\n | SessionBackingOff\n | SessionConnecting<ConnType>\n | SessionHandshaking<ConnType>\n | SessionConnected<ConnType>;\n\nexport const ServerSessionStateGraph = {\n entrypoint: SessionStateGraph.entrypoints.WaitingForHandshake,\n transition: {\n // happy paths\n // WaitingForHandshake -> Connected: handshake complete, session ready\n WaitingForHandshakeToConnected: transitions.WaitingForHandshakeToConnected,\n\n // disconnect paths\n // Connected -> NoConnection: connection closed\n ConnectedToNoConnection: transitions.ConnectedToNoConnection,\n\n // destroy/close paths\n // WaitingForHandshake -> x: handshake timeout elapsed or invalid handshake message or handshake rejection or connection closed\n },\n};\n\nexport type ServerSession<ConnType extends Connection> =\n // SessionWaitingForHandshake<ConnType> is stored separately in the server transport\n SessionConnected<ConnType> | SessionNoConnection;\n\nexport type Session<ConnType extends Connection> =\n | ClientSession<ConnType>\n | ServerSession<ConnType>;\n"],"mappings":"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","names":["SessionState"]}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ProtocolError,
|
|
3
3
|
Transport
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-M5X4JTU3.js";
|
|
5
5
|
import {
|
|
6
6
|
ServerSessionStateGraph,
|
|
7
7
|
defaultServerTransportOptions
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-NC54BC47.js";
|
|
9
9
|
import {
|
|
10
10
|
ControlMessageHandshakeRequestSchema,
|
|
11
11
|
HandshakeErrorCustomHandlerFatalResponseCodes,
|
|
12
12
|
PROTOCOL_VERSION,
|
|
13
13
|
coerceErrorString,
|
|
14
14
|
handshakeResponseMessage
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-M75K5TJS.js";
|
|
16
16
|
|
|
17
17
|
// transport/server.ts
|
|
18
18
|
import { SpanStatusCode } from "@opentelemetry/api";
|
|
@@ -127,13 +127,17 @@ var ServerTransport = class extends Transport {
|
|
|
127
127
|
receivedHandshake = true;
|
|
128
128
|
void this.onHandshakeRequest(pendingSession, msg);
|
|
129
129
|
},
|
|
130
|
-
onInvalidHandshake: (reason) => {
|
|
130
|
+
onInvalidHandshake: (reason, code) => {
|
|
131
131
|
this.log?.error(
|
|
132
132
|
`invalid handshake: ${reason}`,
|
|
133
133
|
pendingSession.loggingMetadata
|
|
134
134
|
);
|
|
135
135
|
this.deletePendingSession(pendingSession);
|
|
136
|
-
this.protocolError(
|
|
136
|
+
this.protocolError({
|
|
137
|
+
type: ProtocolError.HandshakeFailed,
|
|
138
|
+
code,
|
|
139
|
+
message: reason
|
|
140
|
+
});
|
|
137
141
|
}
|
|
138
142
|
},
|
|
139
143
|
this.options,
|
|
@@ -158,7 +162,11 @@ var ServerTransport = class extends Transport {
|
|
|
158
162
|
}
|
|
159
163
|
})
|
|
160
164
|
);
|
|
161
|
-
this.protocolError(
|
|
165
|
+
this.protocolError({
|
|
166
|
+
type: ProtocolError.HandshakeFailed,
|
|
167
|
+
code,
|
|
168
|
+
message: reason
|
|
169
|
+
});
|
|
162
170
|
this.deletePendingSession(session);
|
|
163
171
|
}
|
|
164
172
|
async onHandshakeRequest(session, msg) {
|
|
@@ -207,7 +215,7 @@ var ServerTransport = class extends Transport {
|
|
|
207
215
|
let connectCase = "new session";
|
|
208
216
|
const clientNextExpectedSeq = msg.payload.expectedSessionState.nextExpectedSeq;
|
|
209
217
|
const clientNextSentSeq = msg.payload.expectedSessionState.nextSentSeq ?? 0;
|
|
210
|
-
if (oldSession && oldSession.id === msg.payload.sessionId) {
|
|
218
|
+
if (this.options.enableTransparentSessionReconnects && oldSession && oldSession.id === msg.payload.sessionId) {
|
|
211
219
|
connectCase = "transparent reconnection";
|
|
212
220
|
const ourNextSeq = oldSession.nextSeq();
|
|
213
221
|
const ourAck = oldSession.ack;
|
|
@@ -266,10 +274,11 @@ var ServerTransport = class extends Transport {
|
|
|
266
274
|
}
|
|
267
275
|
if (!oldSession && (clientNextSentSeq > 0 || clientNextExpectedSeq > 0)) {
|
|
268
276
|
connectCase = "unknown session";
|
|
277
|
+
const rejectionMessage = this.options.enableTransparentSessionReconnects ? `client is trying to reconnect to a session the server don't know about: ${msg.payload.sessionId}` : `client is attempting a transparent reconnect to a session but the server does not support it: ${msg.payload.sessionId}`;
|
|
269
278
|
this.rejectHandshakeRequest(
|
|
270
279
|
session,
|
|
271
280
|
msg.from,
|
|
272
|
-
|
|
281
|
+
rejectionMessage,
|
|
273
282
|
"SESSION_STATE_MISMATCH",
|
|
274
283
|
{
|
|
275
284
|
...session.loggingMetadata,
|
|
@@ -320,7 +329,10 @@ var ServerTransport = class extends Transport {
|
|
|
320
329
|
},
|
|
321
330
|
onMessage: (msg2) => this.handleMsg(msg2),
|
|
322
331
|
onInvalidMessage: (reason) => {
|
|
323
|
-
this.protocolError(
|
|
332
|
+
this.protocolError({
|
|
333
|
+
type: ProtocolError.MessageOrderingViolated,
|
|
334
|
+
message: reason
|
|
335
|
+
});
|
|
324
336
|
this.deleteSession(connectedSession);
|
|
325
337
|
}
|
|
326
338
|
}
|
|
@@ -351,16 +363,19 @@ var ServerTransport = class extends Transport {
|
|
|
351
363
|
return false;
|
|
352
364
|
}
|
|
353
365
|
const previousParsedMetadata = existingSession ? this.sessionHandshakeMetadata.get(existingSession.to) : void 0;
|
|
354
|
-
const
|
|
366
|
+
const parsedMetadataOrFailureCode = await this.handshakeExtensions.validate(
|
|
355
367
|
rawMetadata,
|
|
356
368
|
previousParsedMetadata
|
|
357
369
|
);
|
|
358
|
-
if (Value.Check(
|
|
370
|
+
if (Value.Check(
|
|
371
|
+
HandshakeErrorCustomHandlerFatalResponseCodes,
|
|
372
|
+
parsedMetadataOrFailureCode
|
|
373
|
+
)) {
|
|
359
374
|
this.rejectHandshakeRequest(
|
|
360
375
|
handshakingSession,
|
|
361
376
|
from,
|
|
362
377
|
"rejected by handshake handler",
|
|
363
|
-
|
|
378
|
+
parsedMetadataOrFailureCode,
|
|
364
379
|
{
|
|
365
380
|
...handshakingSession.loggingMetadata,
|
|
366
381
|
connectedTo: from,
|
|
@@ -369,11 +384,11 @@ var ServerTransport = class extends Transport {
|
|
|
369
384
|
);
|
|
370
385
|
return false;
|
|
371
386
|
}
|
|
372
|
-
return
|
|
387
|
+
return parsedMetadataOrFailureCode;
|
|
373
388
|
}
|
|
374
389
|
};
|
|
375
390
|
|
|
376
391
|
export {
|
|
377
392
|
ServerTransport
|
|
378
393
|
};
|
|
379
|
-
//# sourceMappingURL=chunk-
|
|
394
|
+
//# sourceMappingURL=chunk-YQABPD3C.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../transport/server.ts"],"sourcesContent":["import { SpanStatusCode } from '@opentelemetry/api';\nimport { ParsedMetadata } from '../router/context';\nimport { ServerHandshakeOptions } from '../router/handshake';\nimport {\n ControlMessageHandshakeRequestSchema,\n HandshakeErrorCustomHandlerFatalResponseCodes,\n HandshakeErrorResponseCodes,\n OpaqueTransportMessage,\n PROTOCOL_VERSION,\n PartialTransportMessage,\n TransportClientId,\n handshakeResponseMessage,\n} from './message';\nimport {\n ProvidedServerTransportOptions,\n ServerTransportOptions,\n defaultServerTransportOptions,\n} from './options';\nimport { Transport } from './transport';\nimport { coerceErrorString } from '../util/stringify';\nimport { Static } from '@sinclair/typebox';\nimport { Value } from '@sinclair/typebox/value';\nimport { ProtocolError } from './events';\nimport { Connection } from './connection';\nimport { MessageMetadata } from '../logging';\nimport { SessionWaitingForHandshake } from './sessionStateMachine/SessionWaitingForHandshake';\nimport { SessionState } from './sessionStateMachine/common';\nimport {\n ServerSession,\n ServerSessionStateGraph,\n} from './sessionStateMachine/transitions';\n\nexport abstract class ServerTransport<\n ConnType extends Connection,\n> extends Transport<ConnType> {\n /**\n * The options for this transport.\n */\n protected options: ServerTransportOptions;\n\n /**\n * Optional handshake options for the server.\n */\n handshakeExtensions?: ServerHandshakeOptions;\n\n /**\n * A map of session handshake data for each session.\n */\n sessionHandshakeMetadata = new Map<TransportClientId, ParsedMetadata>();\n\n sessions = new Map<TransportClientId, ServerSession<ConnType>>();\n pendingSessions = new Set<SessionWaitingForHandshake<ConnType>>();\n\n constructor(\n clientId: TransportClientId,\n providedOptions?: ProvidedServerTransportOptions,\n ) {\n super(clientId, providedOptions);\n this.sessions = new Map();\n this.options = {\n ...defaultServerTransportOptions,\n ...providedOptions,\n };\n this.log?.info(`initiated server transport`, {\n clientId: this.clientId,\n protocolVersion: PROTOCOL_VERSION,\n });\n }\n\n extendHandshake(options: ServerHandshakeOptions) {\n this.handshakeExtensions = options;\n }\n\n send(to: string, msg: PartialTransportMessage): string {\n if (this.getStatus() === 'closed') {\n const err = 'transport is closed, cant send';\n this.log?.error(err, {\n clientId: this.clientId,\n transportMessage: msg,\n tags: ['invariant-violation'],\n });\n\n throw new Error(err);\n }\n\n const session = this.sessions.get(to);\n if (!session) {\n const err = `session to ${to} does not exist`;\n this.log?.error(err, {\n clientId: this.clientId,\n transportMessage: msg,\n tags: ['invariant-violation'],\n });\n\n throw new Error(err);\n }\n\n return session.send(msg);\n }\n\n protected deletePendingSession(\n pendingSession: SessionWaitingForHandshake<ConnType>,\n ) {\n pendingSession.close();\n // we don't dispatch a session disconnect event\n // for a non-identified session, just delete directly\n\n this.pendingSessions.delete(pendingSession);\n }\n\n protected deleteSession(session: ServerSession<ConnType>): void {\n this.sessionHandshakeMetadata.delete(session.to);\n super.deleteSession(session);\n }\n\n protected handleConnection(conn: ConnType) {\n if (this.getStatus() !== 'open') return;\n\n this.log?.info(`new incoming connection`, {\n ...conn.loggingMetadata,\n clientId: this.clientId,\n });\n\n let receivedHandshake = false;\n const pendingSession = ServerSessionStateGraph.entrypoint(\n this.clientId,\n conn,\n {\n onConnectionClosed: () => {\n this.log?.warn(\n `connection from unknown closed before handshake finished`,\n pendingSession.loggingMetadata,\n );\n\n this.deletePendingSession(pendingSession);\n },\n onConnectionErrored: (err) => {\n const errorString = coerceErrorString(err);\n this.log?.warn(\n `connection from unknown errored before handshake finished: ${errorString}`,\n pendingSession.loggingMetadata,\n );\n\n this.deletePendingSession(pendingSession);\n },\n onHandshakeTimeout: () => {\n this.log?.warn(\n `connection from unknown timed out before handshake finished`,\n pendingSession.loggingMetadata,\n );\n\n this.deletePendingSession(pendingSession);\n },\n onHandshake: (msg) => {\n if (receivedHandshake) {\n this.log?.error(\n `received multiple handshake messages from pending session`,\n {\n ...pendingSession.loggingMetadata,\n connectedTo: msg.from,\n transportMessage: msg,\n },\n );\n\n this.deletePendingSession(pendingSession);\n return;\n }\n\n // let this resolve async, we just need to make sure its only\n // called once so we don't race while transitioning to connected\n // onHandshakeRequest is async as custom validation may be async\n receivedHandshake = true;\n void this.onHandshakeRequest(pendingSession, msg);\n },\n onInvalidHandshake: (reason, code) => {\n this.log?.error(\n `invalid handshake: ${reason}`,\n pendingSession.loggingMetadata,\n );\n this.deletePendingSession(pendingSession);\n this.protocolError({\n type: ProtocolError.HandshakeFailed,\n code,\n message: reason,\n });\n },\n },\n this.options,\n this.log,\n );\n\n this.pendingSessions.add(pendingSession);\n }\n\n private rejectHandshakeRequest(\n session: SessionWaitingForHandshake<ConnType>,\n to: TransportClientId,\n reason: string,\n code: Static<typeof HandshakeErrorResponseCodes>,\n metadata: MessageMetadata,\n ) {\n session.conn.telemetry?.span.setStatus({\n code: SpanStatusCode.ERROR,\n message: reason,\n });\n\n this.log?.warn(reason, metadata);\n\n session.sendHandshake(\n handshakeResponseMessage({\n from: this.clientId,\n to,\n status: {\n ok: false,\n code,\n reason,\n },\n }),\n );\n\n this.protocolError({\n type: ProtocolError.HandshakeFailed,\n code,\n message: reason,\n });\n this.deletePendingSession(session);\n }\n\n protected async onHandshakeRequest(\n session: SessionWaitingForHandshake<ConnType>,\n msg: OpaqueTransportMessage,\n ) {\n // invariant: msg is a handshake request\n if (!Value.Check(ControlMessageHandshakeRequestSchema, msg.payload)) {\n this.rejectHandshakeRequest(\n session,\n msg.from,\n 'received invalid handshake request',\n 'MALFORMED_HANDSHAKE',\n {\n ...session.loggingMetadata,\n transportMessage: msg,\n connectedTo: msg.from,\n validationErrors: [\n ...Value.Errors(ControlMessageHandshakeRequestSchema, msg.payload),\n ],\n },\n );\n\n return;\n }\n\n // invariant: handshake request passes all the validation\n const gotVersion = msg.payload.protocolVersion;\n if (gotVersion !== PROTOCOL_VERSION) {\n this.rejectHandshakeRequest(\n session,\n msg.from,\n `expected protocol version ${PROTOCOL_VERSION}, got ${gotVersion}`,\n 'PROTOCOL_VERSION_MISMATCH',\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n transportMessage: msg,\n },\n );\n\n return;\n }\n\n let oldSession = this.sessions.get(msg.from);\n\n // invariant: must pass custom validation if defined\n const parsedMetadata = await this.validateHandshakeMetadata(\n session,\n oldSession,\n msg.payload.metadata,\n msg.from,\n );\n\n if (parsedMetadata === false) {\n return;\n }\n\n // 4 connect cases\n // 1. new session\n // we dont have a session and the client is requesting a new one\n // we can create the session as normal\n // 2. client is reconnecting to an existing session but we don't have it\n // reject this handshake, there's nothing we can do to salvage it\n // 3. transparent reconnect (old session exists and is the same as the client wants)\n // assign to old session\n // 4. hard reconnect (oldSession exists but but the client wants a new one)\n // we close the old session and create a new one\n let connectCase:\n | 'new session'\n | 'unknown session'\n | 'transparent reconnection'\n | 'hard reconnection' = 'new session';\n const clientNextExpectedSeq =\n msg.payload.expectedSessionState.nextExpectedSeq;\n const clientNextSentSeq = msg.payload.expectedSessionState.nextSentSeq ?? 0;\n\n if (\n this.options.enableTransparentSessionReconnects &&\n oldSession &&\n oldSession.id === msg.payload.sessionId\n ) {\n connectCase = 'transparent reconnection';\n\n // invariant: ordering must be correct\n const ourNextSeq = oldSession.nextSeq();\n const ourAck = oldSession.ack;\n\n // two incorrect cases where we cannot permit a reconnect:\n // - if the client is about to send a message in the future w.r.t to the server\n // - client.seq > server.ack => nextSentSeq > oldSession.ack\n if (clientNextSentSeq > ourAck) {\n this.rejectHandshakeRequest(\n session,\n msg.from,\n `client is in the future: server wanted next message to be ${ourAck} but client would have sent ${clientNextSentSeq}`,\n 'SESSION_STATE_MISMATCH',\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n transportMessage: msg,\n },\n );\n\n return;\n }\n\n // - if the server is about to send a message in the future w.r.t to the client\n // - server.seq > client.ack => oldSession.nextSeq() > nextExpectedSeq\n if (ourNextSeq > clientNextExpectedSeq) {\n this.rejectHandshakeRequest(\n session,\n msg.from,\n `server is in the future: client wanted next message to be ${clientNextExpectedSeq} but server would have sent ${ourNextSeq}`,\n 'SESSION_STATE_MISMATCH',\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n transportMessage: msg,\n },\n );\n\n return;\n }\n\n // transparent reconnect seems ok, proceed by transitioning old session\n // to not connected\n if (oldSession.state !== SessionState.NoConnection) {\n const noConnectionSession =\n ServerSessionStateGraph.transition.ConnectedToNoConnection(\n oldSession,\n {\n onSessionGracePeriodElapsed: () => {\n this.onSessionGracePeriodElapsed(noConnectionSession);\n },\n },\n );\n\n oldSession = noConnectionSession;\n }\n\n this.updateSession(oldSession);\n } else if (oldSession) {\n connectCase = 'hard reconnection';\n\n // just nuke the old session entirely and proceed as if this was new\n this.log?.info(\n `client is reconnecting to a new session (${msg.payload.sessionId}) with an old session (${oldSession.id}) already existing, closing old session`,\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n sessionId: msg.payload.sessionId,\n },\n );\n this.deleteSession(oldSession);\n oldSession = undefined;\n }\n\n if (!oldSession && (clientNextSentSeq > 0 || clientNextExpectedSeq > 0)) {\n // we don't have a session, but the client is trying to reconnect\n // to an old session. we can't do anything about this, so we reject\n connectCase = 'unknown session';\n\n const rejectionMessage = this.options.enableTransparentSessionReconnects\n ? `client is trying to reconnect to a session the server don't know about: ${msg.payload.sessionId}`\n : `client is attempting a transparent reconnect to a session but the server does not support it: ${msg.payload.sessionId}`;\n\n this.rejectHandshakeRequest(\n session,\n msg.from,\n rejectionMessage,\n 'SESSION_STATE_MISMATCH',\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n transportMessage: msg,\n },\n );\n return;\n }\n\n // from this point on, we're committed to connecting\n const sessionId = msg.payload.sessionId;\n this.log?.info(\n `handshake from ${msg.from} ok (${connectCase}), responding with handshake success`,\n {\n ...session.loggingMetadata,\n connectedTo: msg.from,\n },\n );\n const responseMsg = handshakeResponseMessage({\n from: this.clientId,\n to: msg.from,\n status: {\n ok: true,\n sessionId,\n },\n });\n session.sendHandshake(responseMsg);\n\n // transition\n const connectedSession =\n ServerSessionStateGraph.transition.WaitingForHandshakeToConnected(\n session,\n // by this point oldSession is either no connection or we dont have an old session\n oldSession,\n sessionId,\n msg.from,\n msg.tracing,\n {\n onConnectionErrored: (err) => {\n // just log, when we error we also emit close\n const errStr = coerceErrorString(err);\n this.log?.warn(\n `connection to ${connectedSession.to} errored: ${errStr}`,\n connectedSession.loggingMetadata,\n );\n },\n onConnectionClosed: () => {\n this.log?.info(\n `connection to ${connectedSession.to} closed`,\n connectedSession.loggingMetadata,\n );\n this.onConnClosed(connectedSession);\n },\n onMessage: (msg) => this.handleMsg(msg),\n onInvalidMessage: (reason) => {\n this.protocolError({\n type: ProtocolError.MessageOrderingViolated,\n message: reason,\n });\n this.deleteSession(connectedSession);\n },\n },\n );\n\n this.sessionHandshakeMetadata.set(connectedSession.to, parsedMetadata);\n this.updateSession(connectedSession);\n this.pendingSessions.delete(session);\n connectedSession.startActiveHeartbeat();\n }\n\n private async validateHandshakeMetadata(\n handshakingSession: SessionWaitingForHandshake<ConnType>,\n existingSession: ServerSession<ConnType> | undefined,\n rawMetadata: Static<\n typeof ControlMessageHandshakeRequestSchema\n >['metadata'],\n from: TransportClientId,\n ): Promise<ParsedMetadata | false> {\n if (!this.handshakeExtensions) {\n return {};\n }\n\n // check that the metadata that was sent is the correct shape\n if (!Value.Check(this.handshakeExtensions.schema, rawMetadata)) {\n this.rejectHandshakeRequest(\n handshakingSession,\n from,\n 'received malformed handshake metadata',\n 'MALFORMED_HANDSHAKE_META',\n {\n ...handshakingSession.loggingMetadata,\n connectedTo: from,\n validationErrors: [\n ...Value.Errors(this.handshakeExtensions.schema, rawMetadata),\n ],\n },\n );\n\n return false;\n }\n\n const previousParsedMetadata = existingSession\n ? this.sessionHandshakeMetadata.get(existingSession.to)\n : undefined;\n\n const parsedMetadataOrFailureCode = await this.handshakeExtensions.validate(\n rawMetadata,\n previousParsedMetadata,\n );\n\n // handler rejected the connection\n if (\n Value.Check(\n HandshakeErrorCustomHandlerFatalResponseCodes,\n parsedMetadataOrFailureCode,\n )\n ) {\n this.rejectHandshakeRequest(\n handshakingSession,\n from,\n 'rejected by handshake handler',\n parsedMetadataOrFailureCode,\n {\n ...handshakingSession.loggingMetadata,\n connectedTo: from,\n clientId: this.clientId,\n },\n );\n\n return false;\n }\n\n return parsedMetadataOrFailureCode;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAAA,SAAS,sBAAsB;AAqB/B,SAAS,aAAa;AAWf,IAAe,kBAAf,cAEG,UAAoB;AAAA;AAAA;AAAA;AAAA,EAIlB;AAAA;AAAA;AAAA;AAAA,EAKV;AAAA;AAAA;AAAA;AAAA,EAKA,2BAA2B,oBAAI,IAAuC;AAAA,EAEtE,WAAW,oBAAI,IAAgD;AAAA,EAC/D,kBAAkB,oBAAI,IAA0C;AAAA,EAEhE,YACE,UACA,iBACA;AACA,UAAM,UAAU,eAAe;AAC/B,SAAK,WAAW,oBAAI,IAAI;AACxB,SAAK,UAAU;AAAA,MACb,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AACA,SAAK,KAAK,KAAK,8BAA8B;AAAA,MAC3C,UAAU,KAAK;AAAA,MACf,iBAAiB;AAAA,IACnB,CAAC;AAAA,EACH;AAAA,EAEA,gBAAgB,SAAiC;AAC/C,SAAK,sBAAsB;AAAA,EAC7B;AAAA,EAEA,KAAK,IAAY,KAAsC;AACrD,QAAI,KAAK,UAAU,MAAM,UAAU;AACjC,YAAM,MAAM;AACZ,WAAK,KAAK,MAAM,KAAK;AAAA,QACnB,UAAU,KAAK;AAAA,QACf,kBAAkB;AAAA,QAClB,MAAM,CAAC,qBAAqB;AAAA,MAC9B,CAAC;AAED,YAAM,IAAI,MAAM,GAAG;AAAA,IACrB;AAEA,UAAM,UAAU,KAAK,SAAS,IAAI,EAAE;AACpC,QAAI,CAAC,SAAS;AACZ,YAAM,MAAM,cAAc,EAAE;AAC5B,WAAK,KAAK,MAAM,KAAK;AAAA,QACnB,UAAU,KAAK;AAAA,QACf,kBAAkB;AAAA,QAClB,MAAM,CAAC,qBAAqB;AAAA,MAC9B,CAAC;AAED,YAAM,IAAI,MAAM,GAAG;AAAA,IACrB;AAEA,WAAO,QAAQ,KAAK,GAAG;AAAA,EACzB;AAAA,EAEU,qBACR,gBACA;AACA,mBAAe,MAAM;AAIrB,SAAK,gBAAgB,OAAO,cAAc;AAAA,EAC5C;AAAA,EAEU,cAAc,SAAwC;AAC9D,SAAK,yBAAyB,OAAO,QAAQ,EAAE;AAC/C,UAAM,cAAc,OAAO;AAAA,EAC7B;AAAA,EAEU,iBAAiB,MAAgB;AACzC,QAAI,KAAK,UAAU,MAAM;AAAQ;AAEjC,SAAK,KAAK,KAAK,2BAA2B;AAAA,MACxC,GAAG,KAAK;AAAA,MACR,UAAU,KAAK;AAAA,IACjB,CAAC;AAED,QAAI,oBAAoB;AACxB,UAAM,iBAAiB,wBAAwB;AAAA,MAC7C,KAAK;AAAA,MACL;AAAA,MACA;AAAA,QACE,oBAAoB,MAAM;AACxB,eAAK,KAAK;AAAA,YACR;AAAA,YACA,eAAe;AAAA,UACjB;AAEA,eAAK,qBAAqB,cAAc;AAAA,QAC1C;AAAA,QACA,qBAAqB,CAAC,QAAQ;AAC5B,gBAAM,cAAc,kBAAkB,GAAG;AACzC,eAAK,KAAK;AAAA,YACR,8DAA8D,WAAW;AAAA,YACzE,eAAe;AAAA,UACjB;AAEA,eAAK,qBAAqB,cAAc;AAAA,QAC1C;AAAA,QACA,oBAAoB,MAAM;AACxB,eAAK,KAAK;AAAA,YACR;AAAA,YACA,eAAe;AAAA,UACjB;AAEA,eAAK,qBAAqB,cAAc;AAAA,QAC1C;AAAA,QACA,aAAa,CAAC,QAAQ;AACpB,cAAI,mBAAmB;AACrB,iBAAK,KAAK;AAAA,cACR;AAAA,cACA;AAAA,gBACE,GAAG,eAAe;AAAA,gBAClB,aAAa,IAAI;AAAA,gBACjB,kBAAkB;AAAA,cACpB;AAAA,YACF;AAEA,iBAAK,qBAAqB,cAAc;AACxC;AAAA,UACF;AAKA,8BAAoB;AACpB,eAAK,KAAK,mBAAmB,gBAAgB,GAAG;AAAA,QAClD;AAAA,QACA,oBAAoB,CAAC,QAAQ,SAAS;AACpC,eAAK,KAAK;AAAA,YACR,sBAAsB,MAAM;AAAA,YAC5B,eAAe;AAAA,UACjB;AACA,eAAK,qBAAqB,cAAc;AACxC,eAAK,cAAc;AAAA,YACjB,MAAM,cAAc;AAAA,YACpB;AAAA,YACA,SAAS;AAAA,UACX,CAAC;AAAA,QACH;AAAA,MACF;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAEA,SAAK,gBAAgB,IAAI,cAAc;AAAA,EACzC;AAAA,EAEQ,uBACN,SACA,IACA,QACA,MACA,UACA;AACA,YAAQ,KAAK,WAAW,KAAK,UAAU;AAAA,MACrC,MAAM,eAAe;AAAA,MACrB,SAAS;AAAA,IACX,CAAC;AAED,SAAK,KAAK,KAAK,QAAQ,QAAQ;AAE/B,YAAQ;AAAA,MACN,yBAAyB;AAAA,QACvB,MAAM,KAAK;AAAA,QACX;AAAA,QACA,QAAQ;AAAA,UACN,IAAI;AAAA,UACJ;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAEA,SAAK,cAAc;AAAA,MACjB,MAAM,cAAc;AAAA,MACpB;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AACD,SAAK,qBAAqB,OAAO;AAAA,EACnC;AAAA,EAEA,MAAgB,mBACd,SACA,KACA;AAEA,QAAI,CAAC,MAAM,MAAM,sCAAsC,IAAI,OAAO,GAAG;AACnE,WAAK;AAAA,QACH;AAAA,QACA,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,UACE,GAAG,QAAQ;AAAA,UACX,kBAAkB;AAAA,UAClB,aAAa,IAAI;AAAA,UACjB,kBAAkB;AAAA,YAChB,GAAG,MAAM,OAAO,sCAAsC,IAAI,OAAO;AAAA,UACnE;AAAA,QACF;AAAA,MACF;AAEA;AAAA,IACF;AAGA,UAAM,aAAa,IAAI,QAAQ;AAC/B,QAAI,eAAe,kBAAkB;AACnC,WAAK;AAAA,QACH;AAAA,QACA,IAAI;AAAA,QACJ,6BAA6B,gBAAgB,SAAS,UAAU;AAAA,QAChE;AAAA,QACA;AAAA,UACE,GAAG,QAAQ;AAAA,UACX,aAAa,IAAI;AAAA,UACjB,kBAAkB;AAAA,QACpB;AAAA,MACF;AAEA;AAAA,IACF;AAEA,QAAI,aAAa,KAAK,SAAS,IAAI,IAAI,IAAI;AAG3C,UAAM,iBAAiB,MAAM,KAAK;AAAA,MAChC;AAAA,MACA;AAAA,MACA,IAAI,QAAQ;AAAA,MACZ,IAAI;AAAA,IACN;AAEA,QAAI,mBAAmB,OAAO;AAC5B;AAAA,IACF;AAYA,QAAI,cAIsB;AAC1B,UAAM,wBACJ,IAAI,QAAQ,qBAAqB;AACnC,UAAM,oBAAoB,IAAI,QAAQ,qBAAqB,eAAe;AAE1E,QACE,KAAK,QAAQ,sCACb,cACA,WAAW,OAAO,IAAI,QAAQ,WAC9B;AACA,oBAAc;AAGd,YAAM,aAAa,WAAW,QAAQ;AACtC,YAAM,SAAS,WAAW;AAK1B,UAAI,oBAAoB,QAAQ;AAC9B,aAAK;AAAA,UACH;AAAA,UACA,IAAI;AAAA,UACJ,6DAA6D,MAAM,+BAA+B,iBAAiB;AAAA,UACnH;AAAA,UACA;AAAA,YACE,GAAG,QAAQ;AAAA,YACX,aAAa,IAAI;AAAA,YACjB,kBAAkB;AAAA,UACpB;AAAA,QACF;AAEA;AAAA,MACF;AAIA,UAAI,aAAa,uBAAuB;AACtC,aAAK;AAAA,UACH;AAAA,UACA,IAAI;AAAA,UACJ,6DAA6D,qBAAqB,+BAA+B,UAAU;AAAA,UAC3H;AAAA,UACA;AAAA,YACE,GAAG,QAAQ;AAAA,YACX,aAAa,IAAI;AAAA,YACjB,kBAAkB;AAAA,UACpB;AAAA,QACF;AAEA;AAAA,MACF;AAIA,UAAI,WAAW,6CAAqC;AAClD,cAAM,sBACJ,wBAAwB,WAAW;AAAA,UACjC;AAAA,UACA;AAAA,YACE,6BAA6B,MAAM;AACjC,mBAAK,4BAA4B,mBAAmB;AAAA,YACtD;AAAA,UACF;AAAA,QACF;AAEF,qBAAa;AAAA,MACf;AAEA,WAAK,cAAc,UAAU;AAAA,IAC/B,WAAW,YAAY;AACrB,oBAAc;AAGd,WAAK,KAAK;AAAA,QACR,4CAA4C,IAAI,QAAQ,SAAS,0BAA0B,WAAW,EAAE;AAAA,QACxG;AAAA,UACE,GAAG,QAAQ;AAAA,UACX,aAAa,IAAI;AAAA,UACjB,WAAW,IAAI,QAAQ;AAAA,QACzB;AAAA,MACF;AACA,WAAK,cAAc,UAAU;AAC7B,mBAAa;AAAA,IACf;AAEA,QAAI,CAAC,eAAe,oBAAoB,KAAK,wBAAwB,IAAI;AAGvE,oBAAc;AAEd,YAAM,mBAAmB,KAAK,QAAQ,qCAClC,2EAA2E,IAAI,QAAQ,SAAS,KAChG,iGAAiG,IAAI,QAAQ,SAAS;AAE1H,WAAK;AAAA,QACH;AAAA,QACA,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,UACE,GAAG,QAAQ;AAAA,UACX,aAAa,IAAI;AAAA,UACjB,kBAAkB;AAAA,QACpB;AAAA,MACF;AACA;AAAA,IACF;AAGA,UAAM,YAAY,IAAI,QAAQ;AAC9B,SAAK,KAAK;AAAA,MACR,kBAAkB,IAAI,IAAI,QAAQ,WAAW;AAAA,MAC7C;AAAA,QACE,GAAG,QAAQ;AAAA,QACX,aAAa,IAAI;AAAA,MACnB;AAAA,IACF;AACA,UAAM,cAAc,yBAAyB;AAAA,MAC3C,MAAM,KAAK;AAAA,MACX,IAAI,IAAI;AAAA,MACR,QAAQ;AAAA,QACN,IAAI;AAAA,QACJ;AAAA,MACF;AAAA,IACF,CAAC;AACD,YAAQ,cAAc,WAAW;AAGjC,UAAM,mBACJ,wBAAwB,WAAW;AAAA,MACjC;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ;AAAA,QACE,qBAAqB,CAAC,QAAQ;AAE5B,gBAAM,SAAS,kBAAkB,GAAG;AACpC,eAAK,KAAK;AAAA,YACR,iBAAiB,iBAAiB,EAAE,aAAa,MAAM;AAAA,YACvD,iBAAiB;AAAA,UACnB;AAAA,QACF;AAAA,QACA,oBAAoB,MAAM;AACxB,eAAK,KAAK;AAAA,YACR,iBAAiB,iBAAiB,EAAE;AAAA,YACpC,iBAAiB;AAAA,UACnB;AACA,eAAK,aAAa,gBAAgB;AAAA,QACpC;AAAA,QACA,WAAW,CAACA,SAAQ,KAAK,UAAUA,IAAG;AAAA,QACtC,kBAAkB,CAAC,WAAW;AAC5B,eAAK,cAAc;AAAA,YACjB,MAAM,cAAc;AAAA,YACpB,SAAS;AAAA,UACX,CAAC;AACD,eAAK,cAAc,gBAAgB;AAAA,QACrC;AAAA,MACF;AAAA,IACF;AAEF,SAAK,yBAAyB,IAAI,iBAAiB,IAAI,cAAc;AACrE,SAAK,cAAc,gBAAgB;AACnC,SAAK,gBAAgB,OAAO,OAAO;AACnC,qBAAiB,qBAAqB;AAAA,EACxC;AAAA,EAEA,MAAc,0BACZ,oBACA,iBACA,aAGA,MACiC;AACjC,QAAI,CAAC,KAAK,qBAAqB;AAC7B,aAAO,CAAC;AAAA,IACV;AAGA,QAAI,CAAC,MAAM,MAAM,KAAK,oBAAoB,QAAQ,WAAW,GAAG;AAC9D,WAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,UACE,GAAG,mBAAmB;AAAA,UACtB,aAAa;AAAA,UACb,kBAAkB;AAAA,YAChB,GAAG,MAAM,OAAO,KAAK,oBAAoB,QAAQ,WAAW;AAAA,UAC9D;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAEA,UAAM,yBAAyB,kBAC3B,KAAK,yBAAyB,IAAI,gBAAgB,EAAE,IACpD;AAEJ,UAAM,8BAA8B,MAAM,KAAK,oBAAoB;AAAA,MACjE;AAAA,MACA;AAAA,IACF;AAGA,QACE,MAAM;AAAA,MACJ;AAAA,MACA;AAAA,IACF,GACA;AACA,WAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,UACE,GAAG,mBAAmB;AAAA,UACtB,aAAa;AAAA,UACb,UAAU,KAAK;AAAA,QACjB;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AACF;","names":["msg"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as Connection, T as Transport, n as ClientTransportOptions, L as LeakyBucketRateLimit, p as ClientHandshakeOptions, q as ClientSession, b as ProvidedClientTransportOptions, f as SessionConnecting, e as SessionNoConnection, g as SessionHandshaking, h as SessionConnected, r as SessionBackingOff } from './handshake-
|
|
2
|
-
import { c as TransportClientId, P as PartialTransportMessage, b as OpaqueTransportMessage } from './message-
|
|
1
|
+
import { C as Connection, T as Transport, n as ClientTransportOptions, L as LeakyBucketRateLimit, p as ClientHandshakeOptions, q as ClientSession, b as ProvidedClientTransportOptions, f as SessionConnecting, e as SessionNoConnection, g as SessionHandshaking, h as SessionConnected, r as SessionBackingOff } from './handshake-1a86f06d.js';
|
|
2
|
+
import { c as TransportClientId, P as PartialTransportMessage, b as OpaqueTransportMessage } from './message-57296605.js';
|
|
3
3
|
|
|
4
4
|
declare abstract class ClientTransport<ConnType extends Connection> extends Transport<ConnType> {
|
|
5
5
|
/**
|
|
@@ -23,8 +23,6 @@ declare abstract class ClientTransport<ConnType extends Connection> extends Tran
|
|
|
23
23
|
extendHandshake(options: ClientHandshakeOptions): void;
|
|
24
24
|
/**
|
|
25
25
|
* Abstract method that creates a new {@link Connection} object.
|
|
26
|
-
* This should call {@link handleConnection} when the connection is created.
|
|
27
|
-
* The downstream client implementation needs to implement this.
|
|
28
26
|
*
|
|
29
27
|
* @param to The client ID of the node to connect to.
|
|
30
28
|
* @returns The new connection object.
|