@floegence/flowersec-core 3.2.0 → 4.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.
Files changed (133) hide show
  1. package/README.md +57 -200
  2. package/THIRD_PARTY_NOTICES.md +11 -11
  3. package/dist/browser/index.d.ts +0 -5
  4. package/dist/browser/index.js +0 -3
  5. package/dist/cli.js +93 -64
  6. package/dist/facade.d.ts +0 -17
  7. package/dist/facade.js +0 -11
  8. package/dist/generated/unicode151.d.ts +2 -0
  9. package/dist/generated/unicode151.js +83 -0
  10. package/dist/interop/proxyServerPeer.js +34 -20
  11. package/dist/interop/serverParityPeer.js +11 -252
  12. package/dist/node/acceptor.d.ts +1 -57
  13. package/dist/node/acceptor.js +3 -420
  14. package/dist/node/acceptorV3.js +2 -2
  15. package/dist/node/connectSessionV3.js +2 -2
  16. package/dist/node/index.d.ts +2 -17
  17. package/dist/node/index.js +1 -9
  18. package/dist/node/nativeTransportAddon.d.ts +7 -36
  19. package/dist/node/nativeTransportAddon.js +7 -27
  20. package/dist/node/proxyServer.d.ts +2 -2
  21. package/dist/node/proxyServer.js +2 -2
  22. package/dist/node/rawQuicAdapterV3.d.ts +2 -2
  23. package/dist/node/rawQuicAdapterV3.js +1 -1
  24. package/dist/node/rawQuicServerV3.d.ts +2 -2
  25. package/dist/node/rawQuicServerV3.js +1 -1
  26. package/dist/node/rawQuicTls.d.ts +2 -0
  27. package/dist/node/{rawQuicAdapter.js → rawQuicTls.js} +30 -45
  28. package/dist/node/tunnelRuntimeV3.js +2 -2
  29. package/dist/proxy/integration.d.ts +5 -5
  30. package/dist/proxy/integration.js +2 -2
  31. package/dist/public/streamHandlers.d.ts +0 -3
  32. package/dist/public/streamHandlers.js +2 -4
  33. package/dist/public/streamMetadata.js +2 -2
  34. package/dist/runtime/errors.d.ts +2 -2
  35. package/dist/testSupport/tlsFixture.d.ts +2 -0
  36. package/dist/testSupport/tlsFixture.js +8 -0
  37. package/dist/utils/errors.d.ts +0 -2
  38. package/dist/utils/errors.js +0 -80
  39. package/dist/v3/artifact.js +17 -3
  40. package/dist/v3/carrier.d.ts +2 -2
  41. package/dist/v3/protocol.js +2 -103
  42. package/dist/v3/retryDisposition.d.ts +2 -2
  43. package/dist/v3/retryDisposition.js +0 -7
  44. package/dist/vendor/tr46.d.ts +4 -0
  45. package/dist/vendor/tr46.js +37 -32
  46. package/package.json +21 -19
  47. package/sbom/cyclonedx.json +62 -62
  48. package/sbom/spdx.json +65 -65
  49. package/dist/browser/connectSession.d.ts +0 -13
  50. package/dist/browser/connectSession.js +0 -40
  51. package/dist/browser/runtimeCapability.d.ts +0 -13
  52. package/dist/browser/runtimeCapability.js +0 -27
  53. package/dist/browser/sessionRuntime.d.ts +0 -2
  54. package/dist/browser/sessionRuntime.js +0 -21
  55. package/dist/browser/v2.d.ts +0 -3
  56. package/dist/browser/v2.js +0 -2
  57. package/dist/browser/webTransportClient.d.ts +0 -8
  58. package/dist/browser/webTransportClient.js +0 -55
  59. package/dist/connectionController.d.ts +0 -55
  60. package/dist/connectionController.js +0 -441
  61. package/dist/connector/adapters/rawQuicCandidate.d.ts +0 -5
  62. package/dist/connector/adapters/rawQuicCandidate.js +0 -71
  63. package/dist/connector/adapters/webSocketCandidate.d.ts +0 -7
  64. package/dist/connector/adapters/webSocketCandidate.js +0 -116
  65. package/dist/connector/adapters/webTransportCandidate.d.ts +0 -5
  66. package/dist/connector/adapters/webTransportCandidate.js +0 -73
  67. package/dist/connector/admissionCommit.d.ts +0 -31
  68. package/dist/connector/admissionCommit.js +0 -239
  69. package/dist/connector/sessionAcceptor.d.ts +0 -38
  70. package/dist/connector/sessionAcceptor.js +0 -158
  71. package/dist/connector/sessionConfig.d.ts +0 -3
  72. package/dist/connector/sessionConfig.js +0 -30
  73. package/dist/connector/sessionConnector.d.ts +0 -47
  74. package/dist/connector/sessionConnector.js +0 -606
  75. package/dist/node/connectSession.d.ts +0 -23
  76. package/dist/node/connectSession.js +0 -93
  77. package/dist/node/controlplane.d.ts +0 -137
  78. package/dist/node/controlplane.js +0 -443
  79. package/dist/node/rawQuicAdapter.d.ts +0 -9
  80. package/dist/node/rawQuicServer.d.ts +0 -24
  81. package/dist/node/rawQuicServer.js +0 -37
  82. package/dist/node/runtimeCapability.d.ts +0 -14
  83. package/dist/node/runtimeCapability.js +0 -24
  84. package/dist/node/sessionRuntime.d.ts +0 -2
  85. package/dist/node/sessionRuntime.js +0 -13
  86. package/dist/node/tunnelRuntime.d.ts +0 -42
  87. package/dist/node/tunnelRuntime.js +0 -559
  88. package/dist/node/v2.d.ts +0 -11
  89. package/dist/node/v2.js +0 -6
  90. package/dist/node/webSocketServer.d.ts +0 -24
  91. package/dist/node/webSocketServer.js +0 -135
  92. package/dist/public/artifact.d.ts +0 -11
  93. package/dist/public/artifact.js +0 -44
  94. package/dist/public/artifactLease.d.ts +0 -10
  95. package/dist/public/artifactLease.js +0 -41
  96. package/dist/public/connectError.d.ts +0 -6
  97. package/dist/public/connectError.js +0 -9
  98. package/dist/transport/webSocketAdapter.d.ts +0 -31
  99. package/dist/transport/webSocketAdapter.js +0 -370
  100. package/dist/transport/webTransportAdapter.d.ts +0 -27
  101. package/dist/transport/webTransportAdapter.js +0 -534
  102. package/dist/v2/admissionError.d.ts +0 -4
  103. package/dist/v2/admissionError.js +0 -8
  104. package/dist/v2/artifact.d.ts +0 -128
  105. package/dist/v2/artifact.js +0 -1131
  106. package/dist/v2/artifactLease.d.ts +0 -1
  107. package/dist/v2/artifactLease.js +0 -7
  108. package/dist/v2/capability.d.ts +0 -29
  109. package/dist/v2/capability.js +0 -190
  110. package/dist/v2/carrier.d.ts +0 -84
  111. package/dist/v2/carrier.js +0 -411
  112. package/dist/v2/contract.d.ts +0 -46
  113. package/dist/v2/contract.js +0 -1
  114. package/dist/v2/handshake.d.ts +0 -80
  115. package/dist/v2/handshake.js +0 -470
  116. package/dist/v2/index.d.ts +0 -14
  117. package/dist/v2/index.js +0 -7
  118. package/dist/v2/opaqueArtifact.d.ts +0 -1
  119. package/dist/v2/opaqueArtifact.js +0 -2
  120. package/dist/v2/protocol.d.ts +0 -99
  121. package/dist/v2/protocol.js +0 -737
  122. package/dist/v2/publicSession.d.ts +0 -1
  123. package/dist/v2/publicSession.js +0 -281
  124. package/dist/v2/retryDisposition.d.ts +0 -16
  125. package/dist/v2/retryDisposition.js +0 -30
  126. package/dist/v2/session.d.ts +0 -310
  127. package/dist/v2/session.js +0 -2127
  128. package/dist/v2/streamLifetimeLedger.d.ts +0 -31
  129. package/dist/v2/streamLifetimeLedger.js +0 -131
  130. package/dist/v2/streamMetadata.d.ts +0 -1
  131. package/dist/v2/streamMetadata.js +0 -7
  132. package/dist/v2/unreliableMessage.d.ts +0 -43
  133. package/dist/v2/unreliableMessage.js +0 -254
