@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
|
@@ -26,7 +26,6 @@ module.exports = __toCommonJS(server_exports);
|
|
|
26
26
|
|
|
27
27
|
// transport/transport.ts
|
|
28
28
|
var import_value = require("@sinclair/typebox/value");
|
|
29
|
-
var import_api2 = require("@opentelemetry/api");
|
|
30
29
|
|
|
31
30
|
// transport/message.ts
|
|
32
31
|
var import_typebox = require("@sinclair/typebox");
|
|
@@ -142,17 +141,62 @@ var EventDispatcher = class {
|
|
|
142
141
|
|
|
143
142
|
// transport/session.ts
|
|
144
143
|
var import_nanoid2 = require("nanoid");
|
|
144
|
+
|
|
145
|
+
// tracing/index.ts
|
|
146
|
+
var import_api = require("@opentelemetry/api");
|
|
147
|
+
|
|
148
|
+
// package.json
|
|
149
|
+
var version = "0.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");
|
|
145
187
|
var nanoid2 = (0, import_nanoid2.customAlphabet)("1234567890abcdefghijklmnopqrstuvxyz", 6);
|
|
146
188
|
var unsafeId = () => nanoid2();
|
|
147
189
|
var Connection = class {
|
|
148
|
-
|
|
190
|
+
id;
|
|
191
|
+
telemetry;
|
|
149
192
|
constructor() {
|
|
150
|
-
this.
|
|
193
|
+
this.id = `conn-${nanoid2(12)}`;
|
|
151
194
|
}
|
|
152
195
|
};
|
|
153
196
|
var Session = class {
|
|
154
197
|
codec;
|
|
155
198
|
options;
|
|
199
|
+
telemetry;
|
|
156
200
|
/**
|
|
157
201
|
* The buffer of messages that have been sent but not yet acknowledged.
|
|
158
202
|
*/
|
|
@@ -199,7 +243,7 @@ var Session = class {
|
|
|
199
243
|
* The interval for sending heartbeats.
|
|
200
244
|
*/
|
|
201
245
|
heartbeat;
|
|
202
|
-
constructor(conn, from, to, options) {
|
|
246
|
+
constructor(conn, from, to, options, propagationCtx) {
|
|
203
247
|
this.id = `session-${nanoid2(12)}`;
|
|
204
248
|
this.options = options;
|
|
205
249
|
this.from = from;
|
|
@@ -211,13 +255,14 @@ var Session = class {
|
|
|
211
255
|
() => this.sendHeartbeat(),
|
|
212
256
|
options.heartbeatIntervalMs
|
|
213
257
|
);
|
|
258
|
+
this.telemetry = createSessionTelemetryInfo(this, propagationCtx);
|
|
214
259
|
}
|
|
215
260
|
get loggingMetadata() {
|
|
216
261
|
return {
|
|
217
262
|
clientId: this.from,
|
|
218
263
|
connectedTo: this.to,
|
|
219
264
|
sessionId: this.id,
|
|
220
|
-
connId: this.connection?.
|
|
265
|
+
connId: this.connection?.id
|
|
221
266
|
};
|
|
222
267
|
}
|
|
223
268
|
/**
|
|
@@ -262,6 +307,7 @@ var Session = class {
|
|
|
262
307
|
`closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
|
|
263
308
|
this.loggingMetadata
|
|
264
309
|
);
|
|
310
|
+
this.telemetry.span.addEvent("closing connection due to inactivity");
|
|
265
311
|
this.closeStaleConnection();
|
|
266
312
|
}
|
|
267
313
|
return;
|
|
@@ -283,32 +329,38 @@ var Session = class {
|
|
|
283
329
|
sendBufferedMessages(conn) {
|
|
284
330
|
log?.info(`resending ${this.sendBuffer.length} buffered messages`, {
|
|
285
331
|
...this.loggingMetadata,
|
|
286
|
-
connId: conn.
|
|
332
|
+
connId: conn.id
|
|
287
333
|
});
|
|
288
334
|
for (const msg of this.sendBuffer) {
|
|
289
335
|
log?.debug(`resending msg`, {
|
|
290
336
|
...this.loggingMetadata,
|
|
291
337
|
fullTransportMessage: msg,
|
|
292
|
-
connId: conn.
|
|
338
|
+
connId: conn.id
|
|
293
339
|
});
|
|
294
340
|
const ok = conn.send(this.codec.toBuffer(msg));
|
|
295
341
|
if (!ok) {
|
|
296
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
|
+
});
|
|
297
347
|
log?.error(errMsg, {
|
|
298
348
|
...this.loggingMetadata,
|
|
299
349
|
fullTransportMessage: msg,
|
|
300
|
-
connId: conn.
|
|
350
|
+
connId: conn.id,
|
|
351
|
+
tags: ["invariant-violation"]
|
|
301
352
|
});
|
|
302
|
-
|
|
353
|
+
conn.close();
|
|
354
|
+
return;
|
|
303
355
|
}
|
|
304
356
|
}
|
|
305
357
|
}
|
|
306
358
|
updateBookkeeping(ack, seq) {
|
|
307
359
|
if (seq + 1 < this.ack) {
|
|
308
|
-
log?.error(
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
);
|
|
360
|
+
log?.error(`received stale seq ${seq} + 1 < ${this.ack}`, {
|
|
361
|
+
...this.loggingMetadata,
|
|
362
|
+
tags: ["invariant-violation"]
|
|
363
|
+
});
|
|
312
364
|
return;
|
|
313
365
|
}
|
|
314
366
|
this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);
|
|
@@ -378,11 +430,6 @@ var Session = class {
|
|
|
378
430
|
}
|
|
379
431
|
};
|
|
380
432
|
|
|
381
|
-
// tracing/index.ts
|
|
382
|
-
var import_api = require("@opentelemetry/api");
|
|
383
|
-
var tracer = import_api.trace.getTracer("river");
|
|
384
|
-
var tracing_default = tracer;
|
|
385
|
-
|
|
386
433
|
// util/stringify.ts
|
|
387
434
|
function coerceErrorString(err) {
|
|
388
435
|
if (err instanceof Error) {
|
|
@@ -444,6 +491,7 @@ var NaiveJsonCodec = {
|
|
|
444
491
|
};
|
|
445
492
|
|
|
446
493
|
// transport/transport.ts
|
|
494
|
+
var import_api3 = require("@opentelemetry/api");
|
|
447
495
|
var defaultTransportOptions = {
|
|
448
496
|
heartbeatIntervalMs: 1e3,
|
|
449
497
|
heartbeatsUntilDead: 2,
|
|
@@ -522,17 +570,22 @@ var Transport = class {
|
|
|
522
570
|
status: "connect",
|
|
523
571
|
conn
|
|
524
572
|
});
|
|
573
|
+
conn.telemetry = createConnectionTelemetryInfo(
|
|
574
|
+
conn,
|
|
575
|
+
session.telemetry.span
|
|
576
|
+
);
|
|
525
577
|
if (isReconnect) {
|
|
526
578
|
session.replaceWithNewConnection(conn);
|
|
527
579
|
log?.info(`reconnected to ${connectedTo}`, session.loggingMetadata);
|
|
528
580
|
}
|
|
529
581
|
}
|
|
530
|
-
createSession(to, conn) {
|
|
582
|
+
createSession(to, conn, propagationCtx) {
|
|
531
583
|
const session = new Session(
|
|
532
584
|
conn,
|
|
533
585
|
this.clientId,
|
|
534
586
|
to,
|
|
535
|
-
this.options
|
|
587
|
+
this.options,
|
|
588
|
+
propagationCtx
|
|
536
589
|
);
|
|
537
590
|
this.sessions.set(session.to, session);
|
|
538
591
|
this.eventDispatcher.dispatchEvent("sessionStatus", {
|
|
@@ -541,11 +594,11 @@ var Transport = class {
|
|
|
541
594
|
});
|
|
542
595
|
return session;
|
|
543
596
|
}
|
|
544
|
-
getOrCreateSession(to, conn, sessionId) {
|
|
597
|
+
getOrCreateSession(to, conn, sessionId, propagationCtx) {
|
|
545
598
|
let session = this.sessions.get(to);
|
|
546
599
|
let isReconnect = session !== void 0;
|
|
547
600
|
if (session?.advertisedSessionId !== void 0 && sessionId !== void 0 && session.advertisedSessionId !== sessionId) {
|
|
548
|
-
log?.
|
|
601
|
+
log?.info(
|
|
549
602
|
`session for ${to} already exists but has a different session id (expected: ${session.advertisedSessionId}, got: ${sessionId}), creating a new one`,
|
|
550
603
|
session.loggingMetadata
|
|
551
604
|
);
|
|
@@ -554,7 +607,7 @@ var Transport = class {
|
|
|
554
607
|
session = void 0;
|
|
555
608
|
}
|
|
556
609
|
if (!session) {
|
|
557
|
-
session = this.createSession(to, conn);
|
|
610
|
+
session = this.createSession(to, conn, propagationCtx);
|
|
558
611
|
log?.info(
|
|
559
612
|
`no session for ${to}, created a new one`,
|
|
560
613
|
session.loggingMetadata
|
|
@@ -567,6 +620,7 @@ var Transport = class {
|
|
|
567
620
|
}
|
|
568
621
|
deleteSession(session) {
|
|
569
622
|
session.close();
|
|
623
|
+
session.telemetry.span.end();
|
|
570
624
|
this.sessions.delete(session.to);
|
|
571
625
|
log?.info(
|
|
572
626
|
`session ${session.id} disconnect from ${session.to}`,
|
|
@@ -583,12 +637,16 @@ var Transport = class {
|
|
|
583
637
|
* @param connectedTo The peer we are connected to.
|
|
584
638
|
*/
|
|
585
639
|
onDisconnect(conn, session) {
|
|
640
|
+
conn.telemetry?.span.end();
|
|
586
641
|
this.eventDispatcher.dispatchEvent("connectionStatus", {
|
|
587
642
|
status: "disconnect",
|
|
588
643
|
conn
|
|
589
644
|
});
|
|
590
645
|
session.connection = void 0;
|
|
591
|
-
session.beginGrace(() =>
|
|
646
|
+
session.beginGrace(() => {
|
|
647
|
+
session.telemetry.span.addEvent("session grace period expired");
|
|
648
|
+
this.deleteSession(session);
|
|
649
|
+
});
|
|
592
650
|
}
|
|
593
651
|
/**
|
|
594
652
|
* Parses a message from a Uint8Array into a {@link OpaqueTransportMessage}.
|
|
@@ -622,9 +680,10 @@ var Transport = class {
|
|
|
622
680
|
return;
|
|
623
681
|
const session = this.sessions.get(msg.from);
|
|
624
682
|
if (!session) {
|
|
625
|
-
log?.error(`
|
|
683
|
+
log?.error(`no existing session for ${msg.from}`, {
|
|
626
684
|
clientId: this.clientId,
|
|
627
|
-
fullTransportMessage: msg
|
|
685
|
+
fullTransportMessage: msg,
|
|
686
|
+
tags: ["invariant-violation"]
|
|
628
687
|
});
|
|
629
688
|
return;
|
|
630
689
|
}
|
|
@@ -643,9 +702,14 @@ var Transport = class {
|
|
|
643
702
|
const errMsg = `received out-of-order msg (got seq: ${msg.seq}, wanted seq: ${session.nextExpectedSeq})`;
|
|
644
703
|
log?.error(`${errMsg}, marking connection as dead`, {
|
|
645
704
|
clientId: this.clientId,
|
|
646
|
-
fullTransportMessage: msg
|
|
705
|
+
fullTransportMessage: msg,
|
|
706
|
+
tags: ["invariant-violation"]
|
|
647
707
|
});
|
|
648
708
|
this.protocolError(ProtocolError.MessageOrderingViolated, errMsg);
|
|
709
|
+
session.telemetry.span.setStatus({
|
|
710
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
711
|
+
message: "message order violated"
|
|
712
|
+
});
|
|
649
713
|
session.close();
|
|
650
714
|
}
|
|
651
715
|
return;
|
|
@@ -687,7 +751,8 @@ var Transport = class {
|
|
|
687
751
|
const err = "transport is destroyed, cant send";
|
|
688
752
|
log?.error(err, {
|
|
689
753
|
clientId: this.clientId,
|
|
690
|
-
partialTransportMessage: msg
|
|
754
|
+
partialTransportMessage: msg,
|
|
755
|
+
tags: ["invariant-violation"]
|
|
691
756
|
});
|
|
692
757
|
this.protocolError(ProtocolError.UseAfterDestroy, err);
|
|
693
758
|
return void 0;
|
|
@@ -755,267 +820,233 @@ var ServerTransport = class extends Transport {
|
|
|
755
820
|
});
|
|
756
821
|
}
|
|
757
822
|
handleConnection(conn) {
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
(
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
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"
|
|
773
844
|
});
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
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) {
|
|
788
860
|
conn.close();
|
|
789
|
-
}
|
|
790
|
-
}, this.options.sessionDisconnectGraceMs);
|
|
791
|
-
const buffer = [];
|
|
792
|
-
let receivedHandshakeMessage = false;
|
|
793
|
-
const handshakeHandler = (data) => {
|
|
794
|
-
if (receivedHandshakeMessage) {
|
|
795
|
-
buffer.push(data);
|
|
796
861
|
return;
|
|
797
862
|
}
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
(
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
span.end();
|
|
805
|
-
conn.close();
|
|
806
|
-
return;
|
|
807
|
-
}
|
|
808
|
-
session = maybeSession;
|
|
809
|
-
const dataHandler = (data2) => {
|
|
810
|
-
const parsed = this.parseMsg(data2);
|
|
811
|
-
if (!parsed) {
|
|
812
|
-
conn.close();
|
|
813
|
-
return;
|
|
814
|
-
}
|
|
815
|
-
this.handleMsg(parsed);
|
|
816
|
-
};
|
|
817
|
-
conn.removeDataListener(handshakeHandler);
|
|
818
|
-
conn.addDataListener(dataHandler);
|
|
819
|
-
for (const data2 of buffer) {
|
|
820
|
-
dataHandler(data2);
|
|
821
|
-
}
|
|
822
|
-
buffer.length = 0;
|
|
863
|
+
session = maybeSession;
|
|
864
|
+
const dataHandler = (data2) => {
|
|
865
|
+
const parsed = this.parseMsg(data2);
|
|
866
|
+
if (!parsed) {
|
|
867
|
+
conn.close();
|
|
868
|
+
return;
|
|
823
869
|
}
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
if (session) {
|
|
829
|
-
log?.info(`connection to ${client()} disconnected`, {
|
|
830
|
-
clientId: this.clientId,
|
|
831
|
-
connId: conn.debugId
|
|
832
|
-
});
|
|
833
|
-
this.onDisconnect(conn, session);
|
|
834
|
-
}
|
|
835
|
-
span.setStatus({ code: import_api2.SpanStatusCode.OK });
|
|
836
|
-
span.end();
|
|
837
|
-
});
|
|
838
|
-
conn.addErrorListener((err) => {
|
|
839
|
-
if (session) {
|
|
840
|
-
log?.warn(
|
|
841
|
-
`connection to ${client()} got an error: ${coerceErrorString(
|
|
842
|
-
err
|
|
843
|
-
)}`,
|
|
844
|
-
{ clientId: this.clientId, connId: conn.debugId }
|
|
845
|
-
);
|
|
870
|
+
this.handleMsg(parsed);
|
|
871
|
+
};
|
|
872
|
+
for (const data2 of buffer) {
|
|
873
|
+
dataHandler(data2);
|
|
846
874
|
}
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
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
|
+
});
|
|
852
903
|
}
|
|
853
904
|
async receiveHandshakeRequestMessage(data, conn) {
|
|
854
905
|
const parsed = this.parseMsg(data);
|
|
855
906
|
if (!parsed) {
|
|
907
|
+
conn.telemetry?.span.setStatus({
|
|
908
|
+
code: import_api3.SpanStatusCode.ERROR,
|
|
909
|
+
message: "non-transport message"
|
|
910
|
+
});
|
|
856
911
|
this.protocolError(
|
|
857
912
|
ProtocolError.HandshakeFailed,
|
|
858
913
|
"received non-transport message"
|
|
859
914
|
);
|
|
860
915
|
return false;
|
|
861
916
|
}
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
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;
|
|
865
939
|
}
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
{
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
const gotVersion = parsed.payload.protocolVersion;
|
|
905
|
-
if (gotVersion !== PROTOCOL_VERSION) {
|
|
906
|
-
const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
|
|
907
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
908
|
-
this.clientId,
|
|
909
|
-
parsed.from,
|
|
910
|
-
{
|
|
911
|
-
ok: false,
|
|
912
|
-
reason
|
|
913
|
-
}
|
|
914
|
-
);
|
|
915
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
916
|
-
log?.warn(
|
|
917
|
-
`received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`,
|
|
918
|
-
{ clientId: this.clientId, connId: conn.debugId }
|
|
919
|
-
);
|
|
920
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
921
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
922
|
-
span.end();
|
|
923
|
-
return false;
|
|
924
|
-
}
|
|
925
|
-
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,
|
|
926
978
|
parsed.from,
|
|
927
|
-
|
|
928
|
-
parsed.payload.sessionId
|
|
979
|
+
{ ok: false, reason }
|
|
929
980
|
);
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
return false;
|
|
955
|
-
}
|
|
956
|
-
const parsedMetadata = await this.options.handshake.parse(
|
|
957
|
-
parsed.payload.metadata,
|
|
958
|
-
session,
|
|
959
|
-
isReconnect
|
|
960
|
-
);
|
|
961
|
-
if (parsedMetadata === false) {
|
|
962
|
-
const reason = "rejected by server";
|
|
963
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
964
|
-
this.clientId,
|
|
965
|
-
parsed.from,
|
|
966
|
-
{ ok: false, reason }
|
|
967
|
-
);
|
|
968
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
969
|
-
log?.warn(`rejected handshake from ${parsed.from}`, {
|
|
970
|
-
clientId: this.clientId,
|
|
971
|
-
connId: conn.debugId
|
|
972
|
-
});
|
|
973
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
974
|
-
this.deleteSession(session);
|
|
975
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
976
|
-
span.end();
|
|
977
|
-
return false;
|
|
978
|
-
}
|
|
979
|
-
if (!import_value.Value.Check(this.options.handshake.parsedSchema, parsedMetadata)) {
|
|
980
|
-
const reason = "failed to parse handshake metadata";
|
|
981
|
-
const responseMsg2 = handshakeResponseMessage(
|
|
982
|
-
this.clientId,
|
|
983
|
-
parsed.from,
|
|
984
|
-
{ ok: false, reason }
|
|
985
|
-
);
|
|
986
|
-
conn.send(this.codec.toBuffer(responseMsg2));
|
|
987
|
-
log?.error(`failed to parse handshake metadata`, {
|
|
988
|
-
clientId: this.clientId,
|
|
989
|
-
connId: conn.debugId
|
|
990
|
-
});
|
|
991
|
-
this.protocolError(ProtocolError.HandshakeFailed, reason);
|
|
992
|
-
this.deleteSession(session);
|
|
993
|
-
span.setStatus({ code: import_api2.SpanStatusCode.ERROR });
|
|
994
|
-
span.end();
|
|
995
|
-
return false;
|
|
996
|
-
}
|
|
997
|
-
handshakeMetadata = parsedMetadata;
|
|
998
|
-
}
|
|
999
|
-
handshakeMetadata ??= {};
|
|
1000
|
-
session.metadata = handshakeMetadata;
|
|
1001
|
-
log?.debug(
|
|
1002
|
-
`handshake from ${parsed.from} ok, responding with handshake success`,
|
|
1003
|
-
{ 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 }
|
|
1004
1005
|
);
|
|
1005
|
-
|
|
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(
|
|
1006
1022
|
this.clientId,
|
|
1007
1023
|
parsed.from,
|
|
1008
|
-
{
|
|
1009
|
-
ok: true,
|
|
1010
|
-
sessionId: session.id
|
|
1011
|
-
}
|
|
1024
|
+
{ ok: false, reason }
|
|
1012
1025
|
);
|
|
1013
|
-
conn.send(this.codec.toBuffer(
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
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;
|
|
1017
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 }
|
|
1018
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;
|
|
1019
1050
|
}
|
|
1020
1051
|
};
|
|
1021
1052
|
|