@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
|
@@ -26,7 +26,6 @@ module.exports = __toCommonJS(server_exports);
|
|
|
26
26
|
|
|
27
27
|
// transport/transport.ts
|
|
28
28
|
var import_value = require("@sinclair/typebox/value");
|
|
29
|
-
var import_api2 = require("@opentelemetry/api");
|
|
30
29
|
|
|
31
30
|
// transport/message.ts
|
|
32
31
|
var import_typebox = require("@sinclair/typebox");
|
|
@@ -142,17 +141,62 @@ var EventDispatcher = class {
|
|
|
142
141
|
|
|
143
142
|
// transport/session.ts
|
|
144
143
|
var import_nanoid2 = require("nanoid");
|
|
144
|
+
|
|
145
|
+
// tracing/index.ts
|
|
146
|
+
var import_api = require("@opentelemetry/api");
|
|
147
|
+
|
|
148
|
+
// package.json
|
|
149
|
+
var version = "0.23.0";
|
|
150
|
+
|
|
151
|
+
// tracing/index.ts
|
|
152
|
+
function createSessionTelemetryInfo(session, propagationCtx) {
|
|
153
|
+
const ctx = propagationCtx ? import_api.propagation.extract(import_api.context.active(), propagationCtx) : import_api.context.active();
|
|
154
|
+
const span = tracer.startSpan(
|
|
155
|
+
`session ${session.id}`,
|
|
156
|
+
{
|
|
157
|
+
attributes: {
|
|
158
|
+
component: "river",
|
|
159
|
+
"river.session.id": session.id,
|
|
160
|
+
"river.session.to": session.to,
|
|
161
|
+
"river.session.from": session.from
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
ctx
|
|
165
|
+
);
|
|
166
|
+
return { span, ctx };
|
|
167
|
+
}
|
|
168
|
+
function createConnectionTelemetryInfo(connection, sessionSpan) {
|
|
169
|
+
const ctx = import_api.trace.setSpan(import_api.context.active(), sessionSpan);
|
|
170
|
+
const span = tracer.startSpan(
|
|
171
|
+
`connection ${connection.id}`,
|
|
172
|
+
{
|
|
173
|
+
attributes: {
|
|
174
|
+
component: "river",
|
|
175
|
+
"river.connection.id": connection.id
|
|
176
|
+
},
|
|
177
|
+
links: [{ context: sessionSpan.spanContext() }]
|
|
178
|
+
},
|
|
179
|
+
ctx
|
|
180
|
+
);
|
|
181
|
+
return { span, ctx };
|
|
182
|
+
}
|
|
183
|
+
var tracer = import_api.trace.getTracer("river", version);
|
|
184
|
+
|
|
185
|
+
// transport/session.ts
|
|
186
|
+
var import_api2 = require("@opentelemetry/api");
|
|
145
187
|
var nanoid2 = (0, import_nanoid2.customAlphabet)("1234567890abcdefghijklmnopqrstuvxyz", 6);
|
|
146
188
|
var unsafeId = () => nanoid2();
|
|
147
189
|
var Connection = class {
|
|
148
|
-
|
|
190
|
+
id;
|
|
191
|
+
telemetry;
|
|
149
192
|
constructor() {
|
|
150
|
-
this.
|
|
193
|
+
this.id = `conn-${nanoid2(12)}`;
|
|
151
194
|
}
|
|
152
195
|
};
|
|
153
196
|
var Session = class {
|
|
154
197
|
codec;
|
|
155
198
|
options;
|
|
199
|
+
telemetry;
|
|
156
200
|
/**
|
|
157
201
|
* The buffer of messages that have been sent but not yet acknowledged.
|
|
158
202
|
*/
|
|
@@ -172,12 +216,6 @@ var Session = class {
|
|
|
172
216
|
* for this session.
|
|
173
217
|
*/
|
|
174
218
|
advertisedSessionId;
|
|
175
|
-
/**
|
|
176
|
-
* The metadata for this session, as parsed from the handshake.
|
|
177
|
-
*
|
|
178
|
-
* Will only ever be populated on the server side.
|
|
179
|
-
*/
|
|
180
|
-
metadata;
|
|
181
219
|
/**
|
|
182
220
|
* Number of messages we've sent along this session (excluding handshake and acks)
|
|
183
221
|
*/
|
|
@@ -199,7 +237,7 @@ var Session = class {
|
|
|
199
237
|
* The interval for sending heartbeats.
|
|
200
238
|
*/
|
|
201
239
|
heartbeat;
|
|
202
|
-
constructor(conn, from, to, options) {
|
|
240
|
+
constructor(conn, from, to, options, propagationCtx) {
|
|
203
241
|
this.id = `session-${nanoid2(12)}`;
|
|
204
242
|
this.options = options;
|
|
205
243
|
this.from = from;
|
|
@@ -211,13 +249,14 @@ var Session = class {
|
|
|
211
249
|
() => this.sendHeartbeat(),
|
|
212
250
|
options.heartbeatIntervalMs
|
|
213
251
|
);
|
|
252
|
+
this.telemetry = createSessionTelemetryInfo(this, propagationCtx);
|
|
214
253
|
}
|
|
215
254
|
get loggingMetadata() {
|
|
216
255
|
return {
|
|
217
256
|
clientId: this.from,
|
|
218
257
|
connectedTo: this.to,
|
|
219
258
|
sessionId: this.id,
|
|
220
|
-
connId: this.connection?.
|
|
259
|
+
connId: this.connection?.id
|
|
221
260
|
};
|
|
222
261
|
}
|
|
223
262
|
/**
|
|
@@ -262,6 +301,7 @@ var Session = class {
|
|
|
262
301
|
`closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
|
|
263
302
|
this.loggingMetadata
|
|
264
303
|
);
|
|
304
|
+
this.telemetry.span.addEvent("closing connection due to inactivity");
|
|
265
305
|
this.closeStaleConnection();
|
|
266
306
|
}
|
|
267
307
|
return;
|
|
@@ -283,21 +323,25 @@ var Session = class {
|
|
|
283
323
|
sendBufferedMessages(conn) {
|
|
284
324
|
log?.info(`resending ${this.sendBuffer.length} buffered messages`, {
|
|
285
325
|
...this.loggingMetadata,
|
|
286
|
-
connId: conn.
|
|
326
|
+
connId: conn.id
|
|
287
327
|
});
|
|
288
328
|
for (const msg of this.sendBuffer) {
|
|
289
329
|
log?.debug(`resending msg`, {
|
|
290
330
|
...this.loggingMetadata,
|
|
291
331
|
fullTransportMessage: msg,
|
|
292
|
-
connId: conn.
|
|
332
|
+
connId: conn.id
|
|
293
333
|
});
|
|
294
334
|
const ok = conn.send(this.codec.toBuffer(msg));
|
|
295
335
|
if (!ok) {
|
|
296
336
|
const errMsg = `failed to send buffered message to ${this.to} (sus, this is a fresh connection)`;
|
|
337
|
+
conn.telemetry?.span.setStatus({
|
|
338
|
+
code: import_api2.SpanStatusCode.ERROR,
|
|
339
|
+
message: errMsg
|
|
340
|
+
});
|
|
297
341
|
log?.error(errMsg, {
|
|
298
342
|
...this.loggingMetadata,
|
|
299
343
|
fullTransportMessage: msg,
|
|
300
|
-
connId: conn.
|
|
344
|
+
connId: conn.id,
|
|
301
345
|
tags: ["invariant-violation"]
|
|
302
346
|
});
|
|
303
347
|
conn.close();
|
|
@@ -380,11 +424,6 @@ var Session = class {
|
|
|
380
424
|
}
|
|
381
425
|
};
|
|
382
426
|
|
|
383
|
-
// tracing/index.ts
|
|
384
|
-
var import_api = require("@opentelemetry/api");
|
|
385
|
-
var tracer = import_api.trace.getTracer("river");
|
|
386
|
-
var tracing_default = tracer;
|
|
387
|
-
|
|
388
427
|
// util/stringify.ts
|
|
389
428
|
function coerceErrorString(err) {
|
|
390
429
|
if (err instanceof Error) {
|
|
@@ -446,6 +485,7 @@ var NaiveJsonCodec = {
|
|
|
446
485
|
};
|
|
447
486
|
|
|
448
487
|
// transport/transport.ts
|
|
488
|
+
var import_api3 = require("@opentelemetry/api");
|
|
449
489
|
var defaultTransportOptions = {
|
|
450
490
|
heartbeatIntervalMs: 1e3,
|
|
451
491
|
heartbeatsUntilDead: 2,
|
|
@@ -524,17 +564,22 @@ var Transport = class {
|
|
|
524
564
|
status: "connect",
|
|
525
565
|
conn
|
|
526
566
|
});
|
|
567
|
+
conn.telemetry = createConnectionTelemetryInfo(
|
|
568
|
+
conn,
|
|
569
|
+
session.telemetry.span
|
|
570
|
+
);
|
|
527
571
|
if (isReconnect) {
|
|
528
572
|
session.replaceWithNewConnection(conn);
|
|
529
573
|
log?.info(`reconnected to ${connectedTo}`, session.loggingMetadata);
|
|
530
574
|
}
|
|
531
575
|
}
|
|
532
|
-
createSession(to, conn) {
|
|
576
|
+
createSession(to, conn, propagationCtx) {
|
|
533
577
|
const session = new Session(
|
|
534
578
|
conn,
|
|
535
579
|
this.clientId,
|
|
536
580
|
to,
|
|
537
|
-
this.options
|
|
581
|
+
this.options,
|
|
582
|
+
propagationCtx
|
|
538
583
|
);
|
|
539
584
|
this.sessions.set(session.to, session);
|
|
540
585
|
this.eventDispatcher.dispatchEvent("sessionStatus", {
|
|
@@ -543,11 +588,11 @@ var Transport = class {
|
|
|
543
588
|
});
|
|
544
589
|
return session;
|
|
545
590
|
}
|
|
546
|
-
getOrCreateSession(to, conn, sessionId) {
|
|
591
|
+
getOrCreateSession(to, conn, sessionId, propagationCtx) {
|
|
547
592
|
let session = this.sessions.get(to);
|
|
548
593
|
let isReconnect = session !== void 0;
|
|
549
594
|
if (session?.advertisedSessionId !== void 0 && sessionId !== void 0 && session.advertisedSessionId !== sessionId) {
|
|
550
|
-
log?.
|
|
595
|
+
log?.info(
|
|
551
596
|
`session for ${to} already exists but has a different session id (expected: ${session.advertisedSessionId}, got: ${sessionId}), creating a new one`,
|
|
552
597
|
session.loggingMetadata
|
|
553
598
|
);
|
|
@@ -556,7 +601,7 @@ var Transport = class {
|
|
|
556
601
|
session = void 0;
|
|
557
602
|
}
|
|
558
603
|
if (!session) {
|
|
559
|
-
session = this.createSession(to, conn);
|
|
604
|
+
session = this.createSession(to, conn, propagationCtx);
|
|
560
605
|
log?.info(
|
|
561
606
|
`no session for ${to}, created a new one`,
|
|
562
607
|
session.loggingMetadata
|
|
@@ -569,6 +614,7 @@ var Transport = class {
|
|
|
569
614
|
}
|
|
570
615
|
deleteSession(session) {
|
|
571
616
|
session.close();
|
|
617
|
+
session.telemetry.span.end();
|
|
572
618
|
this.sessions.delete(session.to);
|
|
573
619
|
log?.info(
|
|
574
620
|
`session ${session.id} disconnect from ${session.to}`,
|
|
@@ -585,12 +631,16 @@ var Transport = class {
|
|
|
585
631
|
* @param connectedTo The peer we are connected to.
|
|
586
632
|
*/
|
|
587
633
|
onDisconnect(conn, session) {
|
|
634
|
+
conn.telemetry?.span.end();
|
|
588
635
|
this.eventDispatcher.dispatchEvent("connectionStatus", {
|
|
589
636
|
status: "disconnect",
|
|
590
637
|
conn
|
|
591
638
|
});
|
|
592
639
|
session.connection = void 0;
|
|
593
|
-
session.beginGrace(() =>
|
|
640
|
+
session.beginGrace(() => {
|
|
641
|
+
session.telemetry.span.addEvent("session grace period expired");
|
|
642
|
+
this.deleteSession(session);
|
|
643
|
+
});
|
|
594
644
|
}
|
|
595
645
|
/**
|
|
596
646
|
* Parses a message from a Uint8Array into a {@link OpaqueTransportMessage}.
|
|
@@ -650,6 +700,10 @@ var Transport = class {
|
|
|
650
700
|
tags: ["invariant-violation"]
|
|
651
701
|
});
|
|
652
702
|
this.protocolError(ProtocolError.MessageOrderingViolated, errMsg);
|
|
703
|
+
session.telemetry.span.setStatus({
|
|
704
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
705
|
+
message: "message order violated"
|
|
706
|
+
});
|
|
653
707
|
session.close();
|
|
654
708
|
}
|
|
655
709
|
return;
|
|
@@ -748,280 +802,240 @@ var ServerTransport = class extends Transport {
|
|
|
748
802
|
* The options for this transport.
|
|
749
803
|
*/
|
|
750
804
|
options;
|
|
805
|
+
/**
|
|
806
|
+
* Optional handshake options for the server.
|
|
807
|
+
*/
|
|
808
|
+
handshakeExtensions;
|
|
809
|
+
/**
|
|
810
|
+
* A map of session handshake data for each session.
|
|
811
|
+
*/
|
|
812
|
+
sessionHandshakeMetadata;
|
|
751
813
|
constructor(clientId, providedOptions) {
|
|
752
814
|
super(clientId, providedOptions);
|
|
753
815
|
this.options = {
|
|
754
816
|
...defaultServerTransportOptions,
|
|
755
817
|
...providedOptions
|
|
756
818
|
};
|
|
819
|
+
this.sessionHandshakeMetadata = /* @__PURE__ */ new WeakMap();
|
|
757
820
|
log?.info(`initiated server transport`, {
|
|
758
821
|
clientId: this.clientId,
|
|
759
822
|
protocolVersion: PROTOCOL_VERSION
|
|
760
823
|
});
|
|
761
824
|
}
|
|
825
|
+
extendHandshake(options) {
|
|
826
|
+
this.handshakeExtensions = options;
|
|
827
|
+
}
|
|
762
828
|
handleConnection(conn) {
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
(
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
829
|
+
if (this.state !== "open")
|
|
830
|
+
return;
|
|
831
|
+
log?.info(`new incoming connection`, {
|
|
832
|
+
clientId: this.clientId,
|
|
833
|
+
connId: conn.id
|
|
834
|
+
});
|
|
835
|
+
let session = void 0;
|
|
836
|
+
const client = () => session?.to ?? "unknown";
|
|
837
|
+
const handshakeTimeout = setTimeout(() => {
|
|
838
|
+
if (!session) {
|
|
839
|
+
log?.warn(
|
|
840
|
+
`connection to ${client()} timed out waiting for handshake, closing`,
|
|
841
|
+
{
|
|
842
|
+
clientId: this.clientId,
|
|
843
|
+
connectedTo: client(),
|
|
844
|
+
connId: conn.id
|
|
845
|
+
}
|
|
846
|
+
);
|
|
847
|
+
conn.telemetry?.span.setStatus({
|
|
848
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
849
|
+
message: "handshake timeout"
|
|
778
850
|
});
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
851
|
+
conn.close();
|
|
852
|
+
}
|
|
853
|
+
}, this.options.sessionDisconnectGraceMs);
|
|
854
|
+
const buffer = [];
|
|
855
|
+
let receivedHandshakeMessage = false;
|
|
856
|
+
const handshakeHandler = (data) => {
|
|
857
|
+
if (receivedHandshakeMessage) {
|
|
858
|
+
buffer.push(data);
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
receivedHandshakeMessage = true;
|
|
862
|
+
clearTimeout(handshakeTimeout);
|
|
863
|
+
void this.receiveHandshakeRequestMessage(data, conn).then(
|
|
864
|
+
(maybeSession) => {
|
|
865
|
+
if (!maybeSession) {
|
|
793
866
|
conn.close();
|
|
794
|
-
}
|
|
795
|
-
}, this.options.sessionDisconnectGraceMs);
|
|
796
|
-
const buffer = [];
|
|
797
|
-
let receivedHandshakeMessage = false;
|
|
798
|
-
const handshakeHandler = (data) => {
|
|
799
|
-
if (receivedHandshakeMessage) {
|
|
800
|
-
buffer.push(data);
|
|
801
867
|
return;
|
|
802
868
|
}
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
(
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
span.end();
|
|
810
|
-
conn.close();
|
|
811
|
-
return;
|
|
812
|
-
}
|
|
813
|
-
session = maybeSession;
|
|
814
|
-
const dataHandler = (data2) => {
|
|
815
|
-
const parsed = this.parseMsg(data2);
|
|
816
|
-
if (!parsed) {
|
|
817
|
-
conn.close();
|
|
818
|
-
return;
|
|
819
|
-
}
|
|
820
|
-
this.handleMsg(parsed);
|
|
821
|
-
};
|
|
822
|
-
conn.removeDataListener(handshakeHandler);
|
|
823
|
-
conn.addDataListener(dataHandler);
|
|
824
|
-
for (const data2 of buffer) {
|
|
825
|
-
dataHandler(data2);
|
|
826
|
-
}
|
|
827
|
-
buffer.length = 0;
|
|
869
|
+
session = maybeSession;
|
|
870
|
+
const dataHandler = (data2) => {
|
|
871
|
+
const parsed = this.parseMsg(data2);
|
|
872
|
+
if (!parsed) {
|
|
873
|
+
conn.close();
|
|
874
|
+
return;
|
|
828
875
|
}
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
if (session) {
|
|
834
|
-
log?.info(`connection to ${client()} disconnected`, {
|
|
835
|
-
clientId: this.clientId,
|
|
836
|
-
connId: conn.debugId
|
|
837
|
-
});
|
|
838
|
-
this.onDisconnect(conn, session);
|
|
876
|
+
this.handleMsg(parsed);
|
|
877
|
+
};
|
|
878
|
+
for (const data2 of buffer) {
|
|
879
|
+
dataHandler(data2);
|
|
839
880
|
}
|
|
840
|
-
|
|
841
|
-
|
|
881
|
+
conn.removeDataListener(handshakeHandler);
|
|
882
|
+
conn.addDataListener(dataHandler);
|
|
883
|
+
buffer.length = 0;
|
|
884
|
+
}
|
|
885
|
+
);
|
|
886
|
+
};
|
|
887
|
+
conn.addDataListener(handshakeHandler);
|
|
888
|
+
conn.addCloseListener(() => {
|
|
889
|
+
if (!session)
|
|
890
|
+
return;
|
|
891
|
+
log?.info(`connection to ${client()} disconnected`, {
|
|
892
|
+
clientId: this.clientId,
|
|
893
|
+
connId: conn.id
|
|
894
|
+
});
|
|
895
|
+
this.onDisconnect(conn, session);
|
|
896
|
+
});
|
|
897
|
+
conn.addErrorListener((err) => {
|
|
898
|
+
conn.telemetry?.span.setStatus({
|
|
899
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
900
|
+
message: "connection error"
|
|
901
|
+
});
|
|
902
|
+
if (!session)
|
|
903
|
+
return;
|
|
904
|
+
log?.warn(
|
|
905
|
+
`connection to ${client()} got an error: ${coerceErrorString(err)}`,
|
|
906
|
+
{ clientId: this.clientId, connId: conn.id }
|
|
907
|
+
);
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
async validateHandshakeMetadata(conn, session, rawMetadata, from) {
|
|
911
|
+
let parsedMetadata = {};
|
|
912
|
+
if (this.handshakeExtensions) {
|
|
913
|
+
if (!import_value.Value.Check(this.handshakeExtensions.schema, rawMetadata)) {
|
|
914
|
+
conn.telemetry?.span.setStatus({
|
|
915
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
916
|
+
message: "malformed handshake meta"
|
|
842
917
|
});
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
853
|
-
span.end();
|
|
918
|
+
const reason = "received malformed handshake metadata";
|
|
919
|
+
const responseMsg = handshakeResponseMessage(this.clientId, from, {
|
|
920
|
+
ok: false,
|
|
921
|
+
reason
|
|
922
|
+
});
|
|
923
|
+
conn.send(this.codec.toBuffer(responseMsg));
|
|
924
|
+
log?.warn(`received malformed handshake metadata from ${from}`, {
|
|
925
|
+
clientId: this.clientId,
|
|
926
|
+
connId: conn.id
|
|
854
927
|
});
|
|
928
|
+
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
929
|
+
return false;
|
|
855
930
|
}
|
|
856
|
-
|
|
931
|
+
parsedMetadata = await this.handshakeExtensions.validate(
|
|
932
|
+
rawMetadata,
|
|
933
|
+
session
|
|
934
|
+
);
|
|
935
|
+
if (parsedMetadata === false) {
|
|
936
|
+
const reason = "rejected by handshake handler";
|
|
937
|
+
conn.telemetry?.span.setStatus({
|
|
938
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
939
|
+
message: reason
|
|
940
|
+
});
|
|
941
|
+
const responseMsg = handshakeResponseMessage(this.clientId, from, {
|
|
942
|
+
ok: false,
|
|
943
|
+
reason
|
|
944
|
+
});
|
|
945
|
+
conn.send(this.codec.toBuffer(responseMsg));
|
|
946
|
+
log?.warn(`rejected handshake from ${from}`, {
|
|
947
|
+
clientId: this.clientId,
|
|
948
|
+
connId: conn.id
|
|
949
|
+
});
|
|
950
|
+
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
951
|
+
return false;
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
return parsedMetadata;
|
|
857
955
|
}
|
|
858
956
|
async receiveHandshakeRequestMessage(data, conn) {
|
|
859
957
|
const parsed = this.parseMsg(data);
|
|
860
958
|
if (!parsed) {
|
|
959
|
+
conn.telemetry?.span.setStatus({
|
|
960
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
961
|
+
message: "non-transport message"
|
|
962
|
+
});
|
|
861
963
|
this.protocolError(
|
|
862
964
|
ProtocolError.HandshakeFailed,
|
|
863
965
|
"received non-transport message"
|
|
864
966
|
);
|
|
865
967
|
return false;
|
|
866
968
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
969
|
+
if (!import_value.Value.Check(ControlMessageHandshakeRequestSchema, parsed.payload)) {
|
|
970
|
+
conn.telemetry?.span.setStatus({
|
|
971
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
972
|
+
message: "invalid handshake request"
|
|
973
|
+
});
|
|
974
|
+
const reason = "received invalid handshake msg";
|
|
975
|
+
const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
|
|
976
|
+
ok: false,
|
|
977
|
+
reason
|
|
978
|
+
});
|
|
979
|
+
conn.send(this.codec.toBuffer(responseMsg2));
|
|
980
|
+
const logData = { ...parsed.payload ?? {}, metadata: "redacted" };
|
|
981
|
+
log?.warn(reason, {
|
|
982
|
+
clientId: this.clientId,
|
|
983
|
+
connId: conn.id,
|
|
984
|
+
partialTransportMessage: { ...parsed, payload: logData }
|
|
985
|
+
});
|
|
986
|
+
this.protocolError(
|
|
987
|
+
ProtocolError.HandshakeFailed,
|
|
988
|
+
"invalid handshake request"
|
|
989
|
+
);
|
|
990
|
+
return false;
|
|
870
991
|
}
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
{
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
} : { ...parsed };
|
|
897
|
-
log?.warn(`${reason}: ${JSON.stringify(logData)}`, {
|
|
898
|
-
clientId: this.clientId,
|
|
899
|
-
connId: conn.debugId
|
|
900
|
-
});
|
|
901
|
-
this.protocolError(
|
|
902
|
-
ProtocolError.HandshakeFailed,
|
|
903
|
-
"invalid handshake request"
|
|
904
|
-
);
|
|
905
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
906
|
-
span.end();
|
|
907
|
-
return false;
|
|
908
|
-
}
|
|
909
|
-
const gotVersion = parsed.payload.protocolVersion;
|
|
910
|
-
if (gotVersion !== PROTOCOL_VERSION) {
|
|
911
|
-
const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
|
|
912
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
913
|
-
this.clientId,
|
|
914
|
-
parsed.from,
|
|
915
|
-
{
|
|
916
|
-
ok: false,
|
|
917
|
-
reason
|
|
918
|
-
}
|
|
919
|
-
);
|
|
920
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
921
|
-
log?.warn(
|
|
922
|
-
`received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`,
|
|
923
|
-
{ clientId: this.clientId, connId: conn.debugId }
|
|
924
|
-
);
|
|
925
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
926
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
927
|
-
span.end();
|
|
928
|
-
return false;
|
|
929
|
-
}
|
|
930
|
-
const { session, isReconnect } = this.getOrCreateSession(
|
|
931
|
-
parsed.from,
|
|
932
|
-
conn,
|
|
933
|
-
parsed.payload.sessionId
|
|
934
|
-
);
|
|
935
|
-
let handshakeMetadata;
|
|
936
|
-
if (this.options.handshake) {
|
|
937
|
-
if (!import_value.Value.Check(
|
|
938
|
-
this.options.handshake.requestSchema,
|
|
939
|
-
parsed.payload.metadata
|
|
940
|
-
)) {
|
|
941
|
-
const reason = "received malformed handshake metadata";
|
|
942
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
943
|
-
this.clientId,
|
|
944
|
-
parsed.from,
|
|
945
|
-
{ ok: false, reason }
|
|
946
|
-
);
|
|
947
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
948
|
-
log?.warn(
|
|
949
|
-
`received malformed handshake metadata from ${parsed.from}`,
|
|
950
|
-
{
|
|
951
|
-
clientId: this.clientId,
|
|
952
|
-
connId: conn.debugId
|
|
953
|
-
}
|
|
954
|
-
);
|
|
955
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
956
|
-
this.deleteSession(session);
|
|
957
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
958
|
-
span.end();
|
|
959
|
-
return false;
|
|
960
|
-
}
|
|
961
|
-
const parsedMetadata = await this.options.handshake.parse(
|
|
962
|
-
parsed.payload.metadata,
|
|
963
|
-
session,
|
|
964
|
-
isReconnect
|
|
965
|
-
);
|
|
966
|
-
if (parsedMetadata === false) {
|
|
967
|
-
const reason = "rejected by server";
|
|
968
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
969
|
-
this.clientId,
|
|
970
|
-
parsed.from,
|
|
971
|
-
{ ok: false, reason }
|
|
972
|
-
);
|
|
973
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
974
|
-
log?.warn(`rejected handshake from ${parsed.from}`, {
|
|
975
|
-
clientId: this.clientId,
|
|
976
|
-
connId: conn.debugId
|
|
977
|
-
});
|
|
978
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
979
|
-
this.deleteSession(session);
|
|
980
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
981
|
-
span.end();
|
|
982
|
-
return false;
|
|
983
|
-
}
|
|
984
|
-
if (!import_value.Value.Check(this.options.handshake.parsedSchema, parsedMetadata)) {
|
|
985
|
-
const reason = "failed to parse handshake metadata";
|
|
986
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
987
|
-
this.clientId,
|
|
988
|
-
parsed.from,
|
|
989
|
-
{ ok: false, reason }
|
|
990
|
-
);
|
|
991
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
992
|
-
log?.error(`failed to parse handshake metadata`, {
|
|
993
|
-
clientId: this.clientId,
|
|
994
|
-
connId: conn.debugId,
|
|
995
|
-
tags: ["invariant-violation"]
|
|
996
|
-
});
|
|
997
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
998
|
-
this.deleteSession(session);
|
|
999
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
1000
|
-
span.end();
|
|
1001
|
-
return false;
|
|
1002
|
-
}
|
|
1003
|
-
handshakeMetadata = parsedMetadata;
|
|
1004
|
-
}
|
|
1005
|
-
handshakeMetadata ??= {};
|
|
1006
|
-
session.metadata = handshakeMetadata;
|
|
1007
|
-
log?.debug(
|
|
1008
|
-
`handshake from ${parsed.from} ok, responding with handshake success`,
|
|
1009
|
-
{ clientId: this.clientId, connId: conn.debugId }
|
|
1010
|
-
);
|
|
1011
|
-
const responseMsg = handshakeResponseMessage(
|
|
1012
|
-
this.clientId,
|
|
1013
|
-
parsed.from,
|
|
1014
|
-
{
|
|
1015
|
-
ok: true,
|
|
1016
|
-
sessionId: session.id
|
|
1017
|
-
}
|
|
1018
|
-
);
|
|
1019
|
-
conn.send(this.codec.toBuffer(responseMsg));
|
|
1020
|
-
this.onConnect(conn, parsed.from, session, isReconnect);
|
|
1021
|
-
span.end();
|
|
1022
|
-
return session;
|
|
1023
|
-
}
|
|
992
|
+
const gotVersion = parsed.payload.protocolVersion;
|
|
993
|
+
if (gotVersion !== PROTOCOL_VERSION) {
|
|
994
|
+
conn.telemetry?.span.setStatus({
|
|
995
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
996
|
+
message: "incorrect protocol version"
|
|
997
|
+
});
|
|
998
|
+
const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
|
|
999
|
+
const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
|
|
1000
|
+
ok: false,
|
|
1001
|
+
reason
|
|
1002
|
+
});
|
|
1003
|
+
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1004
|
+
log?.warn(
|
|
1005
|
+
`received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`,
|
|
1006
|
+
{ clientId: this.clientId, connId: conn.id }
|
|
1007
|
+
);
|
|
1008
|
+
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1009
|
+
return false;
|
|
1010
|
+
}
|
|
1011
|
+
const oldSession = this.sessions.get(parsed.from);
|
|
1012
|
+
const parsedMetadata = await this.validateHandshakeMetadata(
|
|
1013
|
+
conn,
|
|
1014
|
+
oldSession,
|
|
1015
|
+
parsed.payload.metadata,
|
|
1016
|
+
parsed.from
|
|
1024
1017
|
);
|
|
1018
|
+
if (parsedMetadata === false) {
|
|
1019
|
+
return false;
|
|
1020
|
+
}
|
|
1021
|
+
const { session, isReconnect } = this.getOrCreateSession(
|
|
1022
|
+
parsed.from,
|
|
1023
|
+
conn,
|
|
1024
|
+
parsed.payload.sessionId,
|
|
1025
|
+
parsed.tracing
|
|
1026
|
+
);
|
|
1027
|
+
this.sessionHandshakeMetadata.set(session, parsedMetadata);
|
|
1028
|
+
log?.debug(
|
|
1029
|
+
`handshake from ${parsed.from} ok, responding with handshake success`,
|
|
1030
|
+
{ clientId: this.clientId, connId: conn.id }
|
|
1031
|
+
);
|
|
1032
|
+
const responseMsg = handshakeResponseMessage(this.clientId, parsed.from, {
|
|
1033
|
+
ok: true,
|
|
1034
|
+
sessionId: session.id
|
|
1035
|
+
});
|
|
1036
|
+
conn.send(this.codec.toBuffer(responseMsg));
|
|
1037
|
+
this.onConnect(conn, parsed.from, session, isReconnect);
|
|
1038
|
+
return session;
|
|
1025
1039
|
}
|
|
1026
1040
|
};
|
|
1027
1041
|
|