@api.global/typedsocket 5.1.2 → 6.0.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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/index.d.ts +7 -0
- package/dist_ts/index.js +5 -1
- package/dist_ts/nativebytes.codec.d.ts +8 -0
- package/dist_ts/nativebytes.codec.js +328 -0
- package/dist_ts/nativebytes.constants.d.ts +59 -0
- package/dist_ts/nativebytes.constants.js +58 -0
- package/dist_ts/nativebytes.errors.d.ts +13 -0
- package/dist_ts/nativebytes.errors.js +26 -0
- package/dist_ts/nativebytes.manager.d.ts +322 -0
- package/dist_ts/nativebytes.manager.js +2308 -0
- package/dist_ts/nativebytes.types.d.ts +187 -0
- package/dist_ts/nativebytes.types.js +2 -0
- package/dist_ts/typedsocket.classes.typedsocket.d.ts +120 -11
- package/dist_ts/typedsocket.classes.typedsocket.js +1093 -160
- package/dist_ts/typedsocket.plugins.d.ts +3 -2
- package/dist_ts/typedsocket.plugins.js +3 -2
- package/dist_ts/typedsocket.tags.d.ts +105 -0
- package/dist_ts/typedsocket.tags.js +521 -0
- package/{license → license.md} +2 -2
- package/package.json +22 -18
- package/readme.hints.md +27 -11
- package/readme.md +461 -46
- package/npmextra.json +0 -35
- package/ts/00_commitinfo_data.ts +0 -8
- package/ts/index.ts +0 -1
- package/ts/typedsocket.classes.typedsocket.ts +0 -1156
- package/ts/typedsocket.plugins.ts +0 -18
|
@@ -1,7 +1,37 @@
|
|
|
1
1
|
import * as plugins from './typedsocket.plugins.js';
|
|
2
|
+
import { NATIVE_BYTE_PROTOCOL, NATIVE_BYTE_PROTOCOL_MAJOR } from './nativebytes.constants.js';
|
|
3
|
+
import { NativeByteCapabilityError } from './nativebytes.errors.js';
|
|
4
|
+
import { NativeByteManager } from './nativebytes.manager.js';
|
|
5
|
+
import { createTypedSocketTagPayloadSnapshot, TYPEDSOCKET_MAX_CLIENT_TAG_RETAINED_BYTES_PER_PEER, TYPEDSOCKET_MAX_CLIENT_TAGS_PER_PEER, TYPEDSOCKET_MAX_TAG_NAME_BYTES, TypedSocketClientTagDeniedError, TypedSocketTagPolicyManager, } from './typedsocket.tags.js';
|
|
2
6
|
const TAG_PREFIX = '__typedsocket_tag__';
|
|
7
|
+
const textEncoder = new TextEncoder();
|
|
8
|
+
export const TYPEDSOCKET_MAX_TEXT_FRAME_BYTES = 1024 * 1024;
|
|
9
|
+
export const TYPEDSOCKET_MAX_QUEUED_TEXT_FRAMES = 64;
|
|
10
|
+
export const TYPEDSOCKET_MAX_QUEUED_TEXT_BYTES = 4 * 1024 * 1024;
|
|
11
|
+
export const TYPEDSOCKET_MAX_CONCURRENT_CLIENT_HANDLERS = 16;
|
|
12
|
+
export const TYPEDSOCKET_MAX_RETAINED_CLIENT_CALLBACKS = 64;
|
|
13
|
+
export const TYPEDSOCKET_MAX_PENDING_CLIENT_REQUESTS = 1024;
|
|
14
|
+
export const TYPEDSOCKET_MAX_OUTBOUND_BUFFERED_BYTES = 4 * 1024 * 1024;
|
|
15
|
+
export const TYPEDSOCKET_MAX_METHOD_NAME_BYTES = 256;
|
|
16
|
+
export const TYPEDSOCKET_MAX_CORRELATION_ID_BYTES = 256;
|
|
17
|
+
export const TYPEDSOCKET_MAX_REQUEST_TIMEOUT_MS = 5 * 60 * 1000;
|
|
18
|
+
export const TYPEDSOCKET_MAX_CONNECTION_RESTORE_TIMEOUT_MS = 10_000;
|
|
19
|
+
export const TYPEDSOCKET_MAX_RECONNECT_RETRIES = 100;
|
|
20
|
+
export const TYPEDSOCKET_MAX_RECONNECT_BACKOFF_MS = 60_000;
|
|
21
|
+
export const TYPEDSOCKET_MAX_RETAINED_CLIENT_TAG_MUTATIONS_PER_NAME = 8;
|
|
22
|
+
export const TYPEDSOCKET_MAX_RETAINED_CLIENT_TAG_MUTATIONS = 64;
|
|
23
|
+
export const TYPEDSOCKET_MAX_PENDING_SERVER_REQUESTS_PER_PEER = 64;
|
|
24
|
+
export const TYPEDSOCKET_MAX_PENDING_SERVER_REQUESTS = 1024;
|
|
25
|
+
export const TYPEDSOCKET_MAX_RETAINED_SERVER_INTERESTS_PER_PEER = 8;
|
|
26
|
+
export const TYPEDSOCKET_MAX_RETAINED_SERVER_INTERESTS = 64;
|
|
27
|
+
export class TypedSocketConnectionRestoreDeniedError extends Error {
|
|
28
|
+
constructor(messageArg) {
|
|
29
|
+
super(messageArg);
|
|
30
|
+
this.name = 'TypedSocketConnectionRestoreDeniedError';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
3
33
|
/**
|
|
4
|
-
* Creates a wrapper around IWebSocketPeer
|
|
34
|
+
* Creates a typed connection wrapper around one IWebSocketPeer.
|
|
5
35
|
*/
|
|
6
36
|
function wrapSmartServePeer(peer) {
|
|
7
37
|
return {
|
|
@@ -54,6 +84,73 @@ function composeAbortSignals(configuredSignalArg, requestSignalArg) {
|
|
|
54
84
|
cleanup,
|
|
55
85
|
};
|
|
56
86
|
}
|
|
87
|
+
const packageClientLimits = Object.freeze({
|
|
88
|
+
textFrameBytes: TYPEDSOCKET_MAX_TEXT_FRAME_BYTES,
|
|
89
|
+
queuedTextFrames: TYPEDSOCKET_MAX_QUEUED_TEXT_FRAMES,
|
|
90
|
+
queuedTextBytes: TYPEDSOCKET_MAX_QUEUED_TEXT_BYTES,
|
|
91
|
+
concurrentHandlers: TYPEDSOCKET_MAX_CONCURRENT_CLIENT_HANDLERS,
|
|
92
|
+
retainedCallbacks: TYPEDSOCKET_MAX_RETAINED_CLIENT_CALLBACKS,
|
|
93
|
+
pendingRequests: TYPEDSOCKET_MAX_PENDING_CLIENT_REQUESTS,
|
|
94
|
+
outboundBufferedBytes: TYPEDSOCKET_MAX_OUTBOUND_BUFFERED_BYTES,
|
|
95
|
+
requestTimeoutMs: TYPEDSOCKET_MAX_REQUEST_TIMEOUT_MS,
|
|
96
|
+
connectionRestoreTimeoutMs: TYPEDSOCKET_MAX_CONNECTION_RESTORE_TIMEOUT_MS,
|
|
97
|
+
});
|
|
98
|
+
function normalizeClientLimits(limitsArg) {
|
|
99
|
+
const lower = (nameArg, valueArg, maximumArg) => {
|
|
100
|
+
const value = valueArg ?? maximumArg;
|
|
101
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > maximumArg) {
|
|
102
|
+
throw new RangeError(`TypedSocket client limit ${nameArg} must be a positive safe integer no greater than ${maximumArg}.`);
|
|
103
|
+
}
|
|
104
|
+
return value;
|
|
105
|
+
};
|
|
106
|
+
const normalized = {
|
|
107
|
+
textFrameBytes: lower('textFrameBytes', limitsArg?.textFrameBytes, packageClientLimits.textFrameBytes),
|
|
108
|
+
queuedTextFrames: lower('queuedTextFrames', limitsArg?.queuedTextFrames, packageClientLimits.queuedTextFrames),
|
|
109
|
+
queuedTextBytes: lower('queuedTextBytes', limitsArg?.queuedTextBytes, packageClientLimits.queuedTextBytes),
|
|
110
|
+
concurrentHandlers: lower('concurrentHandlers', limitsArg?.concurrentHandlers, packageClientLimits.concurrentHandlers),
|
|
111
|
+
retainedCallbacks: lower('retainedCallbacks', limitsArg?.retainedCallbacks, packageClientLimits.retainedCallbacks),
|
|
112
|
+
pendingRequests: lower('pendingRequests', limitsArg?.pendingRequests, packageClientLimits.pendingRequests),
|
|
113
|
+
outboundBufferedBytes: lower('outboundBufferedBytes', limitsArg?.outboundBufferedBytes, packageClientLimits.outboundBufferedBytes),
|
|
114
|
+
requestTimeoutMs: lower('requestTimeoutMs', limitsArg?.requestTimeoutMs, packageClientLimits.requestTimeoutMs),
|
|
115
|
+
connectionRestoreTimeoutMs: lower('connectionRestoreTimeoutMs', limitsArg?.connectionRestoreTimeoutMs, packageClientLimits.connectionRestoreTimeoutMs),
|
|
116
|
+
};
|
|
117
|
+
if (normalized.queuedTextBytes < normalized.textFrameBytes) {
|
|
118
|
+
throw new RangeError('TypedSocket queuedTextBytes must be at least textFrameBytes.');
|
|
119
|
+
}
|
|
120
|
+
return Object.freeze(normalized);
|
|
121
|
+
}
|
|
122
|
+
function normalizeReconnectInteger(nameArg, valueArg, defaultArg, maximumArg, allowZeroArg) {
|
|
123
|
+
const value = valueArg ?? defaultArg;
|
|
124
|
+
if (!Number.isSafeInteger(value)
|
|
125
|
+
|| value < (allowZeroArg ? 0 : 1)
|
|
126
|
+
|| value > maximumArg) {
|
|
127
|
+
throw new RangeError(`TypedSocket ${nameArg} must be ${allowZeroArg ? 'a non-negative' : 'a positive'} safe integer no greater than ${maximumArg}.`);
|
|
128
|
+
}
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
function isPlainRecord(valueArg) {
|
|
132
|
+
if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg))
|
|
133
|
+
return false;
|
|
134
|
+
const prototype = Object.getPrototypeOf(valueArg);
|
|
135
|
+
return prototype === Object.prototype || prototype === null;
|
|
136
|
+
}
|
|
137
|
+
function isLoopbackHostname(hostnameArg) {
|
|
138
|
+
const hostname = hostnameArg.toLowerCase().replace(/^\[(.*)\]$/, '$1');
|
|
139
|
+
if (hostname === 'localhost' || hostname.endsWith('.localhost') || hostname === '::1') {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
const octets = hostname.split('.');
|
|
143
|
+
return octets.length === 4
|
|
144
|
+
&& octets.every((octetArg) => /^\d{1,3}$/.test(octetArg) && Number(octetArg) <= 255)
|
|
145
|
+
&& Number(octets[0]) === 127;
|
|
146
|
+
}
|
|
147
|
+
function assertBoundedTextIdentifier(valueArg, labelArg, maximumBytesArg) {
|
|
148
|
+
if (typeof valueArg !== 'string'
|
|
149
|
+
|| valueArg.length === 0
|
|
150
|
+
|| textEncoder.encode(valueArg).byteLength > maximumBytesArg) {
|
|
151
|
+
throw new Error(`TypedSocket ${labelArg} must be a non-empty string of at most ${maximumBytesArg} UTF-8 bytes.`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
57
154
|
export class TypedSocket {
|
|
58
155
|
// ============================================================================
|
|
59
156
|
// STATIC METHODS
|
|
@@ -77,18 +174,31 @@ export class TypedSocket {
|
|
|
77
174
|
* ```
|
|
78
175
|
*/
|
|
79
176
|
static async createClient(typedrouterArg, serverUrlArg, options = {}) {
|
|
80
|
-
|
|
81
|
-
autoReconnect
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
177
|
+
if (options.autoReconnect !== undefined && typeof options.autoReconnect !== 'boolean') {
|
|
178
|
+
throw new TypeError('TypedSocket autoReconnect must be a boolean.');
|
|
179
|
+
}
|
|
180
|
+
const maxRetries = normalizeReconnectInteger('maxRetries', options.maxRetries, TYPEDSOCKET_MAX_RECONNECT_RETRIES, TYPEDSOCKET_MAX_RECONNECT_RETRIES, true);
|
|
181
|
+
const initialBackoffMs = normalizeReconnectInteger('initialBackoffMs', options.initialBackoffMs, 1000, TYPEDSOCKET_MAX_RECONNECT_BACKOFF_MS, false);
|
|
182
|
+
const maxBackoffMs = normalizeReconnectInteger('maxBackoffMs', options.maxBackoffMs, TYPEDSOCKET_MAX_RECONNECT_BACKOFF_MS, TYPEDSOCKET_MAX_RECONNECT_BACKOFF_MS, false);
|
|
183
|
+
if (initialBackoffMs > maxBackoffMs) {
|
|
184
|
+
throw new RangeError('TypedSocket initialBackoffMs must not exceed maxBackoffMs.');
|
|
185
|
+
}
|
|
186
|
+
const opts = {
|
|
187
|
+
autoReconnect: options.autoReconnect ?? true,
|
|
188
|
+
maxRetries,
|
|
189
|
+
initialBackoffMs,
|
|
190
|
+
maxBackoffMs,
|
|
191
|
+
abortSignal: options.abortSignal,
|
|
192
|
+
nativeByteCapabilityMode: options.nativeByteCapabilityMode ?? 'optional',
|
|
193
|
+
limits: normalizeClientLimits(options.limits),
|
|
194
|
+
restoreConnection: options.restoreConnection,
|
|
85
195
|
};
|
|
86
|
-
const
|
|
87
|
-
const typedSocket = new TypedSocket('client', typedrouterArg);
|
|
196
|
+
const typedSocket = new TypedSocket('client', typedrouterArg, opts.nativeByteCapabilityMode);
|
|
88
197
|
typedSocket.clientOptions = opts;
|
|
89
198
|
typedSocket.serverUrl = serverUrlArg;
|
|
90
199
|
typedSocket.currentBackoff = opts.initialBackoffMs;
|
|
91
200
|
if (opts.abortSignal?.aborted) {
|
|
201
|
+
await typedSocket.stop();
|
|
92
202
|
throw typedSocket.createAbortError();
|
|
93
203
|
}
|
|
94
204
|
if (opts.abortSignal) {
|
|
@@ -119,7 +229,7 @@ export class TypedSocket {
|
|
|
119
229
|
*
|
|
120
230
|
* Call attachSmartServe() after constructing the SmartServe transport.
|
|
121
231
|
*/
|
|
122
|
-
static createServer(typedRouterOrRoutersArg) {
|
|
232
|
+
static createServer(typedRouterOrRoutersArg, optionsArg = {}) {
|
|
123
233
|
const typedRouters = Array.isArray(typedRouterOrRoutersArg)
|
|
124
234
|
? [...typedRouterOrRoutersArg]
|
|
125
235
|
: [typedRouterOrRoutersArg];
|
|
@@ -129,8 +239,9 @@ export class TypedSocket {
|
|
|
129
239
|
if (new Set(typedRouters).size !== typedRouters.length) {
|
|
130
240
|
throw new Error('TypedSocket.createServer received the same TypedRouter more than once.');
|
|
131
241
|
}
|
|
242
|
+
const typedSocket = new TypedSocket('server', typedRouters[0], optionsArg.nativeByteCapabilityMode ?? 'optional', optionsArg.nativeByteAuthorizationAdapter, optionsArg.clientTagPolicy);
|
|
132
243
|
const protocolRouter = new plugins.typedrequest.TypedRouter();
|
|
133
|
-
TypedSocket.
|
|
244
|
+
TypedSocket.registerProtocolHandlers(protocolRouter, typedSocket);
|
|
134
245
|
const protocolMethods = new Set(protocolRouter.getMethodNames());
|
|
135
246
|
for (const typedRouter of typedRouters) {
|
|
136
247
|
const collision = typedRouter
|
|
@@ -141,20 +252,25 @@ export class TypedSocket {
|
|
|
141
252
|
}
|
|
142
253
|
}
|
|
143
254
|
const detachProtocolRouters = [];
|
|
255
|
+
const detachLegacyPolicies = [];
|
|
144
256
|
try {
|
|
145
257
|
for (const typedRouter of typedRouters) {
|
|
146
258
|
detachProtocolRouters.push(typedRouter.addFallbackRouter(protocolRouter));
|
|
259
|
+
detachLegacyPolicies.push(typedRouter.registerLegacyVirtualStreamPolicy('deny'));
|
|
147
260
|
}
|
|
148
261
|
}
|
|
149
262
|
catch (error) {
|
|
263
|
+
for (const detachLegacyPolicy of detachLegacyPolicies.reverse()) {
|
|
264
|
+
detachLegacyPolicy();
|
|
265
|
+
}
|
|
150
266
|
for (const detachProtocolRouter of detachProtocolRouters.reverse()) {
|
|
151
267
|
detachProtocolRouter();
|
|
152
268
|
}
|
|
153
269
|
throw error;
|
|
154
270
|
}
|
|
155
|
-
const typedSocket = new TypedSocket('server', typedRouters[0]);
|
|
156
271
|
typedSocket.serverTypedRouters = typedRouters;
|
|
157
272
|
typedSocket.detachProtocolRouters = detachProtocolRouters;
|
|
273
|
+
typedSocket.detachLegacyVirtualStreamPolicies = detachLegacyPolicies;
|
|
158
274
|
return typedSocket;
|
|
159
275
|
}
|
|
160
276
|
/**
|
|
@@ -171,55 +287,69 @@ export class TypedSocket {
|
|
|
171
287
|
* const smartServe = new SmartServe({
|
|
172
288
|
* port: 3000,
|
|
173
289
|
* websocket: {
|
|
174
|
-
* typedRouter
|
|
175
|
-
* onConnectionOpen: (peer) => peer.tags.add('client')
|
|
290
|
+
* typedRouter
|
|
176
291
|
* }
|
|
177
292
|
* });
|
|
178
293
|
* await smartServe.start();
|
|
179
294
|
* const typedSocket = TypedSocket.fromSmartServe(smartServe, typedRouter);
|
|
295
|
+
* // Authenticated server handlers assign protected connection metadata with:
|
|
296
|
+
* // typedSocket.setServerTag(peer, 'authenticated', { userId });
|
|
180
297
|
* ```
|
|
181
298
|
*/
|
|
182
|
-
static fromSmartServe(smartServeArg, typedRouterArg) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
.attachSmartServe(smartServeArg);
|
|
299
|
+
static fromSmartServe(smartServeArg, typedRouterArg, optionsArg = {}) {
|
|
300
|
+
const typedSocket = TypedSocket.createServer(typedRouterArg, optionsArg);
|
|
301
|
+
try {
|
|
302
|
+
return typedSocket.attachSmartServe(smartServeArg);
|
|
303
|
+
}
|
|
304
|
+
catch (errorArg) {
|
|
305
|
+
typedSocket.releaseServerComposition();
|
|
306
|
+
throw errorArg;
|
|
307
|
+
}
|
|
186
308
|
}
|
|
187
309
|
/**
|
|
188
310
|
* Registers built-in TypedHandlers for tag management
|
|
189
311
|
*/
|
|
190
|
-
static
|
|
191
|
-
// Set tag handler
|
|
312
|
+
static registerProtocolHandlers(typedRouter, typedSocketArg) {
|
|
192
313
|
typedRouter.addTypedHandler(new plugins.typedrequest.TypedHandler('__typedsocket_setTag', async (data, meta) => {
|
|
193
|
-
const peer = meta
|
|
194
|
-
|
|
195
|
-
console.warn('setTag: No peer found in request context');
|
|
196
|
-
return { success: false };
|
|
197
|
-
}
|
|
198
|
-
peer.tags.add(data.name);
|
|
199
|
-
peer.data.set(`${TAG_PREFIX}${data.name}`, data.payload);
|
|
200
|
-
return { success: true };
|
|
314
|
+
const peer = typedSocketArg.findServerPeerFromRequest(meta);
|
|
315
|
+
return typedSocketArg.tagPolicyManager.setClientTag(peer, data?.name, data?.payload);
|
|
201
316
|
}));
|
|
202
|
-
// Remove tag handler
|
|
203
317
|
typedRouter.addTypedHandler(new plugins.typedrequest.TypedHandler('__typedsocket_removeTag', async (data, meta) => {
|
|
204
|
-
const peer = meta
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
peer.
|
|
210
|
-
|
|
211
|
-
|
|
318
|
+
const peer = typedSocketArg.findServerPeerFromRequest(meta);
|
|
319
|
+
return typedSocketArg.tagPolicyManager.removeClientTag(peer, data?.name);
|
|
320
|
+
}));
|
|
321
|
+
typedRouter.addTypedHandler(new plugins.typedrequest.TypedHandler('__typedsocket_negotiateCapabilities', async (data, meta) => {
|
|
322
|
+
const peer = typedSocketArg.findServerPeerFromRequest(meta);
|
|
323
|
+
if (!peer || !Array.isArray(data.capabilities)) {
|
|
324
|
+
return {
|
|
325
|
+
protocolMajor: NATIVE_BYTE_PROTOCOL_MAJOR,
|
|
326
|
+
capabilities: [],
|
|
327
|
+
required: false,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
const response = typedSocketArg.nativeBytes.negotiateServerPeer(peer, {
|
|
331
|
+
protocolMajor: data.protocolMajor,
|
|
332
|
+
capabilities: data.capabilities,
|
|
333
|
+
});
|
|
334
|
+
return {
|
|
335
|
+
protocolMajor: response.protocolMajor,
|
|
336
|
+
capabilities: [...response.capabilities],
|
|
337
|
+
required: response.required,
|
|
338
|
+
};
|
|
212
339
|
}));
|
|
213
340
|
}
|
|
214
341
|
// ============================================================================
|
|
215
342
|
// CONSTRUCTOR
|
|
216
343
|
// ============================================================================
|
|
217
|
-
constructor(sideArg, typedrouterArg) {
|
|
344
|
+
constructor(sideArg, typedrouterArg, nativeByteCapabilityModeArg = 'optional', nativeByteAuthorizationAdapterArg, clientTagPolicyArg) {
|
|
218
345
|
// Connection status observable
|
|
219
346
|
this.statusSubject = new plugins.smartrx.rxjs.Subject();
|
|
220
347
|
this.connectionStatus = 'new';
|
|
221
348
|
// Client-specific properties
|
|
222
349
|
this.websocket = null;
|
|
350
|
+
this.connectionGeneration = 0;
|
|
351
|
+
this.clientConnectionState = null;
|
|
352
|
+
this.retainedClientCallbacks = 0;
|
|
223
353
|
this.clientOptions = null;
|
|
224
354
|
this.serverUrl = '';
|
|
225
355
|
this.retryCount = 0;
|
|
@@ -227,20 +357,54 @@ export class TypedSocket {
|
|
|
227
357
|
this.stopped = false;
|
|
228
358
|
this.stopListeners = new Set();
|
|
229
359
|
this.pendingRequests = new Map();
|
|
230
|
-
//
|
|
231
|
-
// the fresh server-side connection (server tags die with the old socket).
|
|
360
|
+
// Acknowledged state is diagnostic state for the current server connection.
|
|
232
361
|
this.clientTags = new Map();
|
|
233
|
-
this.
|
|
362
|
+
this.clientTagRevisions = new Map();
|
|
363
|
+
// Desired state survives transport failure and is reconciled on every connection.
|
|
364
|
+
this.desiredClientTags = new Map();
|
|
365
|
+
this.clientTagDesiredMutationQueues = new Map();
|
|
366
|
+
this.clientTagMutationSequence = 0;
|
|
367
|
+
this.clientTagMutationTails = new Map();
|
|
368
|
+
this.retainedClientTagMutations = 0;
|
|
369
|
+
this.retainedClientTagMutationsByName = new Map();
|
|
234
370
|
// Server-specific properties (SmartServe mode)
|
|
235
371
|
this.smartServeRef = null;
|
|
236
372
|
this.serverTypedRouters = [];
|
|
237
373
|
this.detachProtocolRouters = [];
|
|
374
|
+
this.detachLegacyVirtualStreamPolicies = [];
|
|
238
375
|
this.serverStopping = false;
|
|
376
|
+
this.serverLifecycleGeneration = 0;
|
|
239
377
|
this.unsubscribeSmartServeConnectionClose = null;
|
|
378
|
+
this.detachNativeStreamResolvers = [];
|
|
379
|
+
this.detachResponseAuthorityGuards = [];
|
|
240
380
|
this.pendingServerRequests = new Map();
|
|
241
|
-
this.
|
|
381
|
+
this.pendingServerRequestIdsByPeer = new Map();
|
|
382
|
+
this.retainedServerInterests = 0;
|
|
383
|
+
this.retainedServerInterestsByPeer = new Map();
|
|
242
384
|
this.side = sideArg;
|
|
243
385
|
this.typedrouter = typedrouterArg;
|
|
386
|
+
this.nativeBytes = new NativeByteManager({
|
|
387
|
+
side: sideArg,
|
|
388
|
+
capabilityMode: nativeByteCapabilityModeArg,
|
|
389
|
+
});
|
|
390
|
+
this.nativeByteAuthorizationAdapter = nativeByteAuthorizationAdapterArg;
|
|
391
|
+
this.tagPolicyManager = new TypedSocketTagPolicyManager(clientTagPolicyArg);
|
|
392
|
+
this.webSocketTransportOwner = this.nativeBytes.webSocketTransportOwner;
|
|
393
|
+
if (sideArg === 'client') {
|
|
394
|
+
let detachLegacyPolicy;
|
|
395
|
+
let detachNativeStreamResolver;
|
|
396
|
+
try {
|
|
397
|
+
detachLegacyPolicy = typedrouterArg.registerLegacyVirtualStreamPolicy('deny');
|
|
398
|
+
detachNativeStreamResolver = typedrouterArg.registerNativeStreamTransportResolver(() => this.nativeBytes.getClientNativeStreamTransport());
|
|
399
|
+
this.detachLegacyVirtualStreamPolicies.push(detachLegacyPolicy);
|
|
400
|
+
this.detachNativeStreamResolvers.push(detachNativeStreamResolver);
|
|
401
|
+
}
|
|
402
|
+
catch (errorArg) {
|
|
403
|
+
detachNativeStreamResolver?.();
|
|
404
|
+
detachLegacyPolicy?.();
|
|
405
|
+
throw errorArg;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
244
408
|
}
|
|
245
409
|
/**
|
|
246
410
|
* Attaches the SmartServe transport after server router composition.
|
|
@@ -258,12 +422,51 @@ export class TypedSocket {
|
|
|
258
422
|
}
|
|
259
423
|
throw new Error('TypedSocket server is already attached to a SmartServe instance.');
|
|
260
424
|
}
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
425
|
+
const detachResolvers = [];
|
|
426
|
+
const detachResponseGuards = [];
|
|
427
|
+
let unsubscribe;
|
|
428
|
+
let nativeServerAttached = false;
|
|
429
|
+
try {
|
|
430
|
+
for (const typedRouter of this.serverTypedRouters) {
|
|
431
|
+
detachResponseGuards.push(typedRouter.registerIncomingResponseAuthorityGuard((responseArg, contextArg) => {
|
|
432
|
+
return this.authorizeIncomingServerResponse(responseArg, contextArg.typedRouter, contextArg.trustedLocalData);
|
|
433
|
+
}));
|
|
434
|
+
detachResolvers.push(typedRouter.registerNativeStreamTransportResolver((trustedLocalDataArg) => {
|
|
435
|
+
const peer = this.smartServeRef
|
|
436
|
+
?.getWebSocketConnections()
|
|
437
|
+
.find((peerArg) => peerArg === trustedLocalDataArg.peer);
|
|
438
|
+
return peer ? this.nativeBytes.getServerNativeStreamTransport(peer) : undefined;
|
|
439
|
+
}));
|
|
440
|
+
}
|
|
441
|
+
unsubscribe = smartServeArg.subscribeWebSocketConnectionClose((peerArg) => {
|
|
442
|
+
this.tagPolicyManager.handlePeerClose(peerArg);
|
|
443
|
+
this.cancelPendingServerRequestsForPeer(peerArg, new Error(`TypedSocket target connection closed: ${peerArg.id}`));
|
|
444
|
+
});
|
|
445
|
+
this.nativeBytes.attachServer();
|
|
446
|
+
nativeServerAttached = true;
|
|
447
|
+
this.serverLifecycleGeneration++;
|
|
448
|
+
this.tagPolicyManager.setAttachedPeersProvider(() => smartServeArg.getWebSocketConnections().filter((peerArg) => {
|
|
449
|
+
const routingSurface = peerArg.routingSurface;
|
|
450
|
+
return Boolean(routingSurface && this.serverTypedRouters.includes(routingSurface));
|
|
451
|
+
}));
|
|
452
|
+
this.smartServeRef = smartServeArg;
|
|
453
|
+
this.detachNativeStreamResolvers = detachResolvers;
|
|
454
|
+
this.detachResponseAuthorityGuards = detachResponseGuards;
|
|
455
|
+
this.unsubscribeSmartServeConnectionClose = unsubscribe;
|
|
456
|
+
return this;
|
|
457
|
+
}
|
|
458
|
+
catch (errorArg) {
|
|
459
|
+
unsubscribe?.();
|
|
460
|
+
if (nativeServerAttached) {
|
|
461
|
+
this.nativeBytes.detachServer();
|
|
462
|
+
}
|
|
463
|
+
this.tagPolicyManager.setAttachedPeersProvider(undefined);
|
|
464
|
+
for (const detachResponseGuard of detachResponseGuards.reverse())
|
|
465
|
+
detachResponseGuard();
|
|
466
|
+
for (const detachResolver of detachResolvers.reverse())
|
|
467
|
+
detachResolver();
|
|
468
|
+
throw errorArg;
|
|
469
|
+
}
|
|
267
470
|
}
|
|
268
471
|
// ============================================================================
|
|
269
472
|
// CLIENT METHODS
|
|
@@ -299,28 +502,58 @@ export class TypedSocket {
|
|
|
299
502
|
}
|
|
300
503
|
};
|
|
301
504
|
this.updateStatus('connecting');
|
|
302
|
-
// Convert HTTP URL to WebSocket URL
|
|
303
505
|
const wsUrl = this.toWebSocketUrl(this.serverUrl);
|
|
304
|
-
this.
|
|
305
|
-
this.
|
|
506
|
+
const logEndpoint = this.toRedactedLogEndpoint(wsUrl);
|
|
507
|
+
this.logDebug(`TypedSocket connecting to ${logEndpoint}...`);
|
|
508
|
+
if (this.clientConnectionState) {
|
|
509
|
+
this.abortClientConnectionState(this.clientConnectionState, new Error('TypedSocket connection replaced'));
|
|
510
|
+
}
|
|
511
|
+
const generation = ++this.connectionGeneration;
|
|
512
|
+
const websocket = new WebSocket(wsUrl);
|
|
513
|
+
websocket.binaryType = 'arraybuffer';
|
|
514
|
+
this.websocket = websocket;
|
|
515
|
+
const connectionState = {
|
|
516
|
+
generation,
|
|
517
|
+
connectionId: plugins.smartstring.create.createCryptoRandomString(),
|
|
518
|
+
websocket,
|
|
519
|
+
abortController: new AbortController(),
|
|
520
|
+
queuedTextFrames: [],
|
|
521
|
+
queuedTextBytes: 0,
|
|
522
|
+
activeHandlers: 0,
|
|
523
|
+
};
|
|
524
|
+
this.clientConnectionState = connectionState;
|
|
525
|
+
this.nativeBytes.bindClientConnection(websocket, generation);
|
|
306
526
|
abortConnection = () => {
|
|
307
|
-
this.websocket
|
|
527
|
+
if (this.websocket === websocket && this.connectionGeneration === generation) {
|
|
528
|
+
websocket.close();
|
|
529
|
+
}
|
|
308
530
|
settleConnection(this.createAbortError());
|
|
309
531
|
};
|
|
310
532
|
this.stopListeners.add(abortConnection);
|
|
311
533
|
this.clientOptions?.abortSignal?.addEventListener('abort', abortConnection, { once: true });
|
|
312
534
|
connectionTimeout = setTimeout(() => {
|
|
313
535
|
if (this.connectionStatus !== 'connected') {
|
|
314
|
-
this.logTransient(`TypedSocket connection timeout for ${
|
|
315
|
-
this.websocket
|
|
536
|
+
this.logTransient(`TypedSocket connection timeout for ${logEndpoint}`);
|
|
537
|
+
if (this.websocket === websocket && this.connectionGeneration === generation) {
|
|
538
|
+
websocket.close();
|
|
539
|
+
}
|
|
316
540
|
settleConnection(new Error('Connection timeout'));
|
|
317
541
|
}
|
|
318
542
|
}, 10000);
|
|
319
|
-
|
|
320
|
-
const openedWebsocket = this.websocket;
|
|
543
|
+
websocket.onopen = async () => {
|
|
321
544
|
try {
|
|
322
|
-
|
|
323
|
-
|
|
545
|
+
if (this.websocket !== websocket || this.connectionGeneration !== generation)
|
|
546
|
+
return;
|
|
547
|
+
await this.negotiateClientCapabilities(websocket, generation);
|
|
548
|
+
if (this.websocket !== websocket || this.connectionGeneration !== generation)
|
|
549
|
+
return;
|
|
550
|
+
await this.restoreClientConnection(connectionState);
|
|
551
|
+
if (this.websocket !== websocket || this.connectionGeneration !== generation)
|
|
552
|
+
return;
|
|
553
|
+
await this.reapplyClientTags(connectionState);
|
|
554
|
+
if (this.websocket !== websocket
|
|
555
|
+
|| this.connectionGeneration !== generation
|
|
556
|
+
|| websocket.readyState !== WebSocket.OPEN) {
|
|
324
557
|
throw new Error('TypedSocket connection changed while restoring client tags');
|
|
325
558
|
}
|
|
326
559
|
this.logDebug('TypedSocket connected and client registration restored!');
|
|
@@ -333,15 +566,29 @@ export class TypedSocket {
|
|
|
333
566
|
const restorationError = error instanceof Error
|
|
334
567
|
? error
|
|
335
568
|
: new Error(String(error));
|
|
336
|
-
this.logTransient(
|
|
569
|
+
this.logTransient('TypedSocket client registration restoration failed.');
|
|
337
570
|
settleConnection(restorationError);
|
|
338
|
-
|
|
571
|
+
websocket.close();
|
|
339
572
|
}
|
|
340
573
|
};
|
|
341
|
-
|
|
342
|
-
|
|
574
|
+
websocket.onmessage = (event) => {
|
|
575
|
+
if (this.websocket !== websocket || this.connectionGeneration !== generation)
|
|
576
|
+
return;
|
|
577
|
+
if (typeof event.data === 'string') {
|
|
578
|
+
this.enqueueClientTextFrame(connectionState, event.data);
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
if (event.data instanceof ArrayBuffer || ArrayBuffer.isView(event.data)) {
|
|
582
|
+
this.nativeBytes.enqueueClientRawFrame(websocket, generation, event.data);
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
websocket.close(1003, 'Unsupported WebSocket payload');
|
|
343
586
|
};
|
|
344
|
-
|
|
587
|
+
websocket.onclose = () => {
|
|
588
|
+
if (this.websocket !== websocket || this.connectionGeneration !== generation)
|
|
589
|
+
return;
|
|
590
|
+
this.abortClientConnectionState(connectionState, new Error('TypedSocket disconnected'));
|
|
591
|
+
this.nativeBytes.unbindClientConnection(websocket, generation, new Error('TypedSocket disconnected'));
|
|
345
592
|
if (this.connectionStatus === 'connected') {
|
|
346
593
|
this.handleDisconnect();
|
|
347
594
|
}
|
|
@@ -352,10 +599,12 @@ export class TypedSocket {
|
|
|
352
599
|
: new Error('TypedSocket connection closed before it opened'));
|
|
353
600
|
}
|
|
354
601
|
};
|
|
355
|
-
|
|
602
|
+
websocket.onerror = () => {
|
|
603
|
+
if (this.websocket !== websocket || this.connectionGeneration !== generation)
|
|
604
|
+
return;
|
|
356
605
|
// transient socket errors (network blips, proxy TLS hiccups) are expected
|
|
357
606
|
// and handled by reconnection; only exhausted retries surface as errors
|
|
358
|
-
this.logTransient(`TypedSocket websocket error on ${
|
|
607
|
+
this.logTransient(`TypedSocket websocket error on ${logEndpoint}`);
|
|
359
608
|
};
|
|
360
609
|
try {
|
|
361
610
|
await done.promise;
|
|
@@ -364,7 +613,10 @@ export class TypedSocket {
|
|
|
364
613
|
if (connectionTimeout) {
|
|
365
614
|
clearTimeout(connectionTimeout);
|
|
366
615
|
}
|
|
367
|
-
if (
|
|
616
|
+
if (!(err instanceof NativeByteCapabilityError)
|
|
617
|
+
&& !(err instanceof TypedSocketClientTagDeniedError)
|
|
618
|
+
&& !(err instanceof TypedSocketConnectionRestoreDeniedError)
|
|
619
|
+
&& this.shouldReconnect()) {
|
|
368
620
|
await this.scheduleReconnect();
|
|
369
621
|
if (this.connectionStatus !== 'connected') {
|
|
370
622
|
throw this.stopped || this.clientOptions?.abortSignal?.aborted ? this.createAbortError() : err;
|
|
@@ -375,11 +627,144 @@ export class TypedSocket {
|
|
|
375
627
|
}
|
|
376
628
|
}
|
|
377
629
|
}
|
|
630
|
+
async negotiateClientCapabilities(websocketArg, generationArg) {
|
|
631
|
+
const advertisement = this.nativeBytes.getClientNegotiationAdvertisement();
|
|
632
|
+
let negotiatedResponse;
|
|
633
|
+
try {
|
|
634
|
+
const request = {
|
|
635
|
+
method: '__typedsocket_negotiateCapabilities',
|
|
636
|
+
request: {
|
|
637
|
+
protocolMajor: advertisement.protocolMajor,
|
|
638
|
+
capabilities: [...advertisement.capabilities],
|
|
639
|
+
},
|
|
640
|
+
response: {
|
|
641
|
+
protocolMajor: 0,
|
|
642
|
+
capabilities: [],
|
|
643
|
+
required: false,
|
|
644
|
+
},
|
|
645
|
+
};
|
|
646
|
+
const response = await this.sendRequest(request, {
|
|
647
|
+
timeoutMs: Math.min(10_000, this.requireClientOptions().limits.requestTimeoutMs),
|
|
648
|
+
});
|
|
649
|
+
if (response.error)
|
|
650
|
+
throw new NativeByteCapabilityError(response.error.text);
|
|
651
|
+
if (!response.response
|
|
652
|
+
|| !Number.isSafeInteger(response.response.protocolMajor)
|
|
653
|
+
|| !Array.isArray(response.response.capabilities)
|
|
654
|
+
|| response.response.capabilities.some((capabilityArg) => typeof capabilityArg !== 'string')
|
|
655
|
+
|| typeof response.response.required !== 'boolean') {
|
|
656
|
+
throw new NativeByteCapabilityError('TypedSocket server returned malformed capabilities');
|
|
657
|
+
}
|
|
658
|
+
negotiatedResponse = response.response;
|
|
659
|
+
}
|
|
660
|
+
catch (errorArg) {
|
|
661
|
+
if (this.clientOptions?.nativeByteCapabilityMode === 'required') {
|
|
662
|
+
throw errorArg instanceof NativeByteCapabilityError
|
|
663
|
+
? errorArg
|
|
664
|
+
: new NativeByteCapabilityError('Required native-byte-v1 negotiation failed', {
|
|
665
|
+
cause: errorArg,
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
this.nativeBytes.failOptionalClientNegotiation(websocketArg, generationArg);
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
if (negotiatedResponse.required
|
|
672
|
+
&& (negotiatedResponse.protocolMajor !== NATIVE_BYTE_PROTOCOL_MAJOR
|
|
673
|
+
|| negotiatedResponse.capabilities.length !== 1
|
|
674
|
+
|| negotiatedResponse.capabilities[0] !== NATIVE_BYTE_PROTOCOL
|
|
675
|
+
|| this.clientOptions?.nativeByteCapabilityMode === 'disabled')) {
|
|
676
|
+
throw new NativeByteCapabilityError('TypedSocket server requires native-byte-v1');
|
|
677
|
+
}
|
|
678
|
+
this.nativeBytes.completeClientNegotiation(websocketArg, generationArg, negotiatedResponse);
|
|
679
|
+
}
|
|
680
|
+
async restoreClientConnection(stateArg) {
|
|
681
|
+
const restoreConnection = this.clientOptions?.restoreConnection;
|
|
682
|
+
if (!restoreConnection)
|
|
683
|
+
return;
|
|
684
|
+
const limits = this.requireClientOptions().limits;
|
|
685
|
+
if (this.retainedClientCallbacks >= limits.retainedCallbacks) {
|
|
686
|
+
throw new TypedSocketConnectionRestoreDeniedError('TypedSocket connection restoration callback capacity exhausted.');
|
|
687
|
+
}
|
|
688
|
+
const timeoutMs = limits.connectionRestoreTimeoutMs;
|
|
689
|
+
const deadline = Date.now() + timeoutMs;
|
|
690
|
+
const restorationAbortController = new AbortController();
|
|
691
|
+
const interruptRestoration = () => {
|
|
692
|
+
restorationAbortController.abort(new TypedSocketConnectionRestoreDeniedError('TypedSocket connection restoration was interrupted.'));
|
|
693
|
+
};
|
|
694
|
+
stateArg.abortController.signal.addEventListener('abort', interruptRestoration, { once: true });
|
|
695
|
+
if (stateArg.abortController.signal.aborted)
|
|
696
|
+
interruptRestoration();
|
|
697
|
+
const createTypedRequest = (methodNameArg) => {
|
|
698
|
+
if (restorationAbortController.signal.aborted) {
|
|
699
|
+
throw new TypedSocketConnectionRestoreDeniedError('TypedSocket connection restoration request was interrupted.');
|
|
700
|
+
}
|
|
701
|
+
const remainingMs = deadline - Date.now();
|
|
702
|
+
if (!Number.isSafeInteger(remainingMs) || remainingMs < 1) {
|
|
703
|
+
throw new TypedSocketConnectionRestoreDeniedError('TypedSocket connection restoration request exceeded its deadline.');
|
|
704
|
+
}
|
|
705
|
+
return this.createTypedRequest(methodNameArg, undefined, {
|
|
706
|
+
timeoutMs: Math.min(remainingMs + 1, limits.requestTimeoutMs),
|
|
707
|
+
abortSignal: restorationAbortController.signal,
|
|
708
|
+
});
|
|
709
|
+
};
|
|
710
|
+
this.retainedClientCallbacks++;
|
|
711
|
+
const callbackOutcome = Promise.resolve().then(() => restoreConnection(Object.freeze({
|
|
712
|
+
connectionId: stateArg.connectionId,
|
|
713
|
+
abortSignal: restorationAbortController.signal,
|
|
714
|
+
deadline,
|
|
715
|
+
createTypedRequest,
|
|
716
|
+
})));
|
|
717
|
+
void callbackOutcome.then(() => { this.retainedClientCallbacks--; }, () => { this.retainedClientCallbacks--; });
|
|
718
|
+
let timeout;
|
|
719
|
+
let abortListener;
|
|
720
|
+
const interrupted = new Promise((_resolveArg, rejectArg) => {
|
|
721
|
+
timeout = setTimeout(() => {
|
|
722
|
+
const error = new TypedSocketConnectionRestoreDeniedError('TypedSocket connection restoration timed out.');
|
|
723
|
+
restorationAbortController.abort(error);
|
|
724
|
+
rejectArg(error);
|
|
725
|
+
}, timeoutMs);
|
|
726
|
+
abortListener = () => {
|
|
727
|
+
const reason = restorationAbortController.signal.reason;
|
|
728
|
+
rejectArg(reason instanceof TypedSocketConnectionRestoreDeniedError
|
|
729
|
+
? reason
|
|
730
|
+
: new TypedSocketConnectionRestoreDeniedError('TypedSocket connection restoration was interrupted.'));
|
|
731
|
+
};
|
|
732
|
+
restorationAbortController.signal.addEventListener('abort', abortListener, { once: true });
|
|
733
|
+
if (restorationAbortController.signal.aborted)
|
|
734
|
+
abortListener();
|
|
735
|
+
});
|
|
736
|
+
try {
|
|
737
|
+
await Promise.race([callbackOutcome, interrupted]);
|
|
738
|
+
}
|
|
739
|
+
catch (errorArg) {
|
|
740
|
+
if (errorArg instanceof TypedSocketConnectionRestoreDeniedError)
|
|
741
|
+
throw errorArg;
|
|
742
|
+
throw new TypedSocketConnectionRestoreDeniedError('TypedSocket connection restoration was denied.');
|
|
743
|
+
}
|
|
744
|
+
finally {
|
|
745
|
+
if (timeout)
|
|
746
|
+
clearTimeout(timeout);
|
|
747
|
+
if (abortListener) {
|
|
748
|
+
restorationAbortController.signal.removeEventListener('abort', abortListener);
|
|
749
|
+
}
|
|
750
|
+
stateArg.abortController.signal.removeEventListener('abort', interruptRestoration);
|
|
751
|
+
restorationAbortController.abort(new TypedSocketConnectionRestoreDeniedError('TypedSocket connection restoration callback completed.'));
|
|
752
|
+
}
|
|
753
|
+
if (!this.isCurrentClientConnection(stateArg)) {
|
|
754
|
+
throw new TypedSocketConnectionRestoreDeniedError('TypedSocket connection changed during restoration.');
|
|
755
|
+
}
|
|
756
|
+
}
|
|
378
757
|
/**
|
|
379
758
|
* Converts an HTTP(S) URL to a WebSocket URL
|
|
380
759
|
*/
|
|
381
760
|
toWebSocketUrl(url) {
|
|
382
761
|
const parsed = new URL(url);
|
|
762
|
+
if (parsed.username || parsed.password) {
|
|
763
|
+
throw new Error('TypedSocket server URL must not contain userinfo.');
|
|
764
|
+
}
|
|
765
|
+
if (parsed.hash) {
|
|
766
|
+
throw new Error('TypedSocket server URL must not contain a fragment.');
|
|
767
|
+
}
|
|
383
768
|
const wsProtocol = (() => {
|
|
384
769
|
switch (parsed.protocol) {
|
|
385
770
|
case 'http:':
|
|
@@ -392,30 +777,137 @@ export class TypedSocket {
|
|
|
392
777
|
throw new Error('TypedSocket server URL must use http, https, ws, or wss.');
|
|
393
778
|
}
|
|
394
779
|
})();
|
|
395
|
-
|
|
780
|
+
if (wsProtocol === 'ws:' && !isLoopbackHostname(parsed.hostname)) {
|
|
781
|
+
throw new Error('TypedSocket insecure WebSocket transport is restricted to loopback hosts.');
|
|
782
|
+
}
|
|
783
|
+
parsed.protocol = wsProtocol;
|
|
784
|
+
return parsed.toString();
|
|
396
785
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
786
|
+
toRedactedLogEndpoint(urlArg) {
|
|
787
|
+
const parsed = new URL(urlArg);
|
|
788
|
+
return `${parsed.protocol}//${parsed.host}`;
|
|
789
|
+
}
|
|
790
|
+
enqueueClientTextFrame(stateArg, textArg) {
|
|
791
|
+
if (!this.isCurrentClientConnection(stateArg))
|
|
792
|
+
return;
|
|
793
|
+
const limits = this.requireClientOptions().limits;
|
|
794
|
+
const byteLength = textEncoder.encode(textArg).byteLength;
|
|
795
|
+
if (byteLength > limits.textFrameBytes) {
|
|
796
|
+
stateArg.websocket.close(1009, 'TypedSocket text frame exceeds package limit');
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
if (stateArg.queuedTextFrames.length >= limits.queuedTextFrames
|
|
800
|
+
|| stateArg.queuedTextBytes + byteLength > limits.queuedTextBytes) {
|
|
801
|
+
stateArg.websocket.close(1008, 'TypedSocket text queue exceeds package limit');
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
stateArg.queuedTextFrames.push({ text: textArg, byteLength });
|
|
805
|
+
stateArg.queuedTextBytes += byteLength;
|
|
806
|
+
this.drainClientTextFrames(stateArg);
|
|
807
|
+
}
|
|
808
|
+
drainClientTextFrames(stateArg) {
|
|
809
|
+
const limits = this.requireClientOptions().limits;
|
|
810
|
+
while (this.isCurrentClientConnection(stateArg)
|
|
811
|
+
&& !stateArg.abortController.signal.aborted
|
|
812
|
+
&& stateArg.queuedTextFrames.length > 0
|
|
813
|
+
&& stateArg.activeHandlers < limits.concurrentHandlers) {
|
|
814
|
+
if (this.retainedClientCallbacks >= limits.retainedCallbacks) {
|
|
815
|
+
stateArg.websocket.close(1013, 'TypedSocket callback capacity exhausted');
|
|
409
816
|
return;
|
|
410
817
|
}
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
818
|
+
const frame = stateArg.queuedTextFrames.shift();
|
|
819
|
+
if (!frame)
|
|
820
|
+
return;
|
|
821
|
+
stateArg.queuedTextBytes -= frame.byteLength;
|
|
822
|
+
stateArg.activeHandlers++;
|
|
823
|
+
this.retainedClientCallbacks++;
|
|
824
|
+
void this.handleMessage(frame.text, stateArg)
|
|
825
|
+
.catch(() => {
|
|
826
|
+
if (this.isCurrentClientConnection(stateArg)) {
|
|
827
|
+
stateArg.websocket.close(1008, 'TypedSocket rejected malformed text envelope');
|
|
828
|
+
}
|
|
829
|
+
})
|
|
830
|
+
.finally(() => {
|
|
831
|
+
stateArg.activeHandlers--;
|
|
832
|
+
this.retainedClientCallbacks--;
|
|
833
|
+
this.drainClientTextFrames(stateArg);
|
|
834
|
+
});
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
assertClientEnvelope(valueArg) {
|
|
838
|
+
if (!isPlainRecord(valueArg) || Object.hasOwn(valueArg, 'localData')) {
|
|
839
|
+
throw new Error('TypedSocket received an invalid text envelope.');
|
|
840
|
+
}
|
|
841
|
+
assertBoundedTextIdentifier(valueArg.method, 'method', TYPEDSOCKET_MAX_METHOD_NAME_BYTES);
|
|
842
|
+
const correlation = valueArg.correlation;
|
|
843
|
+
if (!isPlainRecord(correlation)) {
|
|
844
|
+
throw new Error('TypedSocket received an invalid correlation envelope.');
|
|
845
|
+
}
|
|
846
|
+
assertBoundedTextIdentifier(correlation.id, 'correlation ID', TYPEDSOCKET_MAX_CORRELATION_ID_BYTES);
|
|
847
|
+
if (correlation.phase !== 'request' && correlation.phase !== 'response') {
|
|
848
|
+
throw new Error('TypedSocket received an invalid correlation phase.');
|
|
849
|
+
}
|
|
850
|
+
if (correlation.phase === 'request' && !Object.hasOwn(valueArg, 'request')) {
|
|
851
|
+
throw new Error('TypedSocket request envelope has no request payload.');
|
|
852
|
+
}
|
|
853
|
+
if (correlation.phase === 'response'
|
|
854
|
+
&& !Object.hasOwn(valueArg, 'response')
|
|
855
|
+
&& !Object.hasOwn(valueArg, 'error')) {
|
|
856
|
+
throw new Error('TypedSocket response envelope has no response or error payload.');
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
async handleMessage(dataArg, stateArg = this.clientConnectionState) {
|
|
860
|
+
if (!stateArg || !this.isCurrentClientConnection(stateArg))
|
|
861
|
+
return;
|
|
862
|
+
const message = plugins.smartjson.parse(dataArg);
|
|
863
|
+
this.assertClientEnvelope(message);
|
|
864
|
+
const correlation = message.correlation;
|
|
865
|
+
if (correlation.phase === 'response') {
|
|
866
|
+
const pending = this.pendingRequests.get(correlation.id);
|
|
867
|
+
if (!pending)
|
|
868
|
+
return;
|
|
869
|
+
if (pending.connectionGeneration !== stateArg.generation
|
|
870
|
+
|| pending.expectedMethod !== message.method) {
|
|
871
|
+
throw new Error('TypedSocket response authority mismatch.');
|
|
415
872
|
}
|
|
873
|
+
this.pendingRequests.delete(correlation.id);
|
|
874
|
+
pending.resolve(message);
|
|
875
|
+
return;
|
|
416
876
|
}
|
|
417
|
-
|
|
418
|
-
|
|
877
|
+
const response = await this.typedrouter.routeAndAddResponse(message);
|
|
878
|
+
if (!response || !this.isCurrentClientConnection(stateArg))
|
|
879
|
+
return;
|
|
880
|
+
this.sendClientTextEnvelope(response, stateArg);
|
|
881
|
+
}
|
|
882
|
+
sendClientTextEnvelope(envelopeArg, stateArg) {
|
|
883
|
+
if (!this.isCurrentClientConnection(stateArg)) {
|
|
884
|
+
throw new Error('TypedSocket connection changed before text send.');
|
|
885
|
+
}
|
|
886
|
+
const encoded = plugins.smartjson.stringify(envelopeArg);
|
|
887
|
+
const byteLength = textEncoder.encode(encoded).byteLength;
|
|
888
|
+
const limits = this.requireClientOptions().limits;
|
|
889
|
+
if (byteLength > limits.textFrameBytes) {
|
|
890
|
+
throw new Error(`TypedSocket outbound envelope exceeds ${limits.textFrameBytes} UTF-8 bytes.`);
|
|
891
|
+
}
|
|
892
|
+
if (stateArg.websocket.bufferedAmount + byteLength > limits.outboundBufferedBytes) {
|
|
893
|
+
throw new Error('TypedSocket outbound WebSocket buffer capacity exceeded.');
|
|
894
|
+
}
|
|
895
|
+
stateArg.websocket.send(encoded);
|
|
896
|
+
}
|
|
897
|
+
isCurrentClientConnection(stateArg) {
|
|
898
|
+
return Boolean(this.clientConnectionState === stateArg
|
|
899
|
+
&& this.websocket === stateArg.websocket
|
|
900
|
+
&& this.connectionGeneration === stateArg.generation
|
|
901
|
+
&& stateArg.websocket.readyState === WebSocket.OPEN);
|
|
902
|
+
}
|
|
903
|
+
abortClientConnectionState(stateArg, reasonArg) {
|
|
904
|
+
if (!stateArg.abortController.signal.aborted) {
|
|
905
|
+
stateArg.abortController.abort(reasonArg);
|
|
906
|
+
}
|
|
907
|
+
stateArg.queuedTextFrames.length = 0;
|
|
908
|
+
stateArg.queuedTextBytes = 0;
|
|
909
|
+
if (this.clientConnectionState === stateArg) {
|
|
910
|
+
this.clientConnectionState = null;
|
|
419
911
|
}
|
|
420
912
|
}
|
|
421
913
|
/**
|
|
@@ -438,7 +930,7 @@ export class TypedSocket {
|
|
|
438
930
|
async scheduleReconnect() {
|
|
439
931
|
if (!this.shouldReconnect())
|
|
440
932
|
return;
|
|
441
|
-
const clientOptions = this.
|
|
933
|
+
const clientOptions = this.requireClientOptions();
|
|
442
934
|
this.updateStatus('reconnecting');
|
|
443
935
|
this.retryCount++;
|
|
444
936
|
// Exponential backoff with jitter
|
|
@@ -453,12 +945,13 @@ export class TypedSocket {
|
|
|
453
945
|
try {
|
|
454
946
|
await this.connect();
|
|
455
947
|
}
|
|
456
|
-
catch
|
|
948
|
+
catch {
|
|
457
949
|
if (this.shouldReconnect()) {
|
|
458
|
-
this.logDebug(
|
|
950
|
+
this.logDebug('TypedSocket reconnection attempt failed.');
|
|
459
951
|
}
|
|
460
952
|
else if (!this.stopped && !this.clientOptions?.abortSignal?.aborted) {
|
|
461
|
-
|
|
953
|
+
const endpoint = this.toRedactedLogEndpoint(this.toWebSocketUrl(this.serverUrl));
|
|
954
|
+
console.error(`TypedSocket giving up on ${endpoint} after ${this.retryCount} attempts.`);
|
|
462
955
|
}
|
|
463
956
|
}
|
|
464
957
|
}
|
|
@@ -537,7 +1030,11 @@ export class TypedSocket {
|
|
|
537
1030
|
* Sends a request to the server and waits for response (client-side)
|
|
538
1031
|
*/
|
|
539
1032
|
async sendRequest(request, optionsArg = {}) {
|
|
540
|
-
if (
|
|
1033
|
+
if (request.method === '##VirtualStream##') {
|
|
1034
|
+
throw new Error('Legacy VirtualStream control request rejected by transport policy');
|
|
1035
|
+
}
|
|
1036
|
+
const state = this.clientConnectionState;
|
|
1037
|
+
if (!state || !this.isCurrentClientConnection(state)) {
|
|
541
1038
|
throw new Error('WebSocket not connected');
|
|
542
1039
|
}
|
|
543
1040
|
const timeoutMs = this.normalizeRequestTimeout(optionsArg.timeoutMs);
|
|
@@ -548,7 +1045,18 @@ export class TypedSocket {
|
|
|
548
1045
|
id: plugins.smartstring.create.createCryptoRandomString(),
|
|
549
1046
|
phase: 'request',
|
|
550
1047
|
};
|
|
1048
|
+
assertBoundedTextIdentifier(request.method, 'method', TYPEDSOCKET_MAX_METHOD_NAME_BYTES);
|
|
1049
|
+
assertBoundedTextIdentifier(request.correlation.id, 'correlation ID', TYPEDSOCKET_MAX_CORRELATION_ID_BYTES);
|
|
1050
|
+
if (request.correlation.phase !== 'request') {
|
|
1051
|
+
throw new Error('TypedSocket outbound requests require request correlation phase.');
|
|
1052
|
+
}
|
|
551
1053
|
const correlationId = request.correlation.id;
|
|
1054
|
+
if (this.pendingRequests.has(correlationId)) {
|
|
1055
|
+
throw new Error(`Duplicate in-flight TypedSocket correlation ID: ${correlationId}`);
|
|
1056
|
+
}
|
|
1057
|
+
if (this.pendingRequests.size >= this.requireClientOptions().limits.pendingRequests) {
|
|
1058
|
+
throw new Error('TypedSocket pending client request capacity exceeded.');
|
|
1059
|
+
}
|
|
552
1060
|
return new Promise((resolve, reject) => {
|
|
553
1061
|
let settled = false;
|
|
554
1062
|
const cleanup = () => {
|
|
@@ -565,6 +1073,9 @@ export class TypedSocket {
|
|
|
565
1073
|
if (errorArg) {
|
|
566
1074
|
reject(errorArg);
|
|
567
1075
|
}
|
|
1076
|
+
else if (!responseArg) {
|
|
1077
|
+
reject(new Error('TypedSocket request settled without a response.'));
|
|
1078
|
+
}
|
|
568
1079
|
else {
|
|
569
1080
|
resolve(responseArg);
|
|
570
1081
|
}
|
|
@@ -574,8 +1085,20 @@ export class TypedSocket {
|
|
|
574
1085
|
settle(new Error('TypedSocket request timed out'));
|
|
575
1086
|
}, timeoutMs);
|
|
576
1087
|
this.pendingRequests.set(correlationId, {
|
|
1088
|
+
expectedMethod: request.method,
|
|
1089
|
+
connectionGeneration: state.generation,
|
|
577
1090
|
resolve: (response) => {
|
|
578
|
-
|
|
1091
|
+
request.response = response.response;
|
|
1092
|
+
request.correlation = response.correlation;
|
|
1093
|
+
if (response.error)
|
|
1094
|
+
request.error = response.error;
|
|
1095
|
+
else
|
|
1096
|
+
delete request.error;
|
|
1097
|
+
if (response.retry)
|
|
1098
|
+
request.retry = response.retry;
|
|
1099
|
+
else
|
|
1100
|
+
delete request.retry;
|
|
1101
|
+
settle(undefined, request);
|
|
579
1102
|
},
|
|
580
1103
|
reject: (error) => {
|
|
581
1104
|
settle(error);
|
|
@@ -587,7 +1110,7 @@ export class TypedSocket {
|
|
|
587
1110
|
return;
|
|
588
1111
|
}
|
|
589
1112
|
try {
|
|
590
|
-
this.
|
|
1113
|
+
this.sendClientTextEnvelope(request, state);
|
|
591
1114
|
}
|
|
592
1115
|
catch (error) {
|
|
593
1116
|
settle(error instanceof Error ? error : new Error(String(error)));
|
|
@@ -595,14 +1118,22 @@ export class TypedSocket {
|
|
|
595
1118
|
});
|
|
596
1119
|
}
|
|
597
1120
|
normalizeRequestTimeout(timeoutMsArg) {
|
|
598
|
-
const
|
|
599
|
-
|
|
600
|
-
|
|
1121
|
+
const maximum = this.clientOptions?.limits.requestTimeoutMs
|
|
1122
|
+
?? TYPEDSOCKET_MAX_REQUEST_TIMEOUT_MS;
|
|
1123
|
+
const timeoutMs = timeoutMsArg ?? Math.min(30_000, maximum);
|
|
1124
|
+
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > maximum) {
|
|
1125
|
+
throw new Error(`TypedSocket request timeout must be a positive safe integer no greater than ${maximum}.`);
|
|
601
1126
|
}
|
|
602
1127
|
return timeoutMs;
|
|
603
1128
|
}
|
|
604
|
-
|
|
605
|
-
|
|
1129
|
+
requireClientOptions() {
|
|
1130
|
+
if (!this.clientOptions) {
|
|
1131
|
+
throw new Error('TypedSocket client options are unavailable on this instance.');
|
|
1132
|
+
}
|
|
1133
|
+
return this.clientOptions;
|
|
1134
|
+
}
|
|
1135
|
+
cancelPendingServerRequestsForPeer(peerArg, errorArg) {
|
|
1136
|
+
const correlationIds = this.pendingServerRequestIdsByPeer.get(peerArg);
|
|
606
1137
|
if (!correlationIds) {
|
|
607
1138
|
return;
|
|
608
1139
|
}
|
|
@@ -610,6 +1141,67 @@ export class TypedSocket {
|
|
|
610
1141
|
this.pendingServerRequests.get(correlationId)?.cancel(errorArg);
|
|
611
1142
|
}
|
|
612
1143
|
}
|
|
1144
|
+
retainServerInterestRegistration(peerArg) {
|
|
1145
|
+
const retainedForPeer = this.retainedServerInterestsByPeer.get(peerArg) ?? 0;
|
|
1146
|
+
if (retainedForPeer >= TYPEDSOCKET_MAX_RETAINED_SERVER_INTERESTS_PER_PEER
|
|
1147
|
+
|| this.retainedServerInterests >= TYPEDSOCKET_MAX_RETAINED_SERVER_INTERESTS) {
|
|
1148
|
+
throw new Error('TypedSocket server interest registration capacity exceeded.');
|
|
1149
|
+
}
|
|
1150
|
+
this.retainedServerInterests++;
|
|
1151
|
+
this.retainedServerInterestsByPeer.set(peerArg, retainedForPeer + 1);
|
|
1152
|
+
let released = false;
|
|
1153
|
+
return () => {
|
|
1154
|
+
if (released)
|
|
1155
|
+
return;
|
|
1156
|
+
released = true;
|
|
1157
|
+
this.retainedServerInterests--;
|
|
1158
|
+
const currentForPeer = this.retainedServerInterestsByPeer.get(peerArg);
|
|
1159
|
+
if (currentForPeer === undefined || currentForPeer < 1) {
|
|
1160
|
+
throw new Error('TypedSocket server interest registration accounting underflow.');
|
|
1161
|
+
}
|
|
1162
|
+
if (currentForPeer === 1) {
|
|
1163
|
+
this.retainedServerInterestsByPeer.delete(peerArg);
|
|
1164
|
+
}
|
|
1165
|
+
else {
|
|
1166
|
+
this.retainedServerInterestsByPeer.set(peerArg, currentForPeer - 1);
|
|
1167
|
+
}
|
|
1168
|
+
};
|
|
1169
|
+
}
|
|
1170
|
+
authorizeIncomingServerResponse(responseArg, routingSurfaceArg, trustedLocalDataArg) {
|
|
1171
|
+
if (this.serverStopping
|
|
1172
|
+
|| !this.smartServeRef
|
|
1173
|
+
|| responseArg.correlation?.phase !== 'response'
|
|
1174
|
+
|| typeof responseArg.correlation.id !== 'string'
|
|
1175
|
+
|| typeof responseArg.method !== 'string') {
|
|
1176
|
+
return false;
|
|
1177
|
+
}
|
|
1178
|
+
const peer = trustedLocalDataArg.peer;
|
|
1179
|
+
if (!peer || typeof peer !== 'object')
|
|
1180
|
+
return false;
|
|
1181
|
+
const pending = this.pendingServerRequests.get(responseArg.correlation.id);
|
|
1182
|
+
return Boolean(pending
|
|
1183
|
+
&& pending.peer === peer
|
|
1184
|
+
&& pending.routingSurface === routingSurfaceArg
|
|
1185
|
+
&& pending.expectedMethod === responseArg.method
|
|
1186
|
+
&& pending.lifecycleGeneration === this.serverLifecycleGeneration
|
|
1187
|
+
&& pending.peer.routingSurface === routingSurfaceArg
|
|
1188
|
+
&& this.isAttachedServerPeer(pending.peer));
|
|
1189
|
+
}
|
|
1190
|
+
isAttachedServerPeer(peerArg) {
|
|
1191
|
+
return Boolean(!this.serverStopping
|
|
1192
|
+
&& this.smartServeRef
|
|
1193
|
+
&& peerArg.readyState === 1
|
|
1194
|
+
&& peerArg.routingSurface
|
|
1195
|
+
&& this.serverTypedRouters.includes(peerArg.routingSurface)
|
|
1196
|
+
&& this.smartServeRef.getWebSocketConnections().includes(peerArg));
|
|
1197
|
+
}
|
|
1198
|
+
findServerPeerFromRequest(typedToolsArg) {
|
|
1199
|
+
const candidate = typedToolsArg?.localData?.peer;
|
|
1200
|
+
const peer = this.smartServeRef
|
|
1201
|
+
?.getWebSocketConnections()
|
|
1202
|
+
.find((peerArg) => peerArg === candidate);
|
|
1203
|
+
return peer && this.isAttachedServerPeer(peer) ? peer : undefined;
|
|
1204
|
+
}
|
|
613
1205
|
async sendServerRequest(typedRequestDataArg, targetArg, optionsArg) {
|
|
614
1206
|
const timeoutMs = this.normalizeRequestTimeout(optionsArg.timeoutMs);
|
|
615
1207
|
if (this.serverStopping || !this.smartServeRef) {
|
|
@@ -622,11 +1214,34 @@ export class TypedSocket {
|
|
|
622
1214
|
id: plugins.smartstring.create.createCryptoRandomString(),
|
|
623
1215
|
phase: 'request',
|
|
624
1216
|
};
|
|
1217
|
+
assertBoundedTextIdentifier(typedRequestDataArg.method, 'method', TYPEDSOCKET_MAX_METHOD_NAME_BYTES);
|
|
1218
|
+
assertBoundedTextIdentifier(typedRequestDataArg.correlation.id, 'correlation ID', TYPEDSOCKET_MAX_CORRELATION_ID_BYTES);
|
|
1219
|
+
if (typedRequestDataArg.correlation.phase !== 'request') {
|
|
1220
|
+
throw new Error('TypedSocket outbound requests require request correlation phase.');
|
|
1221
|
+
}
|
|
625
1222
|
const correlationId = typedRequestDataArg.correlation.id;
|
|
1223
|
+
const peer = targetArg.peer;
|
|
626
1224
|
const peerId = targetArg.peer.id;
|
|
1225
|
+
const routingSurface = peer.routingSurface;
|
|
1226
|
+
if (!routingSurface || !this.serverTypedRouters.includes(routingSurface)) {
|
|
1227
|
+
throw new Error('TypedSocket target connection is not bound to this server routing surface');
|
|
1228
|
+
}
|
|
1229
|
+
if (!this.isAttachedServerPeer(peer)) {
|
|
1230
|
+
throw new Error(`TypedSocket target connection is detached or closed: ${peerId}`);
|
|
1231
|
+
}
|
|
627
1232
|
if (this.pendingServerRequests.has(correlationId)) {
|
|
628
1233
|
throw new Error(`Duplicate in-flight TypedSocket correlation ID: ${correlationId}`);
|
|
629
1234
|
}
|
|
1235
|
+
const requestsForPeer = this.pendingServerRequestIdsByPeer.get(peer) ?? new Set();
|
|
1236
|
+
if (requestsForPeer.size >= TYPEDSOCKET_MAX_PENDING_SERVER_REQUESTS_PER_PEER
|
|
1237
|
+
|| this.pendingServerRequests.size >= TYPEDSOCKET_MAX_PENDING_SERVER_REQUESTS) {
|
|
1238
|
+
throw new Error('TypedSocket pending server request capacity exceeded.');
|
|
1239
|
+
}
|
|
1240
|
+
if ((this.retainedServerInterestsByPeer.get(peer) ?? 0)
|
|
1241
|
+
>= TYPEDSOCKET_MAX_RETAINED_SERVER_INTERESTS_PER_PEER
|
|
1242
|
+
|| this.retainedServerInterests >= TYPEDSOCKET_MAX_RETAINED_SERVER_INTERESTS) {
|
|
1243
|
+
throw new Error('TypedSocket server interest registration capacity exceeded.');
|
|
1244
|
+
}
|
|
630
1245
|
const cancellation = plugins.smartpromise.defer();
|
|
631
1246
|
// A stop/abort may happen while InterestMap.addInterest is yielding. Attach
|
|
632
1247
|
// a rejection handler immediately; Promise.race below still receives the
|
|
@@ -642,14 +1257,17 @@ export class TypedSocket {
|
|
|
642
1257
|
cancellation.reject(errorArg);
|
|
643
1258
|
};
|
|
644
1259
|
const pendingRequest = {
|
|
1260
|
+
peer,
|
|
645
1261
|
peerId,
|
|
1262
|
+
routingSurface,
|
|
1263
|
+
expectedMethod: typedRequestDataArg.method,
|
|
1264
|
+
lifecycleGeneration: this.serverLifecycleGeneration,
|
|
646
1265
|
cancel,
|
|
647
1266
|
cleanupComplete: cleanup.promise,
|
|
648
1267
|
};
|
|
649
1268
|
this.pendingServerRequests.set(correlationId, pendingRequest);
|
|
650
|
-
const requestsForPeer = this.pendingServerRequestIdsByPeerId.get(peerId) ?? new Set();
|
|
651
1269
|
requestsForPeer.add(correlationId);
|
|
652
|
-
this.
|
|
1270
|
+
this.pendingServerRequestIdsByPeer.set(peer, requestsForPeer);
|
|
653
1271
|
const onAbort = () => cancel(new Error('TypedSocket request aborted'));
|
|
654
1272
|
const timeout = setTimeout(() => cancel(new Error(`TypedSocket request timed out after ${timeoutMs}ms`)), timeoutMs);
|
|
655
1273
|
optionsArg.abortSignal?.addEventListener('abort', onAbort, { once: true });
|
|
@@ -658,36 +1276,34 @@ export class TypedSocket {
|
|
|
658
1276
|
}
|
|
659
1277
|
const destroyInterests = [];
|
|
660
1278
|
try {
|
|
661
|
-
const
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
.then((interestArg) => {
|
|
666
|
-
if (cancellationRequested || this.serverStopping) {
|
|
667
|
-
interestArg.destroy();
|
|
668
|
-
}
|
|
669
|
-
return interestArg;
|
|
670
|
-
});
|
|
671
|
-
const interest = await Promise.race([
|
|
672
|
-
interestRegistration,
|
|
673
|
-
cancellation.promise,
|
|
674
|
-
]);
|
|
1279
|
+
const releaseInterestRegistration = this.retainServerInterestRegistration(peer);
|
|
1280
|
+
const interestRegistration = Promise.resolve()
|
|
1281
|
+
.then(() => routingSurface.fireEventInterestMap.addInterest(correlationId, typedRequestDataArg))
|
|
1282
|
+
.then((interestArg) => {
|
|
675
1283
|
if (cancellationRequested || this.serverStopping) {
|
|
676
|
-
|
|
677
|
-
await cancellation.promise;
|
|
1284
|
+
interestArg.destroy();
|
|
678
1285
|
}
|
|
679
|
-
|
|
680
|
-
|
|
1286
|
+
return interestArg;
|
|
1287
|
+
})
|
|
1288
|
+
.finally(releaseInterestRegistration);
|
|
1289
|
+
const interest = await Promise.race([
|
|
1290
|
+
interestRegistration,
|
|
1291
|
+
cancellation.promise,
|
|
1292
|
+
]);
|
|
1293
|
+
if (cancellationRequested || this.serverStopping) {
|
|
1294
|
+
interest.destroy();
|
|
1295
|
+
await cancellation.promise;
|
|
681
1296
|
}
|
|
1297
|
+
destroyInterests.push(() => interest.destroy());
|
|
682
1298
|
// Establish the rejecting race before send so synchronous close/abort and
|
|
683
1299
|
// send failures all use the same cleanup path.
|
|
684
1300
|
const response = Promise.race([
|
|
685
|
-
|
|
1301
|
+
interest.interestFullfilled,
|
|
686
1302
|
cancellation.promise,
|
|
687
1303
|
]);
|
|
688
1304
|
const targetIsStillConnected = this.smartServeRef
|
|
689
1305
|
?.getWebSocketConnections()
|
|
690
|
-
.some((peerArg) => peerArg
|
|
1306
|
+
.some((peerArg) => peerArg === peer) ?? false;
|
|
691
1307
|
if (!targetIsStillConnected) {
|
|
692
1308
|
cancel(new Error(`TypedSocket target connection closed: ${peerId}`));
|
|
693
1309
|
}
|
|
@@ -697,16 +1313,27 @@ export class TypedSocket {
|
|
|
697
1313
|
if (!cancellationRequested && targetIsStillConnected && !this.serverStopping) {
|
|
698
1314
|
targetArg.peer.send(plugins.smartjson.stringify(typedRequestDataArg));
|
|
699
1315
|
}
|
|
700
|
-
|
|
1316
|
+
const routedResponse = await response;
|
|
1317
|
+
typedRequestDataArg.response = routedResponse.response;
|
|
1318
|
+
typedRequestDataArg.correlation = routedResponse.correlation;
|
|
1319
|
+
if (routedResponse.error)
|
|
1320
|
+
typedRequestDataArg.error = routedResponse.error;
|
|
1321
|
+
else
|
|
1322
|
+
delete typedRequestDataArg.error;
|
|
1323
|
+
if (routedResponse.retry)
|
|
1324
|
+
typedRequestDataArg.retry = routedResponse.retry;
|
|
1325
|
+
else
|
|
1326
|
+
delete typedRequestDataArg.retry;
|
|
1327
|
+
return typedRequestDataArg;
|
|
701
1328
|
}
|
|
702
1329
|
finally {
|
|
703
1330
|
clearTimeout(timeout);
|
|
704
1331
|
optionsArg.abortSignal?.removeEventListener('abort', onAbort);
|
|
705
1332
|
this.pendingServerRequests.delete(correlationId);
|
|
706
|
-
const remainingRequestsForPeer = this.
|
|
1333
|
+
const remainingRequestsForPeer = this.pendingServerRequestIdsByPeer.get(peer);
|
|
707
1334
|
remainingRequestsForPeer?.delete(correlationId);
|
|
708
1335
|
if (remainingRequestsForPeer?.size === 0) {
|
|
709
|
-
this.
|
|
1336
|
+
this.pendingServerRequestIdsByPeer.delete(peer);
|
|
710
1337
|
}
|
|
711
1338
|
for (const destroyInterest of destroyInterests) {
|
|
712
1339
|
destroyInterest();
|
|
@@ -724,7 +1351,6 @@ export class TypedSocket {
|
|
|
724
1351
|
*/
|
|
725
1352
|
createTypedRequest(methodName, targetConnection, optionsArg = {}) {
|
|
726
1353
|
const postMethod = async (requestDataArg, postOptionsArg = {}) => {
|
|
727
|
-
const typedRequestData = requestDataArg;
|
|
728
1354
|
const composedAbortSignal = composeAbortSignals(optionsArg.abortSignal, postOptionsArg.signal);
|
|
729
1355
|
const requestOptions = {
|
|
730
1356
|
...optionsArg,
|
|
@@ -732,7 +1358,7 @@ export class TypedSocket {
|
|
|
732
1358
|
};
|
|
733
1359
|
try {
|
|
734
1360
|
if (this.side === 'client') {
|
|
735
|
-
return await this.sendRequest(
|
|
1361
|
+
return await this.sendRequest(requestDataArg, requestOptions);
|
|
736
1362
|
}
|
|
737
1363
|
// Server-side: send to target connection
|
|
738
1364
|
if (!this.smartServeRef) {
|
|
@@ -740,7 +1366,11 @@ export class TypedSocket {
|
|
|
740
1366
|
}
|
|
741
1367
|
let target = targetConnection;
|
|
742
1368
|
if (!target) {
|
|
743
|
-
|
|
1369
|
+
if (this.serverTypedRouters.length > 1) {
|
|
1370
|
+
throw new Error('TypedSocket multi-router servers require an explicit targetConnection');
|
|
1371
|
+
}
|
|
1372
|
+
const routingSurface = this.serverTypedRouters[0];
|
|
1373
|
+
const allConnections = this.smartServeRef.getWebSocketConnections().filter((peerArg) => peerArg.routingSurface === routingSurface);
|
|
744
1374
|
if (allConnections.length === 1) {
|
|
745
1375
|
const peer = allConnections[0];
|
|
746
1376
|
target = wrapSmartServePeer(peer);
|
|
@@ -752,17 +1382,74 @@ export class TypedSocket {
|
|
|
752
1382
|
throw new Error('Multiple connections available - specify targetConnection');
|
|
753
1383
|
}
|
|
754
1384
|
}
|
|
755
|
-
return await this.sendServerRequest(
|
|
1385
|
+
return await this.sendServerRequest(requestDataArg, target, requestOptions);
|
|
756
1386
|
}
|
|
757
1387
|
finally {
|
|
758
1388
|
composedAbortSignal.cleanup();
|
|
759
1389
|
}
|
|
760
1390
|
};
|
|
1391
|
+
const nativeStreamTransport = this.side === 'client'
|
|
1392
|
+
? this.nativeBytes.getClientNativeStreamTransport()
|
|
1393
|
+
: targetConnection
|
|
1394
|
+
? this.nativeBytes.getServerNativeStreamTransport(targetConnection.peer)
|
|
1395
|
+
: undefined;
|
|
761
1396
|
return new plugins.typedrequest.TypedRequest(new plugins.typedrequest.TypedTarget({
|
|
762
1397
|
postMethod,
|
|
763
1398
|
supportsAbortSignal: true,
|
|
1399
|
+
nativeStreamTransport,
|
|
1400
|
+
legacyVirtualStreams: 'deny',
|
|
764
1401
|
}), methodName);
|
|
765
1402
|
}
|
|
1403
|
+
/**
|
|
1404
|
+
* Creates an exact authorized native-byte receive facade for one server peer.
|
|
1405
|
+
* TypedRequest carries its opaque descriptor when the facade enters a DTO.
|
|
1406
|
+
*/
|
|
1407
|
+
createVirtualStream(optionsArg) {
|
|
1408
|
+
if (this.side !== 'server') {
|
|
1409
|
+
throw new Error('createVirtualStream is only available on servers');
|
|
1410
|
+
}
|
|
1411
|
+
if (optionsArg.protocol !== NATIVE_BYTE_PROTOCOL
|
|
1412
|
+
|| optionsArg.direction !== 'receive') {
|
|
1413
|
+
throw new TypeError('createVirtualStream requires native-byte-v1 receive direction');
|
|
1414
|
+
}
|
|
1415
|
+
const authorizationAdapter = this.nativeByteAuthorizationAdapter;
|
|
1416
|
+
if (!authorizationAdapter) {
|
|
1417
|
+
throw new NativeByteCapabilityError('createVirtualStream requires a nativeByteAuthorizationAdapter');
|
|
1418
|
+
}
|
|
1419
|
+
const peer = 'peer' in optionsArg.target
|
|
1420
|
+
? optionsArg.target.peer
|
|
1421
|
+
: optionsArg.target;
|
|
1422
|
+
const transport = this.nativeBytes.getServerNativeStreamTransport(peer);
|
|
1423
|
+
if (!transport) {
|
|
1424
|
+
throw new NativeByteCapabilityError('createVirtualStream target is not an active native-byte-v1 peer');
|
|
1425
|
+
}
|
|
1426
|
+
transport.requireCapability({ capability: NATIVE_BYTE_PROTOCOL });
|
|
1427
|
+
const manifest = this.nativeBytes.normalizeManifest({
|
|
1428
|
+
byteLength: optionsArg.byteLength,
|
|
1429
|
+
sha256: optionsArg.sha256,
|
|
1430
|
+
contentType: optionsArg.contentType,
|
|
1431
|
+
});
|
|
1432
|
+
const authorizationBinding = authorizationAdapter.bind(optionsArg.authorization, Object.freeze({ target: peer, manifest }));
|
|
1433
|
+
if (!authorizationBinding
|
|
1434
|
+
|| typeof authorizationBinding !== 'object'
|
|
1435
|
+
|| typeof Reflect.get(authorizationBinding, 'then') === 'function') {
|
|
1436
|
+
throw new TypeError('nativeByteAuthorizationAdapter.bind() must return a synchronous binding');
|
|
1437
|
+
}
|
|
1438
|
+
const registration = this.nativeBytes.createReceiveRegistration({
|
|
1439
|
+
target: peer,
|
|
1440
|
+
...manifest,
|
|
1441
|
+
initialWindowBytes: optionsArg.initialWindowBytes,
|
|
1442
|
+
principalId: authorizationBinding.principalId,
|
|
1443
|
+
credentialRevision: authorizationBinding.credentialRevision,
|
|
1444
|
+
configRevision: authorizationBinding.configRevision,
|
|
1445
|
+
bindingRevision: authorizationBinding.bindingRevision,
|
|
1446
|
+
revalidate: authorizationBinding.revalidate,
|
|
1447
|
+
});
|
|
1448
|
+
return plugins.typedrequest.VirtualStream.fromNativeByteRegistration({
|
|
1449
|
+
transport,
|
|
1450
|
+
registration,
|
|
1451
|
+
});
|
|
1452
|
+
}
|
|
766
1453
|
/**
|
|
767
1454
|
* Gets the current connection status
|
|
768
1455
|
*/
|
|
@@ -787,7 +1474,13 @@ export class TypedSocket {
|
|
|
787
1474
|
}
|
|
788
1475
|
this.abortSignalListener = undefined;
|
|
789
1476
|
if (this.websocket) {
|
|
790
|
-
this.websocket
|
|
1477
|
+
const websocket = this.websocket;
|
|
1478
|
+
const generation = this.connectionGeneration;
|
|
1479
|
+
if (this.clientConnectionState) {
|
|
1480
|
+
this.abortClientConnectionState(this.clientConnectionState, new Error('TypedSocket stopped'));
|
|
1481
|
+
}
|
|
1482
|
+
this.nativeBytes.unbindClientConnection(websocket, generation, new Error('TypedSocket stopped'));
|
|
1483
|
+
websocket.close();
|
|
791
1484
|
this.websocket = null;
|
|
792
1485
|
}
|
|
793
1486
|
for (const pendingRequest of this.pendingRequests.values()) {
|
|
@@ -797,6 +1490,8 @@ export class TypedSocket {
|
|
|
797
1490
|
}
|
|
798
1491
|
else {
|
|
799
1492
|
this.serverStopping = true;
|
|
1493
|
+
this.serverLifecycleGeneration++;
|
|
1494
|
+
this.tagPolicyManager.stop(this.smartServeRef?.getWebSocketConnections() ?? []);
|
|
800
1495
|
const pendingRequests = Array.from(this.pendingServerRequests.values());
|
|
801
1496
|
for (const pendingRequest of pendingRequests) {
|
|
802
1497
|
pendingRequest.cancel(new Error('TypedSocket server stopped'));
|
|
@@ -804,13 +1499,33 @@ export class TypedSocket {
|
|
|
804
1499
|
await Promise.all(pendingRequests.map((pendingRequest) => pendingRequest.cleanupComplete));
|
|
805
1500
|
this.unsubscribeSmartServeConnectionClose?.();
|
|
806
1501
|
this.unsubscribeSmartServeConnectionClose = null;
|
|
1502
|
+
this.nativeBytes.detachServer();
|
|
1503
|
+
this.tagPolicyManager.setAttachedPeersProvider(undefined);
|
|
807
1504
|
this.smartServeRef = null;
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
1505
|
+
this.pendingServerRequestIdsByPeer.clear();
|
|
1506
|
+
}
|
|
1507
|
+
for (const detachNativeStreamResolver of this.detachNativeStreamResolvers.reverse()) {
|
|
1508
|
+
detachNativeStreamResolver();
|
|
1509
|
+
}
|
|
1510
|
+
this.detachNativeStreamResolvers = [];
|
|
1511
|
+
for (const detachResponseAuthorityGuard of this.detachResponseAuthorityGuards.reverse()) {
|
|
1512
|
+
detachResponseAuthorityGuard();
|
|
1513
|
+
}
|
|
1514
|
+
this.detachResponseAuthorityGuards = [];
|
|
1515
|
+
if (this.side === 'server') {
|
|
1516
|
+
this.releaseServerComposition();
|
|
812
1517
|
}
|
|
813
1518
|
}
|
|
1519
|
+
releaseServerComposition() {
|
|
1520
|
+
for (const detachLegacyPolicy of this.detachLegacyVirtualStreamPolicies.reverse()) {
|
|
1521
|
+
detachLegacyPolicy();
|
|
1522
|
+
}
|
|
1523
|
+
this.detachLegacyVirtualStreamPolicies = [];
|
|
1524
|
+
for (const detachProtocolRouter of this.detachProtocolRouters.reverse()) {
|
|
1525
|
+
detachProtocolRouter();
|
|
1526
|
+
}
|
|
1527
|
+
this.detachProtocolRouters = [];
|
|
1528
|
+
}
|
|
814
1529
|
// ============================================================================
|
|
815
1530
|
// CLIENT-ONLY METHODS
|
|
816
1531
|
// ============================================================================
|
|
@@ -823,36 +1538,63 @@ export class TypedSocket {
|
|
|
823
1538
|
if (this.side !== 'client') {
|
|
824
1539
|
throw new Error('setTag is only available on clients');
|
|
825
1540
|
}
|
|
826
|
-
const
|
|
827
|
-
this.clientTagMutations.set(name, mutation);
|
|
1541
|
+
const releaseMutation = this.retainClientTagMutation(name);
|
|
828
1542
|
try {
|
|
829
|
-
const
|
|
830
|
-
const
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
1543
|
+
const snapshot = createTypedSocketTagPayloadSnapshot(payload);
|
|
1544
|
+
const desired = this.setDesiredClientTag(name, 'set', snapshot.payload, snapshot.byteLength);
|
|
1545
|
+
return await this.serializeClientTagMutation(name, async () => {
|
|
1546
|
+
let applied;
|
|
1547
|
+
try {
|
|
1548
|
+
applied = await this.submitDesiredClientTag(name, desired);
|
|
1549
|
+
}
|
|
1550
|
+
catch (errorArg) {
|
|
1551
|
+
this.settleDesiredClientTag(name, desired, errorArg instanceof TypedSocketClientTagDeniedError ? 'denied' : 'retained');
|
|
1552
|
+
throw errorArg;
|
|
1553
|
+
}
|
|
1554
|
+
this.settleDesiredClientTag(name, desired, applied ? 'accepted' : 'retained');
|
|
1555
|
+
});
|
|
837
1556
|
}
|
|
838
1557
|
finally {
|
|
839
|
-
|
|
840
|
-
this.clientTagMutations.delete(name);
|
|
841
|
-
}
|
|
1558
|
+
releaseMutation();
|
|
842
1559
|
}
|
|
843
1560
|
}
|
|
844
1561
|
/**
|
|
845
1562
|
* Re-applies all client tags after a reconnect, since server-side tags are
|
|
846
1563
|
* bound to the previous connection.
|
|
847
1564
|
*/
|
|
848
|
-
async reapplyClientTags() {
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
1565
|
+
async reapplyClientTags(stateArg = this.clientConnectionState) {
|
|
1566
|
+
if (!stateArg || !this.isCurrentClientConnection(stateArg)) {
|
|
1567
|
+
throw new Error('TypedSocket has no active connection for tag restoration.');
|
|
1568
|
+
}
|
|
1569
|
+
this.clientTags.clear();
|
|
1570
|
+
this.clientTagRevisions.clear();
|
|
1571
|
+
while (this.isCurrentClientConnection(stateArg)) {
|
|
1572
|
+
const snapshot = Array.from(this.desiredClientTags.entries());
|
|
1573
|
+
for (const [name, desired] of snapshot) {
|
|
1574
|
+
try {
|
|
1575
|
+
const applied = await this.submitDesiredClientTag(name, desired, stateArg);
|
|
1576
|
+
if (applied
|
|
1577
|
+
&& desired.operation === 'remove'
|
|
1578
|
+
&& this.desiredClientTags.get(name)?.sequence === desired.sequence) {
|
|
1579
|
+
this.desiredClientTags.delete(name);
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
catch (errorArg) {
|
|
1583
|
+
if (errorArg instanceof TypedSocketClientTagDeniedError
|
|
1584
|
+
&& this.desiredClientTags.get(name)?.sequence === desired.sequence) {
|
|
1585
|
+
this.desiredClientTags.delete(name);
|
|
1586
|
+
}
|
|
1587
|
+
throw errorArg;
|
|
1588
|
+
}
|
|
854
1589
|
}
|
|
1590
|
+
const stable = snapshot.length === this.desiredClientTags.size
|
|
1591
|
+
&& snapshot.every(([name, desired]) => {
|
|
1592
|
+
return this.desiredClientTags.get(name)?.sequence === desired.sequence;
|
|
1593
|
+
});
|
|
1594
|
+
if (stable)
|
|
1595
|
+
return;
|
|
855
1596
|
}
|
|
1597
|
+
throw new Error('TypedSocket connection changed while restoring client tags.');
|
|
856
1598
|
}
|
|
857
1599
|
/**
|
|
858
1600
|
* Removes a tag from this client connection.
|
|
@@ -862,25 +1604,212 @@ export class TypedSocket {
|
|
|
862
1604
|
if (this.side !== 'client') {
|
|
863
1605
|
throw new Error('removeTag is only available on clients');
|
|
864
1606
|
}
|
|
865
|
-
const
|
|
866
|
-
this.clientTagMutations.set(name, mutation);
|
|
867
|
-
this.clientTags.delete(name);
|
|
1607
|
+
const releaseMutation = this.retainClientTagMutation(name);
|
|
868
1608
|
try {
|
|
869
|
-
const
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
1609
|
+
const desired = this.setDesiredClientTag(name, 'remove', undefined, 0);
|
|
1610
|
+
return await this.serializeClientTagMutation(name, async () => {
|
|
1611
|
+
let applied;
|
|
1612
|
+
try {
|
|
1613
|
+
applied = await this.submitDesiredClientTag(name, desired);
|
|
1614
|
+
}
|
|
1615
|
+
catch (errorArg) {
|
|
1616
|
+
this.settleDesiredClientTag(name, desired, errorArg instanceof TypedSocketClientTagDeniedError ? 'denied' : 'retained');
|
|
1617
|
+
throw errorArg;
|
|
1618
|
+
}
|
|
1619
|
+
this.settleDesiredClientTag(name, desired, applied ? 'accepted' : 'retained');
|
|
1620
|
+
});
|
|
1621
|
+
}
|
|
1622
|
+
finally {
|
|
1623
|
+
releaseMutation();
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
retainClientTagMutation(nameArg) {
|
|
1627
|
+
assertBoundedTextIdentifier(nameArg, 'tag name', TYPEDSOCKET_MAX_TAG_NAME_BYTES);
|
|
1628
|
+
const retainedForName = this.retainedClientTagMutationsByName.get(nameArg) ?? 0;
|
|
1629
|
+
if (retainedForName >= TYPEDSOCKET_MAX_RETAINED_CLIENT_TAG_MUTATIONS_PER_NAME
|
|
1630
|
+
|| this.retainedClientTagMutations >= TYPEDSOCKET_MAX_RETAINED_CLIENT_TAG_MUTATIONS) {
|
|
1631
|
+
throw new TypedSocketClientTagDeniedError('TAG_MUTATION_CAPACITY_EXCEEDED', 'TypedSocket retained client tag mutation capacity exceeded.');
|
|
1632
|
+
}
|
|
1633
|
+
this.retainedClientTagMutations++;
|
|
1634
|
+
this.retainedClientTagMutationsByName.set(nameArg, retainedForName + 1);
|
|
1635
|
+
let released = false;
|
|
1636
|
+
return () => {
|
|
1637
|
+
if (released)
|
|
1638
|
+
return;
|
|
1639
|
+
released = true;
|
|
1640
|
+
this.retainedClientTagMutations--;
|
|
1641
|
+
const currentForName = this.retainedClientTagMutationsByName.get(nameArg);
|
|
1642
|
+
if (currentForName === undefined || currentForName < 1) {
|
|
1643
|
+
throw new Error('TypedSocket client tag mutation accounting underflow.');
|
|
873
1644
|
}
|
|
1645
|
+
if (currentForName === 1) {
|
|
1646
|
+
this.retainedClientTagMutationsByName.delete(nameArg);
|
|
1647
|
+
}
|
|
1648
|
+
else {
|
|
1649
|
+
this.retainedClientTagMutationsByName.set(nameArg, currentForName - 1);
|
|
1650
|
+
}
|
|
1651
|
+
};
|
|
1652
|
+
}
|
|
1653
|
+
setDesiredClientTag(nameArg, operationArg, payloadArg, payloadBytesArg) {
|
|
1654
|
+
assertBoundedTextIdentifier(nameArg, 'tag name', TYPEDSOCKET_MAX_TAG_NAME_BYTES);
|
|
1655
|
+
const retainedBytes = textEncoder.encode(nameArg).byteLength + payloadBytesArg;
|
|
1656
|
+
const desired = Object.freeze({
|
|
1657
|
+
sequence: ++this.clientTagMutationSequence,
|
|
1658
|
+
operation: operationArg,
|
|
1659
|
+
payload: operationArg === 'set' ? payloadArg : undefined,
|
|
1660
|
+
retainedBytes,
|
|
1661
|
+
});
|
|
1662
|
+
const alreadyPresent = this.desiredClientTags.has(nameArg);
|
|
1663
|
+
if (!alreadyPresent && this.desiredClientTags.size >= TYPEDSOCKET_MAX_CLIENT_TAGS_PER_PEER) {
|
|
1664
|
+
throw new TypedSocketClientTagDeniedError('TAG_COUNT_LIMIT_EXCEEDED', 'TypedSocket desired client tag count limit exceeded.');
|
|
1665
|
+
}
|
|
1666
|
+
let retainedTotal = retainedBytes;
|
|
1667
|
+
for (const [name, entry] of this.desiredClientTags) {
|
|
1668
|
+
if (name !== nameArg)
|
|
1669
|
+
retainedTotal += entry.retainedBytes;
|
|
1670
|
+
}
|
|
1671
|
+
if (retainedTotal > TYPEDSOCKET_MAX_CLIENT_TAG_RETAINED_BYTES_PER_PEER) {
|
|
1672
|
+
throw new TypedSocketClientTagDeniedError('TAG_RETAINED_BYTES_EXCEEDED', 'TypedSocket desired client tag retained-byte limit exceeded.');
|
|
1673
|
+
}
|
|
1674
|
+
let queue = this.clientTagDesiredMutationQueues.get(nameArg);
|
|
1675
|
+
if (!queue) {
|
|
1676
|
+
queue = {
|
|
1677
|
+
baseline: this.desiredClientTags.get(nameArg),
|
|
1678
|
+
pending: [],
|
|
1679
|
+
};
|
|
1680
|
+
this.clientTagDesiredMutationQueues.set(nameArg, queue);
|
|
1681
|
+
}
|
|
1682
|
+
queue.pending.push(desired);
|
|
1683
|
+
this.desiredClientTags.set(nameArg, desired);
|
|
1684
|
+
return desired;
|
|
1685
|
+
}
|
|
1686
|
+
settleDesiredClientTag(nameArg, desiredArg, outcomeArg) {
|
|
1687
|
+
const queue = this.clientTagDesiredMutationQueues.get(nameArg);
|
|
1688
|
+
const settled = queue?.pending.shift();
|
|
1689
|
+
if (!queue || settled !== desiredArg) {
|
|
1690
|
+
throw new Error('TypedSocket desired client tag mutation order changed unexpectedly.');
|
|
1691
|
+
}
|
|
1692
|
+
if (outcomeArg === 'accepted') {
|
|
1693
|
+
queue.baseline = desiredArg.operation === 'set' ? desiredArg : undefined;
|
|
1694
|
+
}
|
|
1695
|
+
else if (outcomeArg === 'retained') {
|
|
1696
|
+
queue.baseline = desiredArg;
|
|
1697
|
+
}
|
|
1698
|
+
const current = queue.pending.at(-1) ?? queue.baseline;
|
|
1699
|
+
if (current)
|
|
1700
|
+
this.desiredClientTags.set(nameArg, current);
|
|
1701
|
+
else
|
|
1702
|
+
this.desiredClientTags.delete(nameArg);
|
|
1703
|
+
if (queue.pending.length === 0)
|
|
1704
|
+
this.clientTagDesiredMutationQueues.delete(nameArg);
|
|
1705
|
+
}
|
|
1706
|
+
async serializeClientTagMutation(nameArg, mutationArg) {
|
|
1707
|
+
const previous = this.clientTagMutationTails.get(nameArg) ?? Promise.resolve();
|
|
1708
|
+
const operation = previous.catch(() => { }).then(mutationArg);
|
|
1709
|
+
const tail = operation.then(() => { }, () => { });
|
|
1710
|
+
this.clientTagMutationTails.set(nameArg, tail);
|
|
1711
|
+
try {
|
|
1712
|
+
await operation;
|
|
874
1713
|
}
|
|
875
1714
|
finally {
|
|
876
|
-
if (this.
|
|
877
|
-
this.
|
|
1715
|
+
if (this.clientTagMutationTails.get(nameArg) === tail) {
|
|
1716
|
+
this.clientTagMutationTails.delete(nameArg);
|
|
878
1717
|
}
|
|
879
1718
|
}
|
|
880
1719
|
}
|
|
1720
|
+
async submitDesiredClientTag(nameArg, desiredArg, stateArg = this.clientConnectionState) {
|
|
1721
|
+
if (!stateArg || !this.isCurrentClientConnection(stateArg)) {
|
|
1722
|
+
throw new Error('WebSocket not connected');
|
|
1723
|
+
}
|
|
1724
|
+
const connectionGeneration = stateArg.generation;
|
|
1725
|
+
const response = desiredArg.operation === 'set'
|
|
1726
|
+
? this.requireTagMutationSuccess(await this
|
|
1727
|
+
.createTypedRequest('__typedsocket_setTag')
|
|
1728
|
+
.fire({ name: nameArg, payload: desiredArg.payload }))
|
|
1729
|
+
: this.requireTagMutationSuccess(await this
|
|
1730
|
+
.createTypedRequest('__typedsocket_removeTag')
|
|
1731
|
+
.fire({ name: nameArg }));
|
|
1732
|
+
const applied = this.applyClientTagMutation(nameArg, desiredArg.payload, response, connectionGeneration, desiredArg.operation);
|
|
1733
|
+
return applied;
|
|
1734
|
+
}
|
|
1735
|
+
requireTagMutationSuccess(responseArg) {
|
|
1736
|
+
if (!responseArg || typeof responseArg.success !== 'boolean') {
|
|
1737
|
+
throw new TypedSocketClientTagDeniedError('MALFORMED_TAG_RESPONSE', 'TypedSocket server returned a malformed tag mutation response.');
|
|
1738
|
+
}
|
|
1739
|
+
if (!responseArg.success) {
|
|
1740
|
+
if (typeof responseArg.code !== 'string' || typeof responseArg.message !== 'string') {
|
|
1741
|
+
throw new TypedSocketClientTagDeniedError('MALFORMED_TAG_RESPONSE', 'TypedSocket server returned a malformed tag denial response.');
|
|
1742
|
+
}
|
|
1743
|
+
throw new TypedSocketClientTagDeniedError(responseArg.code, responseArg.message);
|
|
1744
|
+
}
|
|
1745
|
+
if (typeof responseArg.connectionId !== 'string'
|
|
1746
|
+
|| responseArg.connectionId.length === 0
|
|
1747
|
+
|| !Number.isSafeInteger(responseArg.tagRevision)
|
|
1748
|
+
|| responseArg.tagRevision < 1) {
|
|
1749
|
+
throw new TypedSocketClientTagDeniedError('MALFORMED_TAG_RESPONSE', 'TypedSocket server returned malformed tag mutation ordering metadata.');
|
|
1750
|
+
}
|
|
1751
|
+
return responseArg;
|
|
1752
|
+
}
|
|
1753
|
+
applyClientTagMutation(nameArg, payloadArg, responseArg, connectionGenerationArg, operationArg) {
|
|
1754
|
+
if (connectionGenerationArg !== this.connectionGeneration)
|
|
1755
|
+
return false;
|
|
1756
|
+
const current = this.clientTagRevisions.get(nameArg);
|
|
1757
|
+
if (current) {
|
|
1758
|
+
if (connectionGenerationArg < current.connectionGeneration)
|
|
1759
|
+
return false;
|
|
1760
|
+
if (connectionGenerationArg === current.connectionGeneration) {
|
|
1761
|
+
if (responseArg.connectionId !== current.connectionId) {
|
|
1762
|
+
throw new TypedSocketClientTagDeniedError('MALFORMED_TAG_RESPONSE', 'TypedSocket server changed tag mutation connection identity within one connection generation.');
|
|
1763
|
+
}
|
|
1764
|
+
if (responseArg.tagRevision <= current.tagRevision)
|
|
1765
|
+
return false;
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
if (operationArg === 'set') {
|
|
1769
|
+
this.clientTagRevisions.set(nameArg, {
|
|
1770
|
+
connectionGeneration: connectionGenerationArg,
|
|
1771
|
+
connectionId: responseArg.connectionId,
|
|
1772
|
+
tagRevision: responseArg.tagRevision,
|
|
1773
|
+
});
|
|
1774
|
+
this.clientTags.set(nameArg, createTypedSocketTagPayloadSnapshot(payloadArg).payload);
|
|
1775
|
+
}
|
|
1776
|
+
else {
|
|
1777
|
+
this.clientTags.delete(nameArg);
|
|
1778
|
+
this.clientTagRevisions.delete(nameArg);
|
|
1779
|
+
}
|
|
1780
|
+
return true;
|
|
1781
|
+
}
|
|
881
1782
|
// ============================================================================
|
|
882
1783
|
// SERVER-ONLY METHODS
|
|
883
1784
|
// ============================================================================
|
|
1785
|
+
/**
|
|
1786
|
+
* Resolves the exact SmartServe transport peer for one incoming TypedRequest.
|
|
1787
|
+
* Server handlers can pass their TypedTools argument without type assertions.
|
|
1788
|
+
*/
|
|
1789
|
+
getServerConnectionForRequest(typedToolsArg) {
|
|
1790
|
+
if (this.side !== 'server') {
|
|
1791
|
+
throw new Error('getServerConnectionForRequest is only available on servers');
|
|
1792
|
+
}
|
|
1793
|
+
const peer = this.findServerPeerFromRequest(typedToolsArg);
|
|
1794
|
+
if (!peer) {
|
|
1795
|
+
throw new Error('TypedSocket request is not bound to an attached transport peer');
|
|
1796
|
+
}
|
|
1797
|
+
return wrapSmartServePeer(peer);
|
|
1798
|
+
}
|
|
1799
|
+
/** Assigns a protected server-owned tag to one connection. */
|
|
1800
|
+
setServerTag(connectionArg, nameArg, payloadArg) {
|
|
1801
|
+
if (this.side !== 'server') {
|
|
1802
|
+
throw new Error('setServerTag is only available on servers');
|
|
1803
|
+
}
|
|
1804
|
+
this.tagPolicyManager.setServerTag('peer' in connectionArg ? connectionArg.peer : connectionArg, nameArg, payloadArg);
|
|
1805
|
+
}
|
|
1806
|
+
/** Removes a server-owned tag while keeping its name protected from clients. */
|
|
1807
|
+
removeServerTag(connectionArg, nameArg) {
|
|
1808
|
+
if (this.side !== 'server') {
|
|
1809
|
+
throw new Error('removeServerTag is only available on servers');
|
|
1810
|
+
}
|
|
1811
|
+
this.tagPolicyManager.removeServerTag('peer' in connectionArg ? connectionArg.peer : connectionArg, nameArg);
|
|
1812
|
+
}
|
|
884
1813
|
/**
|
|
885
1814
|
* Finds all connections matching the filter function.
|
|
886
1815
|
* @server-only
|
|
@@ -891,6 +1820,8 @@ export class TypedSocket {
|
|
|
891
1820
|
}
|
|
892
1821
|
const matchingConnections = [];
|
|
893
1822
|
for (const peer of this.smartServeRef.getWebSocketConnections()) {
|
|
1823
|
+
if (!this.isAttachedServerPeer(peer))
|
|
1824
|
+
continue;
|
|
894
1825
|
const wrapper = wrapSmartServePeer(peer);
|
|
895
1826
|
if (await asyncFindFuncArg(wrapper)) {
|
|
896
1827
|
matchingConnections.push(wrapper);
|
|
@@ -914,7 +1845,9 @@ export class TypedSocket {
|
|
|
914
1845
|
if (this.side !== 'server' || !this.smartServeRef) {
|
|
915
1846
|
throw new Error('findAllTargetConnectionsByTag is only available on servers');
|
|
916
1847
|
}
|
|
917
|
-
const peers = this.smartServeRef
|
|
1848
|
+
const peers = this.smartServeRef
|
|
1849
|
+
.getWebSocketConnectionsByTag(keyArg)
|
|
1850
|
+
.filter((peerArg) => this.isAttachedServerPeer(peerArg));
|
|
918
1851
|
const results = [];
|
|
919
1852
|
for (const peer of peers) {
|
|
920
1853
|
const wrapper = wrapSmartServePeer(peer);
|
|
@@ -938,4 +1871,4 @@ export class TypedSocket {
|
|
|
938
1871
|
return allResults[0];
|
|
939
1872
|
}
|
|
940
1873
|
}
|
|
941
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZWRzb2NrZXQuY2xhc3Nlcy50eXBlZHNvY2tldC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3R5cGVkc29ja2V0LmNsYXNzZXMudHlwZWRzb2NrZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSwwQkFBMEIsQ0FBQztBQUtwRCxNQUFNLFVBQVUsR0FBRyxxQkFBcUIsQ0FBQztBQTJEekM7O0dBRUc7QUFDSCxTQUFTLGtCQUFrQixDQUFDLElBQTRCO0lBQ3RELE9BQU87UUFDTCxJQUFJO1FBQ0osS0FBSyxDQUFDLFVBQVUsQ0FBQyxLQUFhO1lBQzVCLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUMxQixPQUFPLFNBQVMsQ0FBQztZQUNuQixDQUFDO1lBQ0QsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxVQUFVLEdBQUcsS0FBSyxFQUFFLENBQUMsQ0FBQztZQUN2RCxPQUFPLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsQ0FBQztRQUNoQyxDQUFDO0tBQ0YsQ0FBQztBQUNKLENBQUM7QUFFRCxTQUFTLG1CQUFtQixDQUMxQixtQkFBaUMsRUFDakMsZ0JBQThCO0lBRTlCLElBQUksQ0FBQyxtQkFBbUIsSUFBSSxtQkFBbUIsS0FBSyxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3JFLE9BQU87WUFDTCxNQUFNLEVBQUUsZ0JBQWdCLElBQUksbUJBQW1CO1lBQy9DLE9BQU8sRUFBRSxHQUFHLEVBQUUsR0FBRSxDQUFDO1NBQ2xCLENBQUM7SUFDSixDQUFDO0lBQ0QsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDdEIsT0FBTztZQUNMLE1BQU0sRUFBRSxtQkFBbUI7WUFDM0IsT0FBTyxFQUFFLEdBQUcsRUFBRSxHQUFFLENBQUM7U0FDbEIsQ0FBQztJQUNKLENB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
|
|
1874
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZWRzb2NrZXQuY2xhc3Nlcy50eXBlZHNvY2tldC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3R5cGVkc29ja2V0LmNsYXNzZXMudHlwZWRzb2NrZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSwwQkFBMEIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUM5RixPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNwRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUM3RCxPQUFPLEVBQ0wsbUNBQW1DLEVBQ25DLGtEQUFrRCxFQUNsRCxvQ0FBb0MsRUFDcEMsOEJBQThCLEVBQzlCLCtCQUErQixFQUMvQiwyQkFBMkIsR0FDNUIsTUFBTSx1QkFBdUIsQ0FBQztBQWUvQixNQUFNLFVBQVUsR0FBRyxxQkFBcUIsQ0FBQztBQUN6QyxNQUFNLFdBQVcsR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFDO0FBRXRDLE1BQU0sQ0FBQyxNQUFNLGdDQUFnQyxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFDNUQsTUFBTSxDQUFDLE1BQU0sa0NBQWtDLEdBQUcsRUFBRSxDQUFDO0FBQ3JELE1BQU0sQ0FBQyxNQUFNLGlDQUFpQyxHQUFHLENBQUMsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQ2pFLE1BQU0sQ0FBQyxNQUFNLDBDQUEwQyxHQUFHLEVBQUUsQ0FBQztBQUM3RCxNQUFNLENBQUMsTUFBTSx5Q0FBeUMsR0FBRyxFQUFFLENBQUM7QUFDNUQsTUFBTSxDQUFDLE1BQU0sdUNBQXVDLEdBQUcsSUFBSSxDQUFDO0FBQzVELE1BQU0sQ0FBQyxNQUFNLHVDQUF1QyxHQUFHLENBQUMsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQ3ZFLE1BQU0sQ0FBQyxNQUFNLGlDQUFpQyxH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
|