@replit/river 0.23.11 → 0.23.13

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.
Files changed (74) hide show
  1. package/dist/chunk-2FNLANTJ.js +327 -0
  2. package/dist/chunk-2FNLANTJ.js.map +1 -0
  3. package/dist/{chunk-3AW3IXVD.js → chunk-4PVU7J25.js} +1 -21
  4. package/dist/chunk-4PVU7J25.js.map +1 -0
  5. package/dist/{chunk-T6YEMFUF.js → chunk-4QZOW4DH.js} +2 -2
  6. package/dist/{chunk-MEHCOYKJ.js → chunk-ES4XO2XD.js} +2 -2
  7. package/dist/{chunk-MEHCOYKJ.js.map → chunk-ES4XO2XD.js.map} +1 -1
  8. package/dist/{chunk-ZSKCZYVU.js → chunk-KFTGQ3QC.js} +2 -2
  9. package/dist/chunk-KFTGQ3QC.js.map +1 -0
  10. package/dist/chunk-S4DUN7KK.js +455 -0
  11. package/dist/chunk-S4DUN7KK.js.map +1 -0
  12. package/dist/{chunk-HM7VDTDJ.js → chunk-SX6HI63Q.js} +2 -2
  13. package/dist/chunk-XM656KMN.js +408 -0
  14. package/dist/chunk-XM656KMN.js.map +1 -0
  15. package/dist/chunk-ZUKDZY54.js +271 -0
  16. package/dist/chunk-ZUKDZY54.js.map +1 -0
  17. package/dist/client-dd5c9dd0.d.ts +52 -0
  18. package/dist/codec/index.js +20 -2
  19. package/dist/codec/index.js.map +1 -1
  20. package/dist/{connection-261eee8f.d.ts → connection-39816c00.d.ts} +1 -1
  21. package/dist/{connection-c1eeb95d.d.ts → connection-40318f22.d.ts} +1 -1
  22. package/dist/{transport-c8f36f6d.d.ts → handshake-e428d1c8.d.ts} +91 -155
  23. package/dist/{index-60f03cb7.d.ts → index-ea74cdbb.d.ts} +1 -1
  24. package/dist/logging/index.d.cts +1 -1
  25. package/dist/logging/index.d.ts +1 -1
  26. package/dist/router/index.cjs +1 -1
  27. package/dist/router/index.cjs.map +1 -1
  28. package/dist/router/index.d.cts +8 -6
  29. package/dist/router/index.d.ts +8 -6
  30. package/dist/router/index.js +2 -2
  31. package/dist/server-ebf80863.d.ts +24 -0
  32. package/dist/{services-524bab79.d.ts → services-f406b3aa.d.ts} +3 -2
  33. package/dist/transport/impls/uds/client.cjs +222 -174
  34. package/dist/transport/impls/uds/client.cjs.map +1 -1
  35. package/dist/transport/impls/uds/client.d.cts +6 -5
  36. package/dist/transport/impls/uds/client.d.ts +6 -5
  37. package/dist/transport/impls/uds/client.js +6 -4
  38. package/dist/transport/impls/uds/client.js.map +1 -1
  39. package/dist/transport/impls/uds/server.cjs +252 -223
  40. package/dist/transport/impls/uds/server.cjs.map +1 -1
  41. package/dist/transport/impls/uds/server.d.cts +6 -5
  42. package/dist/transport/impls/uds/server.d.ts +6 -5
  43. package/dist/transport/impls/uds/server.js +8 -6
  44. package/dist/transport/impls/uds/server.js.map +1 -1
  45. package/dist/transport/impls/ws/client.cjs +224 -176
  46. package/dist/transport/impls/ws/client.cjs.map +1 -1
  47. package/dist/transport/impls/ws/client.d.cts +6 -5
  48. package/dist/transport/impls/ws/client.d.ts +6 -5
  49. package/dist/transport/impls/ws/client.js +6 -4
  50. package/dist/transport/impls/ws/client.js.map +1 -1
  51. package/dist/transport/impls/ws/server.cjs +206 -177
  52. package/dist/transport/impls/ws/server.cjs.map +1 -1
  53. package/dist/transport/impls/ws/server.d.cts +4 -3
  54. package/dist/transport/impls/ws/server.d.ts +4 -3
  55. package/dist/transport/impls/ws/server.js +8 -6
  56. package/dist/transport/impls/ws/server.js.map +1 -1
  57. package/dist/transport/index.cjs +170 -116
  58. package/dist/transport/index.cjs.map +1 -1
  59. package/dist/transport/index.d.cts +4 -2
  60. package/dist/transport/index.d.ts +4 -2
  61. package/dist/transport/index.js +14 -8
  62. package/dist/util/testHelpers.cjs +6 -8
  63. package/dist/util/testHelpers.cjs.map +1 -1
  64. package/dist/util/testHelpers.d.cts +5 -4
  65. package/dist/util/testHelpers.d.ts +5 -4
  66. package/dist/util/testHelpers.js +4 -5
  67. package/dist/util/testHelpers.js.map +1 -1
  68. package/package.json +1 -1
  69. package/dist/chunk-3AW3IXVD.js.map +0 -1
  70. package/dist/chunk-EOJMKMDO.js +0 -1372
  71. package/dist/chunk-EOJMKMDO.js.map +0 -1
  72. package/dist/chunk-ZSKCZYVU.js.map +0 -1
  73. /package/dist/{chunk-T6YEMFUF.js.map → chunk-4QZOW4DH.js.map} +0 -0
  74. /package/dist/{chunk-HM7VDTDJ.js.map → chunk-SX6HI63Q.js.map} +0 -0
