@replit/river 0.21.1 → 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-NCXUFDVL.js → chunk-GCLEWC26.js} +328 -500
- 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-FDLAPYCK.js → chunk-S3YKQT4J.js} +2 -2
- package/dist/{chunk-JMXO5L2X.js → chunk-ZPBWKBM5.js} +344 -384
- package/dist/chunk-ZPBWKBM5.js.map +1 -0
- package/dist/{connection-76c5ed01.d.ts → connection-8b059ac4.d.ts} +6 -4
- package/dist/{connection-975b25c9.d.ts → connection-bbfe1147.d.ts} +1 -1
- package/dist/{index-dfad460e.d.ts → index-2ece5234.d.ts} +16 -7
- package/dist/logging/index.d.cts +2 -1
- package/dist/logging/index.d.ts +2 -1
- package/dist/router/index.cjs +373 -486
- 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 +4 -3
- package/dist/{services-7b716dcf.d.ts → services-acbcc441.d.ts} +1 -1
- package/dist/{services-9c496c6e.d.ts → services-cb01a7a8.d.ts} +1 -1
- package/dist/transport/impls/uds/client.cjs +186 -145
- 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 +281 -256
- 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 +240 -204
- 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 +303 -270
- 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 +390 -382
- 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 +2 -2
- package/dist/util/testHelpers.cjs +57 -7
- 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 +10 -4
- 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-S3YKQT4J.js.map} +0 -0
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
6
|
var __export = (target, all) => {
|
|
9
7
|
for (var name in all)
|
|
@@ -17,14 +15,6 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
15
|
}
|
|
18
16
|
return to;
|
|
19
17
|
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
19
|
|
|
30
20
|
// transport/impls/ws/server.ts
|
|
@@ -36,7 +26,6 @@ module.exports = __toCommonJS(server_exports);
|
|
|
36
26
|
|
|
37
27
|
// transport/transport.ts
|
|
38
28
|
var import_value = require("@sinclair/typebox/value");
|
|
39
|
-
var import_api2 = require("@opentelemetry/api");
|
|
40
29
|
|
|
41
30
|
// transport/message.ts
|
|
42
31
|
var import_typebox = require("@sinclair/typebox");
|
|
@@ -152,17 +141,62 @@ var EventDispatcher = class {
|
|
|
152
141
|
|
|
153
142
|
// transport/session.ts
|
|
154
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.22.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");
|
|
155
187
|
var nanoid2 = (0, import_nanoid2.customAlphabet)("1234567890abcdefghijklmnopqrstuvxyz", 6);
|
|
156
188
|
var unsafeId = () => nanoid2();
|
|
157
189
|
var Connection = class {
|
|
158
|
-
|
|
190
|
+
id;
|
|
191
|
+
telemetry;
|
|
159
192
|
constructor() {
|
|
160
|
-
this.
|
|
193
|
+
this.id = `conn-${nanoid2(12)}`;
|
|
161
194
|
}
|
|
162
195
|
};
|
|
163
196
|
var Session = class {
|
|
164
197
|
codec;
|
|
165
198
|
options;
|
|
199
|
+
telemetry;
|
|
166
200
|
/**
|
|
167
201
|
* The buffer of messages that have been sent but not yet acknowledged.
|
|
168
202
|
*/
|
|
@@ -209,7 +243,7 @@ var Session = class {
|
|
|
209
243
|
* The interval for sending heartbeats.
|
|
210
244
|
*/
|
|
211
245
|
heartbeat;
|
|
212
|
-
constructor(conn, from, to, options) {
|
|
246
|
+
constructor(conn, from, to, options, propagationCtx) {
|
|
213
247
|
this.id = `session-${nanoid2(12)}`;
|
|
214
248
|
this.options = options;
|
|
215
249
|
this.from = from;
|
|
@@ -221,13 +255,14 @@ var Session = class {
|
|
|
221
255
|
() => this.sendHeartbeat(),
|
|
222
256
|
options.heartbeatIntervalMs
|
|
223
257
|
);
|
|
258
|
+
this.telemetry = createSessionTelemetryInfo(this, propagationCtx);
|
|
224
259
|
}
|
|
225
260
|
get loggingMetadata() {
|
|
226
261
|
return {
|
|
227
262
|
clientId: this.from,
|
|
228
263
|
connectedTo: this.to,
|
|
229
264
|
sessionId: this.id,
|
|
230
|
-
connId: this.connection?.
|
|
265
|
+
connId: this.connection?.id
|
|
231
266
|
};
|
|
232
267
|
}
|
|
233
268
|
/**
|
|
@@ -272,6 +307,7 @@ var Session = class {
|
|
|
272
307
|
`closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
|
|
273
308
|
this.loggingMetadata
|
|
274
309
|
);
|
|
310
|
+
this.telemetry.span.addEvent("closing connection due to inactivity");
|
|
275
311
|
this.closeStaleConnection();
|
|
276
312
|
}
|
|
277
313
|
return;
|
|
@@ -293,21 +329,25 @@ var Session = class {
|
|
|
293
329
|
sendBufferedMessages(conn) {
|
|
294
330
|
log?.info(`resending ${this.sendBuffer.length} buffered messages`, {
|
|
295
331
|
...this.loggingMetadata,
|
|
296
|
-
connId: conn.
|
|
332
|
+
connId: conn.id
|
|
297
333
|
});
|
|
298
334
|
for (const msg of this.sendBuffer) {
|
|
299
335
|
log?.debug(`resending msg`, {
|
|
300
336
|
...this.loggingMetadata,
|
|
301
337
|
fullTransportMessage: msg,
|
|
302
|
-
connId: conn.
|
|
338
|
+
connId: conn.id
|
|
303
339
|
});
|
|
304
340
|
const ok = conn.send(this.codec.toBuffer(msg));
|
|
305
341
|
if (!ok) {
|
|
306
342
|
const errMsg = `failed to send buffered message to ${this.to} (sus, this is a fresh connection)`;
|
|
343
|
+
conn.telemetry?.span.setStatus({
|
|
344
|
+
code: import_api2.SpanStatusCode.ERROR,
|
|
345
|
+
message: errMsg
|
|
346
|
+
});
|
|
307
347
|
log?.error(errMsg, {
|
|
308
348
|
...this.loggingMetadata,
|
|
309
349
|
fullTransportMessage: msg,
|
|
310
|
-
connId: conn.
|
|
350
|
+
connId: conn.id,
|
|
311
351
|
tags: ["invariant-violation"]
|
|
312
352
|
});
|
|
313
353
|
conn.close();
|
|
@@ -390,11 +430,6 @@ var Session = class {
|
|
|
390
430
|
}
|
|
391
431
|
};
|
|
392
432
|
|
|
393
|
-
// tracing/index.ts
|
|
394
|
-
var import_api = require("@opentelemetry/api");
|
|
395
|
-
var tracer = import_api.trace.getTracer("river");
|
|
396
|
-
var tracing_default = tracer;
|
|
397
|
-
|
|
398
433
|
// util/stringify.ts
|
|
399
434
|
function coerceErrorString(err) {
|
|
400
435
|
if (err instanceof Error) {
|
|
@@ -456,6 +491,7 @@ var NaiveJsonCodec = {
|
|
|
456
491
|
};
|
|
457
492
|
|
|
458
493
|
// transport/transport.ts
|
|
494
|
+
var import_api3 = require("@opentelemetry/api");
|
|
459
495
|
var defaultTransportOptions = {
|
|
460
496
|
heartbeatIntervalMs: 1e3,
|
|
461
497
|
heartbeatsUntilDead: 2,
|
|
@@ -534,17 +570,22 @@ var Transport = class {
|
|
|
534
570
|
status: "connect",
|
|
535
571
|
conn
|
|
536
572
|
});
|
|
573
|
+
conn.telemetry = createConnectionTelemetryInfo(
|
|
574
|
+
conn,
|
|
575
|
+
session.telemetry.span
|
|
576
|
+
);
|
|
537
577
|
if (isReconnect) {
|
|
538
578
|
session.replaceWithNewConnection(conn);
|
|
539
579
|
log?.info(`reconnected to ${connectedTo}`, session.loggingMetadata);
|
|
540
580
|
}
|
|
541
581
|
}
|
|
542
|
-
createSession(to, conn) {
|
|
582
|
+
createSession(to, conn, propagationCtx) {
|
|
543
583
|
const session = new Session(
|
|
544
584
|
conn,
|
|
545
585
|
this.clientId,
|
|
546
586
|
to,
|
|
547
|
-
this.options
|
|
587
|
+
this.options,
|
|
588
|
+
propagationCtx
|
|
548
589
|
);
|
|
549
590
|
this.sessions.set(session.to, session);
|
|
550
591
|
this.eventDispatcher.dispatchEvent("sessionStatus", {
|
|
@@ -553,11 +594,11 @@ var Transport = class {
|
|
|
553
594
|
});
|
|
554
595
|
return session;
|
|
555
596
|
}
|
|
556
|
-
getOrCreateSession(to, conn, sessionId) {
|
|
597
|
+
getOrCreateSession(to, conn, sessionId, propagationCtx) {
|
|
557
598
|
let session = this.sessions.get(to);
|
|
558
599
|
let isReconnect = session !== void 0;
|
|
559
600
|
if (session?.advertisedSessionId !== void 0 && sessionId !== void 0 && session.advertisedSessionId !== sessionId) {
|
|
560
|
-
log?.
|
|
601
|
+
log?.info(
|
|
561
602
|
`session for ${to} already exists but has a different session id (expected: ${session.advertisedSessionId}, got: ${sessionId}), creating a new one`,
|
|
562
603
|
session.loggingMetadata
|
|
563
604
|
);
|
|
@@ -566,7 +607,7 @@ var Transport = class {
|
|
|
566
607
|
session = void 0;
|
|
567
608
|
}
|
|
568
609
|
if (!session) {
|
|
569
|
-
session = this.createSession(to, conn);
|
|
610
|
+
session = this.createSession(to, conn, propagationCtx);
|
|
570
611
|
log?.info(
|
|
571
612
|
`no session for ${to}, created a new one`,
|
|
572
613
|
session.loggingMetadata
|
|
@@ -579,6 +620,7 @@ var Transport = class {
|
|
|
579
620
|
}
|
|
580
621
|
deleteSession(session) {
|
|
581
622
|
session.close();
|
|
623
|
+
session.telemetry.span.end();
|
|
582
624
|
this.sessions.delete(session.to);
|
|
583
625
|
log?.info(
|
|
584
626
|
`session ${session.id} disconnect from ${session.to}`,
|
|
@@ -595,12 +637,16 @@ var Transport = class {
|
|
|
595
637
|
* @param connectedTo The peer we are connected to.
|
|
596
638
|
*/
|
|
597
639
|
onDisconnect(conn, session) {
|
|
640
|
+
conn.telemetry?.span.end();
|
|
598
641
|
this.eventDispatcher.dispatchEvent("connectionStatus", {
|
|
599
642
|
status: "disconnect",
|
|
600
643
|
conn
|
|
601
644
|
});
|
|
602
645
|
session.connection = void 0;
|
|
603
|
-
session.beginGrace(() =>
|
|
646
|
+
session.beginGrace(() => {
|
|
647
|
+
session.telemetry.span.addEvent("session grace period expired");
|
|
648
|
+
this.deleteSession(session);
|
|
649
|
+
});
|
|
604
650
|
}
|
|
605
651
|
/**
|
|
606
652
|
* Parses a message from a Uint8Array into a {@link OpaqueTransportMessage}.
|
|
@@ -660,6 +706,10 @@ var Transport = class {
|
|
|
660
706
|
tags: ["invariant-violation"]
|
|
661
707
|
});
|
|
662
708
|
this.protocolError(ProtocolError.MessageOrderingViolated, errMsg);
|
|
709
|
+
session.telemetry.span.setStatus({
|
|
710
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
711
|
+
message: "message order violated"
|
|
712
|
+
});
|
|
663
713
|
session.close();
|
|
664
714
|
}
|
|
665
715
|
return;
|
|
@@ -770,279 +820,262 @@ var ServerTransport = class extends Transport {
|
|
|
770
820
|
});
|
|
771
821
|
}
|
|
772
822
|
handleConnection(conn) {
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
(
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
823
|
+
if (this.state !== "open")
|
|
824
|
+
return;
|
|
825
|
+
log?.info(`new incoming connection`, {
|
|
826
|
+
clientId: this.clientId,
|
|
827
|
+
connId: conn.id
|
|
828
|
+
});
|
|
829
|
+
let session = void 0;
|
|
830
|
+
const client = () => session?.to ?? "unknown";
|
|
831
|
+
const handshakeTimeout = setTimeout(() => {
|
|
832
|
+
if (!session) {
|
|
833
|
+
log?.warn(
|
|
834
|
+
`connection to ${client()} timed out waiting for handshake, closing`,
|
|
835
|
+
{
|
|
836
|
+
clientId: this.clientId,
|
|
837
|
+
connectedTo: client(),
|
|
838
|
+
connId: conn.id
|
|
839
|
+
}
|
|
840
|
+
);
|
|
841
|
+
conn.telemetry?.span.setStatus({
|
|
842
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
843
|
+
message: "handshake timeout"
|
|
788
844
|
});
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
845
|
+
conn.close();
|
|
846
|
+
}
|
|
847
|
+
}, this.options.sessionDisconnectGraceMs);
|
|
848
|
+
const buffer = [];
|
|
849
|
+
let receivedHandshakeMessage = false;
|
|
850
|
+
const handshakeHandler = (data) => {
|
|
851
|
+
if (receivedHandshakeMessage) {
|
|
852
|
+
buffer.push(data);
|
|
853
|
+
return;
|
|
854
|
+
}
|
|
855
|
+
receivedHandshakeMessage = true;
|
|
856
|
+
clearTimeout(handshakeTimeout);
|
|
857
|
+
void this.receiveHandshakeRequestMessage(data, conn).then(
|
|
858
|
+
(maybeSession) => {
|
|
859
|
+
if (!maybeSession) {
|
|
803
860
|
conn.close();
|
|
804
|
-
}
|
|
805
|
-
}, this.options.sessionDisconnectGraceMs);
|
|
806
|
-
const buffer = [];
|
|
807
|
-
let receivedHandshakeMessage = false;
|
|
808
|
-
const handshakeHandler = (data) => {
|
|
809
|
-
if (receivedHandshakeMessage) {
|
|
810
|
-
buffer.push(data);
|
|
811
861
|
return;
|
|
812
862
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
(
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
span.end();
|
|
820
|
-
conn.close();
|
|
821
|
-
return;
|
|
822
|
-
}
|
|
823
|
-
session = maybeSession;
|
|
824
|
-
const dataHandler = (data2) => {
|
|
825
|
-
const parsed = this.parseMsg(data2);
|
|
826
|
-
if (!parsed) {
|
|
827
|
-
conn.close();
|
|
828
|
-
return;
|
|
829
|
-
}
|
|
830
|
-
this.handleMsg(parsed);
|
|
831
|
-
};
|
|
832
|
-
conn.removeDataListener(handshakeHandler);
|
|
833
|
-
conn.addDataListener(dataHandler);
|
|
834
|
-
for (const data2 of buffer) {
|
|
835
|
-
dataHandler(data2);
|
|
836
|
-
}
|
|
837
|
-
buffer.length = 0;
|
|
863
|
+
session = maybeSession;
|
|
864
|
+
const dataHandler = (data2) => {
|
|
865
|
+
const parsed = this.parseMsg(data2);
|
|
866
|
+
if (!parsed) {
|
|
867
|
+
conn.close();
|
|
868
|
+
return;
|
|
838
869
|
}
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
if (session) {
|
|
844
|
-
log?.info(`connection to ${client()} disconnected`, {
|
|
845
|
-
clientId: this.clientId,
|
|
846
|
-
connId: conn.debugId
|
|
847
|
-
});
|
|
848
|
-
this.onDisconnect(conn, session);
|
|
849
|
-
}
|
|
850
|
-
span.setStatus({ code: import_api2.SpanStatusCode.OK });
|
|
851
|
-
span.end();
|
|
852
|
-
});
|
|
853
|
-
conn.addErrorListener((err) => {
|
|
854
|
-
if (session) {
|
|
855
|
-
log?.warn(
|
|
856
|
-
`connection to ${client()} got an error: ${coerceErrorString(
|
|
857
|
-
err
|
|
858
|
-
)}`,
|
|
859
|
-
{ clientId: this.clientId, connId: conn.debugId }
|
|
860
|
-
);
|
|
870
|
+
this.handleMsg(parsed);
|
|
871
|
+
};
|
|
872
|
+
for (const data2 of buffer) {
|
|
873
|
+
dataHandler(data2);
|
|
861
874
|
}
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
875
|
+
conn.removeDataListener(handshakeHandler);
|
|
876
|
+
conn.addDataListener(dataHandler);
|
|
877
|
+
buffer.length = 0;
|
|
878
|
+
}
|
|
879
|
+
);
|
|
880
|
+
};
|
|
881
|
+
conn.addDataListener(handshakeHandler);
|
|
882
|
+
conn.addCloseListener(() => {
|
|
883
|
+
if (!session)
|
|
884
|
+
return;
|
|
885
|
+
log?.info(`connection to ${client()} disconnected`, {
|
|
886
|
+
clientId: this.clientId,
|
|
887
|
+
connId: conn.id
|
|
888
|
+
});
|
|
889
|
+
this.onDisconnect(conn, session);
|
|
890
|
+
});
|
|
891
|
+
conn.addErrorListener((err) => {
|
|
892
|
+
conn.telemetry?.span.setStatus({
|
|
893
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
894
|
+
message: "connection error"
|
|
895
|
+
});
|
|
896
|
+
if (!session)
|
|
897
|
+
return;
|
|
898
|
+
log?.warn(
|
|
899
|
+
`connection to ${client()} got an error: ${coerceErrorString(err)}`,
|
|
900
|
+
{ clientId: this.clientId, connId: conn.id }
|
|
901
|
+
);
|
|
902
|
+
});
|
|
867
903
|
}
|
|
868
904
|
async receiveHandshakeRequestMessage(data, conn) {
|
|
869
905
|
const parsed = this.parseMsg(data);
|
|
870
906
|
if (!parsed) {
|
|
907
|
+
conn.telemetry?.span.setStatus({
|
|
908
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
909
|
+
message: "non-transport message"
|
|
910
|
+
});
|
|
871
911
|
this.protocolError(
|
|
872
912
|
ProtocolError.HandshakeFailed,
|
|
873
913
|
"received non-transport message"
|
|
874
914
|
);
|
|
875
915
|
return false;
|
|
876
916
|
}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
917
|
+
if (!import_value.Value.Check(ControlMessageHandshakeRequestSchema, parsed.payload)) {
|
|
918
|
+
conn.telemetry?.span.setStatus({
|
|
919
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
920
|
+
message: "invalid handshake request"
|
|
921
|
+
});
|
|
922
|
+
const reason = "received invalid handshake msg";
|
|
923
|
+
const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
|
|
924
|
+
ok: false,
|
|
925
|
+
reason
|
|
926
|
+
});
|
|
927
|
+
conn.send(this.codec.toBuffer(responseMsg2));
|
|
928
|
+
const logData = { ...parsed.payload ?? {}, metadata: "redacted" };
|
|
929
|
+
log?.warn(reason, {
|
|
930
|
+
clientId: this.clientId,
|
|
931
|
+
connId: conn.id,
|
|
932
|
+
partialTransportMessage: { ...parsed, payload: logData }
|
|
933
|
+
});
|
|
934
|
+
this.protocolError(
|
|
935
|
+
ProtocolError.HandshakeFailed,
|
|
936
|
+
"invalid handshake request"
|
|
937
|
+
);
|
|
938
|
+
return false;
|
|
880
939
|
}
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
{
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
const gotVersion = parsed.payload.protocolVersion;
|
|
920
|
-
if (gotVersion !== PROTOCOL_VERSION) {
|
|
921
|
-
const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
|
|
922
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
923
|
-
this.clientId,
|
|
924
|
-
parsed.from,
|
|
925
|
-
{
|
|
926
|
-
ok: false,
|
|
927
|
-
reason
|
|
928
|
-
}
|
|
929
|
-
);
|
|
930
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
931
|
-
log?.warn(
|
|
932
|
-
`received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`,
|
|
933
|
-
{ clientId: this.clientId, connId: conn.debugId }
|
|
934
|
-
);
|
|
935
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
936
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
937
|
-
span.end();
|
|
938
|
-
return false;
|
|
939
|
-
}
|
|
940
|
-
const { session, isReconnect } = this.getOrCreateSession(
|
|
940
|
+
const gotVersion = parsed.payload.protocolVersion;
|
|
941
|
+
if (gotVersion !== PROTOCOL_VERSION) {
|
|
942
|
+
conn.telemetry?.span.setStatus({
|
|
943
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
944
|
+
message: "incorrect protocol version"
|
|
945
|
+
});
|
|
946
|
+
const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
|
|
947
|
+
const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
|
|
948
|
+
ok: false,
|
|
949
|
+
reason
|
|
950
|
+
});
|
|
951
|
+
conn.send(this.codec.toBuffer(responseMsg2));
|
|
952
|
+
log?.warn(
|
|
953
|
+
`received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`,
|
|
954
|
+
{ clientId: this.clientId, connId: conn.id }
|
|
955
|
+
);
|
|
956
|
+
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
957
|
+
return false;
|
|
958
|
+
}
|
|
959
|
+
const { session, isReconnect } = this.getOrCreateSession(
|
|
960
|
+
parsed.from,
|
|
961
|
+
conn,
|
|
962
|
+
parsed.payload.sessionId,
|
|
963
|
+
parsed.tracing
|
|
964
|
+
);
|
|
965
|
+
let handshakeMetadata;
|
|
966
|
+
if (this.options.handshake) {
|
|
967
|
+
if (!import_value.Value.Check(
|
|
968
|
+
this.options.handshake.requestSchema,
|
|
969
|
+
parsed.payload.metadata
|
|
970
|
+
)) {
|
|
971
|
+
conn.telemetry?.span.setStatus({
|
|
972
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
973
|
+
message: "malformed handshake meta"
|
|
974
|
+
});
|
|
975
|
+
const reason = "received malformed handshake metadata";
|
|
976
|
+
const responseMsg2 = handshakeResponseMessage(
|
|
977
|
+
this.clientId,
|
|
941
978
|
parsed.from,
|
|
942
|
-
|
|
943
|
-
parsed.payload.sessionId
|
|
979
|
+
{ ok: false, reason }
|
|
944
980
|
);
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
return false;
|
|
970
|
-
}
|
|
971
|
-
const parsedMetadata = await this.options.handshake.parse(
|
|
972
|
-
parsed.payload.metadata,
|
|
973
|
-
session,
|
|
974
|
-
isReconnect
|
|
975
|
-
);
|
|
976
|
-
if (parsedMetadata === false) {
|
|
977
|
-
const reason = "rejected by server";
|
|
978
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
979
|
-
this.clientId,
|
|
980
|
-
parsed.from,
|
|
981
|
-
{ ok: false, reason }
|
|
982
|
-
);
|
|
983
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
984
|
-
log?.warn(`rejected handshake from ${parsed.from}`, {
|
|
985
|
-
clientId: this.clientId,
|
|
986
|
-
connId: conn.debugId
|
|
987
|
-
});
|
|
988
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
989
|
-
this.deleteSession(session);
|
|
990
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
991
|
-
span.end();
|
|
992
|
-
return false;
|
|
993
|
-
}
|
|
994
|
-
if (!import_value.Value.Check(this.options.handshake.parsedSchema, parsedMetadata)) {
|
|
995
|
-
const reason = "failed to parse handshake metadata";
|
|
996
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
997
|
-
this.clientId,
|
|
998
|
-
parsed.from,
|
|
999
|
-
{ ok: false, reason }
|
|
1000
|
-
);
|
|
1001
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1002
|
-
log?.error(`failed to parse handshake metadata`, {
|
|
1003
|
-
clientId: this.clientId,
|
|
1004
|
-
connId: conn.debugId,
|
|
1005
|
-
tags: ["invariant-violation"]
|
|
1006
|
-
});
|
|
1007
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1008
|
-
this.deleteSession(session);
|
|
1009
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
1010
|
-
span.end();
|
|
1011
|
-
return false;
|
|
1012
|
-
}
|
|
1013
|
-
handshakeMetadata = parsedMetadata;
|
|
1014
|
-
}
|
|
1015
|
-
handshakeMetadata ??= {};
|
|
1016
|
-
session.metadata = handshakeMetadata;
|
|
1017
|
-
log?.debug(
|
|
1018
|
-
`handshake from ${parsed.from} ok, responding with handshake success`,
|
|
1019
|
-
{ clientId: this.clientId, connId: conn.debugId }
|
|
981
|
+
conn.send(this.codec.toBuffer(responseMsg2));
|
|
982
|
+
log?.warn(`received malformed handshake metadata from ${parsed.from}`, {
|
|
983
|
+
clientId: this.clientId,
|
|
984
|
+
connId: conn.id
|
|
985
|
+
});
|
|
986
|
+
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
987
|
+
this.deleteSession(session);
|
|
988
|
+
return false;
|
|
989
|
+
}
|
|
990
|
+
const parsedMetadata = await this.options.handshake.parse(
|
|
991
|
+
parsed.payload.metadata,
|
|
992
|
+
session,
|
|
993
|
+
isReconnect
|
|
994
|
+
);
|
|
995
|
+
if (parsedMetadata === false) {
|
|
996
|
+
conn.telemetry?.span.setStatus({
|
|
997
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
998
|
+
message: "rejected by handshake handler"
|
|
999
|
+
});
|
|
1000
|
+
const reason = "rejected by handshake handler";
|
|
1001
|
+
const responseMsg2 = handshakeResponseMessage(
|
|
1002
|
+
this.clientId,
|
|
1003
|
+
parsed.from,
|
|
1004
|
+
{ ok: false, reason }
|
|
1020
1005
|
);
|
|
1021
|
-
|
|
1006
|
+
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1007
|
+
log?.warn(`rejected handshake from ${parsed.from}`, {
|
|
1008
|
+
clientId: this.clientId,
|
|
1009
|
+
connId: conn.id
|
|
1010
|
+
});
|
|
1011
|
+
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1012
|
+
this.deleteSession(session);
|
|
1013
|
+
return false;
|
|
1014
|
+
}
|
|
1015
|
+
if (!import_value.Value.Check(this.options.handshake.parsedSchema, parsedMetadata)) {
|
|
1016
|
+
conn.telemetry?.span.setStatus({
|
|
1017
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
1018
|
+
message: "malformed handshake meta"
|
|
1019
|
+
});
|
|
1020
|
+
const reason = "failed to parse handshake metadata";
|
|
1021
|
+
const responseMsg2 = handshakeResponseMessage(
|
|
1022
1022
|
this.clientId,
|
|
1023
1023
|
parsed.from,
|
|
1024
|
-
{
|
|
1025
|
-
ok: true,
|
|
1026
|
-
sessionId: session.id
|
|
1027
|
-
}
|
|
1024
|
+
{ ok: false, reason }
|
|
1028
1025
|
);
|
|
1029
|
-
conn.send(this.codec.toBuffer(
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1026
|
+
conn.send(this.codec.toBuffer(responseMsg2));
|
|
1027
|
+
log?.error(`failed to parse handshake metadata`, {
|
|
1028
|
+
clientId: this.clientId,
|
|
1029
|
+
connId: conn.id
|
|
1030
|
+
});
|
|
1031
|
+
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1032
|
+
this.deleteSession(session);
|
|
1033
|
+
return false;
|
|
1033
1034
|
}
|
|
1035
|
+
handshakeMetadata = parsedMetadata;
|
|
1036
|
+
}
|
|
1037
|
+
handshakeMetadata ??= {};
|
|
1038
|
+
session.metadata = handshakeMetadata;
|
|
1039
|
+
log?.debug(
|
|
1040
|
+
`handshake from ${parsed.from} ok, responding with handshake success`,
|
|
1041
|
+
{ clientId: this.clientId, connId: conn.id }
|
|
1034
1042
|
);
|
|
1043
|
+
const responseMsg = handshakeResponseMessage(this.clientId, parsed.from, {
|
|
1044
|
+
ok: true,
|
|
1045
|
+
sessionId: session.id
|
|
1046
|
+
});
|
|
1047
|
+
conn.send(this.codec.toBuffer(responseMsg));
|
|
1048
|
+
this.onConnect(conn, parsed.from, session, isReconnect);
|
|
1049
|
+
return session;
|
|
1035
1050
|
}
|
|
1036
1051
|
};
|
|
1037
1052
|
|
|
1038
1053
|
// transport/impls/ws/connection.ts
|
|
1039
|
-
var import_agnostic_ws = __toESM(require("agnostic-ws"), 1);
|
|
1040
1054
|
var WebSocketConnection = class extends Connection {
|
|
1055
|
+
errorCb = null;
|
|
1056
|
+
closeCb = null;
|
|
1041
1057
|
ws;
|
|
1042
1058
|
constructor(ws) {
|
|
1043
1059
|
super();
|
|
1044
1060
|
this.ws = ws;
|
|
1045
1061
|
this.ws.binaryType = "arraybuffer";
|
|
1062
|
+
let didError = false;
|
|
1063
|
+
this.ws.onerror = () => {
|
|
1064
|
+
didError = true;
|
|
1065
|
+
};
|
|
1066
|
+
this.ws.onclose = ({ code, reason }) => {
|
|
1067
|
+
if (didError && this.errorCb) {
|
|
1068
|
+
this.errorCb(
|
|
1069
|
+
new Error(
|
|
1070
|
+
`websocket closed with code and reason: ${code} - ${reason}`
|
|
1071
|
+
)
|
|
1072
|
+
);
|
|
1073
|
+
return;
|
|
1074
|
+
}
|
|
1075
|
+
if (this.closeCb) {
|
|
1076
|
+
this.closeCb();
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
1046
1079
|
}
|
|
1047
1080
|
addDataListener(cb) {
|
|
1048
1081
|
this.ws.onmessage = (msg) => cb(msg.data);
|
|
@@ -1051,13 +1084,13 @@ var WebSocketConnection = class extends Connection {
|
|
|
1051
1084
|
this.ws.onmessage = null;
|
|
1052
1085
|
}
|
|
1053
1086
|
addCloseListener(cb) {
|
|
1054
|
-
this.
|
|
1087
|
+
this.closeCb = cb;
|
|
1055
1088
|
}
|
|
1056
1089
|
addErrorListener(cb) {
|
|
1057
|
-
this.
|
|
1090
|
+
this.errorCb = cb;
|
|
1058
1091
|
}
|
|
1059
1092
|
send(payload) {
|
|
1060
|
-
if (this.ws.readyState ===
|
|
1093
|
+
if (this.ws.readyState === this.ws.OPEN) {
|
|
1061
1094
|
this.ws.send(payload);
|
|
1062
1095
|
return true;
|
|
1063
1096
|
} else {
|