@m4ike1/ion-server 0.1.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.
Files changed (67) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/README.md +99 -0
  3. package/dist/connection.d.ts +32 -0
  4. package/dist/connection.d.ts.map +1 -0
  5. package/dist/connection.js +4 -0
  6. package/dist/connection.js.map +1 -0
  7. package/dist/errors.d.ts +25 -0
  8. package/dist/errors.d.ts.map +1 -0
  9. package/dist/errors.js +41 -0
  10. package/dist/errors.js.map +1 -0
  11. package/dist/index.d.ts +5 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +5 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/listener.d.ts +8 -0
  16. package/dist/listener.d.ts.map +1 -0
  17. package/dist/listener.js +2 -0
  18. package/dist/listener.js.map +1 -0
  19. package/dist/server.d.ts +46 -0
  20. package/dist/server.d.ts.map +1 -0
  21. package/dist/server.js +547 -0
  22. package/dist/server.js.map +1 -0
  23. package/dist/session-router.d.ts +40 -0
  24. package/dist/session-router.d.ts.map +1 -0
  25. package/dist/session-router.js +264 -0
  26. package/dist/session-router.js.map +1 -0
  27. package/dist/testing/client.d.ts +35 -0
  28. package/dist/testing/client.d.ts.map +1 -0
  29. package/dist/testing/client.js +138 -0
  30. package/dist/testing/client.js.map +1 -0
  31. package/dist/testing/host.d.ts +57 -0
  32. package/dist/testing/host.d.ts.map +1 -0
  33. package/dist/testing/host.js +189 -0
  34. package/dist/testing/host.js.map +1 -0
  35. package/dist/testing/index.d.ts +6 -0
  36. package/dist/testing/index.d.ts.map +1 -0
  37. package/dist/testing/index.js +4 -0
  38. package/dist/testing/index.js.map +1 -0
  39. package/dist/testing/server.d.ts +13 -0
  40. package/dist/testing/server.d.ts.map +1 -0
  41. package/dist/testing/server.js +17 -0
  42. package/dist/testing/server.js.map +1 -0
  43. package/dist/transports/unix/address.d.ts +3 -0
  44. package/dist/transports/unix/address.d.ts.map +1 -0
  45. package/dist/transports/unix/address.js +9 -0
  46. package/dist/transports/unix/address.js.map +1 -0
  47. package/dist/transports/unix/index.d.ts +5 -0
  48. package/dist/transports/unix/index.d.ts.map +1 -0
  49. package/dist/transports/unix/index.js +4 -0
  50. package/dist/transports/unix/index.js.map +1 -0
  51. package/dist/transports/unix/listener.d.ts +24 -0
  52. package/dist/transports/unix/listener.d.ts.map +1 -0
  53. package/dist/transports/unix/listener.js +421 -0
  54. package/dist/transports/unix/listener.js.map +1 -0
  55. package/dist/transports/unix/preset.d.ts +7 -0
  56. package/dist/transports/unix/preset.d.ts.map +1 -0
  57. package/dist/transports/unix/preset.js +22 -0
  58. package/dist/transports/unix/preset.js.map +1 -0
  59. package/dist/transports/unix/types.d.ts +15 -0
  60. package/dist/transports/unix/types.d.ts.map +1 -0
  61. package/dist/transports/unix/types.js +2 -0
  62. package/dist/transports/unix/types.js.map +1 -0
  63. package/dist/types.d.ts +49 -0
  64. package/dist/types.d.ts.map +1 -0
  65. package/dist/types.js +2 -0
  66. package/dist/types.js.map +1 -0
  67. package/package.json +58 -0