@@ -1,441 +0,0 @@
1
- import { ConnectError } from "./public/connectError.js";
2
- import { retryDispositionForConnectError, retryDispositionForSessionError, } from "./v2/retryDisposition.js";
3
- import { SDK_DEFAULTS } from "./defaults.js";
4
- const MAX_TIMER_DELAY_MS = 2_147_483_647;
5
- export class ConnectionControllerError extends Error {
6
- code;
7
- failure;
8
- constructor(code, failure = undefined) {
9
- super(`Flowersec connection controller stopped (code=${code})`);
10
- this.code = code;
11
- this.failure = failure;
12
- this.name = "ConnectionControllerError";
13
- }
14
- }
15
- /** @internal Runtime facades supply the only runtime-specific operation: one one-shot connection attempt. */
16
- export function createConnectionControllerV2(source, connectOneShot, options = {}) {
17
- return new ConnectionControllerV2Impl(source, connectOneShot, options);
18
- }
19
- class ConnectionControllerV2Impl {
20
- source;
21
- connectOneShot;
22
- controllerState = "idle";
23
- session;
24
- lastFailure;
25
- currentRetryDisposition;
26
- attempt = 0;
27
- consecutiveFailures = 0;
28
- resetAttemptOnRetry = false;
29
- lifetime = new AbortController();
30
- listeners = new Set();
31
- issuedLeases = new WeakSet();
32
- issuedSessions = new WeakSet();
33
- maxAttempts;
34
- scheduler;
35
- closeOperation;
36
- pendingConnectCleanup;
37
- pendingAcquisitionCleanup;
38
- waitingWake;
39
- manualRetryRequested = false;
40
- retryNotBefore = 0;
41
- constructor(source, connectOneShot, options) {
42
- this.source = source;
43
- this.connectOneShot = connectOneShot;
44
- if (source === null || typeof source !== "object" || typeof source.acquire !== "function") {
45
- throw new TypeError("artifact source must provide acquire()");
46
- }
47
- if (typeof connectOneShot !== "function")
48
- throw new TypeError("one-shot connector is required");
49
- if (options.maximumAttempts !== undefined &&
50
- (!Number.isSafeInteger(options.maximumAttempts) || options.maximumAttempts < 1)) {
51
- throw new TypeError("maximumAttempts must be a positive safe integer");
52
- }
53
- this.maxAttempts = options.maximumAttempts;
54
- }
55
- get state() { return this.controllerState; }
56
- get currentSession() { return this.connectedSession(); }
57
- get failure() { return this.lastFailure; }
58
- start() {
59
- if (this.controllerState !== "idle")
60
- return;
61
- this.scheduler = this.run();
62
- }
63
- retryNow() {
64
- if (this.controllerState !== "waiting" || Date.now() < this.retryNotBefore)
65
- return false;
66
- this.manualRetryRequested = true;
67
- this.waitingWake?.();
68
- return true;
69
- }
70
- async waitForSession(options = {}) {
71
- const ready = this.connectedSession();
72
- if (ready !== undefined)
73
- return ready;
74
- if (this.controllerState === "failed")
75
- throw new ConnectionControllerError("failed", this.lastFailure);
76
- if (this.controllerState === "closed")
77
- throw new ConnectionControllerError("closed", this.lastFailure);
78
- if (options.signal?.aborted === true)
79
- throw new ConnectionControllerError("canceled");
80
- return await new Promise((resolve, reject) => {
81
- const finish = (result) => {
82
- this.listeners.delete(listener);
83
- options.signal?.removeEventListener("abort", canceled);
84
- if (result.session !== undefined)
85
- resolve(result.session);
86
- else
87
- reject(result.error ?? new ConnectionControllerError("failed", this.lastFailure));
88
- };
89
- const listener = (snapshot) => {
90
- if (snapshot.state === "connected" && snapshot.currentSession !== undefined) {
91
- finish({ session: snapshot.currentSession });
92
- }
93
- else if (snapshot.state === "failed") {
94
- finish({ error: new ConnectionControllerError("failed", snapshot.failure) });
95
- }
96
- else if (snapshot.state === "closed") {
97
- finish({ error: new ConnectionControllerError("closed", snapshot.failure) });
98
- }
99
- };
100
- const canceled = () => finish({ error: new ConnectionControllerError("canceled") });
101
- this.listeners.add(listener);
102
- options.signal?.addEventListener("abort", canceled, { once: true });
103
- });
104
- }
105
- subscribe(listener) {
106
- if (typeof listener !== "function")
107
- throw new TypeError("connection listener must be a function");
108
- this.listeners.add(listener);
109
- try {
110
- listener(this.snapshot());
111
- }
112
- catch (error) {
113
- this.listeners.delete(listener);
114
- throw error;
115
- }
116
- return () => { this.listeners.delete(listener); };
117
- }
118
- close() {
119
- if (this.closeOperation !== undefined)
120
- return this.closeOperation;
121
- let resolveClose;
122
- this.closeOperation = new Promise((resolve) => {
123
- resolveClose = resolve;
124
- });
125
- const active = this.session;
126
- // A closed controller must never advertise a session that it has just retired.
127
- this.session = undefined;
128
- this.currentRetryDisposition = undefined;
129
- this.lifetime.abort(new ConnectionControllerError("closed", this.lastFailure));
130
- this.transition("closed");
131
- void this.finishClose(active).then(resolveClose);
132
- return this.closeOperation;
133
- }
134
- async finishClose(active) {
135
- this.waitingWake?.();
136
- const activeClose = active === undefined
137
- ? Promise.resolve()
138
- : active.close();
139
- await Promise.allSettled([this.scheduler ?? Promise.resolve(), activeClose]);
140
- const pendingCleanup = this.pendingConnectCleanup;
141
- const acquisitionCleanup = this.pendingAcquisitionCleanup;
142
- await Promise.allSettled([
143
- ...(pendingCleanup === undefined ? [] : [pendingCleanup]),
144
- ...(acquisitionCleanup === undefined ? [] : [acquisitionCleanup]),
145
- ]);
146
- }
147
- async run() {
148
- let disposition;
149
- while (!this.lifetime.signal.aborted) {
150
- if (disposition !== undefined) {
151
- const canContinue = await this.waitForRetry(disposition);
152
- if (!canContinue)
153
- return;
154
- }
155
- if (this.maxAttempts !== undefined && this.attempt >= this.maxAttempts) {
156
- this.currentRetryDisposition = Object.freeze({ kind: "terminal" });
157
- this.transition("failed");
158
- return;
159
- }
160
- this.currentRetryDisposition = undefined;
161
- this.attempt += 1;
162
- this.transition("connecting");
163
- const acquisition = await this.acquireLease();
164
- if (this.lifetime.signal.aborted)
165
- return;
166
- if (acquisition.kind === "failure") {
167
- this.lastFailure = Object.freeze({ phase: "artifact", code: acquisition.code });
168
- disposition = acquisition.disposition;
169
- this.currentRetryDisposition = disposition;
170
- if (disposition.kind === "terminal") {
171
- this.transition("failed");
172
- return;
173
- }
174
- this.consecutiveFailures += 1;
175
- continue;
176
- }
177
- let connected;
178
- try {
179
- connected = await this.connect(acquisition.lease);
180
- }
181
- catch (error) {
182
- if (this.lifetime.signal.aborted)
183
- return;
184
- const failure = connectFailure(error);
185
- this.lastFailure = failure.failure;
186
- disposition = failure.disposition;
187
- this.currentRetryDisposition = disposition;
188
- if (disposition.kind === "terminal") {
189
- this.transition("failed");
190
- return;
191
- }
192
- this.consecutiveFailures += 1;
193
- continue;
194
- }
195
- if (this.lifetime.signal.aborted) {
196
- await connected.close().catch(() => undefined);
197
- return;
198
- }
199
- this.session = connected;
200
- this.lastFailure = undefined;
201
- this.currentRetryDisposition = undefined;
202
- this.consecutiveFailures = 0;
203
- disposition = undefined;
204
- this.transition("connected");
205
- const termination = await raceTermination(connected, this.lifetime.signal);
206
- if (termination === undefined || this.lifetime.signal.aborted)
207
- return;
208
- // A terminated session is no longer current while the replacement attempt waits.
209
- this.session = undefined;
210
- await connected.close().catch(() => undefined);
211
- if (this.lifetime.signal.aborted)
212
- return;
213
- const failure = sessionFailure(termination.error);
214
- this.lastFailure = failure.failure;
215
- disposition = failure.disposition;
216
- this.currentRetryDisposition = disposition;
217
- if (disposition.kind === "terminal") {
218
- this.transition("failed");
219
- return;
220
- }
221
- this.consecutiveFailures = 1;
222
- this.resetAttemptOnRetry = true;
223
- }
224
- }
225
- async acquireLease() {
226
- let result;
227
- let pending;
228
- try {
229
- pending = this.source.acquire({ signal: this.lifetime.signal });
230
- }
231
- catch {
232
- return terminalArtifactFailure("artifact_source_failed");
233
- }
234
- const cleanup = pending.then(() => undefined, () => undefined);
235
- this.pendingAcquisitionCleanup = cleanup;
236
- void cleanup.finally(() => {
237
- if (this.pendingAcquisitionCleanup === cleanup)
238
- this.pendingAcquisitionCleanup = undefined;
239
- }).catch(() => undefined);
240
- try {
241
- result = await raceAbort(pending, this.lifetime.signal);
242
- }
243
- catch {
244
- return terminalArtifactFailure("artifact_source_failed");
245
- }
246
- try {
247
- if (result === null || typeof result !== "object")
248
- return terminalArtifactFailure("artifact_source_failed");
249
- if (result.kind === "failure") {
250
- if (!validFailureCode(result.code) || !validDisposition(result.disposition)) {
251
- return terminalArtifactFailure("artifact_source_failed");
252
- }
253
- return Object.freeze({ kind: "failure", code: result.code, disposition: normalizeDisposition(result.disposition) });
254
- }
255
- if (result.kind !== "lease" || result.lease === null || typeof result.lease !== "object") {
256
- return terminalArtifactFailure("artifact_source_failed");
257
- }
258
- if (this.issuedLeases.has(result.lease))
259
- return terminalArtifactFailure("reused_artifact_lease");
260
- this.issuedLeases.add(result.lease);
261
- return result;
262
- }
263
- catch {
264
- return terminalArtifactFailure("artifact_source_failed");
265
- }
266
- }
267
- async connect(lease) {
268
- const pending = this.connectOneShot(lease, this.lifetime.signal);
269
- try {
270
- const session = await raceAbort(pending, this.lifetime.signal);
271
- if (session === null || typeof session !== "object" ||
272
- typeof session.close !== "function" || typeof session.waitTermination !== "function") {
273
- throw new TypeError("one-shot connector returned an invalid session");
274
- }
275
- if (this.issuedSessions.has(session)) {
276
- await session.close().catch(() => undefined);
277
- throw new Error("one-shot connector reused a previous session");
278
- }
279
- this.issuedSessions.add(session);
280
- return session;
281
- }
282
- catch (error) {
283
- if (this.lifetime.signal.aborted) {
284
- const cleanup = pending.then(async (lateSession) => await lateSession.close(), () => undefined);
285
- this.pendingConnectCleanup = cleanup;
286
- void cleanup.finally(() => {
287
- if (this.pendingConnectCleanup === cleanup)
288
- this.pendingConnectCleanup = undefined;
289
- }).catch(() => undefined);
290
- }
291
- throw error;
292
- }
293
- }
294
- async waitForRetry(disposition) {
295
- if (this.maxAttempts !== undefined && !this.resetAttemptOnRetry && this.attempt >= this.maxAttempts) {
296
- this.currentRetryDisposition = Object.freeze({ kind: "terminal" });
297
- this.transition("failed");
298
- return false;
299
- }
300
- const now = Date.now();
301
- const backoffDeadline = now + retryDelay(this.consecutiveFailures);
302
- const hardDeadline = disposition.kind === "retry_after"
303
- ? disposition.notBeforeUnixMilliseconds
304
- : 0;
305
- this.retryNotBefore = hardDeadline;
306
- this.manualRetryRequested = false;
307
- this.transition("waiting");
308
- while (!this.lifetime.signal.aborted) {
309
- const deadline = this.manualRetryRequested
310
- ? hardDeadline
311
- : Math.max(backoffDeadline, hardDeadline);
312
- const remaining = deadline - Date.now();
313
- if (remaining <= 0) {
314
- this.waitingWake = undefined;
315
- this.retryNotBefore = 0;
316
- if (this.resetAttemptOnRetry) {
317
- this.attempt = 0;
318
- this.resetAttemptOnRetry = false;
319
- }
320
- return true;
321
- }
322
- await this.wait(Math.min(remaining, MAX_TIMER_DELAY_MS));
323
- }
324
- this.waitingWake = undefined;
325
- this.retryNotBefore = 0;
326
- return false;
327
- }
328
- async wait(milliseconds) {
329
- await new Promise((resolve) => {
330
- let settled = false;
331
- const finish = () => {
332
- if (settled)
333
- return;
334
- settled = true;
335
- clearTimeout(timer);
336
- this.lifetime.signal.removeEventListener("abort", finish);
337
- if (this.waitingWake === finish)
338
- this.waitingWake = undefined;
339
- resolve();
340
- };
341
- const timer = setTimeout(finish, milliseconds);
342
- this.waitingWake = finish;
343
- this.lifetime.signal.addEventListener("abort", finish, { once: true });
344
- });
345
- }
346
- connectedSession() {
347
- return this.controllerState === "connected" ? this.session : undefined;
348
- }
349
- transition(state) {
350
- this.controllerState = state;
351
- const snapshot = this.snapshot();
352
- for (const listener of this.listeners) {
353
- try {
354
- listener(snapshot);
355
- }
356
- catch { /* Listener failures do not own controller lifecycle. */ }
357
- }
358
- }
359
- snapshot() {
360
- const currentSession = this.connectedSession();
361
- return Object.freeze({
362
- state: this.controllerState,
363
- attempt: this.attempt,
364
- ...(currentSession === undefined ? {} : { currentSession }),
365
- ...(this.lastFailure === undefined ? {} : { failure: this.lastFailure }),
366
- ...(this.currentRetryDisposition === undefined ? {} : { retryDisposition: this.currentRetryDisposition }),
367
- });
368
- }
369
- }
370
- function connectFailure(error) {
371
- if (!(error instanceof ConnectError)) {
372
- return Object.freeze({
373
- failure: Object.freeze({ phase: "connect", code: "connection_failed" }),
374
- disposition: Object.freeze({ kind: "terminal" }),
375
- });
376
- }
377
- const disposition = retryDispositionForConnectError(error);
378
- return Object.freeze({
379
- failure: Object.freeze({ phase: "connect", code: error.code }),
380
- disposition,
381
- });
382
- }
383
- function sessionFailure(error) {
384
- const disposition = retryDispositionForSessionError(error);
385
- return Object.freeze({
386
- failure: Object.freeze({ phase: "session", code: error.code }),
387
- disposition,
388
- });
389
- }
390
- function terminalArtifactFailure(code) {
391
- return Object.freeze({
392
- kind: "failure",
393
- code,
394
- disposition: Object.freeze({ kind: "terminal" }),
395
- });
396
- }
397
- function validFailureCode(code) {
398
- return typeof code === "string" && /^[a-z][a-z0-9_]{0,63}$/.test(code);
399
- }
400
- function validDisposition(value) {
401
- if (value === null || typeof value !== "object" || !("kind" in value))
402
- return false;
403
- const disposition = value;
404
- if (disposition.kind === "terminal" || disposition.kind === "retryable")
405
- return true;
406
- return disposition.kind === "retry_after" &&
407
- typeof disposition.notBeforeUnixMilliseconds === "number" &&
408
- Number.isSafeInteger(disposition.notBeforeUnixMilliseconds) &&
409
- disposition.notBeforeUnixMilliseconds >= 0;
410
- }
411
- function normalizeDisposition(disposition) {
412
- if (disposition.kind === "retry_after") {
413
- return Object.freeze({
414
- kind: "retry_after",
415
- notBeforeUnixMilliseconds: disposition.notBeforeUnixMilliseconds,
416
- });
417
- }
418
- return Object.freeze({ kind: disposition.kind });
419
- }
420
- function retryDelay(failures) {
421
- const exponent = Math.max(0, Math.min(30, failures - 1));
422
- return Math.min(SDK_DEFAULTS.connectionController.maxDelayMs, SDK_DEFAULTS.connectionController.initialDelayMs *
423
- (SDK_DEFAULTS.connectionController.factor ** exponent));
424
- }
425
- async function raceAbort(promise, signal) {
426
- if (signal.aborted)
427
- throw signal.reason;
428
- return await new Promise((resolve, reject) => {
429
- const abort = () => reject(signal.reason);
430
- signal.addEventListener("abort", abort, { once: true });
431
- void promise.then(resolve, reject).finally(() => signal.removeEventListener("abort", abort));
432
- });
433
- }
434
- async function raceTermination(session, signal) {
435
- try {
436
- return await raceAbort(session.waitTermination(), signal);
437
- }
438
- catch {
439
- return undefined;
440
- }
441
- }
@@ -1,5 +0,0 @@
1
- import type { ArtifactV2, CanonicalArtifactCandidateV2 } from "../../v2/artifact.js";
2
- import { type NativeCarrierSessionV2 } from "../../v2/carrier.js";
3
- import type { CandidateAttemptFactoryV2 } from "../sessionConnector.js";
4
- export type RawQuicClientFactoryV2 = (candidate: CanonicalArtifactCandidateV2, artifact: ArtifactV2, signal: AbortSignal) => Promise<NativeCarrierSessionV2>;
5
- export declare function createRawQuicCandidateFactoryV2(factory: RawQuicClientFactoryV2): CandidateAttemptFactoryV2;
@@ -1,71 +0,0 @@
1
- import { adaptNativeCarrierSessionV2, } from "../../v2/carrier.js";
2
- export function createRawQuicCandidateFactoryV2(factory) {
3
- return {
4
- create(candidate, artifact) {
5
- if (candidate.carrier !== "raw_quic") {
6
- throw new Error(`unsupported raw QUIC carrier ${candidate.carrier}`);
7
- }
8
- return new RawQuicCandidateAttempt(candidate, artifact, factory);
9
- },
10
- };
11
- }
12
- class RawQuicCandidateAttempt {
13
- candidate;
14
- artifact;
15
- factory;
16
- controller = new AbortController();
17
- carrier;
18
- finalized = false;
19
- constructor(candidate, artifact, factory) {
20
- this.candidate = candidate;
21
- this.artifact = artifact;
22
- this.factory = factory;
23
- }
24
- async ready(signal) {
25
- const unlink = linkAbort(signal, this.controller);
26
- try {
27
- const carrier = await this.factory(this.candidate, this.artifact, this.controller.signal);
28
- this.carrier = carrier;
29
- return {
30
- candidate: this.candidate,
31
- kind: carrier.kind,
32
- path: carrier.path,
33
- inboundBidirectionalStreamCapacity: carrier.inboundBidirectionalStreamCapacity,
34
- openAdmissionChannel: async (channelSignal) => {
35
- const options = channelSignal === undefined ? {} : { signal: channelSignal };
36
- const stream = await carrier.openStream(options);
37
- return {
38
- framing: "stream",
39
- stream,
40
- abort: (error) => stream.abort(error),
41
- };
42
- },
43
- finalize: () => {
44
- if (this.finalized)
45
- throw new Error("raw QUIC candidate already finalized");
46
- this.finalized = true;
47
- return adaptNativeCarrierSessionV2(carrier);
48
- },
49
- close: async () => await carrier.close(),
50
- abort: () => carrier.abort({ code: 6, reason: "candidate aborted" }),
51
- };
52
- }
53
- finally {
54
- unlink();
55
- }
56
- }
57
- abort() {
58
- this.controller.abort(new Error("raw QUIC candidate aborted"));
59
- this.carrier?.abort({ code: 6, reason: "candidate aborted" });
60
- }
61
- }
62
- function linkAbort(parent, child) {
63
- if (parent === undefined)
64
- return () => undefined;
65
- const abort = () => child.abort(parent.reason);
66
- if (parent.aborted)
67
- abort();
68
- else
69
- parent.addEventListener("abort", abort, { once: true });
70
- return () => parent.removeEventListener("abort", abort);
71
- }
@@ -1,7 +0,0 @@
1
- import type { CandidateAttemptFactoryV2 } from "../sessionConnector.js";
2
- import { type WebSocketLike } from "../../ws-client/binaryTransport.js";
3
- type WebSocketLikeWithProtocol = WebSocketLike & Readonly<{
4
- protocol?: string;
5
- }>;
6
- export declare function createWebSocketCandidateFactoryV2(factory: (url: string, subprotocol: string) => WebSocketLikeWithProtocol): CandidateAttemptFactoryV2;
7
- export {};
@@ -1,116 +0,0 @@
1
- import { createWebSocketCarrierSessionV2 } from "../../transport/webSocketAdapter.js";
2
- import { WebSocketBinaryTransport } from "../../ws-client/binaryTransport.js";
3
- export function createWebSocketCandidateFactoryV2(factory) {
4
- return {
5
- create(candidate, artifact) {
6
- if (candidate.carrier !== "websocket")
7
- throw new Error(`unsupported WebSocket carrier ${candidate.carrier}`);
8
- return new WebSocketCandidateAttempt(candidate, artifact, factory);
9
- },
10
- };
11
- }
12
- class WebSocketCandidateAttempt {
13
- candidate;
14
- artifact;
15
- factory;
16
- socket;
17
- transport;
18
- aborted = false;
19
- finalized = false;
20
- constructor(candidate, artifact, factory) {
21
- this.candidate = candidate;
22
- this.artifact = artifact;
23
- this.factory = factory;
24
- }
25
- async ready(signal) {
26
- if (this.aborted)
27
- throw new Error("WebSocket candidate aborted");
28
- const path = this.artifact.path.kind;
29
- const subprotocol = path === "direct" ? "flowersec.direct.v2" : "flowersec.tunnel.v2";
30
- const socket = this.factory(this.candidate.normalized_url, subprotocol);
31
- this.socket = socket;
32
- await waitForOpen(socket, subprotocol, signal);
33
- if (this.aborted)
34
- throw new Error("WebSocket candidate aborted");
35
- const transport = new WebSocketBinaryTransport(socket);
36
- this.transport = transport;
37
- const inboundBidirectionalStreamCapacity = this.artifact.session.max_inbound_streams + 2;
38
- return {
39
- candidate: this.candidate,
40
- kind: "websocket",
41
- path,
42
- inboundBidirectionalStreamCapacity,
43
- openAdmissionChannel: async () => ({
44
- framing: "message",
45
- write: async (data, options = {}) => await transport.writeBinary(data, options),
46
- read: async (options = {}) => await transport.readBinary(options),
47
- abort: () => transport.close(),
48
- }),
49
- finalize: () => {
50
- if (this.finalized)
51
- throw new Error("WebSocket candidate already finalized");
52
- this.finalized = true;
53
- return createWebSocketCarrierSessionV2(transport, {
54
- path,
55
- client: this.artifact.path.kind !== "tunnel" || this.artifact.path.role !== 2,
56
- inboundBidirectionalStreamCapacity,
57
- });
58
- },
59
- close: async () => transport.close(),
60
- abort: () => transport.close(),
61
- };
62
- }
63
- abort() {
64
- this.aborted = true;
65
- this.transport?.close();
66
- this.socket?.close();
67
- }
68
- }
69
- function waitForOpen(socket, expectedProtocol, signal) {
70
- if (socket.readyState === 1) {
71
- validateSubprotocol(socket, expectedProtocol);
72
- return Promise.resolve();
73
- }
74
- return new Promise((resolve, reject) => {
75
- let settled = false;
76
- const cleanup = () => {
77
- socket.removeEventListener("open", open);
78
- socket.removeEventListener("error", error);
79
- socket.removeEventListener("close", close);
80
- signal?.removeEventListener("abort", abort);
81
- };
82
- const finish = (failure) => {
83
- if (settled)
84
- return;
85
- settled = true;
86
- cleanup();
87
- failure === undefined ? resolve() : reject(failure);
88
- };
89
- const open = () => {
90
- try {
91
- validateSubprotocol(socket, expectedProtocol);
92
- finish();
93
- }
94
- catch (cause) {
95
- finish(asError(cause));
96
- }
97
- };
98
- const error = () => finish(new Error("WebSocket candidate failed before ready"));
99
- const close = () => finish(new Error("WebSocket candidate closed before ready"));
100
- const abort = () => { socket.close(); finish(new Error("WebSocket candidate aborted")); };
101
- socket.addEventListener("open", open);
102
- socket.addEventListener("error", error);
103
- socket.addEventListener("close", close);
104
- signal?.addEventListener("abort", abort, { once: true });
105
- if (signal?.aborted === true)
106
- abort();
107
- });
108
- }
109
- function validateSubprotocol(socket, expected) {
110
- if (socket.protocol !== undefined && socket.protocol !== expected) {
111
- throw new Error(`unexpected WebSocket subprotocol ${socket.protocol}`);
112
- }
113
- }
114
- function asError(error) {
115
- return error instanceof Error ? error : new Error(String(error));
116
- }
@@ -1,5 +0,0 @@
1
- import type { ArtifactV2, CanonicalArtifactCandidateV2 } from "../../v2/artifact.js";
2
- import { type NativeCarrierSessionV2 } from "../../v2/carrier.js";
3
- import type { CandidateAttemptFactoryV2 } from "../sessionConnector.js";
4
- export type WebTransportClientFactoryV2 = (candidate: CanonicalArtifactCandidateV2, artifact: ArtifactV2, signal: AbortSignal) => Promise<NativeCarrierSessionV2>;
5
- export declare function createWebTransportCandidateFactoryV2(factory: WebTransportClientFactoryV2): CandidateAttemptFactoryV2;