@replit/river 0.21.0 → 0.22.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-5WFL722S.js → chunk-3MFX6NXA.js} +94 -3
- package/dist/chunk-3MFX6NXA.js.map +1 -0
- package/dist/{chunk-NFV77C2M.js → chunk-GCLEWC26.js} +340 -507
- package/dist/chunk-GCLEWC26.js.map +1 -0
- package/dist/chunk-HUBFYN37.js +60 -0
- package/dist/chunk-HUBFYN37.js.map +1 -0
- package/dist/{chunk-DT5JS6TM.js → chunk-OTQNCLFH.js} +1 -1
- package/dist/chunk-OTQNCLFH.js.map +1 -0
- package/dist/{chunk-MJR36SUY.js → chunk-S3YKQT4J.js} +2 -2
- package/dist/{chunk-QU2EE6YU.js → chunk-ZPBWKBM5.js} +361 -394
- package/dist/chunk-ZPBWKBM5.js.map +1 -0
- package/dist/{connection-8a71dbe2.d.ts → connection-8b059ac4.d.ts} +6 -4
- package/dist/{connection-d49d5d56.d.ts → connection-bbfe1147.d.ts} +1 -1
- package/dist/{index-3ac92295.d.ts → index-2ece5234.d.ts} +18 -7
- package/dist/logging/index.cjs.map +1 -1
- package/dist/logging/index.d.cts +2 -1
- package/dist/logging/index.d.ts +2 -1
- package/dist/logging/index.js +1 -1
- package/dist/router/index.cjs +384 -492
- package/dist/router/index.cjs.map +1 -1
- package/dist/router/index.d.cts +5 -4
- package/dist/router/index.d.ts +5 -4
- package/dist/router/index.js +5 -4
- package/dist/{services-abc077db.d.ts → services-acbcc441.d.ts} +1 -1
- package/dist/{services-8496d6e8.d.ts → services-cb01a7a8.d.ts} +1 -1
- package/dist/transport/impls/uds/client.cjs +202 -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 +4 -4
- package/dist/transport/impls/uds/server.cjs +295 -264
- 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 +4 -4
- package/dist/transport/impls/ws/client.cjs +256 -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 +34 -49
- package/dist/transport/impls/ws/client.js.map +1 -1
- package/dist/transport/impls/ws/server.cjs +317 -278
- 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 +4 -4
- package/dist/transport/impls/ws/server.js.map +1 -1
- package/dist/transport/index.cjs +406 -391
- package/dist/transport/index.cjs.map +1 -1
- package/dist/transport/index.d.cts +5 -5
- package/dist/transport/index.d.ts +5 -5
- package/dist/transport/index.js +3 -3
- package/dist/util/testHelpers.cjs +71 -19
- package/dist/util/testHelpers.cjs.map +1 -1
- package/dist/util/testHelpers.d.cts +20 -8
- package/dist/util/testHelpers.d.ts +20 -8
- package/dist/util/testHelpers.js +13 -12
- package/dist/util/testHelpers.js.map +1 -1
- package/dist/wslike-e0b32dd5.d.ts +40 -0
- package/package.json +4 -5
- package/dist/chunk-2ERP6FUE.js +0 -42
- package/dist/chunk-2ERP6FUE.js.map +0 -1
- package/dist/chunk-5WFL722S.js.map +0 -1
- package/dist/chunk-DT5JS6TM.js.map +0 -1
- package/dist/chunk-NFV77C2M.js.map +0 -1
- package/dist/chunk-QU2EE6YU.js.map +0 -1
- /package/dist/{chunk-MJR36SUY.js.map → chunk-S3YKQT4J.js.map} +0 -0
package/dist/transport/index.cjs
CHANGED
|
@@ -33,7 +33,6 @@ module.exports = __toCommonJS(transport_exports);
|
|
|
33
33
|
|
|
34
34
|
// transport/transport.ts
|
|
35
35
|
var import_value = require("@sinclair/typebox/value");
|
|
36
|
-
var import_api2 = require("@opentelemetry/api");
|
|
37
36
|
|
|
38
37
|
// transport/message.ts
|
|
39
38
|
var import_typebox = require("@sinclair/typebox");
|
|
@@ -167,17 +166,71 @@ var EventDispatcher = class {
|
|
|
167
166
|
|
|
168
167
|
// transport/session.ts
|
|
169
168
|
var import_nanoid2 = require("nanoid");
|
|
169
|
+
|
|
170
|
+
// tracing/index.ts
|
|
171
|
+
var import_api = require("@opentelemetry/api");
|
|
172
|
+
|
|
173
|
+
// package.json
|
|
174
|
+
var version = "0.22.0";
|
|
175
|
+
|
|
176
|
+
// tracing/index.ts
|
|
177
|
+
function getPropagationContext(ctx) {
|
|
178
|
+
const tracing = {
|
|
179
|
+
traceparent: "",
|
|
180
|
+
tracestate: ""
|
|
181
|
+
};
|
|
182
|
+
import_api.propagation.inject(ctx, tracing);
|
|
183
|
+
return tracing;
|
|
184
|
+
}
|
|
185
|
+
function createSessionTelemetryInfo(session, propagationCtx) {
|
|
186
|
+
const ctx = propagationCtx ? import_api.propagation.extract(import_api.context.active(), propagationCtx) : import_api.context.active();
|
|
187
|
+
const span = tracer.startSpan(
|
|
188
|
+
`session ${session.id}`,
|
|
189
|
+
{
|
|
190
|
+
attributes: {
|
|
191
|
+
component: "river",
|
|
192
|
+
"river.session.id": session.id,
|
|
193
|
+
"river.session.to": session.to,
|
|
194
|
+
"river.session.from": session.from
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
ctx
|
|
198
|
+
);
|
|
199
|
+
return { span, ctx };
|
|
200
|
+
}
|
|
201
|
+
function createConnectionTelemetryInfo(connection, sessionSpan) {
|
|
202
|
+
const ctx = import_api.trace.setSpan(import_api.context.active(), sessionSpan);
|
|
203
|
+
const span = tracer.startSpan(
|
|
204
|
+
`connection ${connection.id}`,
|
|
205
|
+
{
|
|
206
|
+
attributes: {
|
|
207
|
+
component: "river",
|
|
208
|
+
"river.connection.id": connection.id
|
|
209
|
+
},
|
|
210
|
+
links: [{ context: sessionSpan.spanContext() }]
|
|
211
|
+
},
|
|
212
|
+
ctx
|
|
213
|
+
);
|
|
214
|
+
return { span, ctx };
|
|
215
|
+
}
|
|
216
|
+
var tracer = import_api.trace.getTracer("river", version);
|
|
217
|
+
var tracing_default = tracer;
|
|
218
|
+
|
|
219
|
+
// transport/session.ts
|
|
220
|
+
var import_api2 = require("@opentelemetry/api");
|
|
170
221
|
var nanoid2 = (0, import_nanoid2.customAlphabet)("1234567890abcdefghijklmnopqrstuvxyz", 6);
|
|
171
222
|
var unsafeId = () => nanoid2();
|
|
172
223
|
var Connection = class {
|
|
173
|
-
|
|
224
|
+
id;
|
|
225
|
+
telemetry;
|
|
174
226
|
constructor() {
|
|
175
|
-
this.
|
|
227
|
+
this.id = `conn-${nanoid2(12)}`;
|
|
176
228
|
}
|
|
177
229
|
};
|
|
178
230
|
var Session = class {
|
|
179
231
|
codec;
|
|
180
232
|
options;
|
|
233
|
+
telemetry;
|
|
181
234
|
/**
|
|
182
235
|
* The buffer of messages that have been sent but not yet acknowledged.
|
|
183
236
|
*/
|
|
@@ -224,7 +277,7 @@ var Session = class {
|
|
|
224
277
|
* The interval for sending heartbeats.
|
|
225
278
|
*/
|
|
226
279
|
heartbeat;
|
|
227
|
-
constructor(conn, from, to, options) {
|
|
280
|
+
constructor(conn, from, to, options, propagationCtx) {
|
|
228
281
|
this.id = `session-${nanoid2(12)}`;
|
|
229
282
|
this.options = options;
|
|
230
283
|
this.from = from;
|
|
@@ -236,13 +289,14 @@ var Session = class {
|
|
|
236
289
|
() => this.sendHeartbeat(),
|
|
237
290
|
options.heartbeatIntervalMs
|
|
238
291
|
);
|
|
292
|
+
this.telemetry = createSessionTelemetryInfo(this, propagationCtx);
|
|
239
293
|
}
|
|
240
294
|
get loggingMetadata() {
|
|
241
295
|
return {
|
|
242
296
|
clientId: this.from,
|
|
243
297
|
connectedTo: this.to,
|
|
244
298
|
sessionId: this.id,
|
|
245
|
-
connId: this.connection?.
|
|
299
|
+
connId: this.connection?.id
|
|
246
300
|
};
|
|
247
301
|
}
|
|
248
302
|
/**
|
|
@@ -287,6 +341,7 @@ var Session = class {
|
|
|
287
341
|
`closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
|
|
288
342
|
this.loggingMetadata
|
|
289
343
|
);
|
|
344
|
+
this.telemetry.span.addEvent("closing connection due to inactivity");
|
|
290
345
|
this.closeStaleConnection();
|
|
291
346
|
}
|
|
292
347
|
return;
|
|
@@ -308,32 +363,38 @@ var Session = class {
|
|
|
308
363
|
sendBufferedMessages(conn) {
|
|
309
364
|
log?.info(`resending ${this.sendBuffer.length} buffered messages`, {
|
|
310
365
|
...this.loggingMetadata,
|
|
311
|
-
connId: conn.
|
|
366
|
+
connId: conn.id
|
|
312
367
|
});
|
|
313
368
|
for (const msg of this.sendBuffer) {
|
|
314
369
|
log?.debug(`resending msg`, {
|
|
315
370
|
...this.loggingMetadata,
|
|
316
371
|
fullTransportMessage: msg,
|
|
317
|
-
connId: conn.
|
|
372
|
+
connId: conn.id
|
|
318
373
|
});
|
|
319
374
|
const ok = conn.send(this.codec.toBuffer(msg));
|
|
320
375
|
if (!ok) {
|
|
321
376
|
const errMsg = `failed to send buffered message to ${this.to} (sus, this is a fresh connection)`;
|
|
377
|
+
conn.telemetry?.span.setStatus({
|
|
378
|
+
code: import_api2.SpanStatusCode.ERROR,
|
|
379
|
+
message: errMsg
|
|
380
|
+
});
|
|
322
381
|
log?.error(errMsg, {
|
|
323
382
|
...this.loggingMetadata,
|
|
324
383
|
fullTransportMessage: msg,
|
|
325
|
-
connId: conn.
|
|
384
|
+
connId: conn.id,
|
|
385
|
+
tags: ["invariant-violation"]
|
|
326
386
|
});
|
|
327
|
-
|
|
387
|
+
conn.close();
|
|
388
|
+
return;
|
|
328
389
|
}
|
|
329
390
|
}
|
|
330
391
|
}
|
|
331
392
|
updateBookkeeping(ack, seq) {
|
|
332
393
|
if (seq + 1 < this.ack) {
|
|
333
|
-
log?.error(
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
);
|
|
394
|
+
log?.error(`received stale seq ${seq} + 1 < ${this.ack}`, {
|
|
395
|
+
...this.loggingMetadata,
|
|
396
|
+
tags: ["invariant-violation"]
|
|
397
|
+
});
|
|
337
398
|
return;
|
|
338
399
|
}
|
|
339
400
|
this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);
|
|
@@ -403,11 +464,6 @@ var Session = class {
|
|
|
403
464
|
}
|
|
404
465
|
};
|
|
405
466
|
|
|
406
|
-
// tracing/index.ts
|
|
407
|
-
var import_api = require("@opentelemetry/api");
|
|
408
|
-
var tracer = import_api.trace.getTracer("river");
|
|
409
|
-
var tracing_default = tracer;
|
|
410
|
-
|
|
411
467
|
// util/stringify.ts
|
|
412
468
|
function coerceErrorString(err) {
|
|
413
469
|
if (err instanceof Error) {
|
|
@@ -540,6 +596,7 @@ var NaiveJsonCodec = {
|
|
|
540
596
|
};
|
|
541
597
|
|
|
542
598
|
// transport/transport.ts
|
|
599
|
+
var import_api3 = require("@opentelemetry/api");
|
|
543
600
|
var defaultTransportOptions = {
|
|
544
601
|
heartbeatIntervalMs: 1e3,
|
|
545
602
|
heartbeatsUntilDead: 2,
|
|
@@ -618,17 +675,22 @@ var Transport = class {
|
|
|
618
675
|
status: "connect",
|
|
619
676
|
conn
|
|
620
677
|
});
|
|
678
|
+
conn.telemetry = createConnectionTelemetryInfo(
|
|
679
|
+
conn,
|
|
680
|
+
session.telemetry.span
|
|
681
|
+
);
|
|
621
682
|
if (isReconnect) {
|
|
622
683
|
session.replaceWithNewConnection(conn);
|
|
623
684
|
log?.info(`reconnected to ${connectedTo}`, session.loggingMetadata);
|
|
624
685
|
}
|
|
625
686
|
}
|
|
626
|
-
createSession(to, conn) {
|
|
687
|
+
createSession(to, conn, propagationCtx) {
|
|
627
688
|
const session = new Session(
|
|
628
689
|
conn,
|
|
629
690
|
this.clientId,
|
|
630
691
|
to,
|
|
631
|
-
this.options
|
|
692
|
+
this.options,
|
|
693
|
+
propagationCtx
|
|
632
694
|
);
|
|
633
695
|
this.sessions.set(session.to, session);
|
|
634
696
|
this.eventDispatcher.dispatchEvent("sessionStatus", {
|
|
@@ -637,11 +699,11 @@ var Transport = class {
|
|
|
637
699
|
});
|
|
638
700
|
return session;
|
|
639
701
|
}
|
|
640
|
-
getOrCreateSession(to, conn, sessionId) {
|
|
702
|
+
getOrCreateSession(to, conn, sessionId, propagationCtx) {
|
|
641
703
|
let session = this.sessions.get(to);
|
|
642
704
|
let isReconnect = session !== void 0;
|
|
643
705
|
if (session?.advertisedSessionId !== void 0 && sessionId !== void 0 && session.advertisedSessionId !== sessionId) {
|
|
644
|
-
log?.
|
|
706
|
+
log?.info(
|
|
645
707
|
`session for ${to} already exists but has a different session id (expected: ${session.advertisedSessionId}, got: ${sessionId}), creating a new one`,
|
|
646
708
|
session.loggingMetadata
|
|
647
709
|
);
|
|
@@ -650,7 +712,7 @@ var Transport = class {
|
|
|
650
712
|
session = void 0;
|
|
651
713
|
}
|
|
652
714
|
if (!session) {
|
|
653
|
-
session = this.createSession(to, conn);
|
|
715
|
+
session = this.createSession(to, conn, propagationCtx);
|
|
654
716
|
log?.info(
|
|
655
717
|
`no session for ${to}, created a new one`,
|
|
656
718
|
session.loggingMetadata
|
|
@@ -663,6 +725,7 @@ var Transport = class {
|
|
|
663
725
|
}
|
|
664
726
|
deleteSession(session) {
|
|
665
727
|
session.close();
|
|
728
|
+
session.telemetry.span.end();
|
|
666
729
|
this.sessions.delete(session.to);
|
|
667
730
|
log?.info(
|
|
668
731
|
`session ${session.id} disconnect from ${session.to}`,
|
|
@@ -679,12 +742,16 @@ var Transport = class {
|
|
|
679
742
|
* @param connectedTo The peer we are connected to.
|
|
680
743
|
*/
|
|
681
744
|
onDisconnect(conn, session) {
|
|
745
|
+
conn.telemetry?.span.end();
|
|
682
746
|
this.eventDispatcher.dispatchEvent("connectionStatus", {
|
|
683
747
|
status: "disconnect",
|
|
684
748
|
conn
|
|
685
749
|
});
|
|
686
750
|
session.connection = void 0;
|
|
687
|
-
session.beginGrace(() =>
|
|
751
|
+
session.beginGrace(() => {
|
|
752
|
+
session.telemetry.span.addEvent("session grace period expired");
|
|
753
|
+
this.deleteSession(session);
|
|
754
|
+
});
|
|
688
755
|
}
|
|
689
756
|
/**
|
|
690
757
|
* Parses a message from a Uint8Array into a {@link OpaqueTransportMessage}.
|
|
@@ -718,9 +785,10 @@ var Transport = class {
|
|
|
718
785
|
return;
|
|
719
786
|
const session = this.sessions.get(msg.from);
|
|
720
787
|
if (!session) {
|
|
721
|
-
log?.error(`
|
|
788
|
+
log?.error(`no existing session for ${msg.from}`, {
|
|
722
789
|
clientId: this.clientId,
|
|
723
|
-
fullTransportMessage: msg
|
|
790
|
+
fullTransportMessage: msg,
|
|
791
|
+
tags: ["invariant-violation"]
|
|
724
792
|
});
|
|
725
793
|
return;
|
|
726
794
|
}
|
|
@@ -739,9 +807,14 @@ var Transport = class {
|
|
|
739
807
|
const errMsg = `received out-of-order msg (got seq: ${msg.seq}, wanted seq: ${session.nextExpectedSeq})`;
|
|
740
808
|
log?.error(`${errMsg}, marking connection as dead`, {
|
|
741
809
|
clientId: this.clientId,
|
|
742
|
-
fullTransportMessage: msg
|
|
810
|
+
fullTransportMessage: msg,
|
|
811
|
+
tags: ["invariant-violation"]
|
|
743
812
|
});
|
|
744
813
|
this.protocolError(ProtocolError.MessageOrderingViolated, errMsg);
|
|
814
|
+
session.telemetry.span.setStatus({
|
|
815
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
816
|
+
message: "message order violated"
|
|
817
|
+
});
|
|
745
818
|
session.close();
|
|
746
819
|
}
|
|
747
820
|
return;
|
|
@@ -783,7 +856,8 @@ var Transport = class {
|
|
|
783
856
|
const err = "transport is destroyed, cant send";
|
|
784
857
|
log?.error(err, {
|
|
785
858
|
clientId: this.clientId,
|
|
786
|
-
partialTransportMessage: msg
|
|
859
|
+
partialTransportMessage: msg,
|
|
860
|
+
tags: ["invariant-violation"]
|
|
787
861
|
});
|
|
788
862
|
this.protocolError(ProtocolError.UseAfterDestroy, err);
|
|
789
863
|
return void 0;
|
|
@@ -868,7 +942,7 @@ var ClientTransport = class extends Transport {
|
|
|
868
942
|
if (!session) {
|
|
869
943
|
log?.warn(
|
|
870
944
|
`connection to ${to} timed out waiting for handshake, closing`,
|
|
871
|
-
{ clientId: this.clientId, connectedTo: to, connId: conn.
|
|
945
|
+
{ clientId: this.clientId, connectedTo: to, connId: conn.id }
|
|
872
946
|
);
|
|
873
947
|
conn.close();
|
|
874
948
|
}
|
|
@@ -886,6 +960,10 @@ var ClientTransport = class extends Transport {
|
|
|
886
960
|
conn.addDataListener((data2) => {
|
|
887
961
|
const parsed = this.parseMsg(data2);
|
|
888
962
|
if (!parsed) {
|
|
963
|
+
conn.telemetry?.span.setStatus({
|
|
964
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
965
|
+
message: "message parse failure"
|
|
966
|
+
});
|
|
889
967
|
conn.close();
|
|
890
968
|
return;
|
|
891
969
|
}
|
|
@@ -908,6 +986,10 @@ var ClientTransport = class extends Transport {
|
|
|
908
986
|
}
|
|
909
987
|
});
|
|
910
988
|
conn.addErrorListener((err) => {
|
|
989
|
+
conn.telemetry?.span.setStatus({
|
|
990
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
991
|
+
message: "connection error"
|
|
992
|
+
});
|
|
911
993
|
log?.warn(`error in connection to ${to}: ${coerceErrorString(err)}`, {
|
|
912
994
|
...session?.loggingMetadata,
|
|
913
995
|
clientId: this.clientId,
|
|
@@ -918,6 +1000,10 @@ var ClientTransport = class extends Transport {
|
|
|
918
1000
|
receiveHandshakeResponseMessage(data, conn) {
|
|
919
1001
|
const parsed = this.parseMsg(data);
|
|
920
1002
|
if (!parsed) {
|
|
1003
|
+
conn.telemetry?.span.setStatus({
|
|
1004
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
1005
|
+
message: "non-transport message"
|
|
1006
|
+
});
|
|
921
1007
|
this.protocolError(
|
|
922
1008
|
ProtocolError.HandshakeFailed,
|
|
923
1009
|
"received non-transport message"
|
|
@@ -925,6 +1011,10 @@ var ClientTransport = class extends Transport {
|
|
|
925
1011
|
return false;
|
|
926
1012
|
}
|
|
927
1013
|
if (!import_value.Value.Check(ControlMessageHandshakeResponseSchema, parsed.payload)) {
|
|
1014
|
+
conn.telemetry?.span.setStatus({
|
|
1015
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
1016
|
+
message: "invalid handshake response"
|
|
1017
|
+
});
|
|
928
1018
|
log?.warn(`received invalid handshake resp`, {
|
|
929
1019
|
clientId: this.clientId,
|
|
930
1020
|
connectedTo: parsed.from,
|
|
@@ -937,7 +1027,11 @@ var ClientTransport = class extends Transport {
|
|
|
937
1027
|
return false;
|
|
938
1028
|
}
|
|
939
1029
|
if (!parsed.payload.status.ok) {
|
|
940
|
-
|
|
1030
|
+
conn.telemetry?.span.setStatus({
|
|
1031
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
1032
|
+
message: "handshake rejected"
|
|
1033
|
+
});
|
|
1034
|
+
log?.warn(`received handshake rejection`, {
|
|
941
1035
|
clientId: this.clientId,
|
|
942
1036
|
connectedTo: parsed.from,
|
|
943
1037
|
fullTransportMessage: parsed
|
|
@@ -967,142 +1061,94 @@ var ClientTransport = class extends Transport {
|
|
|
967
1061
|
* @param to The client ID of the node to connect to.
|
|
968
1062
|
*/
|
|
969
1063
|
async connect(to) {
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
span.recordException(coerceErrorString(e));
|
|
987
|
-
}
|
|
988
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
989
|
-
} finally {
|
|
990
|
-
span.end();
|
|
991
|
-
}
|
|
1064
|
+
const canProceedWithConnection = () => this.state === "open";
|
|
1065
|
+
if (!canProceedWithConnection()) {
|
|
1066
|
+
log?.info(
|
|
1067
|
+
`transport state is no longer open, cancelling attempt to connect to ${to}`,
|
|
1068
|
+
{ clientId: this.clientId, connectedTo: to }
|
|
1069
|
+
);
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
1072
|
+
let reconnectPromise = this.inflightConnectionPromises.get(to);
|
|
1073
|
+
if (!reconnectPromise) {
|
|
1074
|
+
const budgetConsumed = this.retryBudget.getBudgetConsumed(to);
|
|
1075
|
+
if (!this.retryBudget.hasBudget(to)) {
|
|
1076
|
+
const errMsg = `tried to connect to ${to} but retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
|
|
1077
|
+
log?.warn(errMsg, { clientId: this.clientId, connectedTo: to });
|
|
1078
|
+
this.protocolError(ProtocolError.RetriesExceeded, errMsg);
|
|
1079
|
+
return;
|
|
992
1080
|
}
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
{
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
kind: import_api2.SpanKind.CLIENT
|
|
1005
|
-
},
|
|
1006
|
-
async (span) => {
|
|
1081
|
+
let sleep = Promise.resolve();
|
|
1082
|
+
const backoffMs = this.retryBudget.getBackoffMs(to);
|
|
1083
|
+
if (backoffMs > 0) {
|
|
1084
|
+
sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
1085
|
+
}
|
|
1086
|
+
log?.info(`attempting connection to ${to} (${backoffMs}ms backoff)`, {
|
|
1087
|
+
clientId: this.clientId,
|
|
1088
|
+
connectedTo: to
|
|
1089
|
+
});
|
|
1090
|
+
this.retryBudget.consumeBudget(to);
|
|
1091
|
+
reconnectPromise = tracing_default.startActiveSpan("connect", async (span) => {
|
|
1007
1092
|
try {
|
|
1008
|
-
|
|
1093
|
+
span.addEvent("backoff", { backoffMs });
|
|
1094
|
+
await sleep;
|
|
1009
1095
|
if (!canProceedWithConnection()) {
|
|
1010
|
-
|
|
1011
|
-
`transport state is no longer open, cancelling attempt to connect to ${to}`,
|
|
1012
|
-
{ clientId: this.clientId, connectedTo: to }
|
|
1013
|
-
);
|
|
1014
|
-
return false;
|
|
1096
|
+
throw new Error("transport state is no longer open");
|
|
1015
1097
|
}
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
if (!this.retryBudget.hasBudget(to)) {
|
|
1020
|
-
const errMsg = `tried to connect to ${to} but retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
|
|
1021
|
-
log?.warn(errMsg, { clientId: this.clientId, connectedTo: to });
|
|
1022
|
-
this.protocolError(ProtocolError.RetriesExceeded, errMsg);
|
|
1023
|
-
return false;
|
|
1024
|
-
}
|
|
1025
|
-
let sleep = Promise.resolve();
|
|
1026
|
-
const backoffMs = this.retryBudget.getBackoffMs(to);
|
|
1027
|
-
if (backoffMs > 0) {
|
|
1028
|
-
sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
|
|
1029
|
-
}
|
|
1030
|
-
log?.info(
|
|
1031
|
-
`attempting connection to ${to} (${backoffMs}ms backoff)`,
|
|
1032
|
-
{
|
|
1033
|
-
clientId: this.clientId,
|
|
1034
|
-
connectedTo: to
|
|
1035
|
-
}
|
|
1036
|
-
);
|
|
1037
|
-
this.retryBudget.consumeBudget(to);
|
|
1038
|
-
reconnectPromise = sleep.then(() => {
|
|
1039
|
-
if (!canProceedWithConnection()) {
|
|
1040
|
-
throw new Error("transport state is no longer open");
|
|
1041
|
-
}
|
|
1042
|
-
}).then(() => this.createNewOutgoingConnection(to)).then((conn) => {
|
|
1043
|
-
if (!canProceedWithConnection()) {
|
|
1044
|
-
log?.info(
|
|
1045
|
-
`transport state is no longer open, closing pre-handshake connection to ${to}`,
|
|
1046
|
-
{
|
|
1047
|
-
clientId: this.clientId,
|
|
1048
|
-
connectedTo: to,
|
|
1049
|
-
connId: conn.debugId
|
|
1050
|
-
}
|
|
1051
|
-
);
|
|
1052
|
-
conn.close();
|
|
1053
|
-
throw new Error("transport state is no longer open");
|
|
1054
|
-
}
|
|
1055
|
-
return this.sendHandshake(to, conn).then((ok) => {
|
|
1056
|
-
if (!ok) {
|
|
1057
|
-
conn.close();
|
|
1058
|
-
throw new Error("failed to send handshake");
|
|
1059
|
-
}
|
|
1060
|
-
return conn;
|
|
1061
|
-
});
|
|
1062
|
-
});
|
|
1063
|
-
this.inflightConnectionPromises.set(to, reconnectPromise);
|
|
1064
|
-
} else {
|
|
1098
|
+
span.addEvent("connecting");
|
|
1099
|
+
const conn = await this.createNewOutgoingConnection(to);
|
|
1100
|
+
if (!canProceedWithConnection()) {
|
|
1065
1101
|
log?.info(
|
|
1066
|
-
`
|
|
1102
|
+
`transport state is no longer open, closing pre-handshake connection to ${to}`,
|
|
1067
1103
|
{
|
|
1068
1104
|
clientId: this.clientId,
|
|
1069
|
-
connectedTo: to
|
|
1105
|
+
connectedTo: to,
|
|
1106
|
+
connId: conn.id
|
|
1070
1107
|
}
|
|
1071
1108
|
);
|
|
1109
|
+
conn.close();
|
|
1110
|
+
throw new Error("transport state is no longer open");
|
|
1072
1111
|
}
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
if (!this.reconnectOnConnectionDrop || !canProceedWithConnection()) {
|
|
1079
|
-
log?.warn(`connection to ${to} failed (${errStr})`, {
|
|
1080
|
-
clientId: this.clientId,
|
|
1081
|
-
connectedTo: to
|
|
1082
|
-
});
|
|
1083
|
-
} else {
|
|
1084
|
-
log?.warn(`connection to ${to} failed (${errStr}), retrying`, {
|
|
1085
|
-
clientId: this.clientId,
|
|
1086
|
-
connectedTo: to
|
|
1087
|
-
});
|
|
1088
|
-
return true;
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
} catch (e) {
|
|
1092
|
-
if (e instanceof Error) {
|
|
1093
|
-
span.recordException(e);
|
|
1094
|
-
} else {
|
|
1095
|
-
span.recordException(coerceErrorString(e));
|
|
1112
|
+
span.addEvent("sending handshake");
|
|
1113
|
+
const ok = await this.sendHandshake(to, conn);
|
|
1114
|
+
if (!ok) {
|
|
1115
|
+
conn.close();
|
|
1116
|
+
throw new Error("failed to send handshake");
|
|
1096
1117
|
}
|
|
1097
|
-
|
|
1118
|
+
return conn;
|
|
1119
|
+
} catch (err) {
|
|
1120
|
+
const errStr = coerceErrorString(err);
|
|
1121
|
+
span.recordException(errStr);
|
|
1122
|
+
span.setStatus({ code: import_api3.SpanStatusCode.ERROR });
|
|
1123
|
+
throw err;
|
|
1098
1124
|
} finally {
|
|
1099
1125
|
span.end();
|
|
1100
1126
|
}
|
|
1101
|
-
|
|
1127
|
+
});
|
|
1128
|
+
this.inflightConnectionPromises.set(to, reconnectPromise);
|
|
1129
|
+
} else {
|
|
1130
|
+
log?.info(`attempting connection to ${to} (reusing previous attempt)`, {
|
|
1131
|
+
clientId: this.clientId,
|
|
1132
|
+
connectedTo: to
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
try {
|
|
1136
|
+
await reconnectPromise;
|
|
1137
|
+
} catch (error) {
|
|
1138
|
+
this.inflightConnectionPromises.delete(to);
|
|
1139
|
+
const errStr = coerceErrorString(error);
|
|
1140
|
+
if (!this.reconnectOnConnectionDrop || !canProceedWithConnection()) {
|
|
1141
|
+
log?.warn(`connection to ${to} failed (${errStr})`, {
|
|
1142
|
+
clientId: this.clientId,
|
|
1143
|
+
connectedTo: to
|
|
1144
|
+
});
|
|
1145
|
+
} else {
|
|
1146
|
+
log?.warn(`connection to ${to} failed (${errStr}), retrying`, {
|
|
1147
|
+
clientId: this.clientId,
|
|
1148
|
+
connectedTo: to
|
|
1149
|
+
});
|
|
1150
|
+
return this.connect(to);
|
|
1102
1151
|
}
|
|
1103
|
-
);
|
|
1104
|
-
if (retry) {
|
|
1105
|
-
return this.connectAttempt(to, attempt + 1);
|
|
1106
1152
|
}
|
|
1107
1153
|
}
|
|
1108
1154
|
deleteSession(session) {
|
|
@@ -1110,20 +1156,23 @@ var ClientTransport = class extends Transport {
|
|
|
1110
1156
|
super.deleteSession(session);
|
|
1111
1157
|
}
|
|
1112
1158
|
async sendHandshake(to, conn) {
|
|
1113
|
-
const tracing = { traceparent: "", tracestate: "" };
|
|
1114
|
-
import_api2.propagation.inject(import_api2.context.active(), tracing);
|
|
1115
1159
|
let metadata;
|
|
1116
1160
|
if (this.options.handshake) {
|
|
1117
1161
|
metadata = await this.options.handshake.get();
|
|
1118
1162
|
if (!import_value.Value.Check(this.options.handshake.schema, metadata)) {
|
|
1119
1163
|
log?.error(`handshake metadata did not match schema`, {
|
|
1120
1164
|
clientId: this.clientId,
|
|
1121
|
-
connectedTo: to
|
|
1165
|
+
connectedTo: to,
|
|
1166
|
+
tags: ["invariant-violation"]
|
|
1122
1167
|
});
|
|
1123
1168
|
this.protocolError(
|
|
1124
1169
|
ProtocolError.HandshakeFailed,
|
|
1125
1170
|
"handshake metadata did not match schema"
|
|
1126
1171
|
);
|
|
1172
|
+
conn.telemetry?.span.setStatus({
|
|
1173
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
1174
|
+
message: "handshake meta mismatch"
|
|
1175
|
+
});
|
|
1127
1176
|
return false;
|
|
1128
1177
|
}
|
|
1129
1178
|
}
|
|
@@ -1133,7 +1182,7 @@ var ClientTransport = class extends Transport {
|
|
|
1133
1182
|
to,
|
|
1134
1183
|
session.id,
|
|
1135
1184
|
metadata,
|
|
1136
|
-
|
|
1185
|
+
getPropagationContext(session.telemetry.ctx)
|
|
1137
1186
|
);
|
|
1138
1187
|
log?.debug(`sending handshake request to ${to}`, {
|
|
1139
1188
|
clientId: this.clientId,
|
|
@@ -1164,267 +1213,233 @@ var ServerTransport = class extends Transport {
|
|
|
1164
1213
|
});
|
|
1165
1214
|
}
|
|
1166
1215
|
handleConnection(conn) {
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
(
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1216
|
+
if (this.state !== "open")
|
|
1217
|
+
return;
|
|
1218
|
+
log?.info(`new incoming connection`, {
|
|
1219
|
+
clientId: this.clientId,
|
|
1220
|
+
connId: conn.id
|
|
1221
|
+
});
|
|
1222
|
+
let session = void 0;
|
|
1223
|
+
const client = () => session?.to ?? "unknown";
|
|
1224
|
+
const handshakeTimeout = setTimeout(() => {
|
|
1225
|
+
if (!session) {
|
|
1226
|
+
log?.warn(
|
|
1227
|
+
`connection to ${client()} timed out waiting for handshake, closing`,
|
|
1228
|
+
{
|
|
1229
|
+
clientId: this.clientId,
|
|
1230
|
+
connectedTo: client(),
|
|
1231
|
+
connId: conn.id
|
|
1232
|
+
}
|
|
1233
|
+
);
|
|
1234
|
+
conn.telemetry?.span.setStatus({
|
|
1235
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
1236
|
+
message: "handshake timeout"
|
|
1182
1237
|
});
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1238
|
+
conn.close();
|
|
1239
|
+
}
|
|
1240
|
+
}, this.options.sessionDisconnectGraceMs);
|
|
1241
|
+
const buffer = [];
|
|
1242
|
+
let receivedHandshakeMessage = false;
|
|
1243
|
+
const handshakeHandler = (data) => {
|
|
1244
|
+
if (receivedHandshakeMessage) {
|
|
1245
|
+
buffer.push(data);
|
|
1246
|
+
return;
|
|
1247
|
+
}
|
|
1248
|
+
receivedHandshakeMessage = true;
|
|
1249
|
+
clearTimeout(handshakeTimeout);
|
|
1250
|
+
void this.receiveHandshakeRequestMessage(data, conn).then(
|
|
1251
|
+
(maybeSession) => {
|
|
1252
|
+
if (!maybeSession) {
|
|
1197
1253
|
conn.close();
|
|
1198
|
-
}
|
|
1199
|
-
}, this.options.sessionDisconnectGraceMs);
|
|
1200
|
-
const buffer = [];
|
|
1201
|
-
let receivedHandshakeMessage = false;
|
|
1202
|
-
const handshakeHandler = (data) => {
|
|
1203
|
-
if (receivedHandshakeMessage) {
|
|
1204
|
-
buffer.push(data);
|
|
1205
1254
|
return;
|
|
1206
1255
|
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
(
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
span.end();
|
|
1214
|
-
conn.close();
|
|
1215
|
-
return;
|
|
1216
|
-
}
|
|
1217
|
-
session = maybeSession;
|
|
1218
|
-
const dataHandler = (data2) => {
|
|
1219
|
-
const parsed = this.parseMsg(data2);
|
|
1220
|
-
if (!parsed) {
|
|
1221
|
-
conn.close();
|
|
1222
|
-
return;
|
|
1223
|
-
}
|
|
1224
|
-
this.handleMsg(parsed);
|
|
1225
|
-
};
|
|
1226
|
-
conn.removeDataListener(handshakeHandler);
|
|
1227
|
-
conn.addDataListener(dataHandler);
|
|
1228
|
-
for (const data2 of buffer) {
|
|
1229
|
-
dataHandler(data2);
|
|
1230
|
-
}
|
|
1231
|
-
buffer.length = 0;
|
|
1256
|
+
session = maybeSession;
|
|
1257
|
+
const dataHandler = (data2) => {
|
|
1258
|
+
const parsed = this.parseMsg(data2);
|
|
1259
|
+
if (!parsed) {
|
|
1260
|
+
conn.close();
|
|
1261
|
+
return;
|
|
1232
1262
|
}
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
if (session) {
|
|
1238
|
-
log?.info(`connection to ${client()} disconnected`, {
|
|
1239
|
-
clientId: this.clientId,
|
|
1240
|
-
connId: conn.debugId
|
|
1241
|
-
});
|
|
1242
|
-
this.onDisconnect(conn, session);
|
|
1263
|
+
this.handleMsg(parsed);
|
|
1264
|
+
};
|
|
1265
|
+
for (const data2 of buffer) {
|
|
1266
|
+
dataHandler(data2);
|
|
1243
1267
|
}
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
)
|
|
1268
|
+
conn.removeDataListener(handshakeHandler);
|
|
1269
|
+
conn.addDataListener(dataHandler);
|
|
1270
|
+
buffer.length = 0;
|
|
1271
|
+
}
|
|
1272
|
+
);
|
|
1273
|
+
};
|
|
1274
|
+
conn.addDataListener(handshakeHandler);
|
|
1275
|
+
conn.addCloseListener(() => {
|
|
1276
|
+
if (!session)
|
|
1277
|
+
return;
|
|
1278
|
+
log?.info(`connection to ${client()} disconnected`, {
|
|
1279
|
+
clientId: this.clientId,
|
|
1280
|
+
connId: conn.id
|
|
1281
|
+
});
|
|
1282
|
+
this.onDisconnect(conn, session);
|
|
1283
|
+
});
|
|
1284
|
+
conn.addErrorListener((err) => {
|
|
1285
|
+
conn.telemetry?.span.setStatus({
|
|
1286
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
1287
|
+
message: "connection error"
|
|
1288
|
+
});
|
|
1289
|
+
if (!session)
|
|
1290
|
+
return;
|
|
1291
|
+
log?.warn(
|
|
1292
|
+
`connection to ${client()} got an error: ${coerceErrorString(err)}`,
|
|
1293
|
+
{ clientId: this.clientId, connId: conn.id }
|
|
1294
|
+
);
|
|
1295
|
+
});
|
|
1261
1296
|
}
|
|
1262
1297
|
async receiveHandshakeRequestMessage(data, conn) {
|
|
1263
1298
|
const parsed = this.parseMsg(data);
|
|
1264
1299
|
if (!parsed) {
|
|
1300
|
+
conn.telemetry?.span.setStatus({
|
|
1301
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
1302
|
+
message: "non-transport message"
|
|
1303
|
+
});
|
|
1265
1304
|
this.protocolError(
|
|
1266
1305
|
ProtocolError.HandshakeFailed,
|
|
1267
1306
|
"received non-transport message"
|
|
1268
1307
|
);
|
|
1269
1308
|
return false;
|
|
1270
1309
|
}
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1310
|
+
if (!import_value.Value.Check(ControlMessageHandshakeRequestSchema, parsed.payload)) {
|
|
1311
|
+
conn.telemetry?.span.setStatus({
|
|
1312
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
1313
|
+
message: "invalid handshake request"
|
|
1314
|
+
});
|
|
1315
|
+
const reason = "received invalid handshake msg";
|
|
1316
|
+
const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
|
|
1317
|
+
ok: false,
|
|
1318
|
+
reason
|
|
1319
|
+
});
|
|
1320
|
+
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1321
|
+
const logData = { ...parsed.payload ?? {}, metadata: "redacted" };
|
|
1322
|
+
log?.warn(reason, {
|
|
1323
|
+
clientId: this.clientId,
|
|
1324
|
+
connId: conn.id,
|
|
1325
|
+
partialTransportMessage: { ...parsed, payload: logData }
|
|
1326
|
+
});
|
|
1327
|
+
this.protocolError(
|
|
1328
|
+
ProtocolError.HandshakeFailed,
|
|
1329
|
+
"invalid handshake request"
|
|
1330
|
+
);
|
|
1331
|
+
return false;
|
|
1274
1332
|
}
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
{
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
const gotVersion = parsed.payload.protocolVersion;
|
|
1314
|
-
if (gotVersion !== PROTOCOL_VERSION) {
|
|
1315
|
-
const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
|
|
1316
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
1317
|
-
this.clientId,
|
|
1318
|
-
parsed.from,
|
|
1319
|
-
{
|
|
1320
|
-
ok: false,
|
|
1321
|
-
reason
|
|
1322
|
-
}
|
|
1323
|
-
);
|
|
1324
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1325
|
-
log?.warn(
|
|
1326
|
-
`received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`,
|
|
1327
|
-
{ clientId: this.clientId, connId: conn.debugId }
|
|
1328
|
-
);
|
|
1329
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1330
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
1331
|
-
span.end();
|
|
1332
|
-
return false;
|
|
1333
|
-
}
|
|
1334
|
-
const { session, isReconnect } = this.getOrCreateSession(
|
|
1333
|
+
const gotVersion = parsed.payload.protocolVersion;
|
|
1334
|
+
if (gotVersion !== PROTOCOL_VERSION) {
|
|
1335
|
+
conn.telemetry?.span.setStatus({
|
|
1336
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
1337
|
+
message: "incorrect protocol version"
|
|
1338
|
+
});
|
|
1339
|
+
const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
|
|
1340
|
+
const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
|
|
1341
|
+
ok: false,
|
|
1342
|
+
reason
|
|
1343
|
+
});
|
|
1344
|
+
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1345
|
+
log?.warn(
|
|
1346
|
+
`received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`,
|
|
1347
|
+
{ clientId: this.clientId, connId: conn.id }
|
|
1348
|
+
);
|
|
1349
|
+
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1350
|
+
return false;
|
|
1351
|
+
}
|
|
1352
|
+
const { session, isReconnect } = this.getOrCreateSession(
|
|
1353
|
+
parsed.from,
|
|
1354
|
+
conn,
|
|
1355
|
+
parsed.payload.sessionId,
|
|
1356
|
+
parsed.tracing
|
|
1357
|
+
);
|
|
1358
|
+
let handshakeMetadata;
|
|
1359
|
+
if (this.options.handshake) {
|
|
1360
|
+
if (!import_value.Value.Check(
|
|
1361
|
+
this.options.handshake.requestSchema,
|
|
1362
|
+
parsed.payload.metadata
|
|
1363
|
+
)) {
|
|
1364
|
+
conn.telemetry?.span.setStatus({
|
|
1365
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
1366
|
+
message: "malformed handshake meta"
|
|
1367
|
+
});
|
|
1368
|
+
const reason = "received malformed handshake metadata";
|
|
1369
|
+
const responseMsg2 = handshakeResponseMessage(
|
|
1370
|
+
this.clientId,
|
|
1335
1371
|
parsed.from,
|
|
1336
|
-
|
|
1337
|
-
parsed.payload.sessionId
|
|
1372
|
+
{ ok: false, reason }
|
|
1338
1373
|
);
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
return false;
|
|
1364
|
-
}
|
|
1365
|
-
const parsedMetadata = await this.options.handshake.parse(
|
|
1366
|
-
parsed.payload.metadata,
|
|
1367
|
-
session,
|
|
1368
|
-
isReconnect
|
|
1369
|
-
);
|
|
1370
|
-
if (parsedMetadata === false) {
|
|
1371
|
-
const reason = "rejected by server";
|
|
1372
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
1373
|
-
this.clientId,
|
|
1374
|
-
parsed.from,
|
|
1375
|
-
{ ok: false, reason }
|
|
1376
|
-
);
|
|
1377
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1378
|
-
log?.warn(`rejected handshake from ${parsed.from}`, {
|
|
1379
|
-
clientId: this.clientId,
|
|
1380
|
-
connId: conn.debugId
|
|
1381
|
-
});
|
|
1382
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1383
|
-
this.deleteSession(session);
|
|
1384
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
1385
|
-
span.end();
|
|
1386
|
-
return false;
|
|
1387
|
-
}
|
|
1388
|
-
if (!import_value.Value.Check(this.options.handshake.parsedSchema, parsedMetadata)) {
|
|
1389
|
-
const reason = "failed to parse handshake metadata";
|
|
1390
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
1391
|
-
this.clientId,
|
|
1392
|
-
parsed.from,
|
|
1393
|
-
{ ok: false, reason }
|
|
1394
|
-
);
|
|
1395
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1396
|
-
log?.error(`failed to parse handshake metadata`, {
|
|
1397
|
-
clientId: this.clientId,
|
|
1398
|
-
connId: conn.debugId
|
|
1399
|
-
});
|
|
1400
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1401
|
-
this.deleteSession(session);
|
|
1402
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
1403
|
-
span.end();
|
|
1404
|
-
return false;
|
|
1405
|
-
}
|
|
1406
|
-
handshakeMetadata = parsedMetadata;
|
|
1407
|
-
}
|
|
1408
|
-
handshakeMetadata ??= {};
|
|
1409
|
-
session.metadata = handshakeMetadata;
|
|
1410
|
-
log?.debug(
|
|
1411
|
-
`handshake from ${parsed.from} ok, responding with handshake success`,
|
|
1412
|
-
{ clientId: this.clientId, connId: conn.debugId }
|
|
1374
|
+
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1375
|
+
log?.warn(`received malformed handshake metadata from ${parsed.from}`, {
|
|
1376
|
+
clientId: this.clientId,
|
|
1377
|
+
connId: conn.id
|
|
1378
|
+
});
|
|
1379
|
+
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1380
|
+
this.deleteSession(session);
|
|
1381
|
+
return false;
|
|
1382
|
+
}
|
|
1383
|
+
const parsedMetadata = await this.options.handshake.parse(
|
|
1384
|
+
parsed.payload.metadata,
|
|
1385
|
+
session,
|
|
1386
|
+
isReconnect
|
|
1387
|
+
);
|
|
1388
|
+
if (parsedMetadata === false) {
|
|
1389
|
+
conn.telemetry?.span.setStatus({
|
|
1390
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
1391
|
+
message: "rejected by handshake handler"
|
|
1392
|
+
});
|
|
1393
|
+
const reason = "rejected by handshake handler";
|
|
1394
|
+
const responseMsg2 = handshakeResponseMessage(
|
|
1395
|
+
this.clientId,
|
|
1396
|
+
parsed.from,
|
|
1397
|
+
{ ok: false, reason }
|
|
1413
1398
|
);
|
|
1414
|
-
|
|
1399
|
+
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1400
|
+
log?.warn(`rejected handshake from ${parsed.from}`, {
|
|
1401
|
+
clientId: this.clientId,
|
|
1402
|
+
connId: conn.id
|
|
1403
|
+
});
|
|
1404
|
+
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1405
|
+
this.deleteSession(session);
|
|
1406
|
+
return false;
|
|
1407
|
+
}
|
|
1408
|
+
if (!import_value.Value.Check(this.options.handshake.parsedSchema, parsedMetadata)) {
|
|
1409
|
+
conn.telemetry?.span.setStatus({
|
|
1410
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
1411
|
+
message: "malformed handshake meta"
|
|
1412
|
+
});
|
|
1413
|
+
const reason = "failed to parse handshake metadata";
|
|
1414
|
+
const responseMsg2 = handshakeResponseMessage(
|
|
1415
1415
|
this.clientId,
|
|
1416
1416
|
parsed.from,
|
|
1417
|
-
{
|
|
1418
|
-
ok: true,
|
|
1419
|
-
sessionId: session.id
|
|
1420
|
-
}
|
|
1417
|
+
{ ok: false, reason }
|
|
1421
1418
|
);
|
|
1422
|
-
conn.send(this.codec.toBuffer(
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1419
|
+
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1420
|
+
log?.error(`failed to parse handshake metadata`, {
|
|
1421
|
+
clientId: this.clientId,
|
|
1422
|
+
connId: conn.id
|
|
1423
|
+
});
|
|
1424
|
+
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1425
|
+
this.deleteSession(session);
|
|
1426
|
+
return false;
|
|
1426
1427
|
}
|
|
1428
|
+
handshakeMetadata = parsedMetadata;
|
|
1429
|
+
}
|
|
1430
|
+
handshakeMetadata ??= {};
|
|
1431
|
+
session.metadata = handshakeMetadata;
|
|
1432
|
+
log?.debug(
|
|
1433
|
+
`handshake from ${parsed.from} ok, responding with handshake success`,
|
|
1434
|
+
{ clientId: this.clientId, connId: conn.id }
|
|
1427
1435
|
);
|
|
1436
|
+
const responseMsg = handshakeResponseMessage(this.clientId, parsed.from, {
|
|
1437
|
+
ok: true,
|
|
1438
|
+
sessionId: session.id
|
|
1439
|
+
});
|
|
1440
|
+
conn.send(this.codec.toBuffer(responseMsg));
|
|
1441
|
+
this.onConnect(conn, parsed.from, session, isReconnect);
|
|
1442
|
+
return session;
|
|
1428
1443
|
}
|
|
1429
1444
|
};
|
|
1430
1445
|
// Annotate the CommonJS export names for ESM import in node:
|