package/dist/server.js ADDED
@@ -0,0 +1,547 @@
1
+ import { createServiceStateEncoder, decodeServiceControlCall, parseServiceCall, parseServiceSubscriptionSnapshot, RemoteServiceError, } from "@m4ike1/chord";
2
+ import { BACKGROUND_CONTEXT, TODO_CONTEXT, withAbortSignal } from "@m4ike1/ion-agent-core";
3
+ import { ClientMessageDecoder, DEFAULT_MAX_FRAME_LENGTH, encodeServerMessage, isServerId, isSupportedProtocolVersion, PROTOCOL_VERSION, ProtocolValidationError, } from "@m4ike1/ion-protocol";
4
+ import { isTerminalConnection, } from "./connection.js";
5
+ import { INTERNAL_SERVER_ERROR_MESSAGE, ServerError, WrongServerError } from "./errors.js";
6
+ import { SessionRouter } from "./session-router.js";
7
+ const DEFAULT_HANDSHAKE_TIMEOUT_MS = 5_000;
8
+ const MAX_UINT32 = 0xffff_ffff;
9
+ const MAX_TIMER_DELAY_MS = 2_147_483_647;
10
+ export class Server {
11
+ serverId;
12
+ /** Resolves after shutdown, or rejects when listener or routed-Session cleanup fails. */
13
+ closed;
14
+ host;
15
+ listeners;
16
+ maxFrameLength;
17
+ handshakeTimeoutMs;
18
+ onConnectionCountChanged;
19
+ onError;
20
+ connections = new Set();
21
+ sessions;
22
+ closing = false;
23
+ closePromise;
24
+ closedSettled = false;
25
+ rejectClosed;
26
+ resolveClosed;
27
+ startPromise;
28
+ started = false;
29
+ constructor(host, options) {
30
+ const resolved = resolveOptions(options);
31
+ this.host = host;
32
+ this.listeners = options.listeners;
33
+ this.serverId = options.serverId;
34
+ this.maxFrameLength = resolved.maxFrameLength;
35
+ this.handshakeTimeoutMs = resolved.handshakeTimeoutMs;
36
+ this.onConnectionCountChanged = options.onConnectionCountChanged;
37
+ this.onError = options.onError;
38
+ this.sessions = new SessionRouter({
39
+ host,
40
+ serverId: this.serverId,
41
+ isClosing: () => this.closing,
42
+ publishAttachment: async (client, attachment) => {
43
+ await this.sendMessage(client, {
44
+ type: "attachment",
45
+ attachment: attachment ?? null,
46
+ });
47
+ },
48
+ reportError: (error) => this.reportError(error),
49
+ });
50
+ this.closed = new Promise((resolve, reject) => {
51
+ this.resolveClosed = resolve;
52
+ this.rejectClosed = reject;
53
+ });
54
+ void this.closed.catch(() => { });
55
+ }
56
+ start() {
57
+ if (this.started)
58
+ return Promise.reject(new Error("Server is already started"));
59
+ if (this.startPromise)
60
+ return Promise.reject(new Error("Server is already starting"));
61
+ if (this.closing)
62
+ return Promise.reject(new Error("Server is closing or closed"));
63
+ this.startPromise = this.startInternal();
64
+ return this.startPromise;
65
+ }
66
+ async startInternal() {
67
+ const started = [];
68
+ try {
69
+ for (const listener of this.listeners) {
70
+ await listener.start((connection) => this.accept(connection));
71
+ started.push(listener);
72
+ }
73
+ this.started = true;
74
+ return this;
75
+ }
76
+ catch (error) {
77
+ this.closing = true;
78
+ const cleanupErrors = [];
79
+ const listenerResults = await Promise.allSettled(started.map((listener) => listener.close()));
80
+ for (const result of listenerResults) {
81
+ if (result.status === "rejected")
82
+ cleanupErrors.push(result.reason);
83
+ }
84
+ try {
85
+ await this.closeServerState();
86
+ }
87
+ catch (cleanupError) {
88
+ cleanupErrors.push(cleanupError);
89
+ }
90
+ if (cleanupErrors.length > 0) {
91
+ const failure = new AggregateError([error, ...cleanupErrors], "Server startup and cleanup failed");
92
+ this.settleClosed(failure);
93
+ throw failure;
94
+ }
95
+ this.settleClosed();
96
+ throw error;
97
+ }
98
+ finally {
99
+ this.startPromise = undefined;
100
+ }
101
+ }
102
+ accept(connection) {
103
+ if (this.closing) {
104
+ void this.closeConnection(connection);
105
+ return {
106
+ onData: () => { },
107
+ onClose: () => { },
108
+ onError: (error) => this.reportError(error),
109
+ };
110
+ }
111
+ let state;
112
+ const handshakeTimeout = setTimeout(() => {
113
+ void this.failProtocol(state, {
114
+ code: "invalid_request",
115
+ message: "Handshake timeout",
116
+ });
117
+ }, this.handshakeTimeoutMs);
118
+ handshakeTimeout.unref();
119
+ state = {
120
+ connection,
121
+ decoder: new ClientMessageDecoder({ maxFrameLength: this.maxFrameLength }),
122
+ serviceStateEncoders: new Map(),
123
+ stage: "awaitingHello",
124
+ disconnected: false,
125
+ handshakeTimeout,
126
+ activeRequests: new Map(),
127
+ };
128
+ this.connections.add(state);
129
+ this.notifyConnectionCountChanged();
130
+ return {
131
+ onData: (chunk) => this.receive(state, chunk),
132
+ onClose: () => this.transportClosed(state),
133
+ onError: (error) => {
134
+ this.reportError(error);
135
+ void this.closeConnection(connection).then(() => this.disconnect(state));
136
+ },
137
+ };
138
+ }
139
+ async close() {
140
+ if (this.closePromise)
141
+ return this.closePromise;
142
+ this.closing = true;
143
+ this.closePromise = this.closeInternal();
144
+ return this.closePromise;
145
+ }
146
+ async closeInternal() {
147
+ const starting = this.startPromise;
148
+ if (starting)
149
+ await starting.catch(() => { });
150
+ const errors = [];
151
+ const listenerResults = await Promise.allSettled(this.listeners.map((listener) => listener.close()));
152
+ for (const result of listenerResults) {
153
+ if (result.status === "rejected")
154
+ errors.push(result.reason);
155
+ }
156
+ try {
157
+ await this.closeServerState();
158
+ }
159
+ catch (error) {
160
+ errors.push(error);
161
+ }
162
+ this.started = false;
163
+ if (errors.length > 0) {
164
+ const failure = errors.length === 1 && errors[0] instanceof Error
165
+ ? errors[0]
166
+ : new AggregateError(errors, "Server shutdown failed");
167
+ this.settleClosed(failure);
168
+ throw failure;
169
+ }
170
+ this.settleClosed();
171
+ }
172
+ receive(state, chunk) {
173
+ if (isTerminalConnection(state))
174
+ return;
175
+ let messages;
176
+ try {
177
+ messages = state.decoder.push(chunk);
178
+ }
179
+ catch (error) {
180
+ void this.failProtocol(state, this.toProtocolError(error));
181
+ return;
182
+ }
183
+ for (const message of messages) {
184
+ if (isTerminalConnection(state))
185
+ return;
186
+ this.dispatchMessage(state, message);
187
+ }
188
+ }
189
+ dispatchMessage(state, message) {
190
+ if (state.stage === "awaitingHello") {
191
+ if (message.type !== "hello") {
192
+ void this.failProtocol(state, {
193
+ code: "invalid_request",
194
+ message: "The first client message must be hello",
195
+ });
196
+ return;
197
+ }
198
+ state.stage = "handshaking";
199
+ state.handshake = this.finishHandshake(state, message).catch((error) => this.failProtocol(state, this.toProtocolError(error)));
200
+ return;
201
+ }
202
+ if (message.type === "hello") {
203
+ void this.failProtocol(state, {
204
+ code: "invalid_request",
205
+ message: "hello may only be sent as the first message",
206
+ });
207
+ return;
208
+ }
209
+ if (state.stage === "ready") {
210
+ if (message.type === "cancel")
211
+ this.handleCancel(state, message);
212
+ else
213
+ void this.handleRequest(state, message);
214
+ return;
215
+ }
216
+ if (state.stage !== "handshaking")
217
+ return;
218
+ const handshake = state.handshake;
219
+ if (!handshake)
220
+ return;
221
+ void handshake.then(() => {
222
+ if (state.stage !== "ready" || state.disconnected)
223
+ return;
224
+ if (message.type === "cancel")
225
+ this.handleCancel(state, message);
226
+ else
227
+ void this.handleRequest(state, message);
228
+ });
229
+ }
230
+ async finishHandshake(state, hello) {
231
+ if (!isSupportedProtocolVersion(hello.version)) {
232
+ await this.failProtocol(state, {
233
+ code: "version",
234
+ message: `Unsupported protocol version ${hello.version}; expected ${PROTOCOL_VERSION}`,
235
+ });
236
+ return;
237
+ }
238
+ if (this.closing || state.disconnected || state.stage !== "handshaking" || state.connection.closed)
239
+ return;
240
+ const services = await this.host.serverServices.attachClient({
241
+ attachSession: async (sessionId, context) => {
242
+ await this.sessions.attachClient(state, sessionId, context);
243
+ },
244
+ detachSession: (context) => this.sessions.detachClient(state, context),
245
+ prepareSessionRemoval: (sessionId, context) => this.sessions.removeSession(sessionId, context),
246
+ }, TODO_CONTEXT);
247
+ if (this.closing || state.disconnected || state.stage !== "handshaking" || state.connection.closed) {
248
+ await services.release(TODO_CONTEXT);
249
+ return;
250
+ }
251
+ state.serverServices = services;
252
+ const sent = await this.sendMessage(state, {
253
+ type: "hello",
254
+ version: PROTOCOL_VERSION,
255
+ serverId: this.serverId,
256
+ });
257
+ if (sent && !state.disconnected && state.stage === "handshaking") {
258
+ state.stage = "ready";
259
+ clearTimeout(state.handshakeTimeout);
260
+ }
261
+ }
262
+ handleCancel(state, envelope) {
263
+ if (envelope.target.serverId !== this.serverId)
264
+ return;
265
+ const active = state.activeRequests.get(envelope.id);
266
+ if (active !== undefined && sameTarget(active.target, envelope.target)) {
267
+ active.controller.abort(new DOMException("RPC request cancelled", "AbortError"));
268
+ }
269
+ }
270
+ async handleRequest(state, envelope) {
271
+ if (state.activeRequests.has(envelope.id)) {
272
+ await this.sendMessage(state, {
273
+ type: "response",
274
+ id: envelope.id,
275
+ ok: false,
276
+ error: { code: "invalid_request", message: "Request ID is already active" },
277
+ });
278
+ return;
279
+ }
280
+ let call;
281
+ try {
282
+ call = parseServiceCall(envelope.call);
283
+ }
284
+ catch {
285
+ await this.sendMessage(state, {
286
+ type: "response",
287
+ id: envelope.id,
288
+ ok: false,
289
+ error: { code: "invalid_request", message: "Invalid service call" },
290
+ });
291
+ return;
292
+ }
293
+ const controller = new AbortController();
294
+ const active = { controller, target: envelope.target };
295
+ state.activeRequests.set(envelope.id, active);
296
+ const context = withAbortSignal(controller.signal, TODO_CONTEXT);
297
+ const control = decodeServiceControlCall(call);
298
+ const subscribing = control?.type === "subscribe" ? control : undefined;
299
+ const pendingUpdates = [];
300
+ let subscriptionReady = subscribing === undefined;
301
+ let installedSubscriptionEncoder = false;
302
+ let responded = false;
303
+ const publish = async (subscriptionId, update) => {
304
+ if (subscribing !== undefined && subscriptionId === subscribing.subscriptionId && !subscriptionReady) {
305
+ pendingUpdates.push({ update });
306
+ return;
307
+ }
308
+ await this.sendServiceUpdate(state, subscriptionId, update);
309
+ };
310
+ try {
311
+ if (envelope.target.serverId !== this.serverId)
312
+ throw new WrongServerError();
313
+ if (subscribing !== undefined && state.serviceStateEncoders.has(subscribing.subscriptionId)) {
314
+ throw new ProtocolValidationError(`Duplicate service subscription ${subscribing.subscriptionId}`);
315
+ }
316
+ let result;
317
+ if ("sessionId" in envelope.target) {
318
+ result = await this.sessions.executeServiceCall(call, envelope.target, state, publish, context);
319
+ }
320
+ else if (state.serverServices !== undefined) {
321
+ result = await state.serverServices.invokeService(call, publish, context);
322
+ }
323
+ else {
324
+ throw new ProtocolValidationError(`Unknown service member ${call.serviceId}.${call.member}`);
325
+ }
326
+ if (subscribing !== undefined) {
327
+ if (result === undefined)
328
+ throw new ProtocolValidationError("Service subscription did not return a snapshot");
329
+ const stateEncoder = createServiceStateEncoder();
330
+ result = stateEncoder.encodeSnapshot(parseServiceSubscriptionSnapshot(result));
331
+ state.serviceStateEncoders.set(subscribing.subscriptionId, stateEncoder);
332
+ installedSubscriptionEncoder = true;
333
+ }
334
+ else if (control?.type === "unsubscribe") {
335
+ state.serviceStateEncoders.delete(control.subscriptionId);
336
+ }
337
+ await this.sendMessage(state, result === undefined
338
+ ? { type: "response", id: envelope.id, ok: true }
339
+ : { type: "response", id: envelope.id, ok: true, result });
340
+ responded = true;
341
+ if (subscribing !== undefined) {
342
+ while (pendingUpdates.length > 0) {
343
+ const pending = pendingUpdates.shift();
344
+ if (pending !== undefined)
345
+ await this.sendServiceUpdate(state, subscribing.subscriptionId, pending.update);
346
+ }
347
+ subscriptionReady = true;
348
+ }
349
+ }
350
+ catch (error) {
351
+ if (subscribing !== undefined && installedSubscriptionEncoder && !responded) {
352
+ state.serviceStateEncoders.delete(subscribing.subscriptionId);
353
+ }
354
+ if (responded) {
355
+ this.reportError(error);
356
+ await this.closeConnection(state.connection);
357
+ this.disconnect(state);
358
+ }
359
+ else {
360
+ await this.sendMessage(state, {
361
+ type: "response",
362
+ id: envelope.id,
363
+ ok: false,
364
+ error: controller.signal.aborted
365
+ ? { code: "cancelled", message: "RPC request cancelled" }
366
+ : this.toProtocolError(error),
367
+ });
368
+ }
369
+ }
370
+ finally {
371
+ if (state.activeRequests.get(envelope.id) === active)
372
+ state.activeRequests.delete(envelope.id);
373
+ }
374
+ }
375
+ transportClosed(connection) {
376
+ if (!connection.disconnected && connection.stage !== "closing") {
377
+ try {
378
+ connection.decoder.end();
379
+ }
380
+ catch (error) {
381
+ this.reportError(error);
382
+ }
383
+ }
384
+ this.disconnect(connection);
385
+ }
386
+ disconnect(connection) {
387
+ if (connection.disconnected)
388
+ return;
389
+ connection.disconnected = true;
390
+ connection.stage = "closed";
391
+ clearTimeout(connection.handshakeTimeout);
392
+ for (const { controller } of connection.activeRequests.values()) {
393
+ controller.abort(new Error("Client disconnected"));
394
+ }
395
+ connection.activeRequests.clear();
396
+ connection.serviceStateEncoders.clear();
397
+ if (this.connections.delete(connection))
398
+ this.notifyConnectionCountChanged();
399
+ const serverServices = connection.serverServices;
400
+ delete connection.serverServices;
401
+ void Promise.allSettled([
402
+ this.sessions.disconnect(connection, TODO_CONTEXT),
403
+ serverServices?.release(TODO_CONTEXT),
404
+ ]).then((results) => {
405
+ for (const result of results)
406
+ if (result.status === "rejected")
407
+ this.reportError(result.reason);
408
+ });
409
+ }
410
+ async sendServiceUpdate(connection, subscriptionId, update) {
411
+ const stateEncoder = connection.serviceStateEncoders.get(subscriptionId);
412
+ if (stateEncoder === undefined)
413
+ return;
414
+ await this.sendMessage(connection, {
415
+ type: "service_update",
416
+ subscriptionId,
417
+ update: stateEncoder.encodeUpdate(update),
418
+ });
419
+ }
420
+ async sendMessage(connection, message) {
421
+ if (connection.disconnected || connection.connection.closed)
422
+ return false;
423
+ let frame;
424
+ try {
425
+ frame = encodeServerMessage(message, { maxFrameLength: this.maxFrameLength });
426
+ }
427
+ catch (error) {
428
+ this.reportError(error);
429
+ await this.closeConnection(connection.connection);
430
+ this.disconnect(connection);
431
+ return false;
432
+ }
433
+ try {
434
+ await connection.connection.send(frame);
435
+ return true;
436
+ }
437
+ catch (error) {
438
+ this.reportError(error);
439
+ await this.closeConnection(connection.connection);
440
+ this.disconnect(connection);
441
+ return false;
442
+ }
443
+ }
444
+ async failProtocol(connection, error) {
445
+ if (connection.disconnected || connection.stage === "closing" || connection.stage === "closed")
446
+ return;
447
+ connection.stage = "closing";
448
+ clearTimeout(connection.handshakeTimeout);
449
+ const message = { type: "hello_error", error };
450
+ let finalFrame;
451
+ try {
452
+ finalFrame = encodeServerMessage(message, { maxFrameLength: this.maxFrameLength });
453
+ }
454
+ catch (encodeError) {
455
+ this.reportError(encodeError);
456
+ }
457
+ await this.closeConnection(connection.connection, finalFrame);
458
+ this.disconnect(connection);
459
+ }
460
+ async closeServerState() {
461
+ const connections = [...this.connections];
462
+ for (const connection of connections) {
463
+ connection.stage = "closing";
464
+ clearTimeout(connection.handshakeTimeout);
465
+ }
466
+ await Promise.all(connections.map((connection) => this.closeConnection(connection.connection)));
467
+ for (const connection of connections)
468
+ this.disconnect(connection);
469
+ const cleanup = await Promise.allSettled([this.sessions.close(BACKGROUND_CONTEXT)]);
470
+ this.connections.clear();
471
+ const errors = cleanup.flatMap((result) => (result.status === "rejected" ? [result.reason] : []));
472
+ if (errors.length === 1)
473
+ throw errors[0];
474
+ if (errors.length > 1)
475
+ throw new AggregateError(errors, "Failed to close server Sessions");
476
+ }
477
+ async closeConnection(connection, finalChunk) {
478
+ try {
479
+ await connection.close(finalChunk);
480
+ }
481
+ catch (error) {
482
+ this.reportError(error);
483
+ }
484
+ }
485
+ toProtocolError(error) {
486
+ if (error instanceof ServerError || error instanceof RemoteServiceError) {
487
+ return { code: error.code, message: error.message };
488
+ }
489
+ if (error instanceof ProtocolValidationError) {
490
+ return { code: "invalid_request", message: error.message };
491
+ }
492
+ this.reportError(error);
493
+ return { code: "internal_error", message: INTERNAL_SERVER_ERROR_MESSAGE };
494
+ }
495
+ notifyConnectionCountChanged() {
496
+ try {
497
+ this.onConnectionCountChanged?.(this.connections.size);
498
+ }
499
+ catch (error) {
500
+ this.reportError(error);
501
+ }
502
+ }
503
+ reportError(error) {
504
+ try {
505
+ this.onError?.(error instanceof Error ? error : new Error(String(error)));
506
+ }
507
+ catch {
508
+ // Error observers cannot affect server state.
509
+ }
510
+ }
511
+ settleClosed(error) {
512
+ if (this.closedSettled)
513
+ return;
514
+ this.closedSettled = true;
515
+ if (error === undefined)
516
+ this.resolveClosed();
517
+ else
518
+ this.rejectClosed(error);
519
+ }
520
+ }
521
+ function sameTarget(left, right) {
522
+ if (left.serverId !== right.serverId)
523
+ return false;
524
+ if (!("sessionId" in left) || !("sessionId" in right)) {
525
+ return !("sessionId" in left) && !("sessionId" in right);
526
+ }
527
+ return left.sessionId === right.sessionId && left.attachmentId === right.attachmentId;
528
+ }
529
+ function resolveOptions(options) {
530
+ if (!Array.isArray(options.listeners))
531
+ throw new TypeError("Server listeners must be an array");
532
+ if (!isServerId(options.serverId)) {
533
+ throw new TypeError("serverId must be a canonical lowercase UUIDv4");
534
+ }
535
+ const maxFrameLength = options.maxFrameLength ?? DEFAULT_MAX_FRAME_LENGTH;
536
+ if (!Number.isSafeInteger(maxFrameLength) || maxFrameLength <= 0 || maxFrameLength > MAX_UINT32) {
537
+ throw new TypeError(`Server maxFrameLength must be an integer between 1 and ${MAX_UINT32}`);
538
+ }
539
+ const handshakeTimeoutMs = options.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT_MS;
540
+ if (!Number.isSafeInteger(handshakeTimeoutMs) ||
541
+ handshakeTimeoutMs <= 0 ||
542
+ handshakeTimeoutMs > MAX_TIMER_DELAY_MS) {
543
+ throw new TypeError(`Server handshakeTimeoutMs must be an integer between 1 and ${MAX_TIMER_DELAY_MS}`);
544
+ }
545
+ return { maxFrameLength, handshakeTimeoutMs };
546
+ }
547
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tcreateServiceStateEncoder,\n\tdecodeServiceControlCall,\n\ttype JsonValue,\n\tparseServiceCall,\n\tparseServiceSubscriptionSnapshot,\n\tRemoteServiceError,\n\ttype ServiceCall,\n\ttype ServiceProviderUpdate,\n} from \"@m4ike1/chord\";\nimport { BACKGROUND_CONTEXT, type SessionMetadata, TODO_CONTEXT, withAbortSignal } from \"@m4ike1/ion-agent-core\";\nimport {\n\ttype CancelEnvelope,\n\ttype ClientHello,\n\ttype ClientMessage,\n\tClientMessageDecoder,\n\tDEFAULT_MAX_FRAME_LENGTH,\n\tencodeServerMessage,\n\tisServerId,\n\tisSupportedProtocolVersion,\n\tPROTOCOL_VERSION,\n\ttype ProtocolError,\n\tProtocolValidationError,\n\ttype RequestEnvelope,\n\ttype ResponseEnvelope,\n\ttype RpcTarget,\n\ttype ServerHello,\n\ttype ServerHelloError,\n\ttype ServerMessage,\n} from \"@m4ike1/ion-protocol\";\nimport {\n\ttype ByteConnection,\n\ttype ByteConnectionHandler,\n\ttype ConnectionState,\n\tisTerminalConnection,\n} from \"./connection.ts\";\nimport { INTERNAL_SERVER_ERROR_MESSAGE, ServerError, WrongServerError } from \"./errors.ts\";\nimport type { ServerListener } from \"./listener.ts\";\nimport { SessionRouter } from \"./session-router.ts\";\nimport type { ServerHost, ServerOptions } from \"./types.ts\";\n\nconst DEFAULT_HANDSHAKE_TIMEOUT_MS = 5_000;\nconst MAX_UINT32 = 0xffff_ffff;\nconst MAX_TIMER_DELAY_MS = 2_147_483_647;\n\nexport class Server<TMetadata extends SessionMetadata = SessionMetadata> {\n\treadonly serverId: string;\n\t/** Resolves after shutdown, or rejects when listener or routed-Session cleanup fails. */\n\treadonly closed: Promise<void>;\n\n\tprivate readonly host: ServerHost<TMetadata>;\n\tprivate readonly listeners: readonly ServerListener[];\n\tprivate readonly maxFrameLength: number;\n\tprivate readonly handshakeTimeoutMs: number;\n\tprivate readonly onConnectionCountChanged: ((count: number) => void) | undefined;\n\tprivate readonly onError: ((error: Error) => void) | undefined;\n\tprivate readonly connections = new Set<ConnectionState>();\n\tprivate readonly sessions: SessionRouter<TMetadata>;\n\tprivate closing = false;\n\tprivate closePromise?: Promise<void>;\n\tprivate closedSettled = false;\n\tprivate rejectClosed!: (error: unknown) => void;\n\tprivate resolveClosed!: () => void;\n\tprivate startPromise?: Promise<this>;\n\tprivate started = false;\n\n\tconstructor(host: ServerHost<TMetadata>, options: ServerOptions) {\n\t\tconst resolved = resolveOptions(options);\n\t\tthis.host = host;\n\t\tthis.listeners = options.listeners;\n\t\tthis.serverId = options.serverId;\n\t\tthis.maxFrameLength = resolved.maxFrameLength;\n\t\tthis.handshakeTimeoutMs = resolved.handshakeTimeoutMs;\n\t\tthis.onConnectionCountChanged = options.onConnectionCountChanged;\n\t\tthis.onError = options.onError;\n\t\tthis.sessions = new SessionRouter({\n\t\t\thost,\n\t\t\tserverId: this.serverId,\n\t\t\tisClosing: () => this.closing,\n\t\t\tpublishAttachment: async (client, attachment) => {\n\t\t\t\tawait this.sendMessage(client as ConnectionState, {\n\t\t\t\t\ttype: \"attachment\",\n\t\t\t\t\tattachment: attachment ?? null,\n\t\t\t\t});\n\t\t\t},\n\t\t\treportError: (error) => this.reportError(error),\n\t\t});\n\t\tthis.closed = new Promise((resolve, reject) => {\n\t\t\tthis.resolveClosed = resolve;\n\t\t\tthis.rejectClosed = reject;\n\t\t});\n\t\tvoid this.closed.catch(() => {});\n\t}\n\n\tstart(): Promise<this> {\n\t\tif (this.started) return Promise.reject(new Error(\"Server is already started\"));\n\t\tif (this.startPromise) return Promise.reject(new Error(\"Server is already starting\"));\n\t\tif (this.closing) return Promise.reject(new Error(\"Server is closing or closed\"));\n\t\tthis.startPromise = this.startInternal();\n\t\treturn this.startPromise;\n\t}\n\n\tprivate async startInternal(): Promise<this> {\n\t\tconst started: ServerListener[] = [];\n\t\ttry {\n\t\t\tfor (const listener of this.listeners) {\n\t\t\t\tawait listener.start((connection) => this.accept(connection));\n\t\t\t\tstarted.push(listener);\n\t\t\t}\n\t\t\tthis.started = true;\n\t\t\treturn this;\n\t\t} catch (error) {\n\t\t\tthis.closing = true;\n\t\t\tconst cleanupErrors: unknown[] = [];\n\t\t\tconst listenerResults = await Promise.allSettled(started.map((listener) => listener.close()));\n\t\t\tfor (const result of listenerResults) {\n\t\t\t\tif (result.status === \"rejected\") cleanupErrors.push(result.reason);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait this.closeServerState();\n\t\t\t} catch (cleanupError) {\n\t\t\t\tcleanupErrors.push(cleanupError);\n\t\t\t}\n\t\t\tif (cleanupErrors.length > 0) {\n\t\t\t\tconst failure = new AggregateError([error, ...cleanupErrors], \"Server startup and cleanup failed\");\n\t\t\t\tthis.settleClosed(failure);\n\t\t\t\tthrow failure;\n\t\t\t}\n\t\t\tthis.settleClosed();\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tthis.startPromise = undefined;\n\t\t}\n\t}\n\n\taccept(connection: ByteConnection): ByteConnectionHandler {\n\t\tif (this.closing) {\n\t\t\tvoid this.closeConnection(connection);\n\t\t\treturn {\n\t\t\t\tonData: () => {},\n\t\t\t\tonClose: () => {},\n\t\t\t\tonError: (error) => this.reportError(error),\n\t\t\t};\n\t\t}\n\n\t\tlet state: ConnectionState;\n\t\tconst handshakeTimeout = setTimeout(() => {\n\t\t\tvoid this.failProtocol(state, {\n\t\t\t\tcode: \"invalid_request\",\n\t\t\t\tmessage: \"Handshake timeout\",\n\t\t\t});\n\t\t}, this.handshakeTimeoutMs);\n\t\thandshakeTimeout.unref();\n\t\tstate = {\n\t\t\tconnection,\n\t\t\tdecoder: new ClientMessageDecoder({ maxFrameLength: this.maxFrameLength }),\n\t\t\tserviceStateEncoders: new Map(),\n\t\t\tstage: \"awaitingHello\",\n\t\t\tdisconnected: false,\n\t\t\thandshakeTimeout,\n\t\t\tactiveRequests: new Map(),\n\t\t};\n\t\tthis.connections.add(state);\n\t\tthis.notifyConnectionCountChanged();\n\n\t\treturn {\n\t\t\tonData: (chunk) => this.receive(state, chunk),\n\t\t\tonClose: () => this.transportClosed(state),\n\t\t\tonError: (error) => {\n\t\t\t\tthis.reportError(error);\n\t\t\t\tvoid this.closeConnection(connection).then(() => this.disconnect(state));\n\t\t\t},\n\t\t};\n\t}\n\n\tasync close(): Promise<void> {\n\t\tif (this.closePromise) return this.closePromise;\n\t\tthis.closing = true;\n\t\tthis.closePromise = this.closeInternal();\n\t\treturn this.closePromise;\n\t}\n\n\tprivate async closeInternal(): Promise<void> {\n\t\tconst starting = this.startPromise;\n\t\tif (starting) await starting.catch(() => {});\n\t\tconst errors: unknown[] = [];\n\t\tconst listenerResults = await Promise.allSettled(this.listeners.map((listener) => listener.close()));\n\t\tfor (const result of listenerResults) {\n\t\t\tif (result.status === \"rejected\") errors.push(result.reason);\n\t\t}\n\t\ttry {\n\t\t\tawait this.closeServerState();\n\t\t} catch (error) {\n\t\t\terrors.push(error);\n\t\t}\n\t\tthis.started = false;\n\t\tif (errors.length > 0) {\n\t\t\tconst failure =\n\t\t\t\terrors.length === 1 && errors[0] instanceof Error\n\t\t\t\t\t? errors[0]\n\t\t\t\t\t: new AggregateError(errors, \"Server shutdown failed\");\n\t\t\tthis.settleClosed(failure);\n\t\t\tthrow failure;\n\t\t}\n\t\tthis.settleClosed();\n\t}\n\n\tprivate receive(state: ConnectionState, chunk: Uint8Array): void {\n\t\tif (isTerminalConnection(state)) return;\n\t\tlet messages: ClientMessage[];\n\t\ttry {\n\t\t\tmessages = state.decoder.push(chunk);\n\t\t} catch (error) {\n\t\t\tvoid this.failProtocol(state, this.toProtocolError(error));\n\t\t\treturn;\n\t\t}\n\t\tfor (const message of messages) {\n\t\t\tif (isTerminalConnection(state)) return;\n\t\t\tthis.dispatchMessage(state, message);\n\t\t}\n\t}\n\n\tprivate dispatchMessage(state: ConnectionState, message: ClientMessage): void {\n\t\tif (state.stage === \"awaitingHello\") {\n\t\t\tif (message.type !== \"hello\") {\n\t\t\t\tvoid this.failProtocol(state, {\n\t\t\t\t\tcode: \"invalid_request\",\n\t\t\t\t\tmessage: \"The first client message must be hello\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tstate.stage = \"handshaking\";\n\t\t\tstate.handshake = this.finishHandshake(state, message).catch((error: unknown) =>\n\t\t\t\tthis.failProtocol(state, this.toProtocolError(error)),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (message.type === \"hello\") {\n\t\t\tvoid this.failProtocol(state, {\n\t\t\t\tcode: \"invalid_request\",\n\t\t\t\tmessage: \"hello may only be sent as the first message\",\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tif (state.stage === \"ready\") {\n\t\t\tif (message.type === \"cancel\") this.handleCancel(state, message);\n\t\t\telse void this.handleRequest(state, message);\n\t\t\treturn;\n\t\t}\n\t\tif (state.stage !== \"handshaking\") return;\n\t\tconst handshake = state.handshake;\n\t\tif (!handshake) return;\n\t\tvoid handshake.then(() => {\n\t\t\tif (state.stage !== \"ready\" || state.disconnected) return;\n\t\t\tif (message.type === \"cancel\") this.handleCancel(state, message);\n\t\t\telse void this.handleRequest(state, message);\n\t\t});\n\t}\n\n\tprivate async finishHandshake(state: ConnectionState, hello: ClientHello): Promise<void> {\n\t\tif (!isSupportedProtocolVersion(hello.version)) {\n\t\t\tawait this.failProtocol(state, {\n\t\t\t\tcode: \"version\",\n\t\t\t\tmessage: `Unsupported protocol version ${hello.version}; expected ${PROTOCOL_VERSION}`,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.closing || state.disconnected || state.stage !== \"handshaking\" || state.connection.closed) return;\n\t\tconst services = await this.host.serverServices.attachClient(\n\t\t\t{\n\t\t\t\tattachSession: async (sessionId, context) => {\n\t\t\t\t\tawait this.sessions.attachClient(state, sessionId, context);\n\t\t\t\t},\n\t\t\t\tdetachSession: (context) => this.sessions.detachClient(state, context),\n\t\t\t\tprepareSessionRemoval: (sessionId, context) => this.sessions.removeSession(sessionId, context),\n\t\t\t},\n\t\t\tTODO_CONTEXT,\n\t\t);\n\t\tif (this.closing || state.disconnected || state.stage !== \"handshaking\" || state.connection.closed) {\n\t\t\tawait services.release(TODO_CONTEXT);\n\t\t\treturn;\n\t\t}\n\t\tstate.serverServices = services;\n\t\tconst sent = await this.sendMessage(state, {\n\t\t\ttype: \"hello\",\n\t\t\tversion: PROTOCOL_VERSION,\n\t\t\tserverId: this.serverId,\n\t\t} satisfies ServerHello);\n\t\tif (sent && !state.disconnected && state.stage === \"handshaking\") {\n\t\t\tstate.stage = \"ready\";\n\t\t\tclearTimeout(state.handshakeTimeout);\n\t\t}\n\t}\n\n\tprivate handleCancel(state: ConnectionState, envelope: CancelEnvelope): void {\n\t\tif (envelope.target.serverId !== this.serverId) return;\n\t\tconst active = state.activeRequests.get(envelope.id);\n\t\tif (active !== undefined && sameTarget(active.target, envelope.target)) {\n\t\t\tactive.controller.abort(new DOMException(\"RPC request cancelled\", \"AbortError\"));\n\t\t}\n\t}\n\n\tprivate async handleRequest(state: ConnectionState, envelope: RequestEnvelope): Promise<void> {\n\t\tif (state.activeRequests.has(envelope.id)) {\n\t\t\tawait this.sendMessage(state, {\n\t\t\t\ttype: \"response\",\n\t\t\t\tid: envelope.id,\n\t\t\t\tok: false,\n\t\t\t\terror: { code: \"invalid_request\", message: \"Request ID is already active\" },\n\t\t\t} satisfies ResponseEnvelope);\n\t\t\treturn;\n\t\t}\n\t\tlet call: ServiceCall;\n\t\ttry {\n\t\t\tcall = parseServiceCall(envelope.call);\n\t\t} catch {\n\t\t\tawait this.sendMessage(state, {\n\t\t\t\ttype: \"response\",\n\t\t\t\tid: envelope.id,\n\t\t\t\tok: false,\n\t\t\t\terror: { code: \"invalid_request\", message: \"Invalid service call\" },\n\t\t\t} satisfies ResponseEnvelope);\n\t\t\treturn;\n\t\t}\n\t\tconst controller = new AbortController();\n\t\tconst active = { controller, target: envelope.target };\n\t\tstate.activeRequests.set(envelope.id, active);\n\t\tconst context = withAbortSignal(controller.signal, TODO_CONTEXT);\n\t\tconst control = decodeServiceControlCall(call);\n\t\tconst subscribing = control?.type === \"subscribe\" ? control : undefined;\n\t\tconst pendingUpdates: { readonly update: ServiceProviderUpdate }[] = [];\n\t\tlet subscriptionReady = subscribing === undefined;\n\t\tlet installedSubscriptionEncoder = false;\n\t\tlet responded = false;\n\t\tconst publish = async (subscriptionId: string, update: ServiceProviderUpdate): Promise<void> => {\n\t\t\tif (subscribing !== undefined && subscriptionId === subscribing.subscriptionId && !subscriptionReady) {\n\t\t\t\tpendingUpdates.push({ update });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tawait this.sendServiceUpdate(state, subscriptionId, update);\n\t\t};\n\t\ttry {\n\t\t\tif (envelope.target.serverId !== this.serverId) throw new WrongServerError();\n\t\t\tif (subscribing !== undefined && state.serviceStateEncoders.has(subscribing.subscriptionId)) {\n\t\t\t\tthrow new ProtocolValidationError(`Duplicate service subscription ${subscribing.subscriptionId}`);\n\t\t\t}\n\t\t\tlet result: JsonValue | undefined;\n\t\t\tif (\"sessionId\" in envelope.target) {\n\t\t\t\tresult = await this.sessions.executeServiceCall(call, envelope.target, state, publish, context);\n\t\t\t} else if (state.serverServices !== undefined) {\n\t\t\t\tresult = await state.serverServices.invokeService(call, publish, context);\n\t\t\t} else {\n\t\t\t\tthrow new ProtocolValidationError(`Unknown service member ${call.serviceId}.${call.member}`);\n\t\t\t}\n\t\t\tif (subscribing !== undefined) {\n\t\t\t\tif (result === undefined)\n\t\t\t\t\tthrow new ProtocolValidationError(\"Service subscription did not return a snapshot\");\n\t\t\t\tconst stateEncoder = createServiceStateEncoder();\n\t\t\t\tresult = stateEncoder.encodeSnapshot(parseServiceSubscriptionSnapshot(result)) as unknown as JsonValue;\n\t\t\t\tstate.serviceStateEncoders.set(subscribing.subscriptionId, stateEncoder);\n\t\t\t\tinstalledSubscriptionEncoder = true;\n\t\t\t} else if (control?.type === \"unsubscribe\") {\n\t\t\t\tstate.serviceStateEncoders.delete(control.subscriptionId);\n\t\t\t}\n\t\t\tawait this.sendMessage(\n\t\t\t\tstate,\n\t\t\t\tresult === undefined\n\t\t\t\t\t? { type: \"response\", id: envelope.id, ok: true }\n\t\t\t\t\t: { type: \"response\", id: envelope.id, ok: true, result },\n\t\t\t);\n\t\t\tresponded = true;\n\t\t\tif (subscribing !== undefined) {\n\t\t\t\twhile (pendingUpdates.length > 0) {\n\t\t\t\t\tconst pending = pendingUpdates.shift();\n\t\t\t\t\tif (pending !== undefined)\n\t\t\t\t\t\tawait this.sendServiceUpdate(state, subscribing.subscriptionId, pending.update);\n\t\t\t\t}\n\t\t\t\tsubscriptionReady = true;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (subscribing !== undefined && installedSubscriptionEncoder && !responded) {\n\t\t\t\tstate.serviceStateEncoders.delete(subscribing.subscriptionId);\n\t\t\t}\n\t\t\tif (responded) {\n\t\t\t\tthis.reportError(error);\n\t\t\t\tawait this.closeConnection(state.connection);\n\t\t\t\tthis.disconnect(state);\n\t\t\t} else {\n\t\t\t\tawait this.sendMessage(state, {\n\t\t\t\t\ttype: \"response\",\n\t\t\t\t\tid: envelope.id,\n\t\t\t\t\tok: false,\n\t\t\t\t\terror: controller.signal.aborted\n\t\t\t\t\t\t? { code: \"cancelled\", message: \"RPC request cancelled\" }\n\t\t\t\t\t\t: this.toProtocolError(error),\n\t\t\t\t} satisfies ResponseEnvelope);\n\t\t\t}\n\t\t} finally {\n\t\t\tif (state.activeRequests.get(envelope.id) === active) state.activeRequests.delete(envelope.id);\n\t\t}\n\t}\n\n\tprivate transportClosed(connection: ConnectionState): void {\n\t\tif (!connection.disconnected && connection.stage !== \"closing\") {\n\t\t\ttry {\n\t\t\t\tconnection.decoder.end();\n\t\t\t} catch (error) {\n\t\t\t\tthis.reportError(error);\n\t\t\t}\n\t\t}\n\t\tthis.disconnect(connection);\n\t}\n\n\tprivate disconnect(connection: ConnectionState): void {\n\t\tif (connection.disconnected) return;\n\t\tconnection.disconnected = true;\n\t\tconnection.stage = \"closed\";\n\t\tclearTimeout(connection.handshakeTimeout);\n\t\tfor (const { controller } of connection.activeRequests.values()) {\n\t\t\tcontroller.abort(new Error(\"Client disconnected\"));\n\t\t}\n\t\tconnection.activeRequests.clear();\n\t\tconnection.serviceStateEncoders.clear();\n\t\tif (this.connections.delete(connection)) this.notifyConnectionCountChanged();\n\t\tconst serverServices = connection.serverServices;\n\t\tdelete connection.serverServices;\n\t\tvoid Promise.allSettled([\n\t\t\tthis.sessions.disconnect(connection, TODO_CONTEXT),\n\t\t\tserverServices?.release(TODO_CONTEXT),\n\t\t]).then((results) => {\n\t\t\tfor (const result of results) if (result.status === \"rejected\") this.reportError(result.reason);\n\t\t});\n\t}\n\n\tprivate async sendServiceUpdate(\n\t\tconnection: ConnectionState,\n\t\tsubscriptionId: string,\n\t\tupdate: ServiceProviderUpdate,\n\t): Promise<void> {\n\t\tconst stateEncoder = connection.serviceStateEncoders.get(subscriptionId);\n\t\tif (stateEncoder === undefined) return;\n\t\tawait this.sendMessage(connection, {\n\t\t\ttype: \"service_update\",\n\t\t\tsubscriptionId,\n\t\t\tupdate: stateEncoder.encodeUpdate(update) as unknown as JsonValue,\n\t\t});\n\t}\n\n\tprivate async sendMessage(connection: ConnectionState, message: ServerMessage): Promise<boolean> {\n\t\tif (connection.disconnected || connection.connection.closed) return false;\n\t\tlet frame: Uint8Array;\n\t\ttry {\n\t\t\tframe = encodeServerMessage(message, { maxFrameLength: this.maxFrameLength });\n\t\t} catch (error) {\n\t\t\tthis.reportError(error);\n\t\t\tawait this.closeConnection(connection.connection);\n\t\t\tthis.disconnect(connection);\n\t\t\treturn false;\n\t\t}\n\t\ttry {\n\t\t\tawait connection.connection.send(frame);\n\t\t\treturn true;\n\t\t} catch (error) {\n\t\t\tthis.reportError(error);\n\t\t\tawait this.closeConnection(connection.connection);\n\t\t\tthis.disconnect(connection);\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tprivate async failProtocol(connection: ConnectionState, error: ProtocolError): Promise<void> {\n\t\tif (connection.disconnected || connection.stage === \"closing\" || connection.stage === \"closed\") return;\n\t\tconnection.stage = \"closing\";\n\t\tclearTimeout(connection.handshakeTimeout);\n\t\tconst message: ServerHelloError = { type: \"hello_error\", error };\n\t\tlet finalFrame: Uint8Array | undefined;\n\t\ttry {\n\t\t\tfinalFrame = encodeServerMessage(message, { maxFrameLength: this.maxFrameLength });\n\t\t} catch (encodeError) {\n\t\t\tthis.reportError(encodeError);\n\t\t}\n\t\tawait this.closeConnection(connection.connection, finalFrame);\n\t\tthis.disconnect(connection);\n\t}\n\n\tprivate async closeServerState(): Promise<void> {\n\t\tconst connections = [...this.connections];\n\t\tfor (const connection of connections) {\n\t\t\tconnection.stage = \"closing\";\n\t\t\tclearTimeout(connection.handshakeTimeout);\n\t\t}\n\t\tawait Promise.all(connections.map((connection) => this.closeConnection(connection.connection)));\n\t\tfor (const connection of connections) this.disconnect(connection);\n\t\tconst cleanup = await Promise.allSettled([this.sessions.close(BACKGROUND_CONTEXT)]);\n\t\tthis.connections.clear();\n\t\tconst errors = cleanup.flatMap((result) => (result.status === \"rejected\" ? [result.reason] : []));\n\t\tif (errors.length === 1) throw errors[0];\n\t\tif (errors.length > 1) throw new AggregateError(errors, \"Failed to close server Sessions\");\n\t}\n\n\tprivate async closeConnection(connection: ByteConnection, finalChunk?: Uint8Array): Promise<void> {\n\t\ttry {\n\t\t\tawait connection.close(finalChunk);\n\t\t} catch (error) {\n\t\t\tthis.reportError(error);\n\t\t}\n\t}\n\n\tprivate toProtocolError(error: unknown): ProtocolError {\n\t\tif (error instanceof ServerError || error instanceof RemoteServiceError) {\n\t\t\treturn { code: error.code, message: error.message };\n\t\t}\n\t\tif (error instanceof ProtocolValidationError) {\n\t\t\treturn { code: \"invalid_request\", message: error.message };\n\t\t}\n\t\tthis.reportError(error);\n\t\treturn { code: \"internal_error\", message: INTERNAL_SERVER_ERROR_MESSAGE };\n\t}\n\n\tprivate notifyConnectionCountChanged(): void {\n\t\ttry {\n\t\t\tthis.onConnectionCountChanged?.(this.connections.size);\n\t\t} catch (error) {\n\t\t\tthis.reportError(error);\n\t\t}\n\t}\n\n\tprivate reportError(error: unknown): void {\n\t\ttry {\n\t\t\tthis.onError?.(error instanceof Error ? error : new Error(String(error)));\n\t\t} catch {\n\t\t\t// Error observers cannot affect server state.\n\t\t}\n\t}\n\n\tprivate settleClosed(error?: unknown): void {\n\t\tif (this.closedSettled) return;\n\t\tthis.closedSettled = true;\n\t\tif (error === undefined) this.resolveClosed();\n\t\telse this.rejectClosed(error);\n\t}\n}\n\nfunction sameTarget(left: RpcTarget, right: RpcTarget): boolean {\n\tif (left.serverId !== right.serverId) return false;\n\tif (!(\"sessionId\" in left) || !(\"sessionId\" in right)) {\n\t\treturn !(\"sessionId\" in left) && !(\"sessionId\" in right);\n\t}\n\treturn left.sessionId === right.sessionId && left.attachmentId === right.attachmentId;\n}\n\nfunction resolveOptions(options: ServerOptions): {\n\tmaxFrameLength: number;\n\thandshakeTimeoutMs: number;\n} {\n\tif (!Array.isArray(options.listeners)) throw new TypeError(\"Server listeners must be an array\");\n\tif (!isServerId(options.serverId)) {\n\t\tthrow new TypeError(\"serverId must be a canonical lowercase UUIDv4\");\n\t}\n\tconst maxFrameLength = options.maxFrameLength ?? DEFAULT_MAX_FRAME_LENGTH;\n\tif (!Number.isSafeInteger(maxFrameLength) || maxFrameLength <= 0 || maxFrameLength > MAX_UINT32) {\n\t\tthrow new TypeError(`Server maxFrameLength must be an integer between 1 and ${MAX_UINT32}`);\n\t}\n\tconst handshakeTimeoutMs = options.handshakeTimeoutMs ?? DEFAULT_HANDSHAKE_TIMEOUT_MS;\n\tif (\n\t\t!Number.isSafeInteger(handshakeTimeoutMs) ||\n\t\thandshakeTimeoutMs <= 0 ||\n\t\thandshakeTimeoutMs > MAX_TIMER_DELAY_MS\n\t) {\n\t\tthrow new TypeError(`Server handshakeTimeoutMs must be an integer between 1 and ${MAX_TIMER_DELAY_MS}`);\n\t}\n\treturn { maxFrameLength, handshakeTimeoutMs };\n}\n"]}