@replit/river 0.21.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{chunk-5WFL722S.js → chunk-3MFX6NXA.js} +94 -3
- package/dist/chunk-3MFX6NXA.js.map +1 -0
- package/dist/{chunk-NFV77C2M.js → chunk-GCLEWC26.js} +340 -507
- package/dist/chunk-GCLEWC26.js.map +1 -0
- package/dist/chunk-HUBFYN37.js +60 -0
- package/dist/chunk-HUBFYN37.js.map +1 -0
- package/dist/{chunk-DT5JS6TM.js → chunk-OTQNCLFH.js} +1 -1
- package/dist/chunk-OTQNCLFH.js.map +1 -0
- package/dist/{chunk-MJR36SUY.js → chunk-S3YKQT4J.js} +2 -2
- package/dist/{chunk-QU2EE6YU.js → chunk-ZPBWKBM5.js} +361 -394
- package/dist/chunk-ZPBWKBM5.js.map +1 -0
- package/dist/{connection-8a71dbe2.d.ts → connection-8b059ac4.d.ts} +6 -4
- package/dist/{connection-d49d5d56.d.ts → connection-bbfe1147.d.ts} +1 -1
- package/dist/{index-3ac92295.d.ts → index-2ece5234.d.ts} +18 -7
- package/dist/logging/index.cjs.map +1 -1
- package/dist/logging/index.d.cts +2 -1
- package/dist/logging/index.d.ts +2 -1
- package/dist/logging/index.js +1 -1
- package/dist/router/index.cjs +384 -492
- package/dist/router/index.cjs.map +1 -1
- package/dist/router/index.d.cts +5 -4
- package/dist/router/index.d.ts +5 -4
- package/dist/router/index.js +5 -4
- package/dist/{services-abc077db.d.ts → services-acbcc441.d.ts} +1 -1
- package/dist/{services-8496d6e8.d.ts → services-cb01a7a8.d.ts} +1 -1
- package/dist/transport/impls/uds/client.cjs +202 -155
- package/dist/transport/impls/uds/client.cjs.map +1 -1
- package/dist/transport/impls/uds/client.d.cts +3 -2
- package/dist/transport/impls/uds/client.d.ts +3 -2
- package/dist/transport/impls/uds/client.js +4 -4
- package/dist/transport/impls/uds/server.cjs +295 -264
- package/dist/transport/impls/uds/server.cjs.map +1 -1
- package/dist/transport/impls/uds/server.d.cts +3 -2
- package/dist/transport/impls/uds/server.d.ts +3 -2
- package/dist/transport/impls/uds/server.js +4 -4
- package/dist/transport/impls/ws/client.cjs +256 -214
- package/dist/transport/impls/ws/client.cjs.map +1 -1
- package/dist/transport/impls/ws/client.d.cts +6 -6
- package/dist/transport/impls/ws/client.d.ts +6 -6
- package/dist/transport/impls/ws/client.js +34 -49
- package/dist/transport/impls/ws/client.js.map +1 -1
- package/dist/transport/impls/ws/server.cjs +317 -278
- package/dist/transport/impls/ws/server.cjs.map +1 -1
- package/dist/transport/impls/ws/server.d.cts +5 -4
- package/dist/transport/impls/ws/server.d.ts +5 -4
- package/dist/transport/impls/ws/server.js +4 -4
- package/dist/transport/impls/ws/server.js.map +1 -1
- package/dist/transport/index.cjs +406 -391
- package/dist/transport/index.cjs.map +1 -1
- package/dist/transport/index.d.cts +5 -5
- package/dist/transport/index.d.ts +5 -5
- package/dist/transport/index.js +3 -3
- package/dist/util/testHelpers.cjs +71 -19
- package/dist/util/testHelpers.cjs.map +1 -1
- package/dist/util/testHelpers.d.cts +20 -8
- package/dist/util/testHelpers.d.ts +20 -8
- package/dist/util/testHelpers.js +13 -12
- package/dist/util/testHelpers.js.map +1 -1
- package/dist/wslike-e0b32dd5.d.ts +40 -0
- package/package.json +4 -5
- package/dist/chunk-2ERP6FUE.js +0 -42
- package/dist/chunk-2ERP6FUE.js.map +0 -1
- package/dist/chunk-5WFL722S.js.map +0 -1
- package/dist/chunk-DT5JS6TM.js.map +0 -1
- package/dist/chunk-NFV77C2M.js.map +0 -1
- package/dist/chunk-QU2EE6YU.js.map +0 -1
- /package/dist/{chunk-MJR36SUY.js.map → chunk-S3YKQT4J.js.map} +0 -0
|
@@ -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,32 +329,38 @@ 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,
|
|
351
|
+
tags: ["invariant-violation"]
|
|
311
352
|
});
|
|
312
|
-
|
|
353
|
+
conn.close();
|
|
354
|
+
return;
|
|
313
355
|
}
|
|
314
356
|
}
|
|
315
357
|
}
|
|
316
358
|
updateBookkeeping(ack, seq) {
|
|
317
359
|
if (seq + 1 < this.ack) {
|
|
318
|
-
log?.error(
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
);
|
|
360
|
+
log?.error(`received stale seq ${seq} + 1 < ${this.ack}`, {
|
|
361
|
+
...this.loggingMetadata,
|
|
362
|
+
tags: ["invariant-violation"]
|
|
363
|
+
});
|
|
322
364
|
return;
|
|
323
365
|
}
|
|
324
366
|
this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);
|
|
@@ -388,11 +430,6 @@ var Session = class {
|
|
|
388
430
|
}
|
|
389
431
|
};
|
|
390
432
|
|
|
391
|
-
// tracing/index.ts
|
|
392
|
-
var import_api = require("@opentelemetry/api");
|
|
393
|
-
var tracer = import_api.trace.getTracer("river");
|
|
394
|
-
var tracing_default = tracer;
|
|
395
|
-
|
|
396
433
|
// util/stringify.ts
|
|
397
434
|
function coerceErrorString(err) {
|
|
398
435
|
if (err instanceof Error) {
|
|
@@ -454,6 +491,7 @@ var NaiveJsonCodec = {
|
|
|
454
491
|
};
|
|
455
492
|
|
|
456
493
|
// transport/transport.ts
|
|
494
|
+
var import_api3 = require("@opentelemetry/api");
|
|
457
495
|
var defaultTransportOptions = {
|
|
458
496
|
heartbeatIntervalMs: 1e3,
|
|
459
497
|
heartbeatsUntilDead: 2,
|
|
@@ -532,17 +570,22 @@ var Transport = class {
|
|
|
532
570
|
status: "connect",
|
|
533
571
|
conn
|
|
534
572
|
});
|
|
573
|
+
conn.telemetry = createConnectionTelemetryInfo(
|
|
574
|
+
conn,
|
|
575
|
+
session.telemetry.span
|
|
576
|
+
);
|
|
535
577
|
if (isReconnect) {
|
|
536
578
|
session.replaceWithNewConnection(conn);
|
|
537
579
|
log?.info(`reconnected to ${connectedTo}`, session.loggingMetadata);
|
|
538
580
|
}
|
|
539
581
|
}
|
|
540
|
-
createSession(to, conn) {
|
|
582
|
+
createSession(to, conn, propagationCtx) {
|
|
541
583
|
const session = new Session(
|
|
542
584
|
conn,
|
|
543
585
|
this.clientId,
|
|
544
586
|
to,
|
|
545
|
-
this.options
|
|
587
|
+
this.options,
|
|
588
|
+
propagationCtx
|
|
546
589
|
);
|
|
547
590
|
this.sessions.set(session.to, session);
|
|
548
591
|
this.eventDispatcher.dispatchEvent("sessionStatus", {
|
|
@@ -551,11 +594,11 @@ var Transport = class {
|
|
|
551
594
|
});
|
|
552
595
|
return session;
|
|
553
596
|
}
|
|
554
|
-
getOrCreateSession(to, conn, sessionId) {
|
|
597
|
+
getOrCreateSession(to, conn, sessionId, propagationCtx) {
|
|
555
598
|
let session = this.sessions.get(to);
|
|
556
599
|
let isReconnect = session !== void 0;
|
|
557
600
|
if (session?.advertisedSessionId !== void 0 && sessionId !== void 0 && session.advertisedSessionId !== sessionId) {
|
|
558
|
-
log?.
|
|
601
|
+
log?.info(
|
|
559
602
|
`session for ${to} already exists but has a different session id (expected: ${session.advertisedSessionId}, got: ${sessionId}), creating a new one`,
|
|
560
603
|
session.loggingMetadata
|
|
561
604
|
);
|
|
@@ -564,7 +607,7 @@ var Transport = class {
|
|
|
564
607
|
session = void 0;
|
|
565
608
|
}
|
|
566
609
|
if (!session) {
|
|
567
|
-
session = this.createSession(to, conn);
|
|
610
|
+
session = this.createSession(to, conn, propagationCtx);
|
|
568
611
|
log?.info(
|
|
569
612
|
`no session for ${to}, created a new one`,
|
|
570
613
|
session.loggingMetadata
|
|
@@ -577,6 +620,7 @@ var Transport = class {
|
|
|
577
620
|
}
|
|
578
621
|
deleteSession(session) {
|
|
579
622
|
session.close();
|
|
623
|
+
session.telemetry.span.end();
|
|
580
624
|
this.sessions.delete(session.to);
|
|
581
625
|
log?.info(
|
|
582
626
|
`session ${session.id} disconnect from ${session.to}`,
|
|
@@ -593,12 +637,16 @@ var Transport = class {
|
|
|
593
637
|
* @param connectedTo The peer we are connected to.
|
|
594
638
|
*/
|
|
595
639
|
onDisconnect(conn, session) {
|
|
640
|
+
conn.telemetry?.span.end();
|
|
596
641
|
this.eventDispatcher.dispatchEvent("connectionStatus", {
|
|
597
642
|
status: "disconnect",
|
|
598
643
|
conn
|
|
599
644
|
});
|
|
600
645
|
session.connection = void 0;
|
|
601
|
-
session.beginGrace(() =>
|
|
646
|
+
session.beginGrace(() => {
|
|
647
|
+
session.telemetry.span.addEvent("session grace period expired");
|
|
648
|
+
this.deleteSession(session);
|
|
649
|
+
});
|
|
602
650
|
}
|
|
603
651
|
/**
|
|
604
652
|
* Parses a message from a Uint8Array into a {@link OpaqueTransportMessage}.
|
|
@@ -632,9 +680,10 @@ var Transport = class {
|
|
|
632
680
|
return;
|
|
633
681
|
const session = this.sessions.get(msg.from);
|
|
634
682
|
if (!session) {
|
|
635
|
-
log?.error(`
|
|
683
|
+
log?.error(`no existing session for ${msg.from}`, {
|
|
636
684
|
clientId: this.clientId,
|
|
637
|
-
fullTransportMessage: msg
|
|
685
|
+
fullTransportMessage: msg,
|
|
686
|
+
tags: ["invariant-violation"]
|
|
638
687
|
});
|
|
639
688
|
return;
|
|
640
689
|
}
|
|
@@ -653,9 +702,14 @@ var Transport = class {
|
|
|
653
702
|
const errMsg = `received out-of-order msg (got seq: ${msg.seq}, wanted seq: ${session.nextExpectedSeq})`;
|
|
654
703
|
log?.error(`${errMsg}, marking connection as dead`, {
|
|
655
704
|
clientId: this.clientId,
|
|
656
|
-
fullTransportMessage: msg
|
|
705
|
+
fullTransportMessage: msg,
|
|
706
|
+
tags: ["invariant-violation"]
|
|
657
707
|
});
|
|
658
708
|
this.protocolError(ProtocolError.MessageOrderingViolated, errMsg);
|
|
709
|
+
session.telemetry.span.setStatus({
|
|
710
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
711
|
+
message: "message order violated"
|
|
712
|
+
});
|
|
659
713
|
session.close();
|
|
660
714
|
}
|
|
661
715
|
return;
|
|
@@ -697,7 +751,8 @@ var Transport = class {
|
|
|
697
751
|
const err = "transport is destroyed, cant send";
|
|
698
752
|
log?.error(err, {
|
|
699
753
|
clientId: this.clientId,
|
|
700
|
-
partialTransportMessage: msg
|
|
754
|
+
partialTransportMessage: msg,
|
|
755
|
+
tags: ["invariant-violation"]
|
|
701
756
|
});
|
|
702
757
|
this.protocolError(ProtocolError.UseAfterDestroy, err);
|
|
703
758
|
return void 0;
|
|
@@ -765,278 +820,262 @@ var ServerTransport = class extends Transport {
|
|
|
765
820
|
});
|
|
766
821
|
}
|
|
767
822
|
handleConnection(conn) {
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
(
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
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"
|
|
783
844
|
});
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
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) {
|
|
798
860
|
conn.close();
|
|
799
|
-
}
|
|
800
|
-
}, this.options.sessionDisconnectGraceMs);
|
|
801
|
-
const buffer = [];
|
|
802
|
-
let receivedHandshakeMessage = false;
|
|
803
|
-
const handshakeHandler = (data) => {
|
|
804
|
-
if (receivedHandshakeMessage) {
|
|
805
|
-
buffer.push(data);
|
|
806
861
|
return;
|
|
807
862
|
}
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
(
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
span.end();
|
|
815
|
-
conn.close();
|
|
816
|
-
return;
|
|
817
|
-
}
|
|
818
|
-
session = maybeSession;
|
|
819
|
-
const dataHandler = (data2) => {
|
|
820
|
-
const parsed = this.parseMsg(data2);
|
|
821
|
-
if (!parsed) {
|
|
822
|
-
conn.close();
|
|
823
|
-
return;
|
|
824
|
-
}
|
|
825
|
-
this.handleMsg(parsed);
|
|
826
|
-
};
|
|
827
|
-
conn.removeDataListener(handshakeHandler);
|
|
828
|
-
conn.addDataListener(dataHandler);
|
|
829
|
-
for (const data2 of buffer) {
|
|
830
|
-
dataHandler(data2);
|
|
831
|
-
}
|
|
832
|
-
buffer.length = 0;
|
|
863
|
+
session = maybeSession;
|
|
864
|
+
const dataHandler = (data2) => {
|
|
865
|
+
const parsed = this.parseMsg(data2);
|
|
866
|
+
if (!parsed) {
|
|
867
|
+
conn.close();
|
|
868
|
+
return;
|
|
833
869
|
}
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
if (session) {
|
|
839
|
-
log?.info(`connection to ${client()} disconnected`, {
|
|
840
|
-
clientId: this.clientId,
|
|
841
|
-
connId: conn.debugId
|
|
842
|
-
});
|
|
843
|
-
this.onDisconnect(conn, session);
|
|
870
|
+
this.handleMsg(parsed);
|
|
871
|
+
};
|
|
872
|
+
for (const data2 of buffer) {
|
|
873
|
+
dataHandler(data2);
|
|
844
874
|
}
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
)
|
|
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
|
+
});
|
|
862
903
|
}
|
|
863
904
|
async receiveHandshakeRequestMessage(data, conn) {
|
|
864
905
|
const parsed = this.parseMsg(data);
|
|
865
906
|
if (!parsed) {
|
|
907
|
+
conn.telemetry?.span.setStatus({
|
|
908
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
909
|
+
message: "non-transport message"
|
|
910
|
+
});
|
|
866
911
|
this.protocolError(
|
|
867
912
|
ProtocolError.HandshakeFailed,
|
|
868
913
|
"received non-transport message"
|
|
869
914
|
);
|
|
870
915
|
return false;
|
|
871
916
|
}
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
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;
|
|
875
939
|
}
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
{
|
|
879
|
-
|
|
880
|
-
|
|
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
|
-
const gotVersion = parsed.payload.protocolVersion;
|
|
915
|
-
if (gotVersion !== PROTOCOL_VERSION) {
|
|
916
|
-
const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
|
|
917
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
918
|
-
this.clientId,
|
|
919
|
-
parsed.from,
|
|
920
|
-
{
|
|
921
|
-
ok: false,
|
|
922
|
-
reason
|
|
923
|
-
}
|
|
924
|
-
);
|
|
925
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
926
|
-
log?.warn(
|
|
927
|
-
`received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`,
|
|
928
|
-
{ clientId: this.clientId, connId: conn.debugId }
|
|
929
|
-
);
|
|
930
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
931
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
932
|
-
span.end();
|
|
933
|
-
return false;
|
|
934
|
-
}
|
|
935
|
-
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,
|
|
936
978
|
parsed.from,
|
|
937
|
-
|
|
938
|
-
parsed.payload.sessionId
|
|
979
|
+
{ ok: false, reason }
|
|
939
980
|
);
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
return false;
|
|
965
|
-
}
|
|
966
|
-
const parsedMetadata = await this.options.handshake.parse(
|
|
967
|
-
parsed.payload.metadata,
|
|
968
|
-
session,
|
|
969
|
-
isReconnect
|
|
970
|
-
);
|
|
971
|
-
if (parsedMetadata === false) {
|
|
972
|
-
const reason = "rejected by server";
|
|
973
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
974
|
-
this.clientId,
|
|
975
|
-
parsed.from,
|
|
976
|
-
{ ok: false, reason }
|
|
977
|
-
);
|
|
978
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
979
|
-
log?.warn(`rejected handshake from ${parsed.from}`, {
|
|
980
|
-
clientId: this.clientId,
|
|
981
|
-
connId: conn.debugId
|
|
982
|
-
});
|
|
983
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
984
|
-
this.deleteSession(session);
|
|
985
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
986
|
-
span.end();
|
|
987
|
-
return false;
|
|
988
|
-
}
|
|
989
|
-
if (!import_value.Value.Check(this.options.handshake.parsedSchema, parsedMetadata)) {
|
|
990
|
-
const reason = "failed to parse handshake metadata";
|
|
991
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
992
|
-
this.clientId,
|
|
993
|
-
parsed.from,
|
|
994
|
-
{ ok: false, reason }
|
|
995
|
-
);
|
|
996
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
997
|
-
log?.error(`failed to parse handshake metadata`, {
|
|
998
|
-
clientId: this.clientId,
|
|
999
|
-
connId: conn.debugId
|
|
1000
|
-
});
|
|
1001
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
1002
|
-
this.deleteSession(session);
|
|
1003
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
1004
|
-
span.end();
|
|
1005
|
-
return false;
|
|
1006
|
-
}
|
|
1007
|
-
handshakeMetadata = parsedMetadata;
|
|
1008
|
-
}
|
|
1009
|
-
handshakeMetadata ??= {};
|
|
1010
|
-
session.metadata = handshakeMetadata;
|
|
1011
|
-
log?.debug(
|
|
1012
|
-
`handshake from ${parsed.from} ok, responding with handshake success`,
|
|
1013
|
-
{ 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 }
|
|
1014
1005
|
);
|
|
1015
|
-
|
|
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(
|
|
1016
1022
|
this.clientId,
|
|
1017
1023
|
parsed.from,
|
|
1018
|
-
{
|
|
1019
|
-
ok: true,
|
|
1020
|
-
sessionId: session.id
|
|
1021
|
-
}
|
|
1024
|
+
{ ok: false, reason }
|
|
1022
1025
|
);
|
|
1023
|
-
conn.send(this.codec.toBuffer(
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
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;
|
|
1027
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 }
|
|
1028
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;
|
|
1029
1050
|
}
|
|
1030
1051
|
};
|
|
1031
1052
|
|
|
1032
1053
|
// transport/impls/ws/connection.ts
|
|
1033
|
-
var import_agnostic_ws = __toESM(require("agnostic-ws"), 1);
|
|
1034
1054
|
var WebSocketConnection = class extends Connection {
|
|
1055
|
+
errorCb = null;
|
|
1056
|
+
closeCb = null;
|
|
1035
1057
|
ws;
|
|
1036
1058
|
constructor(ws) {
|
|
1037
1059
|
super();
|
|
1038
1060
|
this.ws = ws;
|
|
1039
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
|
+
};
|
|
1040
1079
|
}
|
|
1041
1080
|
addDataListener(cb) {
|
|
1042
1081
|
this.ws.onmessage = (msg) => cb(msg.data);
|
|
@@ -1045,13 +1084,13 @@ var WebSocketConnection = class extends Connection {
|
|
|
1045
1084
|
this.ws.onmessage = null;
|
|
1046
1085
|
}
|
|
1047
1086
|
addCloseListener(cb) {
|
|
1048
|
-
this.
|
|
1087
|
+
this.closeCb = cb;
|
|
1049
1088
|
}
|
|
1050
1089
|
addErrorListener(cb) {
|
|
1051
|
-
this.
|
|
1090
|
+
this.errorCb = cb;
|
|
1052
1091
|
}
|
|
1053
1092
|
send(payload) {
|
|
1054
|
-
if (this.ws.readyState ===
|
|
1093
|
+
if (this.ws.readyState === this.ws.OPEN) {
|
|
1055
1094
|
this.ws.send(payload);
|
|
1056
1095
|
return true;
|
|
1057
1096
|
} else {
|