@@ -1,1372 +0,0 @@
1
- import {
2
- ControlMessageHandshakeRequestSchema,
3
- ControlMessageHandshakeResponseSchema,
4
- OpaqueTransportMessageSchema,
5
- PROTOCOL_VERSION,
6
- coerceErrorString,
7
- createConnectionTelemetryInfo,
8
- createSessionTelemetryInfo,
9
- getPropagationContext,
10
- handshakeRequestMessage,
11
- handshakeResponseMessage,
12
- isAck,
13
- tracing_default
14
- } from "./chunk-MEHCOYKJ.js";
15
- import {
16
- BaseLogger,
17
- createLogProxy
18
- } from "./chunk-6LCL2ZZF.js";
19
- import {
20
- NaiveJsonCodec
21
- } from "./chunk-3AW3IXVD.js";
22
-
23
- // transport/session.ts
24
- import { customAlphabet } from "nanoid";
25
- import { SpanStatusCode } from "@opentelemetry/api";
26
- var nanoid = customAlphabet("1234567890abcdefghijklmnopqrstuvxyz", 6);
27
- var unsafeId = () => nanoid();
28
- var Connection = class {
29
- id;
30
- telemetry;
31
- constructor() {
32
- this.id = `conn-${nanoid(12)}`;
33
- }
34
- get loggingMetadata() {
35
- const metadata = { connId: this.id };
36
- const spanContext = this.telemetry?.span.spanContext();
37
- if (this.telemetry?.span.isRecording() && spanContext) {
38
- metadata.telemetry = {
39
- traceId: spanContext.traceId,
40
- spanId: spanContext.spanId
41
- };
42
- }
43
- return metadata;
44
- }
45
- };
46
- var Session = class {
47
- codec;
48
- options;
49
- telemetry;
50
- /**
51
- * The buffer of messages that have been sent but not yet acknowledged.
52
- */
53
- sendBuffer = [];
54
- /**
55
- * The active connection associated with this session
56
- */
57
- connection;
58
- /**
59
- * A connection that is currently undergoing handshaking. Used to distinguish between the active
60
- * connection, but still be able to close it if needed.
61
- */
62
- handshakingConnection;
63
- from;
64
- to;
65
- /**
66
- * The unique ID of this session.
67
- */
68
- id;
69
- /**
70
- * What the other side advertised as their session ID
71
- * for this session.
72
- */
73
- advertisedSessionId;
74
- /**
75
- * Number of messages we've sent along this session (excluding handshake and acks)
76
- */
77
- seq = 0;
78
- /**
79
- * Number of unique messages we've received this session (excluding handshake and acks)
80
- */
81
- ack = 0;
82
- /**
83
- * The grace period between when the inner connection is disconnected
84
- * and when we should consider the entire session disconnected.
85
- */
86
- disconnectionGrace;
87
- /**
88
- * Number of heartbeats we've sent without a response.
89
- */
90
- heartbeatMisses;
91
- /**
92
- * The interval for sending heartbeats.
93
- */
94
- heartbeat;
95
- log;
96
- constructor(conn, from, to, options, propagationCtx) {
97
- this.id = `session-${nanoid(12)}`;
98
- this.options = options;
99
- this.from = from;
100
- this.to = to;
101
- this.connection = conn;
102
- this.codec = options.codec;
103
- this.heartbeatMisses = 0;
104
- this.heartbeat = setInterval(
105
- () => this.sendHeartbeat(),
106
- options.heartbeatIntervalMs
107
- );
108
- this.telemetry = createSessionTelemetryInfo(this, propagationCtx);
109
- }
110
- bindLogger(log) {
111
- this.log = log;
112
- }
113
- get loggingMetadata() {
114
- const spanContext = this.telemetry.span.spanContext();
115
- return {
116
- clientId: this.from,
117
- connectedTo: this.to,
118
- sessionId: this.id,
119
- connId: this.connection?.id,
120
- telemetry: {
121
- traceId: spanContext.traceId,
122
- spanId: spanContext.spanId
123
- }
124
- };
125
- }
126
- /**
127
- * Sends a message over the session's connection.
128
- * If the connection is not ready or the message fails to send, the message can be buffered for retry unless skipped.
129
- *
130
- * @param msg The partial message to be sent, which will be constructed into a full message.
131
- * @param addToSendBuff Whether to add the message to the send buffer for retry.
132
- * @returns The full transport ID of the message that was attempted to be sent.
133
- */
134
- send(msg) {
135
- const fullMsg = this.constructMsg(msg);
136
- this.log?.debug(`sending msg`, {
137
- ...this.loggingMetadata,
138
- transportMessage: fullMsg
139
- });
140
- if (this.connection) {
141
- const ok = this.connection.send(this.codec.toBuffer(fullMsg));
142
- if (ok)
143
- return fullMsg.id;
144
- this.log?.info(
145
- `failed to send msg to ${fullMsg.to}, connection is probably dead`,
146
- {
147
- ...this.loggingMetadata,
148
- transportMessage: fullMsg
149
- }
150
- );
151
- } else {
152
- this.log?.debug(
153
- `buffering msg to ${fullMsg.to}, connection not ready yet`,
154
- { ...this.loggingMetadata, transportMessage: fullMsg }
155
- );
156
- }
157
- return fullMsg.id;
158
- }
159
- sendHeartbeat() {
160
- const misses = this.heartbeatMisses;
161
- const missDuration = misses * this.options.heartbeatIntervalMs;
162
- if (misses > this.options.heartbeatsUntilDead) {
163
- if (this.connection) {
164
- this.log?.info(
165
- `closing connection to ${this.to} due to inactivity (missed ${misses} heartbeats which is ${missDuration}ms)`,
166
- this.loggingMetadata
167
- );
168
- this.telemetry.span.addEvent("closing connection due to inactivity");
169
- this.closeStaleConnection();
170
- }
171
- return;
172
- }
173
- this.send({
174
- streamId: "heartbeat",
175
- controlFlags: 1 /* AckBit */,
176
- payload: {
177
- type: "ACK"
178
- }
179
- });
180
- this.heartbeatMisses++;
181
- }
182
- resetBufferedMessages() {
183
- this.sendBuffer = [];
184
- this.seq = 0;
185
- this.ack = 0;
186
- }
187
- sendBufferedMessages(conn) {
188
- this.log?.info(`resending ${this.sendBuffer.length} buffered messages`, {
189
- ...this.loggingMetadata,
190
- connId: conn.id
191
- });
192
- for (const msg of this.sendBuffer) {
193
- this.log?.debug(`resending msg`, {
194
- ...this.loggingMetadata,
195
- transportMessage: msg,
196
- connId: conn.id
197
- });
198
- const ok = conn.send(this.codec.toBuffer(msg));
199
- if (!ok) {
200
- const errMsg = `failed to send buffered message to ${this.to} (sus, this is a fresh connection)`;
201
- conn.telemetry?.span.setStatus({
202
- code: SpanStatusCode.ERROR,
203
- message: errMsg
204
- });
205
- this.log?.error(errMsg, {
206
- ...this.loggingMetadata,
207
- transportMessage: msg,
208
- connId: conn.id,
209
- tags: ["invariant-violation"]
210
- });
211
- conn.close();
212
- return;
213
- }
214
- }
215
- }
216
- updateBookkeeping(ack, seq) {
217
- if (seq + 1 < this.ack) {
218
- this.log?.error(`received stale seq ${seq} + 1 < ${this.ack}`, {
219
- ...this.loggingMetadata,
220
- tags: ["invariant-violation"]
221
- });
222
- return;
223
- }
224
- this.sendBuffer = this.sendBuffer.filter((unacked) => unacked.seq >= ack);
225
- this.ack = seq + 1;
226
- }
227
- closeStaleConnection(conn) {
228
- if (this.connection === void 0 || this.connection === conn)
229
- return;
230
- this.log?.info(
231
- `closing old inner connection from session to ${this.to}`,
232
- this.loggingMetadata
233
- );
234
- this.connection.close();
235
- this.connection = void 0;
236
- }
237
- replaceWithNewConnection(newConn) {
238
- this.closeStaleConnection(newConn);
239
- this.cancelGrace();
240
- this.sendBufferedMessages(newConn);
241
- this.connection = newConn;
242
- this.handshakingConnection = void 0;
243
- }
244
- replaceWithNewHandshakingConnection(newConn) {
245
- this.handshakingConnection = newConn;
246
- }
247
- beginGrace(cb) {
248
- this.log?.info(
249
- `starting ${this.options.sessionDisconnectGraceMs}ms grace period until session to ${this.to} is closed`,
250
- this.loggingMetadata
251
- );
252
- this.cancelGrace();
253
- this.disconnectionGrace = setTimeout(() => {
254
- this.log?.info(
255
- `grace period for ${this.to} elapsed`,
256
- this.loggingMetadata
257
- );
258
- cb();
259
- }, this.options.sessionDisconnectGraceMs);
260
- }
261
- // called on reconnect of the underlying session
262
- cancelGrace() {
263
- this.heartbeatMisses = 0;
264
- clearTimeout(this.disconnectionGrace);
265
- this.disconnectionGrace = void 0;
266
- }
267
- /**
268
- * Used to close the handshaking connection, if set.
269
- */
270
- closeHandshakingConnection(expectedHandshakingConn) {
271
- if (this.handshakingConnection === void 0)
272
- return;
273
- if (expectedHandshakingConn !== void 0 && this.handshakingConnection === expectedHandshakingConn) {
274
- return;
275
- }
276
- this.handshakingConnection.close();
277
- this.handshakingConnection = void 0;
278
- }
279
- // closed when we want to discard the whole session
280
- // (i.e. shutdown or session disconnect)
281
- close() {
282
- this.closeStaleConnection();
283
- this.cancelGrace();
284
- this.resetBufferedMessages();
285
- clearInterval(this.heartbeat);
286
- }
287
- get connected() {
288
- return this.connection !== void 0;
289
- }
290
- get nextExpectedSeq() {
291
- return this.ack;
292
- }
293
- constructMsg(partialMsg) {
294
- const msg = {
295
- ...partialMsg,
296
- id: unsafeId(),
297
- to: this.to,
298
- from: this.from,
299
- seq: this.seq,
300
- ack: this.ack
301
- };
302
- this.seq++;
303
- this.sendBuffer.push(msg);
304
- return msg;
305
- }
306
- inspectSendBuffer() {
307
- return this.sendBuffer;
308
- }
309
- };
310
-
311
- // transport/events.ts
312
- var ProtocolError = {
313
- RetriesExceeded: "conn_retry_exceeded",
314
- HandshakeFailed: "handshake_failed",
315
- MessageOrderingViolated: "message_ordering_violated"
316
- };
317
- var EventDispatcher = class {
318
- eventListeners = {};
319
- removeAllListeners() {
320
- this.eventListeners = {};
321
- }
322
- numberOfListeners(eventType) {
323
- return this.eventListeners[eventType]?.size ?? 0;
324
- }
325
- addEventListener(eventType, handler) {
326
- if (!this.eventListeners[eventType]) {
327
- this.eventListeners[eventType] = /* @__PURE__ */ new Set();
328
- }
329
- this.eventListeners[eventType]?.add(handler);
330
- }
331
- removeEventListener(eventType, handler) {
332
- const handlers = this.eventListeners[eventType];
333
- if (handlers) {
334
- this.eventListeners[eventType]?.delete(handler);
335
- }
336
- }
337
- dispatchEvent(eventType, event) {
338
- const handlers = this.eventListeners[eventType];
339
- if (handlers) {
340
- const copy = [...handlers];
341
- for (const handler of copy) {
342
- handler(event);
343
- }
344
- }
345
- }
346
- };
347
-
348
- // transport/transport.ts
349
- import { Value } from "@sinclair/typebox/value";
350
-
351
- // transport/rateLimit.ts
352
- var LeakyBucketRateLimit = class {
353
- budgetConsumed;
354
- intervalHandles;
355
- options;
356
- constructor(options) {
357
- this.options = options;
358
- this.budgetConsumed = /* @__PURE__ */ new Map();
359
- this.intervalHandles = /* @__PURE__ */ new Map();
360
- }
361
- getBackoffMs(user) {
362
- if (!this.budgetConsumed.has(user))
363
- return 0;
364
- const exponent = Math.max(0, this.getBudgetConsumed(user) - 1);
365
- const jitter = Math.floor(Math.random() * this.options.maxJitterMs);
366
- const backoffMs = Math.min(
367
- this.options.baseIntervalMs * 2 ** exponent,
368
- this.options.maxBackoffMs
369
- );
370
- return backoffMs + jitter;
371
- }
372
- get totalBudgetRestoreTime() {
373
- return this.options.budgetRestoreIntervalMs * this.options.attemptBudgetCapacity;
374
- }
375
- consumeBudget(user) {
376
- this.stopLeak(user);
377
- this.budgetConsumed.set(user, this.getBudgetConsumed(user) + 1);
378
- }
379
- getBudgetConsumed(user) {
380
- return this.budgetConsumed.get(user) ?? 0;
381
- }
382
- hasBudget(user) {
383
- return this.getBudgetConsumed(user) < this.options.attemptBudgetCapacity;
384
- }
385
- startRestoringBudget(user) {
386
- if (this.intervalHandles.has(user)) {
387
- return;
388
- }
389
- const restoreBudgetForUser = () => {
390
- const currentBudget = this.budgetConsumed.get(user);
391
- if (!currentBudget) {
392
- this.stopLeak(user);
393
- return;
394
- }
395
- const newBudget = currentBudget - 1;
396
- if (newBudget === 0) {
397
- this.budgetConsumed.delete(user);
398
- return;
399
- }
400
- this.budgetConsumed.set(user, newBudget);
401
- };
402
- const intervalHandle = setInterval(
403
- restoreBudgetForUser,
404
- this.options.budgetRestoreIntervalMs
405
- );
406
- this.intervalHandles.set(user, intervalHandle);
407
- }
408
- stopLeak(user) {
409
- if (!this.intervalHandles.has(user)) {
410
- return;
411
- }
412
- clearInterval(this.intervalHandles.get(user));
413
- this.intervalHandles.delete(user);
414
- }
415
- close() {
416
- for (const user of this.intervalHandles.keys()) {
417
- this.stopLeak(user);
418
- }
419
- }
420
- };
421
-
422
- // transport/transport.ts
423
- import { SpanStatusCode as SpanStatusCode2 } from "@opentelemetry/api";
424
- var defaultTransportOptions = {
425
- heartbeatIntervalMs: 1e3,
426
- heartbeatsUntilDead: 2,
427
- sessionDisconnectGraceMs: 5e3,
428
- codec: NaiveJsonCodec
429
- };
430
- var defaultConnectionRetryOptions = {
431
- baseIntervalMs: 250,
432
- maxJitterMs: 200,
433
- maxBackoffMs: 32e3,
434
- attemptBudgetCapacity: 5,
435
- budgetRestoreIntervalMs: 200
436
- };
437
- var defaultClientTransportOptions = {
438
- ...defaultTransportOptions,
439
- ...defaultConnectionRetryOptions
440
- };
441
- var defaultServerTransportOptions = {
442
- ...defaultTransportOptions
443
- };
444
- var Transport = class {
445
- /**
446
- * The status of the transport.
447
- */
448
- status;
449
- /**
450
- * The {@link Codec} used to encode and decode messages.
451
- */
452
- codec;
453
- /**
454
- * The client ID of this transport.
455
- */
456
- clientId;
457
- /**
458
- * The map of {@link Session}s managed by this transport.
459
- */
460
- sessions;
461
- /**
462
- * The map of {@link Connection}s managed by this transport.
463
- */
464
- get connections() {
465
- return new Map(
466
- [...this.sessions].map(([client, session]) => [client, session.connection]).filter((entry) => entry[1] !== void 0)
467
- );
468
- }
469
- /**
470
- * The event dispatcher for handling events of type EventTypes.
471
- */
472
- eventDispatcher;
473
- /**
474
- * The options for this transport.
475
- */
476
- options;
477
- log;
478
- /**
479
- * Creates a new Transport instance.
480
- * This should also set up {@link onConnect}, and {@link onDisconnect} listeners.
481
- * @param codec The codec used to encode and decode messages.
482
- * @param clientId The client ID of this transport.
483
- */
484
- constructor(clientId, providedOptions) {
485
- this.options = { ...defaultTransportOptions, ...providedOptions };
486
- this.eventDispatcher = new EventDispatcher();
487
- this.sessions = /* @__PURE__ */ new Map();
488
- this.codec = this.options.codec;
489
- this.clientId = clientId;
490
- this.status = "open";
491
- }
492
- bindLogger(fn, level) {
493
- if (typeof fn === "function") {
494
- this.log = createLogProxy(new BaseLogger(fn, level));
495
- return;
496
- }
497
- this.log = createLogProxy(fn);
498
- }
499
- /**
500
- * Called when a new connection is established
501
- * and we know the identity of the connected client.
502
- * @param conn The connection object.
503
- */
504
- onConnect(conn, session, isReconnect) {
505
- this.eventDispatcher.dispatchEvent("connectionStatus", {
506
- status: "connect",
507
- conn
508
- });
509
- conn.telemetry = createConnectionTelemetryInfo(conn, session.telemetry);
510
- if (isReconnect) {
511
- session.replaceWithNewConnection(conn);
512
- }
513
- this.log?.info(`connected to ${session.to}`, {
514
- ...conn.loggingMetadata,
515
- ...session.loggingMetadata
516
- });
517
- }
518
- createSession(to, conn, propagationCtx) {
519
- const session = new Session(
520
- conn,
521
- this.clientId,
522
- to,
523
- this.options,
524
- propagationCtx
525
- );
526
- if (this.log) {
527
- session.bindLogger(this.log);
528
- }
529
- this.sessions.set(session.to, session);
530
- this.eventDispatcher.dispatchEvent("sessionStatus", {
531
- status: "connect",
532
- session
533
- });
534
- return session;
535
- }
536
- getOrCreateSession({
537
- to,
538
- conn,
539
- handshakingConn,
540
- sessionId,
541
- propagationCtx
542
- }) {
543
- let session = this.sessions.get(to);
544
- let isReconnect = session !== void 0;
545
- if (session?.advertisedSessionId !== void 0 && sessionId !== void 0 && session.advertisedSessionId !== sessionId) {
546
- this.log?.info(
547
- `session for ${to} already exists but has a different session id (expected: ${session.advertisedSessionId}, got: ${sessionId}), creating a new one`,
548
- session.loggingMetadata
549
- );
550
- this.deleteSession({
551
- session,
552
- closeHandshakingConnection: handshakingConn !== void 0,
553
- handshakingConn
554
- });
555
- isReconnect = false;
556
- session = void 0;
557
- }
558
- if (!session) {
559
- session = this.createSession(to, conn, propagationCtx);
560
- this.log?.info(
561
- `no session for ${to}, created a new one`,
562
- session.loggingMetadata
563
- );
564
- }
565
- if (sessionId !== void 0) {
566
- session.advertisedSessionId = sessionId;
567
- }
568
- if (handshakingConn !== void 0) {
569
- session.replaceWithNewHandshakingConnection(handshakingConn);
570
- }
571
- return { session, isReconnect };
572
- }
573
- deleteSession({
574
- session,
575
- closeHandshakingConnection,
576
- handshakingConn
577
- }) {
578
- if (closeHandshakingConnection) {
579
- session.closeHandshakingConnection(handshakingConn);
580
- }
581
- session.close();
582
- session.telemetry.span.end();
583
- this.sessions.delete(session.to);
584
- this.log?.info(
585
- `session ${session.id} disconnect from ${session.to}`,
586
- session.loggingMetadata
587
- );
588
- this.eventDispatcher.dispatchEvent("sessionStatus", {
589
- status: "disconnect",
590
- session
591
- });
592
- }
593
- /**
594
- * The downstream implementation needs to call this when a connection is closed.
595
- * @param conn The connection object.
596
- * @param connectedTo The peer we are connected to.
597
- */
598
- onDisconnect(conn, session) {
599
- conn.telemetry?.span.end();
600
- this.eventDispatcher.dispatchEvent("connectionStatus", {
601
- status: "disconnect",
602
- conn
603
- });
604
- session.connection = void 0;
605
- session.beginGrace(() => {
606
- session.telemetry.span.addEvent("session grace period expired");
607
- this.deleteSession({
608
- session,
609
- closeHandshakingConnection: true,
610
- handshakingConn: conn
611
- });
612
- });
613
- }
614
- /**
615
- * Parses a message from a Uint8Array into a {@link OpaqueTransportMessage}.
616
- * @param msg The message to parse.
617
- * @returns The parsed message, or null if the message is malformed or invalid.
618
- */
619
- parseMsg(msg, conn) {
620
- const parsedMsg = this.codec.fromBuffer(msg);
621
- if (parsedMsg === null) {
622
- const decodedBuffer = new TextDecoder().decode(Buffer.from(msg));
623
- this.log?.error(
624
- `received malformed msg, killing conn: ${decodedBuffer}`,
625
- {
626
- clientId: this.clientId,
627
- ...conn.loggingMetadata
628
- }
629
- );
630
- return null;
631
- }
632
- if (!Value.Check(OpaqueTransportMessageSchema, parsedMsg)) {
633
- this.log?.error(`received invalid msg: ${JSON.stringify(parsedMsg)}`, {
634
- clientId: this.clientId,
635
- ...conn.loggingMetadata,
636
- validationErrors: [
637
- ...Value.Errors(OpaqueTransportMessageSchema, parsedMsg)
638
- ]
639
- });
640
- return null;
641
- }
642
- return parsedMsg;
643
- }
644
- /**
645
- * Called when a message is received by this transport.
646
- * You generally shouldn't need to override this in downstream transport implementations.
647
- * @param msg The received message.
648
- */
649
- handleMsg(msg, conn) {
650
- if (this.getStatus() !== "open")
651
- return;
652
- const session = this.sessions.get(msg.from);
653
- if (!session) {
654
- this.log?.error(`received message for unknown session from ${msg.from}`, {
655
- clientId: this.clientId,
656
- transportMessage: msg,
657
- ...conn.loggingMetadata,
658
- tags: ["invariant-violation"]
659
- });
660
- return;
661
- }
662
- session.cancelGrace();
663
- this.log?.debug(`received msg`, {
664
- clientId: this.clientId,
665
- transportMessage: msg,
666
- ...conn.loggingMetadata
667
- });
668
- if (msg.seq !== session.nextExpectedSeq) {
669
- if (msg.seq < session.nextExpectedSeq) {
670
- this.log?.debug(
671
- `received duplicate msg (got seq: ${msg.seq}, wanted seq: ${session.nextExpectedSeq}), discarding`,
672
- {
673
- clientId: this.clientId,
674
- transportMessage: msg,
675
- ...conn.loggingMetadata
676
- }
677
- );
678
- } else {
679
- const errMsg = `received out-of-order msg (got seq: ${msg.seq}, wanted seq: ${session.nextExpectedSeq})`;
680
- this.log?.error(`${errMsg}, marking connection as dead`, {
681
- clientId: this.clientId,
682
- transportMessage: msg,
683
- ...conn.loggingMetadata,
684
- tags: ["invariant-violation"]
685
- });
686
- this.protocolError(ProtocolError.MessageOrderingViolated, errMsg);
687
- session.telemetry.span.setStatus({
688
- code: SpanStatusCode2.ERROR,
689
- message: "message order violated"
690
- });
691
- this.deleteSession({ session, closeHandshakingConnection: true });
692
- }
693
- return;
694
- }
695
- session.updateBookkeeping(msg.ack, msg.seq);
696
- if (!isAck(msg.controlFlags)) {
697
- this.eventDispatcher.dispatchEvent("message", msg);
698
- } else {
699
- this.log?.debug(`discarding msg (ack bit set)`, {
700
- clientId: this.clientId,
701
- transportMessage: msg,
702
- ...conn.loggingMetadata
703
- });
704
- }
705
- }
706
- /**
707
- * Adds a listener to this transport.
708
- * @param the type of event to listen for
709
- * @param handler The message handler to add.
710
- */
711
- addEventListener(type, handler) {
712
- this.eventDispatcher.addEventListener(type, handler);
713
- }
714
- /**
715
- * Removes a listener from this transport.
716
- * @param the type of event to un-listen on
717
- * @param handler The message handler to remove.
718
- */
719
- removeEventListener(type, handler) {
720
- this.eventDispatcher.removeEventListener(type, handler);
721
- }
722
- /**
723
- * Sends a message over this transport, delegating to the appropriate connection to actually
724
- * send the message.
725
- * @param msg The message to send.
726
- * @returns The ID of the sent message or undefined if it wasn't sent
727
- */
728
- send(to, msg) {
729
- if (this.getStatus() === "closed") {
730
- const err = "transport is closed, cant send";
731
- this.log?.error(err, {
732
- clientId: this.clientId,
733
- transportMessage: msg,
734
- tags: ["invariant-violation"]
735
- });
736
- throw new Error(err);
737
- }
738
- return this.getOrCreateSession({ to }).session.send(msg);
739
- }
740
- // control helpers
741
- sendCloseStream(to, streamId) {
742
- return this.send(to, {
743
- streamId,
744
- controlFlags: 4 /* StreamClosedBit */,
745
- payload: {
746
- type: "CLOSE"
747
- }
748
- });
749
- }
750
- protocolError(type, message) {
751
- this.eventDispatcher.dispatchEvent("protocolError", { type, message });
752
- }
753
- /**
754
- * Default close implementation for transports. You should override this in the downstream
755
- * implementation if you need to do any additional cleanup and call super.close() at the end.
756
- * Closes the transport. Any messages sent while the transport is closed will be silently discarded.
757
- */
758
- close() {
759
- this.status = "closed";
760
- for (const session of this.sessions.values()) {
761
- this.deleteSession({ session, closeHandshakingConnection: true });
762
- }
763
- this.eventDispatcher.dispatchEvent("transportStatus", {
764
- status: this.status
765
- });
766
- this.eventDispatcher.removeAllListeners();
767
- this.log?.info(`manually closed transport`, { clientId: this.clientId });
768
- }
769
- getStatus() {
770
- return this.status;
771
- }
772
- };
773
- var ClientTransport = class extends Transport {
774
- /**
775
- * The options for this transport.
776
- */
777
- options;
778
- /**
779
- * The map of reconnect promises for each client ID.
780
- */
781
- inflightConnectionPromises;
782
- retryBudget;
783
- /**
784
- * A flag indicating whether the transport should automatically reconnect
785
- * when a connection is dropped.
786
- * Realistically, this should always be true for clients unless you are writing
787
- * tests or a special case where you don't want to reconnect.
788
- */
789
- reconnectOnConnectionDrop = true;
790
- /**
791
- * Optional handshake options for this client.
792
- */
793
- handshakeExtensions;
794
- constructor(clientId, providedOptions) {
795
- super(clientId, providedOptions);
796
- this.options = {
797
- ...defaultClientTransportOptions,
798
- ...providedOptions
799
- };
800
- this.inflightConnectionPromises = /* @__PURE__ */ new Map();
801
- this.retryBudget = new LeakyBucketRateLimit(this.options);
802
- }
803
- extendHandshake(options) {
804
- this.handshakeExtensions = options;
805
- }
806
- handleConnection(conn, to) {
807
- if (this.getStatus() !== "open")
808
- return;
809
- let session = void 0;
810
- const handshakeTimeout = setTimeout(() => {
811
- if (session)
812
- return;
813
- this.log?.warn(
814
- `connection to ${to} timed out waiting for handshake, closing`,
815
- { ...conn.loggingMetadata, clientId: this.clientId, connectedTo: to }
816
- );
817
- conn.close();
818
- }, this.options.sessionDisconnectGraceMs);
819
- const handshakeHandler = (data) => {
820
- const maybeSession = this.receiveHandshakeResponseMessage(data, conn);
821
- clearTimeout(handshakeTimeout);
822
- if (!maybeSession) {
823
- conn.close();
824
- return;
825
- } else {
826
- session = maybeSession;
827
- }
828
- conn.removeDataListener(handshakeHandler);
829
- conn.addDataListener((data2) => {
830
- const parsed = this.parseMsg(data2, conn);
831
- if (!parsed) {
832
- conn.telemetry?.span.setStatus({
833
- code: SpanStatusCode2.ERROR,
834
- message: "message parse failure"
835
- });
836
- conn.close();
837
- return;
838
- }
839
- this.handleMsg(parsed, conn);
840
- });
841
- };
842
- conn.addDataListener(handshakeHandler);
843
- conn.addCloseListener(() => {
844
- if (session) {
845
- this.onDisconnect(conn, session);
846
- }
847
- const willReconnect = this.reconnectOnConnectionDrop && this.getStatus() === "open";
848
- this.log?.info(
849
- `connection to ${to} disconnected` + (willReconnect ? ", reconnecting" : ""),
850
- {
851
- ...conn.loggingMetadata,
852
- ...session?.loggingMetadata,
853
- clientId: this.clientId,
854
- connectedTo: to
855
- }
856
- );
857
- this.inflightConnectionPromises.delete(to);
858
- if (this.reconnectOnConnectionDrop) {
859
- void this.connect(to);
860
- }
861
- });
862
- conn.addErrorListener((err) => {
863
- conn.telemetry?.span.setStatus({
864
- code: SpanStatusCode2.ERROR,
865
- message: "connection error"
866
- });
867
- this.log?.warn(
868
- `error in connection to ${to}: ${coerceErrorString(err)}`,
869
- {
870
- ...conn.loggingMetadata,
871
- ...session?.loggingMetadata,
872
- clientId: this.clientId,
873
- connectedTo: to
874
- }
875
- );
876
- });
877
- }
878
- receiveHandshakeResponseMessage(data, conn) {
879
- const parsed = this.parseMsg(data, conn);
880
- if (!parsed) {
881
- conn.telemetry?.span.setStatus({
882
- code: SpanStatusCode2.ERROR,
883
- message: "non-transport message"
884
- });
885
- this.protocolError(
886
- ProtocolError.HandshakeFailed,
887
- "received non-transport message"
888
- );
889
- return false;
890
- }
891
- if (!Value.Check(ControlMessageHandshakeResponseSchema, parsed.payload)) {
892
- conn.telemetry?.span.setStatus({
893
- code: SpanStatusCode2.ERROR,
894
- message: "invalid handshake response"
895
- });
896
- this.log?.warn(`received invalid handshake resp`, {
897
- ...conn.loggingMetadata,
898
- clientId: this.clientId,
899
- connectedTo: parsed.from,
900
- transportMessage: parsed,
901
- validationErrors: [
902
- ...Value.Errors(
903
- ControlMessageHandshakeResponseSchema,
904
- parsed.payload
905
- )
906
- ]
907
- });
908
- this.protocolError(
909
- ProtocolError.HandshakeFailed,
910
- "invalid handshake resp"
911
- );
912
- return false;
913
- }
914
- if (!parsed.payload.status.ok) {
915
- conn.telemetry?.span.setStatus({
916
- code: SpanStatusCode2.ERROR,
917
- message: "handshake rejected"
918
- });
919
- this.log?.warn(`received handshake rejection`, {
920
- ...conn.loggingMetadata,
921
- clientId: this.clientId,
922
- connectedTo: parsed.from,
923
- transportMessage: parsed
924
- });
925
- this.protocolError(
926
- ProtocolError.HandshakeFailed,
927
- parsed.payload.status.reason
928
- );
929
- return false;
930
- }
931
- this.log?.debug(`handshake from ${parsed.from} ok`, {
932
- ...conn.loggingMetadata,
933
- clientId: this.clientId,
934
- connectedTo: parsed.from,
935
- transportMessage: parsed
936
- });
937
- const { session, isReconnect } = this.getOrCreateSession({
938
- to: parsed.from,
939
- conn,
940
- sessionId: parsed.payload.status.sessionId
941
- });
942
- this.onConnect(conn, session, isReconnect);
943
- this.retryBudget.startRestoringBudget(session.to);
944
- return session;
945
- }
946
- /**
947
- * Manually attempts to connect to a client.
948
- * @param to The client ID of the node to connect to.
949
- */
950
- async connect(to) {
951
- if (this.connections.has(to)) {
952
- this.log?.info(`already connected to ${to}, skipping connect attempt`, {
953
- clientId: this.clientId,
954
- connectedTo: to
955
- });
956
- return;
957
- }
958
- const canProceedWithConnection = () => this.getStatus() === "open";
959
- if (!canProceedWithConnection()) {
960
- this.log?.info(
961
- `transport state is no longer open, cancelling attempt to connect to ${to}`,
962
- { clientId: this.clientId, connectedTo: to }
963
- );
964
- return;
965
- }
966
- let reconnectPromise = this.inflightConnectionPromises.get(to);
967
- if (!reconnectPromise) {
968
- if (!this.retryBudget.hasBudget(to)) {
969
- const budgetConsumed = this.retryBudget.getBudgetConsumed(to);
970
- const errMsg = `tried to connect to ${to} but retry budget exceeded (more than ${budgetConsumed} attempts in the last ${this.retryBudget.totalBudgetRestoreTime}ms)`;
971
- this.log?.error(errMsg, { clientId: this.clientId, connectedTo: to });
972
- this.protocolError(ProtocolError.RetriesExceeded, errMsg);
973
- return;
974
- }
975
- let sleep = Promise.resolve();
976
- const backoffMs = this.retryBudget.getBackoffMs(to);
977
- if (backoffMs > 0) {
978
- sleep = new Promise((resolve) => setTimeout(resolve, backoffMs));
979
- }
980
- this.log?.info(
981
- `attempting connection to ${to} (${backoffMs}ms backoff)`,
982
- {
983
- clientId: this.clientId,
984
- connectedTo: to
985
- }
986
- );
987
- this.retryBudget.consumeBudget(to);
988
- reconnectPromise = tracing_default.startActiveSpan("connect", async (span) => {
989
- try {
990
- span.addEvent("backoff", { backoffMs });
991
- await sleep;
992
- if (!canProceedWithConnection()) {
993
- throw new Error("transport state is no longer open");
994
- }
995
- span.addEvent("connecting");
996
- const conn = await this.createNewOutgoingConnection(to);
997
- if (!canProceedWithConnection()) {
998
- this.log?.info(
999
- `transport state is no longer open, closing pre-handshake connection to ${to}`,
1000
- {
1001
- ...conn.loggingMetadata,
1002
- clientId: this.clientId,
1003
- connectedTo: to
1004
- }
1005
- );
1006
- conn.close();
1007
- throw new Error("transport state is no longer open");
1008
- }
1009
- span.addEvent("sending handshake");
1010
- const ok = await this.sendHandshake(to, conn);
1011
- if (!ok) {
1012
- conn.close();
1013
- throw new Error("failed to send handshake");
1014
- }
1015
- return conn;
1016
- } catch (err) {
1017
- const errStr = coerceErrorString(err);
1018
- span.recordException(errStr);
1019
- span.setStatus({ code: SpanStatusCode2.ERROR });
1020
- throw err;
1021
- } finally {
1022
- span.end();
1023
- }
1024
- });
1025
- this.inflightConnectionPromises.set(to, reconnectPromise);
1026
- } else {
1027
- this.log?.info(
1028
- `attempting connection to ${to} (reusing previous attempt)`,
1029
- {
1030
- clientId: this.clientId,
1031
- connectedTo: to
1032
- }
1033
- );
1034
- }
1035
- try {
1036
- await reconnectPromise;
1037
- } catch (error) {
1038
- this.inflightConnectionPromises.delete(to);
1039
- const errStr = coerceErrorString(error);
1040
- if (!this.reconnectOnConnectionDrop || !canProceedWithConnection()) {
1041
- this.log?.warn(`connection to ${to} failed (${errStr})`, {
1042
- clientId: this.clientId,
1043
- connectedTo: to
1044
- });
1045
- } else {
1046
- this.log?.warn(`connection to ${to} failed (${errStr}), retrying`, {
1047
- clientId: this.clientId,
1048
- connectedTo: to
1049
- });
1050
- await this.connect(to);
1051
- }
1052
- }
1053
- }
1054
- deleteSession({
1055
- session,
1056
- closeHandshakingConnection,
1057
- handshakingConn
1058
- }) {
1059
- this.inflightConnectionPromises.delete(session.to);
1060
- super.deleteSession({
1061
- session,
1062
- closeHandshakingConnection,
1063
- handshakingConn
1064
- });
1065
- }
1066
- async sendHandshake(to, conn) {
1067
- let metadata = void 0;
1068
- if (this.handshakeExtensions) {
1069
- metadata = await this.handshakeExtensions.construct();
1070
- if (!Value.Check(this.handshakeExtensions.schema, metadata)) {
1071
- this.log?.error(`constructed handshake metadata did not match schema`, {
1072
- ...conn.loggingMetadata,
1073
- clientId: this.clientId,
1074
- connectedTo: to,
1075
- validationErrors: [
1076
- ...Value.Errors(this.handshakeExtensions.schema, metadata)
1077
- ],
1078
- tags: ["invariant-violation"]
1079
- });
1080
- this.protocolError(
1081
- ProtocolError.HandshakeFailed,
1082
- "handshake metadata did not match schema"
1083
- );
1084
- conn.telemetry?.span.setStatus({
1085
- code: SpanStatusCode2.ERROR,
1086
- message: "handshake meta mismatch"
1087
- });
1088
- return false;
1089
- }
1090
- }
1091
- const { session } = this.getOrCreateSession({ to, handshakingConn: conn });
1092
- const requestMsg = handshakeRequestMessage(
1093
- this.clientId,
1094
- to,
1095
- session.id,
1096
- metadata,
1097
- getPropagationContext(session.telemetry.ctx)
1098
- );
1099
- this.log?.debug(`sending handshake request to ${to}`, {
1100
- ...conn.loggingMetadata,
1101
- clientId: this.clientId,
1102
- connectedTo: to,
1103
- transportMessage: requestMsg
1104
- });
1105
- conn.send(this.codec.toBuffer(requestMsg));
1106
- return true;
1107
- }
1108
- close() {
1109
- this.retryBudget.close();
1110
- super.close();
1111
- }
1112
- };
1113
- var ServerTransport = class extends Transport {
1114
- /**
1115
- * The options for this transport.
1116
- */
1117
- options;
1118
- /**
1119
- * Optional handshake options for the server.
1120
- */
1121
- handshakeExtensions;
1122
- /**
1123
- * A map of session handshake data for each session.
1124
- */
1125
- sessionHandshakeMetadata;
1126
- constructor(clientId, providedOptions) {
1127
- super(clientId, providedOptions);
1128
- this.options = {
1129
- ...defaultServerTransportOptions,
1130
- ...providedOptions
1131
- };
1132
- this.sessionHandshakeMetadata = /* @__PURE__ */ new WeakMap();
1133
- this.log?.info(`initiated server transport`, {
1134
- clientId: this.clientId,
1135
- protocolVersion: PROTOCOL_VERSION
1136
- });
1137
- }
1138
- extendHandshake(options) {
1139
- this.handshakeExtensions = options;
1140
- }
1141
- handleConnection(conn) {
1142
- if (this.getStatus() !== "open")
1143
- return;
1144
- this.log?.info(`new incoming connection`, {
1145
- ...conn.loggingMetadata,
1146
- clientId: this.clientId
1147
- });
1148
- let session = void 0;
1149
- const client = () => session?.to ?? "unknown";
1150
- const handshakeTimeout = setTimeout(() => {
1151
- if (!session) {
1152
- this.log?.warn(
1153
- `connection to ${client()} timed out waiting for handshake, closing`,
1154
- {
1155
- ...conn.loggingMetadata,
1156
- clientId: this.clientId,
1157
- connectedTo: client()
1158
- }
1159
- );
1160
- conn.telemetry?.span.setStatus({
1161
- code: SpanStatusCode2.ERROR,
1162
- message: "handshake timeout"
1163
- });
1164
- conn.close();
1165
- }
1166
- }, this.options.sessionDisconnectGraceMs);
1167
- const buffer = [];
1168
- let receivedHandshakeMessage = false;
1169
- const handshakeHandler = (data) => {
1170
- if (receivedHandshakeMessage) {
1171
- buffer.push(data);
1172
- return;
1173
- }
1174
- receivedHandshakeMessage = true;
1175
- clearTimeout(handshakeTimeout);
1176
- void this.receiveHandshakeRequestMessage(data, conn).then(
1177
- (maybeSession) => {
1178
- if (!maybeSession) {
1179
- conn.close();
1180
- return;
1181
- }
1182
- session = maybeSession;
1183
- const dataHandler = (data2) => {
1184
- const parsed = this.parseMsg(data2, conn);
1185
- if (!parsed) {
1186
- conn.close();
1187
- return;
1188
- }
1189
- this.handleMsg(parsed, conn);
1190
- };
1191
- for (const data2 of buffer) {
1192
- dataHandler(data2);
1193
- }
1194
- conn.removeDataListener(handshakeHandler);
1195
- conn.addDataListener(dataHandler);
1196
- buffer.length = 0;
1197
- }
1198
- );
1199
- };
1200
- conn.addDataListener(handshakeHandler);
1201
- conn.addCloseListener(() => {
1202
- if (!session)
1203
- return;
1204
- this.log?.info(`connection to ${client()} disconnected`, {
1205
- ...conn.loggingMetadata,
1206
- clientId: this.clientId
1207
- });
1208
- this.onDisconnect(conn, session);
1209
- });
1210
- conn.addErrorListener((err) => {
1211
- conn.telemetry?.span.setStatus({
1212
- code: SpanStatusCode2.ERROR,
1213
- message: "connection error"
1214
- });
1215
- if (!session)
1216
- return;
1217
- this.log?.warn(
1218
- `connection to ${client()} got an error: ${coerceErrorString(err)}`,
1219
- { ...conn.loggingMetadata, clientId: this.clientId }
1220
- );
1221
- });
1222
- }
1223
- async validateHandshakeMetadata(conn, session, rawMetadata, from) {
1224
- let parsedMetadata = {};
1225
- if (this.handshakeExtensions) {
1226
- if (!Value.Check(this.handshakeExtensions.schema, rawMetadata)) {
1227
- conn.telemetry?.span.setStatus({
1228
- code: SpanStatusCode2.ERROR,
1229
- message: "malformed handshake meta"
1230
- });
1231
- const reason = "received malformed handshake metadata";
1232
- const responseMsg = handshakeResponseMessage(this.clientId, from, {
1233
- ok: false,
1234
- reason
1235
- });
1236
- conn.send(this.codec.toBuffer(responseMsg));
1237
- this.log?.warn(`received malformed handshake metadata from ${from}`, {
1238
- ...conn.loggingMetadata,
1239
- clientId: this.clientId,
1240
- validationErrors: [
1241
- ...Value.Errors(this.handshakeExtensions.schema, rawMetadata)
1242
- ]
1243
- });
1244
- this.protocolError(ProtocolError.HandshakeFailed, reason);
1245
- return false;
1246
- }
1247
- const previousParsedMetadata = session ? this.sessionHandshakeMetadata.get(session) : void 0;
1248
- parsedMetadata = await this.handshakeExtensions.validate(
1249
- rawMetadata,
1250
- previousParsedMetadata
1251
- );
1252
- if (parsedMetadata === false) {
1253
- const reason = "rejected by handshake handler";
1254
- conn.telemetry?.span.setStatus({
1255
- code: SpanStatusCode2.ERROR,
1256
- message: reason
1257
- });
1258
- const responseMsg = handshakeResponseMessage(this.clientId, from, {
1259
- ok: false,
1260
- reason
1261
- });
1262
- conn.send(this.codec.toBuffer(responseMsg));
1263
- this.log?.warn(`rejected handshake from ${from}`, {
1264
- ...conn.loggingMetadata,
1265
- clientId: this.clientId
1266
- });
1267
- this.protocolError(ProtocolError.HandshakeFailed, reason);
1268
- return false;
1269
- }
1270
- }
1271
- return parsedMetadata;
1272
- }
1273
- async receiveHandshakeRequestMessage(data, conn) {
1274
- const parsed = this.parseMsg(data, conn);
1275
- if (!parsed) {
1276
- conn.telemetry?.span.setStatus({
1277
- code: SpanStatusCode2.ERROR,
1278
- message: "non-transport message"
1279
- });
1280
- this.protocolError(
1281
- ProtocolError.HandshakeFailed,
1282
- "received non-transport message"
1283
- );
1284
- return false;
1285
- }
1286
- if (!Value.Check(ControlMessageHandshakeRequestSchema, parsed.payload)) {
1287
- conn.telemetry?.span.setStatus({
1288
- code: SpanStatusCode2.ERROR,
1289
- message: "invalid handshake request"
1290
- });
1291
- const reason = "received invalid handshake msg";
1292
- const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
1293
- ok: false,
1294
- reason
1295
- });
1296
- conn.send(this.codec.toBuffer(responseMsg2));
1297
- this.log?.warn(reason, {
1298
- ...conn.loggingMetadata,
1299
- clientId: this.clientId,
1300
- // safe to this.log metadata here as we remove the payload
1301
- // before passing it to user-land
1302
- transportMessage: parsed,
1303
- validationErrors: [
1304
- ...Value.Errors(ControlMessageHandshakeRequestSchema, parsed.payload)
1305
- ]
1306
- });
1307
- this.protocolError(
1308
- ProtocolError.HandshakeFailed,
1309
- "invalid handshake request"
1310
- );
1311
- return false;
1312
- }
1313
- const gotVersion = parsed.payload.protocolVersion;
1314
- if (gotVersion !== PROTOCOL_VERSION) {
1315
- conn.telemetry?.span.setStatus({
1316
- code: SpanStatusCode2.ERROR,
1317
- message: "incorrect protocol version"
1318
- });
1319
- const reason = `incorrect version (got: ${gotVersion} wanted ${PROTOCOL_VERSION})`;
1320
- const responseMsg2 = handshakeResponseMessage(this.clientId, parsed.from, {
1321
- ok: false,
1322
- reason
1323
- });
1324
- conn.send(this.codec.toBuffer(responseMsg2));
1325
- this.log?.warn(
1326
- `received handshake msg with incompatible protocol version (got: ${gotVersion}, expected: ${PROTOCOL_VERSION})`,
1327
- { ...conn.loggingMetadata, clientId: this.clientId }
1328
- );
1329
- this.protocolError(ProtocolError.HandshakeFailed, reason);
1330
- return false;
1331
- }
1332
- const oldSession = this.sessions.get(parsed.from);
1333
- const parsedMetadata = await this.validateHandshakeMetadata(
1334
- conn,
1335
- oldSession,
1336
- parsed.payload.metadata,
1337
- parsed.from
1338
- );
1339
- if (parsedMetadata === false) {
1340
- return false;
1341
- }
1342
- const { session, isReconnect } = this.getOrCreateSession({
1343
- to: parsed.from,
1344
- conn,
1345
- sessionId: parsed.payload.sessionId,
1346
- propagationCtx: parsed.tracing
1347
- });
1348
- this.sessionHandshakeMetadata.set(session, parsedMetadata);
1349
- this.log?.debug(
1350
- `handshake from ${parsed.from} ok, responding with handshake success`,
1351
- conn.loggingMetadata
1352
- );
1353
- const responseMsg = handshakeResponseMessage(this.clientId, parsed.from, {
1354
- ok: true,
1355
- sessionId: session.id
1356
- });
1357
- conn.send(this.codec.toBuffer(responseMsg));
1358
- this.onConnect(conn, session, isReconnect);
1359
- return session;
1360
- }
1361
- };
1362
-
1363
- export {
1364
- Connection,
1365
- Session,
1366
- ProtocolError,
1367
- defaultTransportOptions,
1368
- Transport,
1369
- ClientTransport,
1370
- ServerTransport
1371
- };
1372
- //# sourceMappingURL=chunk-EOJMKMDO.js.map