@replit/river 0.21.1 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{chunk-FDLAPYCK.js → chunk-DZOATC6M.js} +2 -2
- package/dist/{chunk-JMXO5L2X.js → chunk-MJUFKPBT.js} +354 -398
- package/dist/chunk-MJUFKPBT.js.map +1 -0
- package/dist/{chunk-5WFL722S.js → chunk-PCKHBAVP.js} +94 -3
- package/dist/chunk-PCKHBAVP.js.map +1 -0
- package/dist/{chunk-NCXUFDVL.js → chunk-VOJVLWVX.js} +360 -516
- package/dist/chunk-VOJVLWVX.js.map +1 -0
- package/dist/chunk-ZF2UFTNN.js +60 -0
- package/dist/chunk-ZF2UFTNN.js.map +1 -0
- package/dist/{connection-76c5ed01.d.ts → connection-5685d817.d.ts} +6 -4
- package/dist/{connection-975b25c9.d.ts → connection-7582fb92.d.ts} +1 -1
- package/dist/{index-dfad460e.d.ts → index-a6fe0edd.d.ts} +55 -59
- package/dist/logging/index.d.cts +2 -1
- package/dist/logging/index.d.ts +2 -1
- package/dist/router/index.cjs +405 -502
- package/dist/router/index.cjs.map +1 -1
- package/dist/router/index.d.cts +12 -6
- package/dist/router/index.d.ts +12 -6
- package/dist/router/index.js +4 -3
- package/dist/{services-9c496c6e.d.ts → services-be91b485.d.ts} +21 -52
- package/dist/{services-7b716dcf.d.ts → services-eb9326a1.d.ts} +21 -52
- package/dist/transport/impls/uds/client.cjs +197 -155
- package/dist/transport/impls/uds/client.cjs.map +1 -1
- package/dist/transport/impls/uds/client.d.cts +3 -2
- package/dist/transport/impls/uds/client.d.ts +3 -2
- package/dist/transport/impls/uds/client.js +3 -3
- package/dist/transport/impls/uds/server.cjs +280 -266
- package/dist/transport/impls/uds/server.cjs.map +1 -1
- package/dist/transport/impls/uds/server.d.cts +3 -2
- package/dist/transport/impls/uds/server.d.ts +3 -2
- package/dist/transport/impls/uds/server.js +3 -3
- package/dist/transport/impls/ws/client.cjs +251 -214
- package/dist/transport/impls/ws/client.cjs.map +1 -1
- package/dist/transport/impls/ws/client.d.cts +6 -6
- package/dist/transport/impls/ws/client.d.ts +6 -6
- package/dist/transport/impls/ws/client.js +33 -48
- package/dist/transport/impls/ws/client.js.map +1 -1
- package/dist/transport/impls/ws/server.cjs +302 -280
- package/dist/transport/impls/ws/server.cjs.map +1 -1
- package/dist/transport/impls/ws/server.d.cts +5 -4
- package/dist/transport/impls/ws/server.d.ts +5 -4
- package/dist/transport/impls/ws/server.js +3 -3
- package/dist/transport/impls/ws/server.js.map +1 -1
- package/dist/transport/index.cjs +400 -396
- package/dist/transport/index.cjs.map +1 -1
- package/dist/transport/index.d.cts +25 -14
- package/dist/transport/index.d.ts +25 -14
- package/dist/transport/index.js +2 -2
- package/dist/util/testHelpers.cjs +59 -14
- package/dist/util/testHelpers.cjs.map +1 -1
- package/dist/util/testHelpers.d.cts +14 -5
- package/dist/util/testHelpers.d.ts +14 -5
- package/dist/util/testHelpers.js +12 -5
- package/dist/util/testHelpers.js.map +1 -1
- package/dist/wslike-e0b32dd5.d.ts +40 -0
- package/package.json +4 -5
- package/dist/chunk-3Y7AB5EB.js +0 -42
- package/dist/chunk-3Y7AB5EB.js.map +0 -1
- package/dist/chunk-5WFL722S.js.map +0 -1
- package/dist/chunk-JMXO5L2X.js.map +0 -1
- package/dist/chunk-NCXUFDVL.js.map +0 -1
- /package/dist/{chunk-FDLAPYCK.js.map → chunk-DZOATC6M.js.map} +0 -0
|
@@ -4,11 +4,14 @@ import {
|
|
|
4
4
|
OpaqueTransportMessageSchema,
|
|
5
5
|
PROTOCOL_VERSION,
|
|
6
6
|
coerceErrorString,
|
|
7
|
+
createConnectionTelemetryInfo,
|
|
8
|
+
createSessionTelemetryInfo,
|
|
9
|
+
getPropagationContext,
|
|
7
10
|
handshakeRequestMessage,
|
|
8
11
|
handshakeResponseMessage,
|
|
9
12
|
isAck,
|
|
10
13
|
tracing_default
|
|
11
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-PCKHBAVP.js";
|
|
12
15
|
import {
|
|
13
16
|
log
|
|
14
17
|
} from "./chunk-OTQNCLFH.js";
|
|
@@ -18,17 +21,20 @@ import {
|
|
|
18
21
|
|
|
19
22
|
// transport/session.ts
|
|
20
23
|
import { customAlphabet } from "nanoid";
|
|
24
|
+
import { SpanStatusCode } from "@opentelemetry/api";
|
|
21
25
|
var nanoid = customAlphabet("1234567890abcdefghijklmnopqrstuvxyz", 6);
|
|
22
26
|
var unsafeId = () => nanoid();
|
|
23
27
|
var Connection = class {
|
|
24
|
-
|
|
28
|
+
id;
|
|
29
|
+
telemetry;
|
|
25
30
|
constructor() {
|
|
26
|
-
this.
|
|
31
|
+
this.id = `conn-${nanoid(12)}`;
|
|
27
32
|
}
|
|
28
33
|
};
|
|
29
34
|
var Session = class {
|
|
30
35
|
codec;
|
|
31
36
|
options;
|
|
37
|
+
telemetry;
|
|
32
38
|
/**
|
|
33
39
|
* The buffer of messages that have been sent but not yet acknowledged.
|
|
34
40
|
*/
|
|
@@ -48,12 +54,6 @@ var Session = class {
|
|
|
48
54
|
* for this session.
|
|
49
55
|
*/
|
|
50
56
|
advertisedSessionId;
|
|
51
|
-
/**
|
|
52
|
-
* The metadata for this session, as parsed from the handshake.
|
|
53
|
-
*
|
|
54
|
-
* Will only ever be populated on the server side.
|
|
55
|
-
*/
|
|
56
|
-
metadata;
|
|
57
57
|
/**
|
|
58
58
|
* Number of messages we've sent along this session (excluding handshake and acks)
|
|
59
59
|
*/
|
|
@@ -75,7 +75,7 @@ var Session = class {
|
|
|
75
75
|
* The interval for sending heartbeats.
|
|
76
76
|
*/
|
|
77
77
|
heartbeat;
|
|
78
|
-
constructor(conn, from, to, options) {
|
|
78
|
+
constructor(conn, from, to, options, propagationCtx) {
|
|
79
79
|
this.id = `session-${nanoid(12)}`;
|
|
80
80
|
this.options = options;
|
|
81
81
|
this.from = from;
|
|
@@ -87,13 +87,14 @@ var Session = class {
|
|
|
87
87
|
() => this.sendHeartbeat(),
|
|
88
88
|
options.heartbeatIntervalMs
|
|
89
89
|
);
|
|
90
|
+
this.telemetry = createSessionTelemetryInfo(this, propagationCtx);
|
|
90
91
|
}
|
|
91
92
|
get loggingMetadata() {
|
|
92
93
|
return {
|
|
93
94
|
clientId: this.from,
|
|
94
95
|
connectedTo: this.to,
|
|
95
96
|
sessionId: this.id,
|
|
96
|
-
connId: this.connection?.
|
|
97
|
+
connId: this.connection?.id
|
|
97
98
|
};
|
|
98
99
|
}
|
|
99
100
|
/**
|
|
@@ -138,6 +139,7 @@ var Session = class {
|
|
|
138
139
|
`closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
|
|
139
140
|
this.loggingMetadata
|
|
140
141
|
);
|
|
142
|
+
this.telemetry.span.addEvent("closing connection due to inactivity");
|
|
141
143
|
this.closeStaleConnection();
|
|
142
144
|
}
|
|
143
145
|
return;
|
|
@@ -159,21 +161,25 @@ var Session = class {
|
|
|
159
161
|
sendBufferedMessages(conn) {
|
|
160
162
|
log?.info(`resending ${this.sendBuffer.length} buffered messages`, {
|
|
161
163
|
...this.loggingMetadata,
|
|
162
|
-
connId: conn.
|
|
164
|
+
connId: conn.id
|
|
163
165
|
});
|
|
164
166
|
for (const msg of this.sendBuffer) {
|
|
165
167
|
log?.debug(`resending msg`, {
|
|
166
168
|
...this.loggingMetadata,
|
|
167
169
|
fullTransportMessage: msg,
|
|
168
|
-
connId: conn.
|
|
170
|
+
connId: conn.id
|
|
169
171
|
});
|
|
170
172
|
const ok = conn.send(this.codec.toBuffer(msg));
|
|
171
173
|
if (!ok) {
|
|
172
174
|
const errMsg = `failed to send buffered message to ${this.to} (sus, this is a fresh connection)`;
|
|
175
|
+
conn.telemetry?.span.setStatus({
|
|
176
|
+
code: SpanStatusCode.ERROR,
|
|
177
|
+
message: errMsg
|
|
178
|
+
});
|
|
173
179
|
log?.error(errMsg, {
|
|
174
180
|
...this.loggingMetadata,
|
|
175
181
|
fullTransportMessage: msg,
|
|
176
|
-
connId: conn.
|
|
182
|
+
connId: conn.id,
|
|
177
183
|
tags: ["invariant-violation"]
|
|
178
184
|
});
|
|
179
185
|
conn.close();
|
|
@@ -292,12 +298,6 @@ var EventDispatcher = class {
|
|
|
292
298
|
|
|
293
299
|
// transport/transport.ts
|
|
294
300
|
import { Value } from "@sinclair/typebox/value";
|
|
295
|
-
import {
|
|
296
|
-
context,
|
|
297
|
-
propagation,
|
|
298
|
-
SpanKind,
|
|
299
|
-
SpanStatusCode
|
|
300
|
-
} from "@opentelemetry/api";
|
|
301
301
|
|
|
302
302
|
// transport/rateLimit.ts
|
|
303
303
|
var LeakyBucketRateLimit = class {
|
|
@@ -371,6 +371,7 @@ var LeakyBucketRateLimit = class {
|
|
|
371
371
|
};
|
|
372
372
|
|
|
373
373
|
// transport/transport.ts
|
|
374
|
+
import { SpanStatusCode as SpanStatusCode2 } from "@opentelemetry/api";
|
|
374
375
|
var defaultTransportOptions = {
|
|
375
376
|
heartbeatIntervalMs: 1e3,
|
|
376
377
|
heartbeatsUntilDead: 2,
|
|
@@ -449,17 +450,22 @@ var Transport = class {
|
|
|
449
450
|
status: "connect",
|
|
450
451
|
conn
|
|
451
452
|
});
|
|
453
|
+
conn.telemetry = createConnectionTelemetryInfo(
|
|
454
|
+
conn,
|
|
455
|
+
session.telemetry.span
|
|
456
|
+
);
|
|
452
457
|
if (isReconnect) {
|
|
453
458
|
session.replaceWithNewConnection(conn);
|
|
454
459
|
log?.info(`reconnected to ${connectedTo}`, session.loggingMetadata);
|
|
455
460
|
}
|
|
456
461
|
}
|
|
457
|
-
createSession(to, conn) {
|
|
462
|
+
createSession(to, conn, propagationCtx) {
|
|
458
463
|
const session = new Session(
|
|
459
464
|
conn,
|
|
460
465
|
this.clientId,
|
|
461
466
|
to,
|
|
462
|
-
this.options
|
|
467
|
+
this.options,
|
|
468
|
+
propagationCtx
|
|
463
469
|
);
|
|
464
470
|
this.sessions.set(session.to, session);
|
|
465
471
|
this.eventDispatcher.dispatchEvent("sessionStatus", {
|
|
@@ -468,11 +474,11 @@ var Transport = class {
|
|
|
468
474
|
});
|
|
469
475
|
return session;
|
|
470
476
|
}
|
|
471
|
-
getOrCreateSession(to, conn, sessionId) {
|
|
477
|
+
getOrCreateSession(to, conn, sessionId, propagationCtx) {
|
|
472
478
|
let session = this.sessions.get(to);
|
|
473
479
|
let isReconnect = session !== void 0;
|
|
474
480
|
if (session?.advertisedSessionId !== void 0 && sessionId !== void 0 && session.advertisedSessionId !== sessionId) {
|
|
475
|
-
log?.
|
|
481
|
+
log?.info(
|
|
476
482
|
`session for ${to} already exists but has a different session id (expected: ${session.advertisedSessionId}, got: ${sessionId}), creating a new one`,
|
|
477
483
|
session.loggingMetadata
|
|
478
484
|
);
|
|
@@ -481,7 +487,7 @@ var Transport = class {
|
|
|
481
487
|
session = void 0;
|
|
482
488
|
}
|
|
483
489
|
if (!session) {
|
|
484
|
-
session = this.createSession(to, conn);
|
|
490
|
+
session = this.createSession(to, conn, propagationCtx);
|
|
485
491
|
log?.info(
|
|
486
492
|
`no session for ${to}, created a new one`,
|
|
487
493
|
session.loggingMetadata
|
|
@@ -494,6 +500,7 @@ var Transport = class {
|
|
|
494
500
|
}
|
|
495
501
|
deleteSession(session) {
|
|
496
502
|
session.close();
|
|
503
|
+
session.telemetry.span.end();
|
|
497
504
|
this.sessions.delete(session.to);
|
|
498
505
|
log?.info(
|
|
499
506
|
`session ${session.id} disconnect from ${session.to}`,
|
|
@@ -510,12 +517,16 @@ var Transport = class {
|
|
|
510
517
|
* @param connectedTo The peer we are connected to.
|
|
511
518
|
*/
|
|
512
519
|
onDisconnect(conn, session) {
|
|
520
|
+
conn.telemetry?.span.end();
|
|
513
521
|
this.eventDispatcher.dispatchEvent("connectionStatus", {
|
|
514
522
|
status: "disconnect",
|
|
515
523
|
conn
|
|
516
524
|
});
|
|
517
525
|
session.connection = void 0;
|
|
518
|
-
session.beginGrace(() =>
|
|
526
|
+
session.beginGrace(() => {
|
|
527
|
+
session.telemetry.span.addEvent("session grace period expired");
|
|
528
|
+
this.deleteSession(session);
|
|
529
|
+
});
|
|
519
530
|
}
|
|
520
531
|
/**
|
|
521
532
|
* Parses a message from a Uint8Array into a {@link OpaqueTransportMessage}.
|
|
@@ -575,6 +586,10 @@ var Transport = class {
|
|
|
575
586
|
tags: ["invariant-violation"]
|
|
576
587
|
});
|
|
577
588
|
this.protocolError(ProtocolError.MessageOrderingViolated, errMsg);
|
|
589
|
+
session.telemetry.span.setStatus({
|
|
590
|
+
code: SpanStatusCode2.ERROR,
|
|
591
|
+
message: "message order violated"
|
|
592
|
+
});
|
|
578
593
|
session.close();
|
|
579
594
|
}
|
|
580
595
|
return;
|
|
@@ -685,6 +700,10 @@ var ClientTransport = class extends Transport {
|
|
|
685
700
|
* tests or a special case where you don't want to reconnect.
|
|
686
701
|
*/
|
|
687
702
|
reconnectOnConnectionDrop = true;
|
|
703
|
+
/**
|
|
704
|
+
* Optional handshake options for this client.
|
|
705
|
+
*/
|
|
706
|
+
handshakeExtensions;
|
|
688
707
|
constructor(clientId, providedOptions) {
|
|
689
708
|
super(clientId, providedOptions);
|
|
690
709
|
this.options = {
|
|
@@ -694,6 +713,9 @@ var ClientTransport = class extends Transport {
|
|
|
694
713
|
this.inflightConnectionPromises = /* @__PURE__ */ new Map();
|
|
695
714
|
this.retryBudget = new LeakyBucketRateLimit(this.options);
|
|
696
715
|
}
|
|
716
|
+
extendHandshake(options) {
|
|
717
|
+
this.handshakeExtensions = options;
|
|
718
|
+
}
|
|
697
719
|
handleConnection(conn, to) {
|
|
698
720
|
if (this.state !== "open")
|
|
699
721
|
return;
|
|
@@ -702,7 +724,7 @@ var ClientTransport = class extends Transport {
|
|
|
702
724
|
if (!session) {
|
|
703
725
|
log?.warn(
|
|
704
726
|
`connection to ${to} timed out waiting for handshake, closing`,
|
|
705
|
-
{ clientId: this.clientId, connectedTo: to, connId: conn.
|
|
727
|
+
{ clientId: this.clientId, connectedTo: to, connId: conn.id }
|
|
706
728
|
);
|
|
707
729
|
conn.close();
|
|
708
730
|
}
|
|
@@ -720,6 +742,10 @@ var ClientTransport = class extends Transport {
|
|
|
720
742
|
conn.addDataListener((data2) => {
|
|
721
743
|
const parsed = this.parseMsg(data2);
|
|
722
744
|
if (!parsed) {
|
|
745
|
+
conn.telemetry?.span.setStatus({
|
|
746
|
+
code: SpanStatusCode2.ERROR,
|
|
747
|
+
message: "message parse failure"
|
|
748
|
+
});
|
|
723
749
|
conn.close();
|
|
724
750
|
return;
|
|
725
751
|
}
|
|
@@ -742,6 +768,10 @@ var ClientTransport = class extends Transport {
|
|
|
742
768
|
}
|
|
743
769
|
});
|
|
744
770
|
conn.addErrorListener((err) => {
|
|
771
|
+
conn.telemetry?.span.setStatus({
|
|
772
|
+
code: SpanStatusCode2.ERROR,
|
|
773
|
+
message: "connection error"
|
|
774
|
+
});
|
|
745
775
|
log?.warn(`error in connection to ${to}: ${coerceErrorString(err)}`, {
|
|
746
776
|
...session?.loggingMetadata,
|
|
747
777
|
clientId: this.clientId,
|
|
@@ -752,6 +782,10 @@ var ClientTransport = class extends Transport {
|
|
|
752
782
|
receiveHandshakeResponseMessage(data, conn) {
|
|
753
783
|
const parsed = this.parseMsg(data);
|
|
754
784
|
if (!parsed) {
|
|
785
|
+
conn.telemetry?.span.setStatus({
|
|
786
|
+
code: SpanStatusCode2.ERROR,
|
|
787
|
+
message: "non-transport message"
|
|
788
|
+
});
|
|
755
789
|
this.protocolError(
|
|
756
790
|
ProtocolError.HandshakeFailed,
|
|
757
791
|
"received non-transport message"
|
|
@@ -759,6 +793,10 @@ var ClientTransport = class extends Transport {
|
|
|
759
793
|
return false;
|
|
760
794
|
}
|
|
761
795
|
if (!Value.Check(ControlMessageHandshakeResponseSchema, parsed.payload)) {
|
|
796
|
+
conn.telemetry?.span.setStatus({
|
|
797
|
+
code: SpanStatusCode2.ERROR,
|
|
798
|
+
message: "invalid handshake response"
|
|
799
|
+
});
|
|
762
800
|
log?.warn(`received invalid handshake resp`, {
|
|
763
801
|
clientId: this.clientId,
|
|
764
802
|
connectedTo: parsed.from,
|
|
@@ -771,7 +809,11 @@ var ClientTransport = class extends Transport {
|
|
|
771
809
|
return false;
|
|
772
810
|
}
|
|
773
811
|
if (!parsed.payload.status.ok) {
|
|
774
|
-
|
|
812
|
+
conn.telemetry?.span.setStatus({
|
|
813
|
+
code: SpanStatusCode2.ERROR,
|
|
814
|
+
message: "handshake rejected"
|
|
815
|
+
});
|
|
816
|
+
log?.warn(`received handshake rejection`, {
|
|
775
817
|
clientId: this.clientId,
|
|
776
818
|
connectedTo: parsed.from,
|
|
777
819
|
fullTransportMessage: parsed
|
|
@@ -801,142 +843,94 @@ var ClientTransport = class extends Transport {
|
|
|
801
843
|
* @param to The client ID of the node to connect to.
|
|
802
844
|
*/
|
|
803
845
|
async connect(to) {
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
span.recordException(coerceErrorString(e));
|
|
821
|
-
}
|
|
822
|
-
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
823
|
-
} finally {
|
|
824
|
-
span.end();
|
|
825
|
-
}
|
|
846
|
+
const canProceedWithConnection = () => this.state === "open";
|
|
847
|
+
if (!canProceedWithConnection()) {
|
|
848
|
+
log?.info(
|
|
849
|
+
`transport state is no longer open, cancelling attempt to connect to ${to}`,
|
|
850
|
+
{ clientId: this.clientId, connectedTo: to }
|
|
851
|
+
);
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
let reconnectPromise = this.inflightConnectionPromises.get(to);
|
|
855
|
+
if (!reconnectPromise) {
|
|
856
|
+
const budgetConsumed = this.retryBudget.getBudgetConsumed(to);
|
|
857
|
+
if (!this.retryBudget.hasBudget(to)) {
|
|
858
|
+
const errMsg = `tried to connect to ${to} but retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
|
|
859
|
+
log?.warn(errMsg, { clientId: this.clientId, connectedTo: to });
|
|
860
|
+
this.protocolError(ProtocolError.RetriesExceeded, errMsg);
|
|
861
|
+
return;
|
|
826
862
|
}
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
{
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
kind: SpanKind.CLIENT
|
|
839
|
-
},
|
|
840
|
-
async (span) => {
|
|
863
|
+
let sleep = Promise.resolve();
|
|
864
|
+
const backoffMs = this.retryBudget.getBackoffMs(to);
|
|
865
|
+
if (backoffMs > 0) {
|
|
866
|
+
sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
867
|
+
}
|
|
868
|
+
log?.info(`attempting connection to ${to} (${backoffMs}ms backoff)`, {
|
|
869
|
+
clientId: this.clientId,
|
|
870
|
+
connectedTo: to
|
|
871
|
+
});
|
|
872
|
+
this.retryBudget.consumeBudget(to);
|
|
873
|
+
reconnectPromise = tracing_default.startActiveSpan("connect", async (span) => {
|
|
841
874
|
try {
|
|
842
|
-
|
|
875
|
+
span.addEvent("backoff", { backoffMs });
|
|
876
|
+
await sleep;
|
|
843
877
|
if (!canProceedWithConnection()) {
|
|
844
|
-
|
|
845
|
-
`transport state is no longer open, cancelling attempt to connect to ${to}`,
|
|
846
|
-
{ clientId: this.clientId, connectedTo: to }
|
|
847
|
-
);
|
|
848
|
-
return false;
|
|
878
|
+
throw new Error("transport state is no longer open");
|
|
849
879
|
}
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
if (!this.retryBudget.hasBudget(to)) {
|
|
854
|
-
const errMsg = `tried to connect to ${to} but retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
|
|
855
|
-
log?.warn(errMsg, { clientId: this.clientId, connectedTo: to });
|
|
856
|
-
this.protocolError(ProtocolError.RetriesExceeded, errMsg);
|
|
857
|
-
return false;
|
|
858
|
-
}
|
|
859
|
-
let sleep = Promise.resolve();
|
|
860
|
-
const backoffMs = this.retryBudget.getBackoffMs(to);
|
|
861
|
-
if (backoffMs > 0) {
|
|
862
|
-
sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
863
|
-
}
|
|
864
|
-
log?.info(
|
|
865
|
-
`attempting connection to ${to} (${backoffMs}ms backoff)`,
|
|
866
|
-
{
|
|
867
|
-
clientId: this.clientId,
|
|
868
|
-
connectedTo: to
|
|
869
|
-
}
|
|
870
|
-
);
|
|
871
|
-
this.retryBudget.consumeBudget(to);
|
|
872
|
-
reconnectPromise = sleep.then(() => {
|
|
873
|
-
if (!canProceedWithConnection()) {
|
|
874
|
-
throw new Error("transport state is no longer open");
|
|
875
|
-
}
|
|
876
|
-
}).then(() => this.createNewOutgoingConnection(to)).then((conn) => {
|
|
877
|
-
if (!canProceedWithConnection()) {
|
|
878
|
-
log?.info(
|
|
879
|
-
`transport state is no longer open, closing pre-handshake connection to ${to}`,
|
|
880
|
-
{
|
|
881
|
-
clientId: this.clientId,
|
|
882
|
-
connectedTo: to,
|
|
883
|
-
connId: conn.debugId
|
|
884
|
-
}
|
|
885
|
-
);
|
|
886
|
-
conn.close();
|
|
887
|
-
throw new Error("transport state is no longer open");
|
|
888
|
-
}
|
|
889
|
-
return this.sendHandshake(to, conn).then((ok) => {
|
|
890
|
-
if (!ok) {
|
|
891
|
-
conn.close();
|
|
892
|
-
throw new Error("failed to send handshake");
|
|
893
|
-
}
|
|
894
|
-
return conn;
|
|
895
|
-
});
|
|
896
|
-
});
|
|
897
|
-
this.inflightConnectionPromises.set(to, reconnectPromise);
|
|
898
|
-
} else {
|
|
880
|
+
span.addEvent("connecting");
|
|
881
|
+
const conn = await this.createNewOutgoingConnection(to);
|
|
882
|
+
if (!canProceedWithConnection()) {
|
|
899
883
|
log?.info(
|
|
900
|
-
`
|
|
884
|
+
`transport state is no longer open, closing pre-handshake connection to ${to}`,
|
|
901
885
|
{
|
|
902
886
|
clientId: this.clientId,
|
|
903
|
-
connectedTo: to
|
|
887
|
+
connectedTo: to,
|
|
888
|
+
connId: conn.id
|
|
904
889
|
}
|
|
905
890
|
);
|
|
891
|
+
conn.close();
|
|
892
|
+
throw new Error("transport state is no longer open");
|
|
906
893
|
}
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
if (!this.reconnectOnConnectionDrop || !canProceedWithConnection()) {
|
|
913
|
-
log?.warn(`connection to ${to} failed (${errStr})`, {
|
|
914
|
-
clientId: this.clientId,
|
|
915
|
-
connectedTo: to
|
|
916
|
-
});
|
|
917
|
-
} else {
|
|
918
|
-
log?.warn(`connection to ${to} failed (${errStr}), retrying`, {
|
|
919
|
-
clientId: this.clientId,
|
|
920
|
-
connectedTo: to
|
|
921
|
-
});
|
|
922
|
-
return true;
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
} catch (e) {
|
|
926
|
-
if (e instanceof Error) {
|
|
927
|
-
span.recordException(e);
|
|
928
|
-
} else {
|
|
929
|
-
span.recordException(coerceErrorString(e));
|
|
894
|
+
span.addEvent("sending handshake");
|
|
895
|
+
const ok = await this.sendHandshake(to, conn);
|
|
896
|
+
if (!ok) {
|
|
897
|
+
conn.close();
|
|
898
|
+
throw new Error("failed to send handshake");
|
|
930
899
|
}
|
|
931
|
-
|
|
900
|
+
return conn;
|
|
901
|
+
} catch (err) {
|
|
902
|
+
const errStr = coerceErrorString(err);
|
|
903
|
+
span.recordException(errStr);
|
|
904
|
+
span.setStatus({ code: SpanStatusCode2.ERROR });
|
|
905
|
+
throw err;
|
|
932
906
|
} finally {
|
|
933
907
|
span.end();
|
|
934
908
|
}
|
|
935
|
-
|
|
909
|
+
});
|
|
910
|
+
this.inflightConnectionPromises.set(to, reconnectPromise);
|
|
911
|
+
} else {
|
|
912
|
+
log?.info(`attempting connection to ${to} (reusing previous attempt)`, {
|
|
913
|
+
clientId: this.clientId,
|
|
914
|
+
connectedTo: to
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
try {
|
|
918
|
+
await reconnectPromise;
|
|
919
|
+
} catch (error) {
|
|
920
|
+
this.inflightConnectionPromises.delete(to);
|
|
921
|
+
const errStr = coerceErrorString(error);
|
|
922
|
+
if (!this.reconnectOnConnectionDrop || !canProceedWithConnection()) {
|
|
923
|
+
log?.warn(`connection to ${to} failed (${errStr})`, {
|
|
924
|
+
clientId: this.clientId,
|
|
925
|
+
connectedTo: to
|
|
926
|
+
});
|
|
927
|
+
} else {
|
|
928
|
+
log?.warn(`connection to ${to} failed (${errStr}), retrying`, {
|
|
929
|
+
clientId: this.clientId,
|
|
930
|
+
connectedTo: to
|
|
931
|
+
});
|
|
932
|
+
return this.connect(to);
|
|
936
933
|
}
|
|
937
|
-
);
|
|
938
|
-
if (retry) {
|
|
939
|
-
return this.connectAttempt(to, attempt + 1);
|
|
940
934
|
}
|
|
941
935
|
}
|
|
942
936
|
deleteSession(session) {
|
|
@@ -944,13 +938,11 @@ var ClientTransport = class extends Transport {
|
|
|
944
938
|
super.deleteSession(session);
|
|
945
939
|
}
|
|
946
940
|
async sendHandshake(to, conn) {
|
|
947
|
-
const tracing = { traceparent: "", tracestate: "" };
|
|
948
|
-
propagation.inject(context.active(), tracing);
|
|
949
941
|
let metadata;
|
|
950
|
-
if (this.
|
|
951
|
-
metadata = await this.
|
|
952
|
-
if (!Value.Check(this.
|
|
953
|
-
log?.error(`handshake metadata did not match schema`, {
|
|
942
|
+
if (this.handshakeExtensions) {
|
|
943
|
+
metadata = await this.handshakeExtensions.construct();
|
|
944
|
+
if (!Value.Check(this.handshakeExtensions.schema, metadata)) {
|
|
945
|
+
log?.error(`constructed handshake metadata did not match schema`, {
|
|
954
946
|
clientId: this.clientId,
|
|
955
947
|
connectedTo: to,
|
|
956
948
|
tags: ["invariant-violation"]
|
|
@@ -959,6 +951,10 @@ var ClientTransport = class extends Transport {
|
|
|
959
951
|
ProtocolError.HandshakeFailed,
|
|
960
952
|
"handshake metadata did not match schema"
|
|
961
953
|
);
|
|
954
|
+
conn.telemetry?.span.setStatus({
|
|
955
|
+
code: SpanStatusCode2.ERROR,
|
|
956
|
+
message: "handshake meta mismatch"
|
|
957
|
+
});
|
|
962
958
|
return false;
|
|
963
959
|
}
|
|
964
960
|
}
|
|
@@ -968,7 +964,7 @@ var ClientTransport = class extends Transport {
|
|
|
968
964
|
to,
|
|
969
965
|
session.id,
|
|
970
966
|
metadata,
|
|
971
|
-
|
|
967
|
+
getPropagationContext(session.telemetry.ctx)
|
|
972
968
|
);
|
|
973
969
|
log?.debug(`sending handshake request to ${to}`, {
|
|
974
970
|
clientId: this.clientId,
|
|
@@ -987,280 +983,240 @@ var ServerTransport = class extends Transport {
|
|
|
987
983
|
* The options for this transport.
|
|
988
984
|
*/
|
|
989
985
|
options;
|
|
986
|
+
/**
|
|
987
|
+
* Optional handshake options for the server.
|
|
988
|
+
*/
|
|
989
|
+
handshakeExtensions;
|
|
990
|
+
/**
|
|
991
|
+
* A map of session handshake data for each session.
|
|
992
|
+
*/
|
|
993
|
+
sessionHandshakeMetadata;
|
|
990
994
|
constructor(clientId, providedOptions) {
|
|
991
995
|
super(clientId, providedOptions);
|
|
992
996
|
this.options = {
|
|
993
997
|
...defaultServerTransportOptions,
|
|
994
998
|
...providedOptions
|
|
995
999
|
};
|
|
1000
|
+
this.sessionHandshakeMetadata = /* @__PURE__ */ new WeakMap();
|
|
996
1001
|
log?.info(`initiated server transport`, {
|
|
997
1002
|
clientId: this.clientId,
|
|
998
1003
|
protocolVersion: PROTOCOL_VERSION
|
|
999
1004
|
});
|
|
1000
1005
|
}
|
|
1006
|
+
extendHandshake(options) {
|
|
1007
|
+
this.handshakeExtensions = options;
|
|
1008
|
+
}
|
|
1001
1009
|
handleConnection(conn) {
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
(
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1010
|
+
if (this.state !== "open")
|
|
1011
|
+
return;
|
|
1012
|
+
log?.info(`new incoming connection`, {
|
|
1013
|
+
clientId: this.clientId,
|
|
1014
|
+
connId: conn.id
|
|
1015
|
+
});
|
|
1016
|
+
let session = void 0;
|
|
1017
|
+
const client = () => session?.to ?? "unknown";
|
|
1018
|
+
const handshakeTimeout = setTimeout(() => {
|
|
1019
|
+
if (!session) {
|
|
1020
|
+
log?.warn(
|
|
1021
|
+
`connection to ${client()} timed out waiting for handshake, closing`,
|
|
1022
|
+
{
|
|
1023
|
+
clientId: this.clientId,
|
|
1024
|
+
connectedTo: client(),
|
|
1025
|
+
connId: conn.id
|
|
1026
|
+
}
|
|
1027
|
+
);
|
|
1028
|
+
conn.telemetry?.span.setStatus({
|
|
1029
|
+
code: SpanStatusCode2.ERROR,
|
|
1030
|
+
message: "handshake timeout"
|
|
1017
1031
|
});
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
+
conn.close();
|
|
1033
|
+
}
|
|
1034
|
+
}, this.options.sessionDisconnectGraceMs);
|
|
1035
|
+
const buffer = [];
|
|
1036
|
+
let receivedHandshakeMessage = false;
|
|
1037
|
+
const handshakeHandler = (data) => {
|
|
1038
|
+
if (receivedHandshakeMessage) {
|
|
1039
|
+
buffer.push(data);
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
receivedHandshakeMessage = true;
|
|
1043
|
+
clearTimeout(handshakeTimeout);
|
|
1044
|
+
void this.receiveHandshakeRequestMessage(data, conn).then(
|
|
1045
|
+
(maybeSession) => {
|
|
1046
|
+
if (!maybeSession) {
|
|
1032
1047
|
conn.close();
|
|
1033
|
-
}
|
|
1034
|
-
}, this.options.sessionDisconnectGraceMs);
|
|
1035
|
-
const buffer = [];
|
|
1036
|
-
let receivedHandshakeMessage = false;
|
|
1037
|
-
const handshakeHandler = (data) => {
|
|
1038
|
-
if (receivedHandshakeMessage) {
|
|
1039
|
-
buffer.push(data);
|
|
1040
1048
|
return;
|
|
1041
1049
|
}
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
(
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
span.end();
|
|
1049
|
-
conn.close();
|
|
1050
|
-
return;
|
|
1051
|
-
}
|
|
1052
|
-
session = maybeSession;
|
|
1053
|
-
const dataHandler = (data2) => {
|
|
1054
|
-
const parsed = this.parseMsg(data2);
|
|
1055
|
-
if (!parsed) {
|
|
1056
|
-
conn.close();
|
|
1057
|
-
return;
|
|
1058
|
-
}
|
|
1059
|
-
this.handleMsg(parsed);
|
|
1060
|
-
};
|
|
1061
|
-
conn.removeDataListener(handshakeHandler);
|
|
1062
|
-
conn.addDataListener(dataHandler);
|
|
1063
|
-
for (const data2 of buffer) {
|
|
1064
|
-
dataHandler(data2);
|
|
1065
|
-
}
|
|
1066
|
-
buffer.length = 0;
|
|
1050
|
+
session = maybeSession;
|
|
1051
|
+
const dataHandler = (data2) => {
|
|
1052
|
+
const parsed = this.parseMsg(data2);
|
|
1053
|
+
if (!parsed) {
|
|
1054
|
+
conn.close();
|
|
1055
|
+
return;
|
|
1067
1056
|
}
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
if (session) {
|
|
1073
|
-
log?.info(`connection to ${client()} disconnected`, {
|
|
1074
|
-
clientId: this.clientId,
|
|
1075
|
-
connId: conn.debugId
|
|
1076
|
-
});
|
|
1077
|
-
this.onDisconnect(conn, session);
|
|
1057
|
+
this.handleMsg(parsed);
|
|
1058
|
+
};
|
|
1059
|
+
for (const data2 of buffer) {
|
|
1060
|
+
dataHandler(data2);
|
|
1078
1061
|
}
|
|
1079
|
-
|
|
1080
|
-
|
|
1062
|
+
conn.removeDataListener(handshakeHandler);
|
|
1063
|
+
conn.addDataListener(dataHandler);
|
|
1064
|
+
buffer.length = 0;
|
|
1065
|
+
}
|
|
1066
|
+
);
|
|
1067
|
+
};
|
|
1068
|
+
conn.addDataListener(handshakeHandler);
|
|
1069
|
+
conn.addCloseListener(() => {
|
|
1070
|
+
if (!session)
|
|
1071
|
+
return;
|
|
1072
|
+
log?.info(`connection to ${client()} disconnected`, {
|
|
1073
|
+
clientId: this.clientId,
|
|
1074
|
+
connId: conn.id
|
|
1075
|
+
});
|
|
1076
|
+
this.onDisconnect(conn, session);
|
|
1077
|
+
});
|
|
1078
|
+
conn.addErrorListener((err) => {
|
|
1079
|
+
conn.telemetry?.span.setStatus({
|
|
1080
|
+
code: SpanStatusCode2.ERROR,
|
|
1081
|
+
message: "connection error"
|
|
1082
|
+
});
|
|
1083
|
+
if (!session)
|
|
1084
|
+
return;
|
|
1085
|
+
log?.warn(
|
|
1086
|
+
`connection to ${client()} got an error: ${coerceErrorString(err)}`,
|
|
1087
|
+
{ clientId: this.clientId, connId: conn.id }
|
|
1088
|
+
);
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1091
|
+
async validateHandshakeMetadata(conn, session, rawMetadata, from) {
|
|
1092
|
+
let parsedMetadata = {};
|
|
1093
|
+
if (this.handshakeExtensions) {
|
|
1094
|
+
if (!Value.Check(this.handshakeExtensions.schema, rawMetadata)) {
|
|
1095
|
+
conn.telemetry?.span.setStatus({
|
|
1096
|
+
code: SpanStatusCode2.ERROR,
|
|
1097
|
+
message: "malformed handshake meta"
|
|
1081
1098
|
});
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
1092
|
-
span.end();
|
|
1099
|
+
const reason = "received malformed handshake metadata";
|
|
1100
|
+
const responseMsg = handshakeResponseMessage(this.clientId, from, {
|
|
1101
|
+
ok: false,
|
|
1102
|
+
reason
|
|
1103
|
+
});
|
|
1104
|
+
conn.send(this.codec.toBuffer(responseMsg));
|
|
1105
|
+
log?.warn(`received malformed handshake metadata from ${from}`, {
|
|
1106
|
+
clientId: this.clientId,
|
|
1107
|
+
connId: conn.id
|
|
1093
1108
|
});
|
|
1109
|
+
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1110
|
+
return false;
|
|
1094
1111
|
}
|
|
1095
|
-
|
|
1112
|
+
parsedMetadata = await this.handshakeExtensions.validate(
|
|
1113
|
+
rawMetadata,
|
|
1114
|
+
session
|
|
1115
|
+
);
|
|
1116
|
+
if (parsedMetadata === false) {
|
|
1117
|
+
const reason = "rejected by handshake handler";
|
|
1118
|
+
conn.telemetry?.span.setStatus({
|
|
1119
|
+
code: SpanStatusCode2.ERROR,
|
|
1120
|
+
message: reason
|
|
1121
|
+
});
|
|
1122
|
+
const responseMsg = handshakeResponseMessage(this.clientId, from, {
|
|
1123
|
+
ok: false,
|
|
1124
|
+
reason
|
|
1125
|
+
});
|
|
1126
|
+
conn.send(this.codec.toBuffer(responseMsg));
|
|
1127
|
+
log?.warn(`rejected handshake from ${from}`, {
|
|
1128
|
+
clientId: this.clientId,
|
|
1129
|
+
connId: conn.id
|
|
1130
|
+
});
|
|
1131
|
+
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1132
|
+
return false;
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
return parsedMetadata;
|
|
1096
1136
|
}
|
|
1097
1137
|
async receiveHandshakeRequestMessage(data, conn) {
|
|
1098
1138
|
const parsed = this.parseMsg(data);
|
|
1099
1139
|
if (!parsed) {
|
|
1140
|
+
conn.telemetry?.span.setStatus({
|
|
1141
|
+
code: SpanStatusCode2.ERROR,
|
|
1142
|
+
message: "non-transport message"
|
|
1143
|
+
});
|
|
1100
1144
|
this.protocolError(
|
|
1101
1145
|
ProtocolError.HandshakeFailed,
|
|
1102
1146
|
"received non-transport message"
|
|
1103
1147
|
);
|
|
1104
1148
|
return false;
|
|
1105
1149
|
}
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1150
|
+
if (!Value.Check(ControlMessageHandshakeRequestSchema, parsed.payload)) {
|
|
1151
|
+
conn.telemetry?.span.setStatus({
|
|
1152
|
+
code: SpanStatusCode2.ERROR,
|
|
1153
|
+
message: "invalid handshake request"
|
|
1154
|
+
});
|
|
1155
|
+
const reason = "received invalid handshake msg";
|
|
1156
|
+
const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
|
|
1157
|
+
ok: false,
|
|
1158
|
+
reason
|
|
1159
|
+
});
|
|
1160
|
+
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1161
|
+
const logData = { ...parsed.payload ?? {}, metadata: "redacted" };
|
|
1162
|
+
log?.warn(reason, {
|
|
1163
|
+
clientId: this.clientId,
|
|
1164
|
+
connId: conn.id,
|
|
1165
|
+
partialTransportMessage: { ...parsed, payload: logData }
|
|
1166
|
+
});
|
|
1167
|
+
this.protocolError(
|
|
1168
|
+
ProtocolError.HandshakeFailed,
|
|
1169
|
+
"invalid handshake request"
|
|
1170
|
+
);
|
|
1171
|
+
return false;
|
|
1109
1172
|
}
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
{
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
} : { ...parsed };
|
|
1136
|
-
log?.warn(`${reason}: ${JSON.stringify(logData)}`, {
|
|
1137
|
-
clientId: this.clientId,
|
|
1138
|
-
connId: conn.debugId
|
|
1139
|
-
});
|
|
1140
|
-
this.protocolError(
|
|
1141
|
-
ProtocolError.HandshakeFailed,
|
|
1142
|
-
"invalid handshake request"
|
|
1143
|
-
);
|
|
1144
|
-
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
1145
|
-
span.end();
|
|
1146
|
-
return false;
|
|
1147
|
-
}
|
|
1148
|
-
const gotVersion = parsed.payload.protocolVersion;
|
|
1149
|
-
if (gotVersion !== PROTOCOL_VERSION) {
|
|
1150
|
-
const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
|
|
1151
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
1152
|
-
this.clientId,
|
|
1153
|
-
parsed.from,
|
|
1154
|
-
{
|
|
1155
|
-
ok: false,
|
|
1156
|
-
reason
|
|
1157
|
-
}
|
|
1158
|
-
);
|
|
1159
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1160
|
-
log?.warn(
|
|
1161
|
-
`received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`,
|
|
1162
|
-
{ clientId: this.clientId, connId: conn.debugId }
|
|
1163
|
-
);
|
|
1164
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1165
|
-
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
1166
|
-
span.end();
|
|
1167
|
-
return false;
|
|
1168
|
-
}
|
|
1169
|
-
const { session, isReconnect } = this.getOrCreateSession(
|
|
1170
|
-
parsed.from,
|
|
1171
|
-
conn,
|
|
1172
|
-
parsed.payload.sessionId
|
|
1173
|
-
);
|
|
1174
|
-
let handshakeMetadata;
|
|
1175
|
-
if (this.options.handshake) {
|
|
1176
|
-
if (!Value.Check(
|
|
1177
|
-
this.options.handshake.requestSchema,
|
|
1178
|
-
parsed.payload.metadata
|
|
1179
|
-
)) {
|
|
1180
|
-
const reason = "received malformed handshake metadata";
|
|
1181
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
1182
|
-
this.clientId,
|
|
1183
|
-
parsed.from,
|
|
1184
|
-
{ ok: false, reason }
|
|
1185
|
-
);
|
|
1186
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1187
|
-
log?.warn(
|
|
1188
|
-
`received malformed handshake metadata from ${parsed.from}`,
|
|
1189
|
-
{
|
|
1190
|
-
clientId: this.clientId,
|
|
1191
|
-
connId: conn.debugId
|
|
1192
|
-
}
|
|
1193
|
-
);
|
|
1194
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1195
|
-
this.deleteSession(session);
|
|
1196
|
-
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
1197
|
-
span.end();
|
|
1198
|
-
return false;
|
|
1199
|
-
}
|
|
1200
|
-
const parsedMetadata = await this.options.handshake.parse(
|
|
1201
|
-
parsed.payload.metadata,
|
|
1202
|
-
session,
|
|
1203
|
-
isReconnect
|
|
1204
|
-
);
|
|
1205
|
-
if (parsedMetadata === false) {
|
|
1206
|
-
const reason = "rejected by server";
|
|
1207
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
1208
|
-
this.clientId,
|
|
1209
|
-
parsed.from,
|
|
1210
|
-
{ ok: false, reason }
|
|
1211
|
-
);
|
|
1212
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1213
|
-
log?.warn(`rejected handshake from ${parsed.from}`, {
|
|
1214
|
-
clientId: this.clientId,
|
|
1215
|
-
connId: conn.debugId
|
|
1216
|
-
});
|
|
1217
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1218
|
-
this.deleteSession(session);
|
|
1219
|
-
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
1220
|
-
span.end();
|
|
1221
|
-
return false;
|
|
1222
|
-
}
|
|
1223
|
-
if (!Value.Check(this.options.handshake.parsedSchema, parsedMetadata)) {
|
|
1224
|
-
const reason = "failed to parse handshake metadata";
|
|
1225
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
1226
|
-
this.clientId,
|
|
1227
|
-
parsed.from,
|
|
1228
|
-
{ ok: false, reason }
|
|
1229
|
-
);
|
|
1230
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1231
|
-
log?.error(`failed to parse handshake metadata`, {
|
|
1232
|
-
clientId: this.clientId,
|
|
1233
|
-
connId: conn.debugId,
|
|
1234
|
-
tags: ["invariant-violation"]
|
|
1235
|
-
});
|
|
1236
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1237
|
-
this.deleteSession(session);
|
|
1238
|
-
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
1239
|
-
span.end();
|
|
1240
|
-
return false;
|
|
1241
|
-
}
|
|
1242
|
-
handshakeMetadata = parsedMetadata;
|
|
1243
|
-
}
|
|
1244
|
-
handshakeMetadata ??= {};
|
|
1245
|
-
session.metadata = handshakeMetadata;
|
|
1246
|
-
log?.debug(
|
|
1247
|
-
`handshake from ${parsed.from} ok, responding with handshake success`,
|
|
1248
|
-
{ clientId: this.clientId, connId: conn.debugId }
|
|
1249
|
-
);
|
|
1250
|
-
const responseMsg = handshakeResponseMessage(
|
|
1251
|
-
this.clientId,
|
|
1252
|
-
parsed.from,
|
|
1253
|
-
{
|
|
1254
|
-
ok: true,
|
|
1255
|
-
sessionId: session.id
|
|
1256
|
-
}
|
|
1257
|
-
);
|
|
1258
|
-
conn.send(this.codec.toBuffer(responseMsg));
|
|
1259
|
-
this.onConnect(conn, parsed.from, session, isReconnect);
|
|
1260
|
-
span.end();
|
|
1261
|
-
return session;
|
|
1262
|
-
}
|
|
1173
|
+
const gotVersion = parsed.payload.protocolVersion;
|
|
1174
|
+
if (gotVersion !== PROTOCOL_VERSION) {
|
|
1175
|
+
conn.telemetry?.span.setStatus({
|
|
1176
|
+
code: SpanStatusCode2.ERROR,
|
|
1177
|
+
message: "incorrect protocol version"
|
|
1178
|
+
});
|
|
1179
|
+
const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
|
|
1180
|
+
const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
|
|
1181
|
+
ok: false,
|
|
1182
|
+
reason
|
|
1183
|
+
});
|
|
1184
|
+
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1185
|
+
log?.warn(
|
|
1186
|
+
`received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`,
|
|
1187
|
+
{ clientId: this.clientId, connId: conn.id }
|
|
1188
|
+
);
|
|
1189
|
+
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1190
|
+
return false;
|
|
1191
|
+
}
|
|
1192
|
+
const oldSession = this.sessions.get(parsed.from);
|
|
1193
|
+
const parsedMetadata = await this.validateHandshakeMetadata(
|
|
1194
|
+
conn,
|
|
1195
|
+
oldSession,
|
|
1196
|
+
parsed.payload.metadata,
|
|
1197
|
+
parsed.from
|
|
1263
1198
|
);
|
|
1199
|
+
if (parsedMetadata === false) {
|
|
1200
|
+
return false;
|
|
1201
|
+
}
|
|
1202
|
+
const { session, isReconnect } = this.getOrCreateSession(
|
|
1203
|
+
parsed.from,
|
|
1204
|
+
conn,
|
|
1205
|
+
parsed.payload.sessionId,
|
|
1206
|
+
parsed.tracing
|
|
1207
|
+
);
|
|
1208
|
+
this.sessionHandshakeMetadata.set(session, parsedMetadata);
|
|
1209
|
+
log?.debug(
|
|
1210
|
+
`handshake from ${parsed.from} ok, responding with handshake success`,
|
|
1211
|
+
{ clientId: this.clientId, connId: conn.id }
|
|
1212
|
+
);
|
|
1213
|
+
const responseMsg = handshakeResponseMessage(this.clientId, parsed.from, {
|
|
1214
|
+
ok: true,
|
|
1215
|
+
sessionId: session.id
|
|
1216
|
+
});
|
|
1217
|
+
conn.send(this.codec.toBuffer(responseMsg));
|
|
1218
|
+
this.onConnect(conn, parsed.from, session, isReconnect);
|
|
1219
|
+
return session;
|
|
1264
1220
|
}
|
|
1265
1221
|
};
|
|
1266
1222
|
|
|
@@ -1273,4 +1229,4 @@ export {
|
|
|
1273
1229
|
ClientTransport,
|
|
1274
1230
|
ServerTransport
|
|
1275
1231
|
};
|
|
1276
|
-
//# sourceMappingURL=chunk-
|
|
1232
|
+
//# sourceMappingURL=chunk-MJUFKPBT.js.map
|