@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
|
@@ -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.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");
|
|
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
|
*/
|
|
@@ -182,12 +216,6 @@ var Session = class {
|
|
|
182
216
|
* for this session.
|
|
183
217
|
*/
|
|
184
218
|
advertisedSessionId;
|
|
185
|
-
/**
|
|
186
|
-
* The metadata for this session, as parsed from the handshake.
|
|
187
|
-
*
|
|
188
|
-
* Will only ever be populated on the server side.
|
|
189
|
-
*/
|
|
190
|
-
metadata;
|
|
191
219
|
/**
|
|
192
220
|
* Number of messages we've sent along this session (excluding handshake and acks)
|
|
193
221
|
*/
|
|
@@ -209,7 +237,7 @@ var Session = class {
|
|
|
209
237
|
* The interval for sending heartbeats.
|
|
210
238
|
*/
|
|
211
239
|
heartbeat;
|
|
212
|
-
constructor(conn, from, to, options) {
|
|
240
|
+
constructor(conn, from, to, options, propagationCtx) {
|
|
213
241
|
this.id = `session-${nanoid2(12)}`;
|
|
214
242
|
this.options = options;
|
|
215
243
|
this.from = from;
|
|
@@ -221,13 +249,14 @@ var Session = class {
|
|
|
221
249
|
() => this.sendHeartbeat(),
|
|
222
250
|
options.heartbeatIntervalMs
|
|
223
251
|
);
|
|
252
|
+
this.telemetry = createSessionTelemetryInfo(this, propagationCtx);
|
|
224
253
|
}
|
|
225
254
|
get loggingMetadata() {
|
|
226
255
|
return {
|
|
227
256
|
clientId: this.from,
|
|
228
257
|
connectedTo: this.to,
|
|
229
258
|
sessionId: this.id,
|
|
230
|
-
connId: this.connection?.
|
|
259
|
+
connId: this.connection?.id
|
|
231
260
|
};
|
|
232
261
|
}
|
|
233
262
|
/**
|
|
@@ -272,6 +301,7 @@ var Session = class {
|
|
|
272
301
|
`closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
|
|
273
302
|
this.loggingMetadata
|
|
274
303
|
);
|
|
304
|
+
this.telemetry.span.addEvent("closing connection due to inactivity");
|
|
275
305
|
this.closeStaleConnection();
|
|
276
306
|
}
|
|
277
307
|
return;
|
|
@@ -293,21 +323,25 @@ var Session = class {
|
|
|
293
323
|
sendBufferedMessages(conn) {
|
|
294
324
|
log?.info(`resending ${this.sendBuffer.length} buffered messages`, {
|
|
295
325
|
...this.loggingMetadata,
|
|
296
|
-
connId: conn.
|
|
326
|
+
connId: conn.id
|
|
297
327
|
});
|
|
298
328
|
for (const msg of this.sendBuffer) {
|
|
299
329
|
log?.debug(`resending msg`, {
|
|
300
330
|
...this.loggingMetadata,
|
|
301
331
|
fullTransportMessage: msg,
|
|
302
|
-
connId: conn.
|
|
332
|
+
connId: conn.id
|
|
303
333
|
});
|
|
304
334
|
const ok = conn.send(this.codec.toBuffer(msg));
|
|
305
335
|
if (!ok) {
|
|
306
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
|
+
});
|
|
307
341
|
log?.error(errMsg, {
|
|
308
342
|
...this.loggingMetadata,
|
|
309
343
|
fullTransportMessage: msg,
|
|
310
|
-
connId: conn.
|
|
344
|
+
connId: conn.id,
|
|
311
345
|
tags: ["invariant-violation"]
|
|
312
346
|
});
|
|
313
347
|
conn.close();
|
|
@@ -390,11 +424,6 @@ var Session = class {
|
|
|
390
424
|
}
|
|
391
425
|
};
|
|
392
426
|
|
|
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
427
|
// util/stringify.ts
|
|
399
428
|
function coerceErrorString(err) {
|
|
400
429
|
if (err instanceof Error) {
|
|
@@ -456,6 +485,7 @@ var NaiveJsonCodec = {
|
|
|
456
485
|
};
|
|
457
486
|
|
|
458
487
|
// transport/transport.ts
|
|
488
|
+
var import_api3 = require("@opentelemetry/api");
|
|
459
489
|
var defaultTransportOptions = {
|
|
460
490
|
heartbeatIntervalMs: 1e3,
|
|
461
491
|
heartbeatsUntilDead: 2,
|
|
@@ -534,17 +564,22 @@ var Transport = class {
|
|
|
534
564
|
status: "connect",
|
|
535
565
|
conn
|
|
536
566
|
});
|
|
567
|
+
conn.telemetry = createConnectionTelemetryInfo(
|
|
568
|
+
conn,
|
|
569
|
+
session.telemetry.span
|
|
570
|
+
);
|
|
537
571
|
if (isReconnect) {
|
|
538
572
|
session.replaceWithNewConnection(conn);
|
|
539
573
|
log?.info(`reconnected to ${connectedTo}`, session.loggingMetadata);
|
|
540
574
|
}
|
|
541
575
|
}
|
|
542
|
-
createSession(to, conn) {
|
|
576
|
+
createSession(to, conn, propagationCtx) {
|
|
543
577
|
const session = new Session(
|
|
544
578
|
conn,
|
|
545
579
|
this.clientId,
|
|
546
580
|
to,
|
|
547
|
-
this.options
|
|
581
|
+
this.options,
|
|
582
|
+
propagationCtx
|
|
548
583
|
);
|
|
549
584
|
this.sessions.set(session.to, session);
|
|
550
585
|
this.eventDispatcher.dispatchEvent("sessionStatus", {
|
|
@@ -553,11 +588,11 @@ var Transport = class {
|
|
|
553
588
|
});
|
|
554
589
|
return session;
|
|
555
590
|
}
|
|
556
|
-
getOrCreateSession(to, conn, sessionId) {
|
|
591
|
+
getOrCreateSession(to, conn, sessionId, propagationCtx) {
|
|
557
592
|
let session = this.sessions.get(to);
|
|
558
593
|
let isReconnect = session !== void 0;
|
|
559
594
|
if (session?.advertisedSessionId !== void 0 && sessionId !== void 0 && session.advertisedSessionId !== sessionId) {
|
|
560
|
-
log?.
|
|
595
|
+
log?.info(
|
|
561
596
|
`session for ${to} already exists but has a different session id (expected: ${session.advertisedSessionId}, got: ${sessionId}), creating a new one`,
|
|
562
597
|
session.loggingMetadata
|
|
563
598
|
);
|
|
@@ -566,7 +601,7 @@ var Transport = class {
|
|
|
566
601
|
session = void 0;
|
|
567
602
|
}
|
|
568
603
|
if (!session) {
|
|
569
|
-
session = this.createSession(to, conn);
|
|
604
|
+
session = this.createSession(to, conn, propagationCtx);
|
|
570
605
|
log?.info(
|
|
571
606
|
`no session for ${to}, created a new one`,
|
|
572
607
|
session.loggingMetadata
|
|
@@ -579,6 +614,7 @@ var Transport = class {
|
|
|
579
614
|
}
|
|
580
615
|
deleteSession(session) {
|
|
581
616
|
session.close();
|
|
617
|
+
session.telemetry.span.end();
|
|
582
618
|
this.sessions.delete(session.to);
|
|
583
619
|
log?.info(
|
|
584
620
|
`session ${session.id} disconnect from ${session.to}`,
|
|
@@ -595,12 +631,16 @@ var Transport = class {
|
|
|
595
631
|
* @param connectedTo The peer we are connected to.
|
|
596
632
|
*/
|
|
597
633
|
onDisconnect(conn, session) {
|
|
634
|
+
conn.telemetry?.span.end();
|
|
598
635
|
this.eventDispatcher.dispatchEvent("connectionStatus", {
|
|
599
636
|
status: "disconnect",
|
|
600
637
|
conn
|
|
601
638
|
});
|
|
602
639
|
session.connection = void 0;
|
|
603
|
-
session.beginGrace(() =>
|
|
640
|
+
session.beginGrace(() => {
|
|
641
|
+
session.telemetry.span.addEvent("session grace period expired");
|
|
642
|
+
this.deleteSession(session);
|
|
643
|
+
});
|
|
604
644
|
}
|
|
605
645
|
/**
|
|
606
646
|
* Parses a message from a Uint8Array into a {@link OpaqueTransportMessage}.
|
|
@@ -660,6 +700,10 @@ var Transport = class {
|
|
|
660
700
|
tags: ["invariant-violation"]
|
|
661
701
|
});
|
|
662
702
|
this.protocolError(ProtocolError.MessageOrderingViolated, errMsg);
|
|
703
|
+
session.telemetry.span.setStatus({
|
|
704
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
705
|
+
message: "message order violated"
|
|
706
|
+
});
|
|
663
707
|
session.close();
|
|
664
708
|
}
|
|
665
709
|
return;
|
|
@@ -758,291 +802,269 @@ var ServerTransport = class extends Transport {
|
|
|
758
802
|
* The options for this transport.
|
|
759
803
|
*/
|
|
760
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;
|
|
761
813
|
constructor(clientId, providedOptions) {
|
|
762
814
|
super(clientId, providedOptions);
|
|
763
815
|
this.options = {
|
|
764
816
|
...defaultServerTransportOptions,
|
|
765
817
|
...providedOptions
|
|
766
818
|
};
|
|
819
|
+
this.sessionHandshakeMetadata = /* @__PURE__ */ new WeakMap();
|
|
767
820
|
log?.info(`initiated server transport`, {
|
|
768
821
|
clientId: this.clientId,
|
|
769
822
|
protocolVersion: PROTOCOL_VERSION
|
|
770
823
|
});
|
|
771
824
|
}
|
|
825
|
+
extendHandshake(options) {
|
|
826
|
+
this.handshakeExtensions = options;
|
|
827
|
+
}
|
|
772
828
|
handleConnection(conn) {
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
(
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
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"
|
|
788
850
|
});
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
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) {
|
|
803
866
|
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
867
|
return;
|
|
812
868
|
}
|
|
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;
|
|
869
|
+
session = maybeSession;
|
|
870
|
+
const dataHandler = (data2) => {
|
|
871
|
+
const parsed = this.parseMsg(data2);
|
|
872
|
+
if (!parsed) {
|
|
873
|
+
conn.close();
|
|
874
|
+
return;
|
|
838
875
|
}
|
|
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);
|
|
876
|
+
this.handleMsg(parsed);
|
|
877
|
+
};
|
|
878
|
+
for (const data2 of buffer) {
|
|
879
|
+
dataHandler(data2);
|
|
849
880
|
}
|
|
850
|
-
|
|
851
|
-
|
|
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"
|
|
852
917
|
});
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
863
|
-
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
|
|
864
927
|
});
|
|
928
|
+
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
929
|
+
return false;
|
|
865
930
|
}
|
|
866
|
-
|
|
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;
|
|
867
955
|
}
|
|
868
956
|
async receiveHandshakeRequestMessage(data, conn) {
|
|
869
957
|
const parsed = this.parseMsg(data);
|
|
870
958
|
if (!parsed) {
|
|
959
|
+
conn.telemetry?.span.setStatus({
|
|
960
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
961
|
+
message: "non-transport message"
|
|
962
|
+
});
|
|
871
963
|
this.protocolError(
|
|
872
964
|
ProtocolError.HandshakeFailed,
|
|
873
965
|
"received non-transport message"
|
|
874
966
|
);
|
|
875
967
|
return false;
|
|
876
968
|
}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
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;
|
|
880
991
|
}
|
|
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
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
916
|
-
span.end();
|
|
917
|
-
return false;
|
|
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(
|
|
941
|
-
parsed.from,
|
|
942
|
-
conn,
|
|
943
|
-
parsed.payload.sessionId
|
|
944
|
-
);
|
|
945
|
-
let handshakeMetadata;
|
|
946
|
-
if (this.options.handshake) {
|
|
947
|
-
if (!import_value.Value.Check(
|
|
948
|
-
this.options.handshake.requestSchema,
|
|
949
|
-
parsed.payload.metadata
|
|
950
|
-
)) {
|
|
951
|
-
const reason = "received malformed handshake metadata";
|
|
952
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
953
|
-
this.clientId,
|
|
954
|
-
parsed.from,
|
|
955
|
-
{ ok: false, reason }
|
|
956
|
-
);
|
|
957
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
958
|
-
log?.warn(
|
|
959
|
-
`received malformed handshake metadata from ${parsed.from}`,
|
|
960
|
-
{
|
|
961
|
-
clientId: this.clientId,
|
|
962
|
-
connId: conn.debugId
|
|
963
|
-
}
|
|
964
|
-
);
|
|
965
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
966
|
-
this.deleteSession(session);
|
|
967
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
968
|
-
span.end();
|
|
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 }
|
|
1020
|
-
);
|
|
1021
|
-
const responseMsg = handshakeResponseMessage(
|
|
1022
|
-
this.clientId,
|
|
1023
|
-
parsed.from,
|
|
1024
|
-
{
|
|
1025
|
-
ok: true,
|
|
1026
|
-
sessionId: session.id
|
|
1027
|
-
}
|
|
1028
|
-
);
|
|
1029
|
-
conn.send(this.codec.toBuffer(responseMsg));
|
|
1030
|
-
this.onConnect(conn, parsed.from, session, isReconnect);
|
|
1031
|
-
span.end();
|
|
1032
|
-
return session;
|
|
1033
|
-
}
|
|
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
|
|
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
|
|
1034
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;
|
|
1035
1039
|
}
|
|
1036
1040
|
};
|
|
1037
1041
|
|
|
1038
1042
|
// transport/impls/ws/connection.ts
|
|
1039
|
-
var import_agnostic_ws = __toESM(require("agnostic-ws"), 1);
|
|
1040
1043
|
var WebSocketConnection = class extends Connection {
|
|
1044
|
+
errorCb = null;
|
|
1045
|
+
closeCb = null;
|
|
1041
1046
|
ws;
|
|
1042
1047
|
constructor(ws) {
|
|
1043
1048
|
super();
|
|
1044
1049
|
this.ws = ws;
|
|
1045
1050
|
this.ws.binaryType = "arraybuffer";
|
|
1051
|
+
let didError = false;
|
|
1052
|
+
this.ws.onerror = () => {
|
|
1053
|
+
didError = true;
|
|
1054
|
+
};
|
|
1055
|
+
this.ws.onclose = ({ code, reason }) => {
|
|
1056
|
+
if (didError && this.errorCb) {
|
|
1057
|
+
this.errorCb(
|
|
1058
|
+
new Error(
|
|
1059
|
+
`websocket closed with code and reason: ${code} - ${reason}`
|
|
1060
|
+
)
|
|
1061
|
+
);
|
|
1062
|
+
return;
|
|
1063
|
+
}
|
|
1064
|
+
if (this.closeCb) {
|
|
1065
|
+
this.closeCb();
|
|
1066
|
+
}
|
|
1067
|
+
};
|
|
1046
1068
|
}
|
|
1047
1069
|
addDataListener(cb) {
|
|
1048
1070
|
this.ws.onmessage = (msg) => cb(msg.data);
|
|
@@ -1051,13 +1073,13 @@ var WebSocketConnection = class extends Connection {
|
|
|
1051
1073
|
this.ws.onmessage = null;
|
|
1052
1074
|
}
|
|
1053
1075
|
addCloseListener(cb) {
|
|
1054
|
-
this.
|
|
1076
|
+
this.closeCb = cb;
|
|
1055
1077
|
}
|
|
1056
1078
|
addErrorListener(cb) {
|
|
1057
|
-
this.
|
|
1079
|
+
this.errorCb = cb;
|
|
1058
1080
|
}
|
|
1059
1081
|
send(payload) {
|
|
1060
|
-
if (this.ws.readyState ===
|
|
1082
|
+
if (this.ws.readyState === this.ws.OPEN) {
|
|
1061
1083
|
this.ws.send(payload);
|
|
1062
1084
|
return true;
|
|
1063
1085
|
} else {
|