velocious 1.0.626 → 1.0.628
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -3
- package/build/background-jobs/job-runner.js +9 -1
- package/build/background-jobs/local-dispatcher.js +23 -1
- package/build/background-jobs/main.js +6 -4
- package/build/background-jobs/perform-job.js +10 -1
- package/build/background-jobs/platform-job.js +62 -0
- package/build/background-jobs/runtime.js +6 -3
- package/build/background-jobs/types.js +8 -0
- package/build/background-jobs/worker.js +3 -1
- package/build/database/pool/async-tracked-multi-connection.js +46 -9
- package/build/database/pool/base.js +3 -0
- package/build/database/pool/checkout-timeout-error.js +16 -0
- package/build/http-client/websocket-client.js +52 -0
- package/build/http-server/client/index.js +6 -0
- package/build/http-server/client/websocket-session.js +30 -0
- package/build/http-server/index.js +202 -38
- package/build/http-server/worker-handler/index.js +15 -1
- package/build/http-server/worker-handler/worker-thread.js +8 -0
- package/build/src/background-jobs/job-runner.d.ts.map +1 -1
- package/build/src/background-jobs/job-runner.js +10 -2
- package/build/src/background-jobs/local-dispatcher.d.ts.map +1 -1
- package/build/src/background-jobs/local-dispatcher.js +24 -2
- package/build/src/background-jobs/main.d.ts.map +1 -1
- package/build/src/background-jobs/main.js +7 -5
- package/build/src/background-jobs/perform-job.d.ts +5 -1
- package/build/src/background-jobs/perform-job.d.ts.map +1 -1
- package/build/src/background-jobs/perform-job.js +11 -2
- package/build/src/background-jobs/platform-job.d.ts +34 -0
- package/build/src/background-jobs/platform-job.d.ts.map +1 -1
- package/build/src/background-jobs/platform-job.js +56 -1
- package/build/src/background-jobs/runtime.d.ts.map +1 -1
- package/build/src/background-jobs/runtime.js +7 -4
- package/build/src/background-jobs/types.d.ts +30 -0
- package/build/src/background-jobs/types.d.ts.map +1 -1
- package/build/src/background-jobs/types.js +9 -1
- package/build/src/background-jobs/worker.d.ts.map +1 -1
- package/build/src/background-jobs/worker.js +4 -2
- package/build/src/database/pool/async-tracked-multi-connection.d.ts +22 -2
- package/build/src/database/pool/async-tracked-multi-connection.d.ts.map +1 -1
- package/build/src/database/pool/async-tracked-multi-connection.js +44 -10
- package/build/src/database/pool/base.d.ts +15 -0
- package/build/src/database/pool/base.d.ts.map +1 -1
- package/build/src/database/pool/base.js +4 -1
- package/build/src/database/pool/checkout-timeout-error.d.ts +13 -0
- package/build/src/database/pool/checkout-timeout-error.d.ts.map +1 -0
- package/build/src/database/pool/checkout-timeout-error.js +15 -0
- package/build/src/http-client/websocket-client.d.ts +18 -0
- package/build/src/http-client/websocket-client.d.ts.map +1 -1
- package/build/src/http-client/websocket-client.js +48 -1
- package/build/src/http-server/client/index.d.ts.map +1 -1
- package/build/src/http-server/client/index.js +7 -1
- package/build/src/http-server/client/websocket-session.d.ts +6 -0
- package/build/src/http-server/client/websocket-session.d.ts.map +1 -1
- package/build/src/http-server/client/websocket-session.js +27 -1
- package/build/src/http-server/index.d.ts +82 -10
- package/build/src/http-server/index.d.ts.map +1 -1
- package/build/src/http-server/index.js +186 -33
- package/build/src/http-server/worker-handler/index.d.ts +28 -1
- package/build/src/http-server/worker-handler/index.d.ts.map +1 -1
- package/build/src/http-server/worker-handler/index.js +23 -2
- package/build/src/http-server/worker-handler/worker-thread.d.ts.map +1 -1
- package/build/src/http-server/worker-handler/worker-thread.js +7 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/background-jobs/job-runner.js +9 -1
- package/src/background-jobs/local-dispatcher.js +23 -1
- package/src/background-jobs/main.js +6 -4
- package/src/background-jobs/perform-job.js +10 -1
- package/src/background-jobs/platform-job.js +62 -0
- package/src/background-jobs/runtime.js +6 -3
- package/src/background-jobs/types.js +8 -0
- package/src/background-jobs/worker.js +3 -1
- package/src/database/pool/async-tracked-multi-connection.js +46 -9
- package/src/database/pool/base.js +3 -0
- package/src/database/pool/checkout-timeout-error.js +16 -0
- package/src/http-client/websocket-client.js +52 -0
- package/src/http-server/client/index.js +6 -0
- package/src/http-server/client/websocket-session.js +30 -0
- package/src/http-server/index.js +202 -38
- package/src/http-server/worker-handler/index.js +15 -1
- package/src/http-server/worker-handler/worker-thread.js +8 -0
|
@@ -5,6 +5,7 @@ import EventEmitter from "../utils/event-emitter.js";
|
|
|
5
5
|
import InProcessHandler from "./worker-handler/in-process.js";
|
|
6
6
|
import Logger from "../logger.js";
|
|
7
7
|
import Net from "net";
|
|
8
|
+
import os from "node:os";
|
|
8
9
|
import ServerClient from "./server-client.js";
|
|
9
10
|
import WorkerHandler from "./worker-handler/index.js";
|
|
10
11
|
/**
|
|
@@ -12,21 +13,24 @@ import WorkerHandler from "./worker-handler/index.js";
|
|
|
12
13
|
* @typedef {{start: () => Promise<void>, stop: () => Promise<void>}} DevelopmentReloaderLike */
|
|
13
14
|
/**
|
|
14
15
|
* Defines this typedef.
|
|
15
|
-
* @typedef {(args: {configuration: import("../configuration.js").default, workerCount: number}) => (WorkerHandler | InProcessHandler)} WorkerHandlerFactory */
|
|
16
|
+
* @typedef {(args: {configuration: import("../configuration.js").default, onWebsocketSessionOwned: (args: {sessionId: string, workerHandler: WorkerHandler}) => void, onWebsocketSessionReleased: (args: {sessionId: string, workerHandler: WorkerHandler}) => void, onWorkerStopped: (args: {workerHandler: WorkerHandler}) => void, workerCount: number}) => (WorkerHandler | InProcessHandler)} WorkerHandlerFactory */
|
|
16
17
|
/**
|
|
17
18
|
* Runs normalize worker count.
|
|
18
19
|
* @param {object} args - Options object.
|
|
19
20
|
* @param {number} [args.maxWorkers] - Backward-compatible worker count alias.
|
|
20
21
|
* @param {number} [args.workers] - Configured worker count.
|
|
22
|
+
* @param {number} args.defaultWorkerCount - Process-available CPU count.
|
|
21
23
|
* @returns {number} - Normalized worker count.
|
|
22
24
|
*/
|
|
23
|
-
function normalizeWorkerCount({ maxWorkers, workers }) {
|
|
24
|
-
const workerCount = workers ?? maxWorkers ??
|
|
25
|
+
function normalizeWorkerCount({ defaultWorkerCount, maxWorkers, workers }) {
|
|
26
|
+
const workerCount = workers ?? maxWorkers ?? defaultWorkerCount;
|
|
25
27
|
if (!Number.isInteger(workerCount) || workerCount < 1) {
|
|
26
28
|
throw new Error("HTTP server workers must be a positive integer");
|
|
27
29
|
}
|
|
28
30
|
return workerCount;
|
|
29
31
|
}
|
|
32
|
+
const MAX_INITIAL_REQUEST_HEADER_BYTES = 64 * 1024;
|
|
33
|
+
const WEBSOCKET_SESSION_ROUTING_PARAMETER = "velociousSessionId";
|
|
30
34
|
export default class VelociousHttpServer {
|
|
31
35
|
clientCount = 0;
|
|
32
36
|
_starting = false;
|
|
@@ -57,10 +61,8 @@ export default class VelociousHttpServer {
|
|
|
57
61
|
* @type {Array<WorkerHandler | InProcessHandler>} */
|
|
58
62
|
workerHandlers = [];
|
|
59
63
|
nextWorkerHandlerIndex = 0;
|
|
60
|
-
/**
|
|
61
|
-
|
|
62
|
-
* @type {Map<string, WorkerHandler | InProcessHandler>} */
|
|
63
|
-
stickyWorkerHandlers = new Map();
|
|
64
|
+
/** Worker ownership for live or grace-paused resumable WebSocket sessions. */
|
|
65
|
+
websocketSessionOwners = new Map();
|
|
64
66
|
/**
|
|
65
67
|
* Runs constructor.
|
|
66
68
|
* @param {object} args - Options object.
|
|
@@ -70,10 +72,11 @@ export default class VelociousHttpServer {
|
|
|
70
72
|
* @param {number} [args.port] - Port.
|
|
71
73
|
* @param {number} [args.maxWorkers] - Max workers.
|
|
72
74
|
* @param {number} [args.workers] - Worker handlers to start.
|
|
75
|
+
* @param {() => number} [args.availableParallelism] - CPU availability owner seam.
|
|
73
76
|
* @param {(args: {configuration: import("../configuration.js").default, onReload: (args: {changedPath: string}) => Promise<void>}) => {start: () => Promise<void>, stop: () => Promise<void>}} [args.developmentReloaderFactory] - Development reloader factory.
|
|
74
77
|
* @param {WorkerHandlerFactory} [args.workerHandlerFactory] - Worker handler factory.
|
|
75
78
|
*/
|
|
76
|
-
constructor({ configuration, developmentReloaderFactory, host, inProcess, maxWorkers, port, workerHandlerFactory, workers }) {
|
|
79
|
+
constructor({ availableParallelism = os.availableParallelism, configuration, developmentReloaderFactory, host, inProcess, maxWorkers, port, workerHandlerFactory, workers }) {
|
|
77
80
|
this.configuration = configuration;
|
|
78
81
|
this.developmentReloaderFactory = developmentReloaderFactory;
|
|
79
82
|
this.workerHandlerFactory = workerHandlerFactory;
|
|
@@ -81,7 +84,8 @@ export default class VelociousHttpServer {
|
|
|
81
84
|
this.logger = new Logger(this);
|
|
82
85
|
this.host = host ?? "0.0.0.0";
|
|
83
86
|
this.port = port ?? 3006;
|
|
84
|
-
this.workers = normalizeWorkerCount({ maxWorkers, workers });
|
|
87
|
+
this.workers = normalizeWorkerCount({ defaultWorkerCount: availableParallelism(), maxWorkers, workers });
|
|
88
|
+
this.effectiveWorkers = this.inProcess && workers === undefined && maxWorkers === undefined ? 1 : this.workers;
|
|
85
89
|
}
|
|
86
90
|
/**
|
|
87
91
|
* Runs start.
|
|
@@ -147,7 +151,7 @@ export default class VelociousHttpServer {
|
|
|
147
151
|
this.developmentReloader = startupState.developmentReloader;
|
|
148
152
|
this.netServer = startupState.netServer;
|
|
149
153
|
this.workerHandlers = startupState.workerHandlers;
|
|
150
|
-
this.
|
|
154
|
+
this.websocketSessionOwners.clear();
|
|
151
155
|
}
|
|
152
156
|
/**
|
|
153
157
|
* Runs net server listen.
|
|
@@ -183,7 +187,7 @@ export default class VelociousHttpServer {
|
|
|
183
187
|
* @returns {Promise<void>} - Resolves when complete.
|
|
184
188
|
*/
|
|
185
189
|
async _ensureWorkers() {
|
|
186
|
-
while (this.workerHandlers.length < this.
|
|
190
|
+
while (this.workerHandlers.length < this.effectiveWorkers) {
|
|
187
191
|
await this.spawnWorker();
|
|
188
192
|
}
|
|
189
193
|
}
|
|
@@ -207,6 +211,7 @@ export default class VelociousHttpServer {
|
|
|
207
211
|
activeSocketCount: this._activeSockets.size,
|
|
208
212
|
clientCount: Object.keys(this.clients).length,
|
|
209
213
|
configuredWorkerCount: this.workers,
|
|
214
|
+
effectiveWorkerCount: this.effectiveWorkers,
|
|
210
215
|
inProcess: this.inProcess,
|
|
211
216
|
workerCount: this.workerHandlers.length,
|
|
212
217
|
workers: await Promise.all(this.workerHandlers.map((handler) => this.workerDebugSnapshot(handler)))
|
|
@@ -292,7 +297,7 @@ export default class VelociousHttpServer {
|
|
|
292
297
|
const stopTasks = this.workerHandlers.map((handler) => handler.stop());
|
|
293
298
|
await Promise.all(stopTasks);
|
|
294
299
|
this.workerHandlers = [];
|
|
295
|
-
this.
|
|
300
|
+
this.websocketSessionOwners.clear();
|
|
296
301
|
}
|
|
297
302
|
/**
|
|
298
303
|
* On close.
|
|
@@ -326,24 +331,173 @@ export default class VelociousHttpServer {
|
|
|
326
331
|
}]);
|
|
327
332
|
this.clientCount++;
|
|
328
333
|
try {
|
|
329
|
-
// Paused WebSocket sessions are worker-local, so reconnects from
|
|
330
|
-
// the same client address must return to the same worker.
|
|
331
|
-
const workerHandler = this.workerHandlerToUse({ stickyKey: socket.remoteAddress });
|
|
332
334
|
const client = new ServerClient({
|
|
333
335
|
clientCount,
|
|
334
336
|
configuration: this.configuration,
|
|
335
337
|
socket
|
|
336
338
|
});
|
|
337
339
|
client.events.on("close", this.onClientClose);
|
|
338
|
-
this.logger.debug(`Gave client ${clientCount} to worker ${workerHandler.workerCount}`);
|
|
339
|
-
workerHandler.addSocketConnection(client);
|
|
340
340
|
this.clients[clientCount] = client;
|
|
341
|
+
this.routeClientAfterInitialRoutingData(client);
|
|
341
342
|
}
|
|
342
343
|
catch (error) {
|
|
343
344
|
this.logger.error(`Failed to initialize client ${clientCount} on new connection`, error);
|
|
344
345
|
socket.destroy();
|
|
345
346
|
}
|
|
346
347
|
};
|
|
348
|
+
/**
|
|
349
|
+
* Buffers only the bounded initial request data needed to recognize a
|
|
350
|
+
* WebSocket resume routing hint, then replays it to the selected worker.
|
|
351
|
+
* @param {ServerClient} client - Unassigned socket client.
|
|
352
|
+
* @returns {void}
|
|
353
|
+
*/
|
|
354
|
+
routeClientAfterInitialRoutingData(client) {
|
|
355
|
+
const { socket } = client;
|
|
356
|
+
/** @type {Buffer[]} */
|
|
357
|
+
const chunks = [];
|
|
358
|
+
let byteLength = 0;
|
|
359
|
+
const cleanup = () => {
|
|
360
|
+
socket.off("data", onData);
|
|
361
|
+
socket.off("close", cleanup);
|
|
362
|
+
};
|
|
363
|
+
const onData = (/** @type {Buffer} */ chunk) => {
|
|
364
|
+
chunks.push(chunk);
|
|
365
|
+
byteLength += chunk.length;
|
|
366
|
+
const initialRequest = Buffer.concat(chunks, byteLength);
|
|
367
|
+
if (this.initialRequestNeedsMoreRoutingData(initialRequest) && byteLength < MAX_INITIAL_REQUEST_HEADER_BYTES)
|
|
368
|
+
return;
|
|
369
|
+
cleanup();
|
|
370
|
+
this.assignClientToWorker(client, initialRequest);
|
|
371
|
+
};
|
|
372
|
+
socket.on("data", onData);
|
|
373
|
+
socket.once("close", cleanup);
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Checks whether the buffered initial HTTP headers are complete.
|
|
377
|
+
* @param {Buffer} initialRequest - Buffered initial request bytes.
|
|
378
|
+
* @returns {boolean} - Whether a header terminator is present.
|
|
379
|
+
*/
|
|
380
|
+
initialRequestHeadersComplete(initialRequest) {
|
|
381
|
+
return initialRequest.includes("\r\n\r\n") || initialRequest.includes("\n\n");
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Checks whether a possible resumable WebSocket request still needs headers.
|
|
385
|
+
* Ordinary and malformed requests can reach the existing request parser as
|
|
386
|
+
* soon as their first line is complete.
|
|
387
|
+
* @param {Buffer} initialRequest - Buffered initial request bytes.
|
|
388
|
+
* @returns {boolean} - Whether more routing data is required.
|
|
389
|
+
*/
|
|
390
|
+
initialRequestNeedsMoreRoutingData(initialRequest) {
|
|
391
|
+
if (this.initialRequestHeadersComplete(initialRequest))
|
|
392
|
+
return false;
|
|
393
|
+
const lineEnd = initialRequest.indexOf("\n");
|
|
394
|
+
if (lineEnd === -1)
|
|
395
|
+
return true;
|
|
396
|
+
const requestLine = initialRequest.subarray(0, lineEnd).toString("latin1").replace(/\r$/, "");
|
|
397
|
+
const requestLineMatch = requestLine.match(/^GET ([^ ]+) HTTP\/[^ ]+$/);
|
|
398
|
+
if (!requestLineMatch)
|
|
399
|
+
return false;
|
|
400
|
+
try {
|
|
401
|
+
const requestUrl = new URL(requestLineMatch[1], "http://velocious.invalid");
|
|
402
|
+
return requestUrl.searchParams.has(WEBSOCKET_SESSION_ROUTING_PARAMETER);
|
|
403
|
+
}
|
|
404
|
+
catch {
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Assigns a buffered client and replays the exact bytes into its worker.
|
|
410
|
+
* @param {ServerClient} client - Client awaiting assignment.
|
|
411
|
+
* @param {Buffer} initialRequest - Initial request bytes.
|
|
412
|
+
* @returns {void}
|
|
413
|
+
*/
|
|
414
|
+
assignClientToWorker(client, initialRequest) {
|
|
415
|
+
if (client.socket.destroyed)
|
|
416
|
+
return;
|
|
417
|
+
try {
|
|
418
|
+
const workerHandler = this.workerHandlerForInitialRequest(initialRequest);
|
|
419
|
+
this.logger.debug(`Gave client ${client.clientCount} to worker ${workerHandler.workerCount}`);
|
|
420
|
+
workerHandler.addSocketConnection(client);
|
|
421
|
+
client.onSocketData(initialRequest);
|
|
422
|
+
}
|
|
423
|
+
catch (error) {
|
|
424
|
+
this.logger.error(`Failed to assign client ${client.clientCount} to a worker`, error);
|
|
425
|
+
client.destroy(error instanceof Error ? error : new Error("Failed to assign HTTP client to worker", { cause: error }));
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Selects the owner of a resumable WebSocket session or the next ordinary worker.
|
|
430
|
+
* @param {Buffer} initialRequest - Initial HTTP request headers.
|
|
431
|
+
* @returns {WorkerHandler | InProcessHandler} - Selected worker.
|
|
432
|
+
*/
|
|
433
|
+
workerHandlerForInitialRequest(initialRequest) {
|
|
434
|
+
const sessionId = this.websocketResumeSessionId(initialRequest);
|
|
435
|
+
if (sessionId) {
|
|
436
|
+
const owner = this.websocketSessionOwners.get(sessionId);
|
|
437
|
+
if (owner && this.workerHandlers.includes(owner))
|
|
438
|
+
return owner;
|
|
439
|
+
if (owner)
|
|
440
|
+
this.websocketSessionOwners.delete(sessionId);
|
|
441
|
+
}
|
|
442
|
+
return this.workerHandlerToUse();
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Reads the resumable WebSocket session routing hint from an upgrade request.
|
|
446
|
+
* @param {Buffer} initialRequest - Initial HTTP request headers.
|
|
447
|
+
* @returns {string | undefined} - Session identity, if present on a WebSocket upgrade.
|
|
448
|
+
*/
|
|
449
|
+
websocketResumeSessionId(initialRequest) {
|
|
450
|
+
const headerEnd = initialRequest.indexOf("\r\n\r\n");
|
|
451
|
+
const fallbackHeaderEnd = headerEnd === -1 ? initialRequest.indexOf("\n\n") : headerEnd;
|
|
452
|
+
if (fallbackHeaderEnd === -1)
|
|
453
|
+
return;
|
|
454
|
+
const lines = initialRequest.subarray(0, fallbackHeaderEnd).toString("latin1").split(/\r?\n/);
|
|
455
|
+
const [method, requestTarget] = lines[0]?.split(" ") || [];
|
|
456
|
+
if (method !== "GET" || !requestTarget)
|
|
457
|
+
return;
|
|
458
|
+
/** @type {Map<string, string>} */
|
|
459
|
+
const headers = new Map();
|
|
460
|
+
for (const line of lines.slice(1)) {
|
|
461
|
+
const separatorIndex = line.indexOf(":");
|
|
462
|
+
if (separatorIndex === -1)
|
|
463
|
+
continue;
|
|
464
|
+
headers.set(line.slice(0, separatorIndex).trim().toLowerCase(), line.slice(separatorIndex + 1).trim().toLowerCase());
|
|
465
|
+
}
|
|
466
|
+
if (headers.get("upgrade") !== "websocket" || !headers.get("connection")?.split(",").map((value) => value.trim()).includes("upgrade"))
|
|
467
|
+
return;
|
|
468
|
+
const sessionId = new URL(requestTarget, "http://velocious.invalid").searchParams.get(WEBSOCKET_SESSION_ROUTING_PARAMETER);
|
|
469
|
+
return sessionId || undefined;
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Records the live worker owner for a resumable session.
|
|
473
|
+
* @param {{sessionId: string, workerHandler: WorkerHandler | InProcessHandler}} args - Ownership claim.
|
|
474
|
+
* @returns {void}
|
|
475
|
+
*/
|
|
476
|
+
claimWebsocketSession({ sessionId, workerHandler }) {
|
|
477
|
+
if (!this.workerHandlers.includes(workerHandler))
|
|
478
|
+
return;
|
|
479
|
+
this.websocketSessionOwners.set(sessionId, workerHandler);
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Releases a session only when the releasing worker still owns it.
|
|
483
|
+
* @param {{sessionId: string, workerHandler: WorkerHandler | InProcessHandler}} args - Ownership release.
|
|
484
|
+
* @returns {void}
|
|
485
|
+
*/
|
|
486
|
+
releaseWebsocketSession({ sessionId, workerHandler }) {
|
|
487
|
+
if (this.websocketSessionOwners.get(sessionId) === workerHandler)
|
|
488
|
+
this.websocketSessionOwners.delete(sessionId);
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Releases every session owned by a worker leaving service.
|
|
492
|
+
* @param {WorkerHandler | InProcessHandler} workerHandler - Worker leaving service.
|
|
493
|
+
* @returns {void}
|
|
494
|
+
*/
|
|
495
|
+
releaseWebsocketSessionsForWorker(workerHandler) {
|
|
496
|
+
for (const [sessionId, owner] of this.websocketSessionOwners) {
|
|
497
|
+
if (owner === workerHandler)
|
|
498
|
+
this.websocketSessionOwners.delete(sessionId);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
347
501
|
/**
|
|
348
502
|
* On client close.
|
|
349
503
|
* @param {ServerClient} client - Client instance.
|
|
@@ -375,7 +529,7 @@ export default class VelociousHttpServer {
|
|
|
375
529
|
* Worker handlers.
|
|
376
530
|
* @type {Array<WorkerHandler | InProcessHandler>} */
|
|
377
531
|
const workerHandlers = [];
|
|
378
|
-
for (let index = 0; index < this.
|
|
532
|
+
for (let index = 0; index < this.effectiveWorkers; index += 1) {
|
|
379
533
|
workerHandlers.push(await this._buildWorkerHandler());
|
|
380
534
|
}
|
|
381
535
|
return workerHandlers;
|
|
@@ -389,9 +543,18 @@ export default class VelociousHttpServer {
|
|
|
389
543
|
this.workerCount++;
|
|
390
544
|
const Handler = this.inProcess ? InProcessHandler : WorkerHandler;
|
|
391
545
|
const workerHandler = this.workerHandlerFactory
|
|
392
|
-
? this.workerHandlerFactory({
|
|
546
|
+
? this.workerHandlerFactory({
|
|
547
|
+
configuration: this.configuration,
|
|
548
|
+
onWebsocketSessionOwned: ({ sessionId, workerHandler }) => this.claimWebsocketSession({ sessionId, workerHandler }),
|
|
549
|
+
onWebsocketSessionReleased: ({ sessionId, workerHandler }) => this.releaseWebsocketSession({ sessionId, workerHandler }),
|
|
550
|
+
onWorkerStopped: ({ workerHandler }) => this.releaseWebsocketSessionsForWorker(workerHandler),
|
|
551
|
+
workerCount
|
|
552
|
+
})
|
|
393
553
|
: new Handler({
|
|
394
554
|
configuration: this.configuration,
|
|
555
|
+
onWebsocketSessionOwned: ({ sessionId, workerHandler }) => this.claimWebsocketSession({ sessionId, workerHandler }),
|
|
556
|
+
onWebsocketSessionReleased: ({ sessionId, workerHandler }) => this.releaseWebsocketSession({ sessionId, workerHandler }),
|
|
557
|
+
onWorkerStopped: ({ workerHandler }) => this.releaseWebsocketSessionsForWorker(workerHandler),
|
|
395
558
|
workerCount
|
|
396
559
|
});
|
|
397
560
|
await workerHandler.start();
|
|
@@ -399,20 +562,9 @@ export default class VelociousHttpServer {
|
|
|
399
562
|
}
|
|
400
563
|
/**
|
|
401
564
|
* Runs worker handler to use.
|
|
402
|
-
* @param {object} [args] - Options object.
|
|
403
|
-
* @param {string} [args.stickyKey] - Stable key that must keep routing to the same worker.
|
|
404
565
|
* @returns {WorkerHandler | InProcessHandler} - The worker handler to use.
|
|
405
566
|
*/
|
|
406
|
-
workerHandlerToUse(
|
|
407
|
-
if (stickyKey) {
|
|
408
|
-
const stickyWorkerHandler = this.stickyWorkerHandlers.get(stickyKey);
|
|
409
|
-
if (stickyWorkerHandler && this.workerHandlers.includes(stickyWorkerHandler)) {
|
|
410
|
-
return stickyWorkerHandler;
|
|
411
|
-
}
|
|
412
|
-
const workerHandler = this._nextRoundRobinWorkerHandler();
|
|
413
|
-
this.stickyWorkerHandlers.set(stickyKey, workerHandler);
|
|
414
|
-
return workerHandler;
|
|
415
|
-
}
|
|
567
|
+
workerHandlerToUse() {
|
|
416
568
|
return this._nextRoundRobinWorkerHandler();
|
|
417
569
|
}
|
|
418
570
|
/**
|
|
@@ -475,7 +627,8 @@ export default class VelociousHttpServer {
|
|
|
475
627
|
const newWorkerHandlers = await this._buildWorkerHandlers();
|
|
476
628
|
this.workerHandlers = newWorkerHandlers;
|
|
477
629
|
this.nextWorkerHandlerIndex = 0;
|
|
478
|
-
|
|
630
|
+
for (const workerHandler of oldWorkerHandlers)
|
|
631
|
+
this.releaseWebsocketSessionsForWorker(workerHandler);
|
|
479
632
|
await Promise.all(oldWorkerHandlers.map((workerHandler) => workerHandler.stop()));
|
|
480
633
|
} while (this._reloadWorkersForDevelopmentQueued && !this._stopping);
|
|
481
634
|
}
|
|
@@ -484,4 +637,4 @@ export default class VelociousHttpServer {
|
|
|
484
637
|
}
|
|
485
638
|
}
|
|
486
639
|
}
|
|
487
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaHR0cC1zZXJ2ZXIvaW5kZXguanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sRUFBQyxJQUFJLEVBQUMsTUFBTSxXQUFXLENBQUE7QUFDOUIsT0FBTyxtQkFBbUIsTUFBTSwyQkFBMkIsQ0FBQTtBQUMzRCxPQUFPLFlBQVksTUFBTSwyQkFBMkIsQ0FBQTtBQUNwRCxPQUFPLGdCQUFnQixNQUFNLGdDQUFnQyxDQUFBO0FBQzdELE9BQU8sTUFBTSxNQUFNLGNBQWMsQ0FBQTtBQUNqQyxPQUFPLEdBQUcsTUFBTSxLQUFLLENBQUE7QUFDckIsT0FBTyxZQUFZLE1BQU0sb0JBQW9CLENBQUE7QUFDN0MsT0FBTyxhQUFhLE1BQU0sMkJBQTJCLENBQUE7QUFFckQ7O2dHQUVnRztBQUNoRzs7K0pBRStKO0FBRS9KOzs7Ozs7R0FNRztBQUNILFNBQVMsb0JBQW9CLENBQUMsRUFBQyxVQUFVLEVBQUUsT0FBTyxFQUFDO0lBQ2pELE1BQU0sV0FBVyxHQUFHLE9BQU8sSUFBSSxVQUFVLElBQUksQ0FBQyxDQUFBO0lBRTlDLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxJQUFJLFdBQVcsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUN0RCxNQUFNLElBQUksS0FBSyxDQUFDLGdEQUFnRCxDQUFDLENBQUE7SUFDbkUsQ0FBQztJQUVELE9BQU8sV0FBVyxDQUFBO0FBQ3BCLENBQUM7QUFFRCxNQUFNLENBQUMsT0FBTyxPQUFPLG1CQUFtQjtJQUN0QyxXQUFXLEdBQUcsQ0FBQyxDQUFBO0lBQ2YsU0FBUyxHQUFHLEtBQUssQ0FBQTtJQUVqQjs7MkVBRXVFO0lBQ3ZFLG1CQUFtQixDQUFBO0lBRW5COztrREFFOEM7SUFDOUMsU0FBUyxDQUFBO0lBRVQ7O2tEQUU4QztJQUM5QyxvQkFBb0IsQ0FBQTtJQUVwQjs7K0NBRTJDO0lBQzNDLE9B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QUFvQixDQUFDLEtBQUssRUFBRSxDQUFBO2dCQUVqQyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFBO1lBQ25GLENBQUMsUUFBUSxJQUFJLENBQUMsa0NBQWtDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFDO1FBQ3RFLENBQUM7Z0JBQVMsQ0FBQztZQUNULElBQUksQ0FBQywrQkFBK0IsR0FBRyxLQUFLLENBQUE7UUFDOUMsQ0FBQztJQUNILENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQge2RpZ2d9IGZyb20gXCJkaWdnZXJpemVcIlxuaW1wb3J0IERldmVsb3BtZW50UmVsb2FkZXIgZnJvbSBcIi4vZGV2ZWxvcG1lbnQtcmVsb2FkZXIuanNcIlxuaW1wb3J0IEV2ZW50RW1pdHRlciBmcm9tIFwiLi4vdXRpbHMvZXZlbnQtZW1pdHRlci5qc1wiXG5pbXBvcnQgSW5Qcm9jZXNzSGFuZGxlciBmcm9tIFwiLi93b3JrZXItaGFuZGxlci9pbi1wcm9jZXNzLmpzXCJcbmltcG9ydCBMb2dnZXIgZnJvbSBcIi4uL2xvZ2dlci5qc1wiXG5pbXBvcnQgTmV0IGZyb20gXCJuZXRcIlxuaW1wb3J0IFNlcnZlckNsaWVudCBmcm9tIFwiLi9zZXJ2ZXItY2xpZW50LmpzXCJcbmltcG9ydCBXb3JrZXJIYW5kbGVyIGZyb20gXCIuL3dvcmtlci1oYW5kbGVyL2luZGV4LmpzXCJcblxuLyoqXG4gKiBEZWZpbmVzIHRoaXMgdHlwZWRlZi5cbiAqIEB0eXBlZGVmIHt7c3RhcnQ6ICgpID0+IFByb21pc2U8dm9pZD4sIHN0b3A6ICgpID0+IFByb21pc2U8dm9pZD59fSBEZXZlbG9wbWVudFJlbG9hZGVyTGlrZSAqL1xuLyoqXG4gKiBEZWZpbmVzIHRoaXMgdHlwZWRlZi5cbiAqIEB0eXBlZGVmIHsoYXJnczoge2NvbmZpZ3VyYXRpb246IGltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24uanNcIikuZGVmYXVsdCwgd29ya2VyQ291bnQ6IG51bWJlcn0pID0+IChXb3JrZXJIYW5kbGVyIHwgSW5Qcm9jZXNzSGFuZGxlcil9IFdvcmtlckhhbmRsZXJGYWN0b3J5ICovXG5cbi8qKlxuICogUnVucyBub3JtYWxpemUgd29ya2VyIGNvdW50LlxuICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zIG9iamVjdC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbYXJncy5tYXhXb3JrZXJzXSAtIEJhY2t3YXJkLWNvbXBhdGlibGUgd29ya2VyIGNvdW50IGFsaWFzLlxuICogQHBhcmFtIHtudW1iZXJ9IFthcmdzLndvcmtlcnNdIC0gQ29uZmlndXJlZCB3b3JrZXIgY291bnQuXG4gKiBAcmV0dXJucyB7bnVtYmVyfSAtIE5vcm1hbGl6ZWQgd29ya2VyIGNvdW50LlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVXb3JrZXJDb3VudCh7bWF4V29ya2Vycywgd29ya2Vyc30pIHtcbiAgY29uc3Qgd29ya2VyQ291bnQgPSB3b3JrZXJzID8/IG1heFdvcmtlcnMgPz8gMVxuXG4gIGlmICghTnVtYmVyLmlzSW50ZWdlcih3b3JrZXJDb3VudCkgfHwgd29ya2VyQ291bnQgPCAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiSFRUUCBzZXJ2ZXIgd29ya2VycyBtdXN0IGJlIGEgcG9zaXRpdmUgaW50ZWdlclwiKVxuICB9XG5cbiAgcmV0dXJuIHdvcmtlckNvdW50XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFZlbG9jaW91c0h0dHBTZXJ2ZXIge1xuICBjbGllbnRDb3VudCA9IDBcbiAgX3N0YXJ0aW5nID0gZmFsc2VcblxuICAvKipcbiAgICogTmFycm93cyB0aGUgcnVudGltZSB2YWx1ZSB0byB0aGUgZG9jdW1lbnRlZCB0eXBlLlxuICAgKiBAdHlwZSB7RGV2ZWxvcG1lbnRSZWxvYWRlciB8IERldmVsb3BtZW50UmVsb2FkZXJMaWtlIHwgdW5kZWZpbmVkfSAqL1xuICBkZXZlbG9wbWVudFJlbG9hZGVyXG5cbiAgLyoqXG4gICAqIE5hcnJvd3MgdGhlIHJ1bnRpbWUgdmFsdWUgdG8gdGhlIGRvY3VtZW50ZWQgdHlwZS5cbiAgICogQHR5cGUge2ltcG9ydChcIm5ldFwiKS5TZXJ2ZXIgfCB1bmRlZmluZWR9ICovXG4gIG5ldFNlcnZlclxuXG4gIC8qKlxuICAgKiBOYXJyb3dzIHRoZSBydW50aW1lIHZhbHVlIHRvIHRoZSBkb2N1bWVudGVkIHR5cGUuXG4gICAqIEB0eXBlIHtXb3JrZXJIYW5kbGVyRmFjdG9yeSB8IHVuZGVmaW5lZH0gKi9cbiAgd29ya2VySGFuZGxlckZhY3RvcnlcblxuICAvKipcbiAgICogQ2xpZW50cy5cbiAgICogQHR5cGUge1JlY29yZDxzdHJpbmcsIFNlcnZlckNsaWVudD59ICAqL1xuICBjbGllbnRzID0ge31cblxuICAvKipcbiAgICogQWN0aXZlIHNvY2tldHMuXG4gICAqIEB0eXBlIHtTZXQ8aW1wb3J0KFwibmV0XCIpLlNvY2tldD59ICovXG4gIF9hY3RpdmVTb2NrZXRzID0gbmV3IFNldCgpXG5cbiAgZXZlbnRzID0gbmV3IEV2ZW50RW1pdHRlcigpXG4gIHdvcmtlckNvdW50ID0gMFxuXG4gIC8qKlxuICAgKiBXb3JrZXIgaGFuZGxlcnMuXG4gICAqIEB0eXBlIHtBcnJheTxXb3JrZXJIYW5kbGVyIHwgSW5Qcm9jZXNzSGFuZGxlcj59ICovXG4gIHdvcmtlckhhbmRsZXJzID0gW11cbiAgbmV4dFdvcmtlckhhbmRsZXJJbmRleCA9IDBcbiAgLyoqXG4gICAqIFN0aWNreSB3b3JrZXIgaGFuZGxlcnMuXG4gICAqIEB0eXBlIHtNYXA8c3RyaW5nLCBXb3JrZXJIYW5kbGVyIHwgSW5Qcm9jZXNzSGFuZGxlcj59ICovXG4gIHN0aWNreVdvcmtlckhhbmRsZXJzID0gbmV3IE1hcCgpXG5cbiAgLyoqXG4gICAqIFJ1bnMgY29uc3RydWN0b3IuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucyBvYmplY3QuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0fSBhcmdzLmNvbmZpZ3VyYXRpb24gLSBDb25maWd1cmF0aW9uIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2FyZ3MuaG9zdF0gLSBIb3N0LlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFthcmdzLmluUHJvY2Vzc10gLSBSdW4gSFRUUCBoYW5kbGVycyBpbiB0aGUgbWFpbiB0aHJlYWQgaW5zdGVhZCBvZiB3b3JrZXIgdGhyZWFkcy5cbiAgICogQHBhcmFtIHtudW1iZXJ9IFthcmdzLnBvcnRdIC0gUG9ydC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IFthcmdzLm1heFdvcmtlcnNdIC0gTWF4IHdvcmtlcnMuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJncy53b3JrZXJzXSAtIFdvcmtlciBoYW5kbGVycyB0byBzdGFydC5cbiAgICogQHBhcmFtIHsoYXJnczoge2NvbmZpZ3VyYXRpb246IGltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24uanNcIikuZGVmYXVsdCwgb25SZWxvYWQ6IChhcmdzOiB7Y2hhbmdlZFBhdGg6IHN0cmluZ30pID0+IFByb21pc2U8dm9pZD59KSA9PiB7c3RhcnQ6ICgpID0+IFByb21pc2U8dm9pZD4sIHN0b3A6ICgpID0+IFByb21pc2U8dm9pZD59fSBbYXJncy5kZXZlbG9wbWVudFJlbG9hZGVyRmFjdG9yeV0gLSBEZXZlbG9wbWVudCByZWxvYWRlciBmYWN0b3J5LlxuICAgKiBAcGFyYW0ge1dvcmtlckhhbmRsZXJGYWN0b3J5fSBbYXJncy53b3JrZXJIYW5kbGVyRmFjdG9yeV0gLSBXb3JrZXIgaGFuZGxlciBmYWN0b3J5LlxuICAgKi9cbiAgY29uc3RydWN0b3Ioe2NvbmZpZ3VyYXRpb24sIGRldmVsb3BtZW50UmVsb2FkZXJGYWN0b3J5LCBob3N0LCBpblByb2Nlc3MsIG1heFdvcmtlcnMsIHBvcnQsIHdvcmtlckhhbmRsZXJGYWN0b3J5LCB3b3JrZXJzfSkge1xuICAgIHRoaXMuY29uZmlndXJhdGlvbiA9IGNvbmZpZ3VyYXRpb25cbiAgICB0aGlzLmRldmVsb3BtZW50UmVsb2FkZXJGYWN0b3J5ID0gZGV2ZWxvcG1lbnRSZWxvYWRlckZhY3RvcnlcbiAgICB0aGlzLndvcmtlckhhbmRsZXJGYWN0b3J5ID0gd29ya2VySGFuZGxlckZhY3RvcnlcbiAgICB0aGlzLmluUHJvY2VzcyA9IGluUHJvY2VzcyB8fCBmYWxzZVxuICAgIHRoaXMubG9nZ2VyID0gbmV3IExvZ2dlcih0aGlzKVxuICAgIHRoaXMuaG9zdCA9IGhvc3QgPz8gXCIwLjAuMC4wXCJcbiAgICB0aGlzLnBvcnQgPSBwb3J0ID8/IDMwMDZcbiAgICB0aGlzLndvcmtlcnMgPSBub3JtYWxpemVXb3JrZXJDb3VudCh7bWF4V29ya2Vycywgd29ya2Vyc30pXG4gIH1cblxuICAvKipcbiAgICogUnVucyBzdGFydC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjb21wbGV0ZS5cbiAgICovXG4gIGFzeW5jIHN0YXJ0KCkge1xuICAgIGlmICh0aGlzLl9zdGFydGluZykgdGhyb3cgbmV3IEVycm9yKFwiVmVsb2Npb3VzIEhUVFAgc2VydmVyIGlzIGFscmVhZHkgc3RhcnRpbmdcIilcbiAgICBpZiAodGhpcy5pc0FjdGl2ZSgpKSB0aHJvdyBuZXcgRXJyb3IoXCJWZWxvY2lvdXMgSFRUUCBzZXJ2ZXIgaXMgYWxyZWFkeSBydW5uaW5nXCIpXG5cbiAgICB0aGlzLl9zdGFydGluZyA9IHRydWVcbiAgICBjb25zdCBzdGFydHVwU3RhdGUgPSB0aGlzLl9jYXB0dXJlU3RhcnR1cFN0YXRlKClcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLl9lbnN1cmVXb3JrZXJzKClcbiAgICAgIGF3YWl0IHRoaXMuX3N0YXJ0RGV2ZWxvcG1lbnRSZWxvYWRlcigpXG4gICAgICAvKipcbiAgICAgICAqIE5ldCBzZXJ2ZXIuXG4gICAgICAgKiBAdHlwZSB7aW1wb3J0KFwibmV0XCIpLlNlcnZlcn0gKi9cbiAgICAgIGNvbnN0IG5ldFNlcnZlciA9IG5ldyBOZXQuU2VydmVyKClcbiAgICAgIHRoaXMubmV0U2VydmVyID0gbmV0U2VydmVyXG4gICAgICBuZXRTZXJ2ZXIub24oXCJjbG9zZVwiLCB0aGlzLm9uQ2xvc2UpXG4gICAgICBuZXRTZXJ2ZXIub24oXCJjb25uZWN0aW9uXCIsIHRoaXMub25Db25uZWN0aW9uKVxuICAgICAgbmV0U2VydmVyLm9uKFwiZXJyb3JcIiwgdGhpcy5vblNlcnZlckVycm9yKVxuICAgICAgYXdhaXQgdGhpcy5fbmV0U2VydmVyTGlzdGVuKClcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgYXdhaXQgdGhpcy5fc3RvcFN0YXJ0dXBSZXNvdXJjZXMoc3RhcnR1cFN0YXRlKVxuICAgICAgdGhyb3cgZXJyb3JcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5fc3RhcnRpbmcgPSBmYWxzZVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGNhcHR1cmUgc3RhcnR1cCBzdGF0ZS5cbiAgICogQHJldHVybnMge3tkZXZlbG9wbWVudFJlbG9hZGVyOiBEZXZlbG9wbWVudFJlbG9hZGVyIHwgRGV2ZWxvcG1lbnRSZWxvYWRlckxpa2UgfCB1bmRlZmluZWQsIG5ldFNlcnZlcjogaW1wb3J0KFwibmV0XCIpLlNlcnZlciB8IHVuZGVmaW5lZCwgd29ya2VySGFuZGxlcnM6IEFycmF5PFdvcmtlckhhbmRsZXIgfCBJblByb2Nlc3NIYW5kbGVyPn19IC0gU3RhcnR1cCBzdGF0ZS5cbiAgICovXG4gIF9jYXB0dXJlU3RhcnR1cFN0YXRlKCkge1xuICAgIHJldHVybiB7XG4gICAgICBkZXZlbG9wbWVudFJlbG9hZGVyOiB0aGlzLmRldmVsb3BtZW50UmVsb2FkZXIsXG4gICAgICBuZXRTZXJ2ZXI6IHRoaXMubmV0U2VydmVyLFxuICAgICAgd29ya2VySGFuZGxlcnM6IFsuLi50aGlzLndvcmtlckhhbmRsZXJzXVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHN0b3Agc3RhcnR1cCByZXNvdXJjZXMuXG4gICAqIEBwYXJhbSB7UmV0dXJuVHlwZTxWZWxvY2lvdXNIdHRwU2VydmVyW1wiX2NhcHR1cmVTdGFydHVwU3RhdGVcIl0+fSBzdGFydHVwU3RhdGUgLSBTdGF0ZSBjYXB0dXJlZCBiZWZvcmUgc3RhcnR1cC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjbGVhbnVwIGlzIGNvbXBsZXRlLlxuICAgKi9cbiAgYXN5bmMgX3N0b3BTdGFydHVwUmVzb3VyY2VzKHN0YXJ0dXBTdGF0ZSkge1xuICAgIC8qKlxuICAgICAqIFN0YXJ0dXAgbmV0IHNlcnZlci5cbiAgICAgKiBAdHlwZSB7aW1wb3J0KFwibmV0XCIpLlNlcnZlciB8IHVuZGVmaW5lZH0gKi9cbiAgICBjb25zdCBzdGFydHVwTmV0U2VydmVyID0gdGhpcy5uZXRTZXJ2ZXJcblxuICAgIGlmICh0aGlzLmRldmVsb3BtZW50UmVsb2FkZXIgJiYgdGhpcy5kZXZlbG9wbWVudFJlbG9hZGVyICE9PSBzdGFydHVwU3RhdGUuZGV2ZWxvcG1lbnRSZWxvYWRlcikge1xuICAgICAgYXdhaXQgdGhpcy5kZXZlbG9wbWVudFJlbG9hZGVyLnN0b3AoKVxuICAgIH1cblxuICAgIGlmIChzdGFydHVwTmV0U2VydmVyICYmIHN0YXJ0dXBOZXRTZXJ2ZXIgIT09IHN0YXJ0dXBTdGF0ZS5uZXRTZXJ2ZXIpIHtcbiAgICAgIGF3YWl0IHRoaXMuc3RvcFNlcnZlcihzdGFydHVwTmV0U2VydmVyKVxuICAgIH1cblxuICAgIGNvbnN0IHN0YXJ0dXBXb3JrZXJIYW5kbGVycyA9IHRoaXMud29ya2VySGFuZGxlcnMuZmlsdGVyKCh3b3JrZXJIYW5kbGVyKSA9PiAhc3RhcnR1cFN0YXRlLndvcmtlckhhbmRsZXJzLmluY2x1ZGVzKHdvcmtlckhhbmRsZXIpKVxuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoc3RhcnR1cFdvcmtlckhhbmRsZXJzLm1hcCgoaGFuZGxlcikgPT4gaGFuZGxlci5zdG9wKCkpKVxuXG4gICAgdGhpcy5kZXZlbG9wbWVudFJlbG9hZGVyID0gc3RhcnR1cFN0YXRlLmRldmVsb3BtZW50UmVsb2FkZXJcbiAgICB0aGlzLm5ldFNlcnZlciA9IHN0YXJ0dXBTdGF0ZS5uZXRTZXJ2ZXJcbiAgICB0aGlzLndvcmtlckhhbmRsZXJzID0gc3RhcnR1cFN0YXRlLndvcmtlckhhbmRsZXJzXG4gICAgdGhpcy5zdGlja3lXb3JrZXJIYW5kbGVycy5jbGVhcigpXG4gIH1cblxuICAvKipcbiAgICogUnVucyBuZXQgc2VydmVyIGxpc3Rlbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjb21wbGV0ZS5cbiAgICovXG4gIF9uZXRTZXJ2ZXJMaXN0ZW4oKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGlmICghdGhpcy5uZXRTZXJ2ZXIpIHRocm93IG5ldyBFcnJvcihcIk5vIG5ldFNlcnZlclwiKVxuXG4gICAgICAvKipcbiAgICAgICAqIE9uIGxpc3RlbiBlcnJvci5cbiAgICAgICAqIEBwYXJhbSB7RXJyb3J9IGVycm9yIC0gTGlzdGVuIGVycm9yLlxuICAgICAgICovXG4gICAgICBjb25zdCBvbkxpc3RlbkVycm9yID0gKGVycm9yKSA9PiB7XG4gICAgICAgIHRoaXMubmV0U2VydmVyPy5vZmYoXCJlcnJvclwiLCBvbkxpc3RlbkVycm9yKVxuICAgICAgICByZWplY3QoZXJyb3IpXG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXMubmV0U2VydmVyLm9uY2UoXCJlcnJvclwiLCBvbkxpc3RlbkVycm9yKVxuICAgICAgICB0aGlzLm5ldFNlcnZlci5saXN0ZW4odGhpcy5wb3J0LCB0aGlzLmhvc3QsICgpID0+IHtcbiAgICAgICAgICB0aGlzLm5ldFNlcnZlcj8ub2ZmKFwiZXJyb3JcIiwgb25MaXN0ZW5FcnJvcilcbiAgICAgICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhgVmVsb2Npb3VzIGxpc3RlbmluZyBvbiAke3RoaXMuaG9zdH06JHt0aGlzLnBvcnR9YClcbiAgICAgICAgICByZXNvbHZlKHVuZGVmaW5lZClcbiAgICAgICAgfSlcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHJlamVjdChlcnJvcilcbiAgICAgIH1cbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgZW5zdXJlIHdvcmtlcnMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY29tcGxldGUuXG4gICAqL1xuICBhc3luYyBfZW5zdXJlV29ya2VycygpIHtcbiAgICB3aGlsZSAodGhpcy53b3JrZXJIYW5kbGVycy5sZW5ndGggPCB0aGlzLndvcmtlcnMpIHtcbiAgICAgIGF3YWl0IHRoaXMuc3Bhd25Xb3JrZXIoKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGlzIGFjdGl2ZS5cbiAgICogQHJldHVybnMge2Jvb2xlYW59IC0gV2hldGhlciBhY3RpdmUuXG4gICAqL1xuICBpc0FjdGl2ZSgpIHtcbiAgICBpZiAodGhpcy5uZXRTZXJ2ZXIpIHtcbiAgICAgIHJldHVybiB0aGlzLm5ldFNlcnZlci5saXN0ZW5pbmdcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2VcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGdldCBkZWJ1ZyBzbmFwc2hvdC5cbiAgICogQHJldHVybnMge1Byb21pc2U8UmVjb3JkPHN0cmluZywgUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4+Pn0gLSBIVFRQIHNlcnZlciB3b3JrZXIgZGlhZ25vc3RpY3MuXG4gICAqL1xuICBhc3luYyBnZXREZWJ1Z1NuYXBzaG90KCkge1xuICAgIHJldHVybiB7XG4gICAgICBhY3RpdmU6IHRoaXMuaXNBY3RpdmUoKSxcbiAgICAgIGFjdGl2ZVNvY2tldENvdW50OiB0aGlzLl9hY3RpdmVTb2NrZXRzLnNpemUsXG4gICAgICBjbGllbnRDb3VudDogT2JqZWN0LmtleXModGhpcy5jbGllbnRzKS5sZW5ndGgsXG4gICAgICBjb25maWd1cmVkV29ya2VyQ291bnQ6IHRoaXMud29ya2VycyxcbiAgICAgIGluUHJvY2VzczogdGhpcy5pblByb2Nlc3MsXG4gICAgICB3b3JrZXJDb3VudDogdGhpcy53b3JrZXJIYW5kbGVycy5sZW5ndGgsXG4gICAgICB3b3JrZXJzOiBhd2FpdCBQcm9taXNlLmFsbCh0aGlzLndvcmtlckhhbmRsZXJzLm1hcCgoaGFuZGxlcikgPT4gdGhpcy53b3JrZXJEZWJ1Z1NuYXBzaG90KGhhbmRsZXIpKSlcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyB3b3JrZXIgZGVidWcgc25hcHNob3QuXG4gICAqIEBwYXJhbSB7V29ya2VySGFuZGxlciB8IEluUHJvY2Vzc0hhbmRsZXJ9IHdvcmtlckhhbmRsZXIgLSBXb3JrZXIgaGFuZGxlciB0byBpbnNwZWN0LlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj4+fSBXb3JrZXIgZGVidWcgc25hcHNob3QuXG4gICAqL1xuICBhc3luYyB3b3JrZXJEZWJ1Z1NuYXBzaG90KHdvcmtlckhhbmRsZXIpIHtcbiAgICBpZiAod29ya2VySGFuZGxlciBpbnN0YW5jZW9mIFdvcmtlckhhbmRsZXIpIHJldHVybiBhd2FpdCB3b3JrZXJIYW5kbGVyLmdldERlYnVnU25hcHNob3QoKVxuICAgIGlmICh3b3JrZXJIYW5kbGVyIGluc3RhbmNlb2YgSW5Qcm9jZXNzSGFuZGxlcikgcmV0dXJuIHRoaXMuaW5Qcm9jZXNzV29ya2VyRGVidWdTbmFwc2hvdCh3b3JrZXJIYW5kbGVyKVxuXG4gICAgcmV0dXJuIHthY3RpdmU6IGZhbHNlLCBlcnJvcjogXCJVbmtub3duIHdvcmtlciBoYW5kbGVyIHR5cGVcIn1cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGluIHByb2Nlc3Mgd29ya2VyIGRlYnVnIHNuYXBzaG90LlxuICAgKiBAcGFyYW0ge0luUHJvY2Vzc0hhbmRsZXJ9IHdvcmtlckhhbmRsZXIgLSBJbi1wcm9jZXNzIHdvcmtlciBoYW5kbGVyIHRvIGluc3BlY3QuXG4gICAqIEByZXR1cm5zIHtSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPj59IFdvcmtlciBkZWJ1ZyBzbmFwc2hvdC5cbiAgICovXG4gIGluUHJvY2Vzc1dvcmtlckRlYnVnU25hcHNob3Qod29ya2VySGFuZGxlcikge1xuICAgIHJldHVybiB7XG4gICAgICBhY3RpdmU6IHRydWUsXG4gICAgICBjbGllbnRDb3VudDogT2JqZWN0LmtleXMod29ya2VySGFuZGxlci5jbGllbnRzKS5sZW5ndGgsXG4gICAgICBzbmFwc2hvdDogd29ya2VySGFuZGxlci5jb25maWd1cmF0aW9uLmdldExvY2FsRGVidWdTbmFwc2hvdCgpLFxuICAgICAgd29ya2VyQ291bnQ6IHdvcmtlckhhbmRsZXIud29ya2VyQ291bnRcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyBzdG9wIGNsaWVudHMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY29tcGxldGUuXG4gICAqL1xuICBhc3luYyBzdG9wQ2xpZW50cygpIHtcbiAgICBjb25zdCBwcm9taXNlcyA9IFtdXG5cbiAgICBmb3IgKGNvbnN0IGNsaWVudENvdW50IGluIHRoaXMuY2xpZW50cykge1xuICAgICAgY29uc3QgY2xpZW50ID0gdGhpcy5jbGllbnRzW2NsaWVudENvdW50XVxuXG4gICAgICBwcm9taXNlcy5wdXNoKGNsaWVudC5lbmQoKSlcbiAgICB9XG5cbiAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcylcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHN0b3Agc2VydmVyLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIm5ldFwiKS5TZXJ2ZXIgfCB1bmRlZmluZWR9IFtuZXRTZXJ2ZXJdIC0gU2VydmVyIHRvIHN0b3AuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY29tcGxldGUuXG4gICAqL1xuICBzdG9wU2VydmVyKG5ldFNlcnZlciA9IHRoaXMubmV0U2VydmVyKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGlmICghbmV0U2VydmVyIHx8ICFuZXRTZXJ2ZXIubGlzdGVuaW5nKSB7XG4gICAgICAgIHJlc29sdmUodW5kZWZpbmVkKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgaWYgKG5ldFNlcnZlciA9PT0gdGhpcy5uZXRTZXJ2ZXIpIHtcbiAgICAgICAgLy8gRm9yY2UtY2xvc2UgbGluZ2VyaW5nIHNvY2tldHMgKGUuZy4gV2ViU29ja2V0IHVwZ3JhZGVcbiAgICAgICAgLy8gY29ubmVjdGlvbnMgbWlkLWNsb3NlLWhhbmRzaGFrZSkgc28gdGhlIHBvcnQgaXMgcmVsZWFzZWRcbiAgICAgICAgLy8gaW1tZWRpYXRlbHkgaW5zdGVhZCBvZiB3YWl0aW5nIGZvciBncmFjZWZ1bCBkcmFpbi5cbiAgICAgICAgZm9yIChjb25zdCBzb2NrZXQgb2YgdGhpcy5fYWN0aXZlU29ja2V0cykge1xuICAgICAgICAgIHNvY2tldC5kZXN0cm95KClcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2FjdGl2ZVNvY2tldHMuY2xlYXIoKVxuICAgICAgfVxuXG4gICAgICBuZXRTZXJ2ZXIuY2xvc2UoKGVycm9yKSA9PiB7XG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgIHJlamVjdChlcnJvcilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXNvbHZlKHVuZGVmaW5lZClcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgc3RvcC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjb21wbGV0ZS5cbiAgICovXG4gIGFzeW5jIHN0b3AoKSB7XG4gICAgdGhpcy5fc3RvcHBpbmcgPSB0cnVlXG4gICAgYXdhaXQgdGhpcy5kZXZlbG9wbWVudFJlbG9hZGVyPy5zdG9wKClcbiAgICB0aGlzLmRldmVsb3BtZW50UmVsb2FkZXIgPSB1bmRlZmluZWRcbiAgICBhd2FpdCB0aGlzLnN0b3BDbGllbnRzKClcbiAgICBhd2FpdCB0aGlzLnN0b3BTZXJ2ZXIoKVxuXG4gICAgY29uc3Qgc3RvcFRhc2tzID0gdGhpcy53b3JrZXJIYW5kbGVycy5tYXAoKGhhbmRsZXIpID0+IGhhbmRsZXIuc3RvcCgpKVxuICAgIGF3YWl0IFByb21pc2UuYWxsKHN0b3BUYXNrcylcbiAgICB0aGlzLndvcmtlckhhbmRsZXJzID0gW11cbiAgICB0aGlzLnN0aWNreVdvcmtlckhhbmRsZXJzLmNsZWFyKClcbiAgfVxuXG4gIC8qKlxuICAgKiBPbiBjbG9zZS5cbiAgICogQHJldHVybnMge3ZvaWR9IC0gTm8gcmV0dXJuIHZhbHVlLlxuICAgKi9cbiAgb25DbG9zZSA9ICgpID0+IHtcbiAgICB0aGlzLmV2ZW50cy5lbWl0KFwiY2xvc2VcIilcbiAgfVxuXG4gIC8qKlxuICAgKiBPbiBzZXJ2ZXIgZXJyb3IuXG4gICAqIEBwYXJhbSB7RXJyb3J9IGVycm9yIC0gU2VydmVyIHNvY2tldCBlcnJvci5cbiAgICogQHJldHVybnMge3ZvaWR9IC0gTm8gcmV0dXJuIHZhbHVlLlxuICAgKi9cbiAgb25TZXJ2ZXJFcnJvciA9IChlcnJvcikgPT4ge1xuICAgIHRoaXMubG9nZ2VyLmVycm9yKGBWZWxvY2lvdXMgSFRUUCBzZXJ2ZXIgc29ja2V0IGVycm9yIG9uICR7dGhpcy5ob3N0fToke3RoaXMucG9ydH1gLCBlcnJvcilcbiAgfVxuXG4gIC8qKlxuICAgKiBPbiBjb25uZWN0aW9uLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIm5ldFwiKS5Tb2NrZXR9IHNvY2tldCAtIFNvY2tldCBpbnN0YW5jZS5cbiAgICogQHJldHVybnMge3ZvaWR9IC0gTm8gcmV0dXJuIHZhbHVlLlxuICAgKi9cbiAgb25Db25uZWN0aW9uID0gKHNvY2tldCkgPT4ge1xuICAgIGNvbnN0IGNsaWVudENvdW50ID0gdGhpcy5jbGllbnRDb3VudFxuXG4gICAgdGhpcy5fYWN0aXZlU29ja2V0cy5hZGQoc29ja2V0KVxuICAgIHNvY2tldC5vbmNlKFwiY2xvc2VcIiwgKCkgPT4gdGhpcy5fYWN0aXZlU29ja2V0cy5kZWxldGUoc29ja2V0KSlcblxuICAgIHRoaXMubG9nZ2VyLmRlYnVnKCgpID0+IFtcIk5ldyBjbGllbnRcIiwge1xuICAgICAgY2xpZW50Q291bnQsXG4gICAgICByZW1vdGVBZGRyZXNzOiBzb2NrZXQucmVtb3RlQWRkcmVzcyxcbiAgICAgIHJlbW90ZUZhbWlseTogc29ja2V0LnJlbW90ZUZhbWlseSxcbiAgICAgIHJlbW90ZVBvcnQ6IHNvY2tldC5yZW1vdGVQb3J0XG4gICAgfV0pXG4gICAgdGhpcy5jbGllbnRDb3VudCsrXG5cbiAgICB0cnkge1xuICAgICAgLy8gUGF1c2VkIFdlYlNvY2tldCBzZXNzaW9ucyBhcmUgd29ya2VyLWxvY2FsLCBzbyByZWNvbm5lY3RzIGZyb21cbiAgICAgIC8vIHRoZSBzYW1lIGNsaWVudCBhZGRyZXNzIG11c3QgcmV0dXJuIHRvIHRoZSBzYW1lIHdvcmtlci5cbiAgICAgIGNvbnN0IHdvcmtlckhhbmRsZXIgPSB0aGlzLndvcmtlckhhbmRsZXJUb1VzZSh7c3RpY2t5S2V5OiBzb2NrZXQucmVtb3RlQWRkcmVzc30pXG4gICAgICBjb25zdCBjbGllbnQgPSBuZXcgU2VydmVyQ2xpZW50KHtcbiAgICAgICAgY2xpZW50Q291bnQsXG4gICAgICAgIGNvbmZpZ3VyYXRpb246IHRoaXMuY29uZmlndXJhdGlvbixcbiAgICAgICAgc29ja2V0XG4gICAgICB9KVxuXG4gICAgICBjbGllbnQuZXZlbnRzLm9uKFwiY2xvc2VcIiwgdGhpcy5vbkNsaWVudENsb3NlKVxuXG4gICAgICB0aGlzLmxvZ2dlci5kZWJ1ZyhgR2F2ZSBjbGllbnQgJHtjbGllbnRDb3VudH0gdG8gd29ya2VyICR7d29ya2VySGFuZGxlci53b3JrZXJDb3VudH1gKVxuICAgICAgd29ya2VySGFuZGxlci5hZGRTb2NrZXRDb25uZWN0aW9uKGNsaWVudClcbiAgICAgIHRoaXMuY2xpZW50c1tjbGllbnRDb3VudF0gPSBjbGllbnRcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoYEZhaWxlZCB0byBpbml0aWFsaXplIGNsaWVudCAke2NsaWVudENvdW50fSBvbiBuZXcgY29ubmVjdGlvbmAsIGVycm9yKVxuICAgICAgc29ja2V0LmRlc3Ryb3koKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBPbiBjbGllbnQgY2xvc2UuXG4gICAqIEBwYXJhbSB7U2VydmVyQ2xpZW50fSBjbGllbnQgLSBDbGllbnQgaW5zdGFuY2UuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIG9uQ2xpZW50Q2xvc2UgPSAoY2xpZW50KSA9PiB7XG4gICAgY29uc3QgY2xpZW50Q291bnQgPSBkaWdnKGNsaWVudCwgXCJjbGllbnRDb3VudFwiKVxuICAgIGNvbnN0IG9sZENsaWVudHNMZW5ndGggPSBPYmplY3Qua2V5cyh0aGlzLmNsaWVudHMpLmxlbmd0aFxuXG4gICAgZGVsZXRlIHRoaXMuY2xpZW50c1tjbGllbnRDb3VudF1cblxuICAgIGNvbnN0IG5ld0NsaWVudHNMZW5ndGggPSBPYmplY3Qua2V5cyh0aGlzLmNsaWVudHMpLmxlbmd0aFxuXG4gICAgaWYgKG5ld0NsaWVudHNMZW5ndGggIT0gKG9sZENsaWVudHNMZW5ndGggLSAxKSkge1xuICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoYEV4cGVjdGVkIGNsaWVudCB0byBoYXZlIGJlZW4gcmVtb3ZlZCBidXQgbGVuZ3RoIGRpZG4ndCBjaGFuZ2UgZnJvbSAke29sZENsaWVudHNMZW5ndGh9IHRvICR7b2xkQ2xpZW50c0xlbmd0aCAtIDF9YClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyBzcGF3biB3b3JrZXIuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY29tcGxldGUuXG4gICAqL1xuICBhc3luYyBzcGF3bldvcmtlcigpIHtcbiAgICBjb25zdCB3b3JrZXJIYW5kbGVyID0gYXdhaXQgdGhpcy5fYnVpbGRXb3JrZXJIYW5kbGVyKClcblxuICAgIHRoaXMud29ya2VySGFuZGxlcnMucHVzaCh3b3JrZXJIYW5kbGVyKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgYnVpbGQgd29ya2VyIGhhbmRsZXJzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxBcnJheTxXb3JrZXJIYW5kbGVyIHwgSW5Qcm9jZXNzSGFuZGxlcj4+fSAtIFN0YXJ0ZWQgd29ya2VyIGhhbmRsZXJzLlxuICAgKi9cbiAgYXN5bmMgX2J1aWxkV29ya2VySGFuZGxlcnMoKSB7XG4gICAgLyoqXG4gICAgICogV29ya2VyIGhhbmRsZXJzLlxuICAgICAqIEB0eXBlIHtBcnJheTxXb3JrZXJIYW5kbGVyIHwgSW5Qcm9jZXNzSGFuZGxlcj59ICovXG4gICAgY29uc3Qgd29ya2VySGFuZGxlcnMgPSBbXVxuXG4gICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHRoaXMud29ya2VyczsgaW5kZXggKz0gMSkge1xuICAgICAgd29ya2VySGFuZGxlcnMucHVzaChhd2FpdCB0aGlzLl9idWlsZFdvcmtlckhhbmRsZXIoKSlcbiAgICB9XG5cbiAgICByZXR1cm4gd29ya2VySGFuZGxlcnNcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGJ1aWxkIHdvcmtlciBoYW5kbGVyLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxXb3JrZXJIYW5kbGVyIHwgSW5Qcm9jZXNzSGFuZGxlcj59IC0gU3RhcnRlZCB3b3JrZXIgaGFuZGxlci5cbiAgICovXG4gIGFzeW5jIF9idWlsZFdvcmtlckhhbmRsZXIoKSB7XG4gICAgY29uc3Qgd29ya2VyQ291bnQgPSB0aGlzLndvcmtlckNvdW50XG5cbiAgICB0aGlzLndvcmtlckNvdW50KytcblxuICAgIGNvbnN0IEhhbmRsZXIgPSB0aGlzLmluUHJvY2VzcyA/IEluUHJvY2Vzc0hhbmRsZXIgOiBXb3JrZXJIYW5kbGVyXG4gICAgY29uc3Qgd29ya2VySGFuZGxlciA9IHRoaXMud29ya2VySGFuZGxlckZhY3RvcnlcbiAgICAgID8gdGhpcy53b3JrZXJIYW5kbGVyRmFjdG9yeSh7Y29uZmlndXJhdGlvbjogdGhpcy5jb25maWd1cmF0aW9uLCB3b3JrZXJDb3VudH0pXG4gICAgICA6IG5ldyBIYW5kbGVyKHtcbiAgICAgICAgY29uZmlndXJhdGlvbjogdGhpcy5jb25maWd1cmF0aW9uLFxuICAgICAgICB3b3JrZXJDb3VudFxuICAgICAgfSlcblxuICAgIGF3YWl0IHdvcmtlckhhbmRsZXIuc3RhcnQoKVxuXG4gICAgcmV0dXJuIHdvcmtlckhhbmRsZXJcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHdvcmtlciBoYW5kbGVyIHRvIHVzZS5cbiAgICogQHBhcmFtIHtvYmplY3R9IFthcmdzXSAtIE9wdGlvbnMgb2JqZWN0LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2FyZ3Muc3RpY2t5S2V5XSAtIFN0YWJsZSBrZXkgdGhhdCBtdXN0IGtlZXAgcm91dGluZyB0byB0aGUgc2FtZSB3b3JrZXIuXG4gICAqIEByZXR1cm5zIHtXb3JrZXJIYW5kbGVyIHwgSW5Qcm9jZXNzSGFuZGxlcn0gLSBUaGUgd29ya2VyIGhhbmRsZXIgdG8gdXNlLlxuICAgKi9cbiAgd29ya2VySGFuZGxlclRvVXNlKHtzdGlja3lLZXl9ID0ge30pIHtcbiAgICBpZiAoc3RpY2t5S2V5KSB7XG4gICAgICBjb25zdCBzdGlja3lXb3JrZXJIYW5kbGVyID0gdGhpcy5zdGlja3lXb3JrZXJIYW5kbGVycy5nZXQoc3RpY2t5S2V5KVxuXG4gICAgICBpZiAoc3RpY2t5V29ya2VySGFuZGxlciAmJiB0aGlzLndvcmtlckhhbmRsZXJzLmluY2x1ZGVzKHN0aWNreVdvcmtlckhhbmRsZXIpKSB7XG4gICAgICAgIHJldHVybiBzdGlja3lXb3JrZXJIYW5kbGVyXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHdvcmtlckhhbmRsZXIgPSB0aGlzLl9uZXh0Um91bmRSb2JpbldvcmtlckhhbmRsZXIoKVxuXG4gICAgICB0aGlzLnN0aWNreVdvcmtlckhhbmRsZXJzLnNldChzdGlja3lLZXksIHdvcmtlckhhbmRsZXIpXG5cbiAgICAgIHJldHVybiB3b3JrZXJIYW5kbGVyXG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX25leHRSb3VuZFJvYmluV29ya2VySGFuZGxlcigpXG4gIH1cblxuICAvKipcbiAgICogUnVucyBuZXh0IHJvdW5kIHJvYmluIHdvcmtlciBoYW5kbGVyLlxuICAgKiBAcmV0dXJucyB7V29ya2VySGFuZGxlciB8IEluUHJvY2Vzc0hhbmRsZXJ9IC0gVGhlIG5leHQgcm91bmQtcm9iaW4gd29ya2VyIGhhbmRsZXIuXG4gICAqL1xuICBfbmV4dFJvdW5kUm9iaW5Xb3JrZXJIYW5kbGVyKCkge1xuICAgIHRoaXMubG9nZ2VyLmRlYnVnKGBXb3JrZXIgaGFuZGxlcnMgbGVuZ3RoOiAke3RoaXMud29ya2VySGFuZGxlcnMubGVuZ3RofWApXG5cbiAgICBjb25zdCB3b3JrZXJIYW5kbGVySW5kZXggPSB0aGlzLm5leHRXb3JrZXJIYW5kbGVySW5kZXggJSB0aGlzLndvcmtlckhhbmRsZXJzLmxlbmd0aFxuICAgIGNvbnN0IHdvcmtlckhhbmRsZXIgPSB0aGlzLndvcmtlckhhbmRsZXJzW3dvcmtlckhhbmRsZXJJbmRleF1cblxuICAgIGlmICghd29ya2VySGFuZGxlcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyB3b3JrZXJIYW5kbGVyIGJ5IHRoYXQgbnVtYmVyOiAke3dvcmtlckhhbmRsZXJJbmRleH1gKVxuICAgIH1cblxuICAgIHRoaXMubmV4dFdvcmtlckhhbmRsZXJJbmRleCArPSAxXG5cbiAgICByZXR1cm4gd29ya2VySGFuZGxlclxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgc2hvdWxkIHVzZSBkZXZlbG9wbWVudCBob3QgcmVsb2FkLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBXaGV0aGVyIGRldmVsb3BtZW50IHdvcmtlciBob3QgcmVsb2FkIHNob3VsZCBydW4uXG4gICAqL1xuICBzaG91bGRVc2VEZXZlbG9wbWVudEhvdFJlbG9hZCgpIHtcbiAgICByZXR1cm4gIXRoaXMuaW5Qcm9jZXNzICYmIHRoaXMuY29uZmlndXJhdGlvbi5nZXRFbnZpcm9ubWVudCgpID09PSBcImRldmVsb3BtZW50XCJcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHN0YXJ0IGRldmVsb3BtZW50IHJlbG9hZGVyLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIHdhdGNoZXIgc2V0dXAgZmluaXNoZXMuXG4gICAqL1xuICBhc3luYyBfc3RhcnREZXZlbG9wbWVudFJlbG9hZGVyKCkge1xuICAgIGlmICghdGhpcy5zaG91bGRVc2VEZXZlbG9wbWVudEhvdFJlbG9hZCgpKSByZXR1cm5cbiAgICBpZiAodGhpcy5kZXZlbG9wbWVudFJlbG9hZGVyKSByZXR1cm5cblxuICAgIGNvbnN0IGNyZWF0ZURldmVsb3BtZW50UmVsb2FkZXIgPSB0aGlzLmRldmVsb3BtZW50UmVsb2FkZXJGYWN0b3J5XG4gICAgICB8fCAoKGFyZ3MpID0+IG5ldyBEZXZlbG9wbWVudFJlbG9hZGVyKGFyZ3MpKVxuXG4gICAgdGhpcy5kZXZlbG9wbWVudFJlbG9hZGVyID0gY3JlYXRlRGV2ZWxvcG1lbnRSZWxvYWRlcih7XG4gICAgICBjb25maWd1cmF0aW9uOiB0aGlzLmNvbmZpZ3VyYXRpb24sXG4gICAgICBvblJlbG9hZDogYXN5bmMgKHtjaGFuZ2VkUGF0aH0pID0+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5sb2dnZXIuaW5mbyhgRGV2ZWxvcG1lbnQgaG90IHJlbG9hZCBkZXRlY3RlZCBjaGFuZ2UgaW4gJHtjaGFuZ2VkUGF0aH1gKVxuICAgICAgICBhd2FpdCB0aGlzLnJlbG9hZFdvcmtlcnNGb3JEZXZlbG9wbWVudCgpXG4gICAgICB9XG4gICAgfSlcblxuICAgIGF3YWl0IHRoaXMuZGV2ZWxvcG1lbnRSZWxvYWRlci5zdGFydCgpXG4gIH1cblxuICAvKipcbiAgICogUnVucyByZWxvYWQgd29ya2VycyBmb3IgZGV2ZWxvcG1lbnQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gd29ya2VycyBoYXZlIGJlZW4gcmVmcmVzaGVkLlxuICAgKi9cbiAgYXN5bmMgcmVsb2FkV29ya2Vyc0ZvckRldmVsb3BtZW50KCkge1xuICAgIGlmICh0aGlzLl9zdG9wcGluZykgcmV0dXJuXG5cbiAgICBpZiAodGhpcy5fcmVsb2FkaW5nV29ya2Vyc0ZvckRldmVsb3BtZW50KSB7XG4gICAgICB0aGlzLl9yZWxvYWRXb3JrZXJzRm9yRGV2ZWxvcG1lbnRRdWV1ZWQgPSB0cnVlXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICB0aGlzLl9yZWxvYWRpbmdXb3JrZXJzRm9yRGV2ZWxvcG1lbnQgPSB0cnVlXG5cbiAgICB0cnkge1xuICAgICAgZG8ge1xuICAgICAgICB0aGlzLl9yZWxvYWRXb3JrZXJzRm9yRGV2ZWxvcG1lbnRRdWV1ZWQgPSBmYWxzZVxuXG4gICAgICAgIGNvbnN0IG9sZFdvcmtlckhhbmRsZXJzID0gWy4uLnRoaXMud29ya2VySGFuZGxlcnNdXG4gICAgICAgIGNvbnN0IG5ld1dvcmtlckhhbmRsZXJzID0gYXdhaXQgdGhpcy5fYnVpbGRXb3JrZXJIYW5kbGVycygpXG5cbiAgICAgICAgdGhpcy53b3JrZXJIYW5kbGVycyA9IG5ld1dvcmtlckhhbmRsZXJzXG4gICAgICAgIHRoaXMubmV4dFdvcmtlckhhbmRsZXJJbmRleCA9IDBcbiAgICAgICAgdGhpcy5zdGlja3lXb3JrZXJIYW5kbGVycy5jbGVhcigpXG5cbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwob2xkV29ya2VySGFuZGxlcnMubWFwKCh3b3JrZXJIYW5kbGVyKSA9PiB3b3JrZXJIYW5kbGVyLnN0b3AoKSkpXG4gICAgICB9IHdoaWxlICh0aGlzLl9yZWxvYWRXb3JrZXJzRm9yRGV2ZWxvcG1lbnRRdWV1ZWQgJiYgIXRoaXMuX3N0b3BwaW5nKVxuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLl9yZWxvYWRpbmdXb3JrZXJzRm9yRGV2ZWxvcG1lbnQgPSBmYWxzZVxuICAgIH1cbiAgfVxufVxuIl19
|
|
640
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvaHR0cC1zZXJ2ZXIvaW5kZXguanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sRUFBQyxJQUFJLEVBQUMsTUFBTSxXQUFXLENBQUE7QUFDOUIsT0FBTyxtQkFBbUIsTUFBTSwyQkFBMkIsQ0FBQTtBQUMzRCxPQUFPLFlBQVksTUFBTSwyQkFBMkIsQ0FBQTtBQUNwRCxPQUFPLGdCQUFnQixNQUFNLGdDQUFnQyxDQUFBO0FBQzdELE9BQU8sTUFBTSxNQUFNLGNBQWMsQ0FBQTtBQUNqQyxPQUFPLEdBQUcsTUFBTSxLQUFLLENBQUE7QUFDckIsT0FBTyxFQUFFLE1BQU0sU0FBUyxDQUFBO0FBQ3hCLE9BQU8sWUFBWSxNQUFNLG9CQUFvQixDQUFBO0FBQzdDLE9BQU8sYUFBYSxNQUFNLDJCQUEyQixDQUFBO0FBRXJEOztnR0FFZ0c7QUFDaEc7OzJaQUUyWjtBQUUzWjs7Ozs7OztHQU9HO0FBQ0gsU0FBUyxvQkFBb0IsQ0FBQyxFQUFDLGtCQUFrQixFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUM7SUFDckUsTUFBTSxXQUFXLEdBQUcsT0FBTyxJQUFJLFVBQVUsSUFBSSxrQkFBa0IsQ0FBQTtJQUUvRCxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsSUFBSSxXQUFXLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDdEQsTUFBTSxJQUFJLEtBQUssQ0FBQyxnREFBZ0QsQ0FBQyxDQUFBO0lBQ25FLENBQUM7SUFFRCxPQUFPLFdBQVcsQ0FBQTtBQUNwQixDQUFDO0FBRUQsTUFBTSxnQ0FBZ0MsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFBO0FBQ2xELE1BQU0sbUNBQW1DLEdBQUcsb0JBQW9CLENBQUE7QUFFaEUsTUFBTSxDQUFDLE9BQU8sT0FBTyxtQkFBbUI7SUFDdEMsV0FBVyxHQUFHLENBQUMsQ0FBQTtJQUNmLFNBQVMsR0FBRyxL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LENBQUMsa0NBQWtDLEdBQUcsSUFBSSxDQUFBO1lBQzlDLE9BQU07UUFDUixDQUFDO1FBRUQsSUFBSSxDQUFDLCtCQUErQixHQUFHLElBQUksQ0FBQTtRQUUzQyxJQUFJLENBQUM7WUFDSCxHQUFHLENBQUM7Z0JBQ0YsSUFBSSxDQUFDLGtDQUFrQyxHQUFHLEtBQUssQ0FBQTtnQkFFL0MsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFBO2dCQUNsRCxNQUFNLGlCQUFpQixHQUFHLE1BQU0sSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUE7Z0JBRTNELElBQUksQ0FBQyxjQUFjLEdBQUcsaUJBQWlCLENBQUE7Z0JBQ3ZDLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxDQUFDLENBQUE7Z0JBQy9CLEtBQUssTUFBTSxhQUFhLElBQUksaUJBQWlCO29CQUFFLElBQUksQ0FBQyxpQ0FBaUMsQ0FBQyxhQUFhLENBQUMsQ0FBQTtnQkFFcEcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQTtZQUNuRixDQUFDLFFBQVEsSUFBSSxDQUFDLGtDQUFrQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBQztRQUN0RSxDQUFDO2dCQUFTLENBQUM7WUFDVCxJQUFJLENBQUMsK0JBQStCLEdBQUcsS0FBSyxDQUFBO1FBQzlDLENBQUM7SUFDSCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHtkaWdnfSBmcm9tIFwiZGlnZ2VyaXplXCJcbmltcG9ydCBEZXZlbG9wbWVudFJlbG9hZGVyIGZyb20gXCIuL2RldmVsb3BtZW50LXJlbG9hZGVyLmpzXCJcbmltcG9ydCBFdmVudEVtaXR0ZXIgZnJvbSBcIi4uL3V0aWxzL2V2ZW50LWVtaXR0ZXIuanNcIlxuaW1wb3J0IEluUHJvY2Vzc0hhbmRsZXIgZnJvbSBcIi4vd29ya2VyLWhhbmRsZXIvaW4tcHJvY2Vzcy5qc1wiXG5pbXBvcnQgTG9nZ2VyIGZyb20gXCIuLi9sb2dnZXIuanNcIlxuaW1wb3J0IE5ldCBmcm9tIFwibmV0XCJcbmltcG9ydCBvcyBmcm9tIFwibm9kZTpvc1wiXG5pbXBvcnQgU2VydmVyQ2xpZW50IGZyb20gXCIuL3NlcnZlci1jbGllbnQuanNcIlxuaW1wb3J0IFdvcmtlckhhbmRsZXIgZnJvbSBcIi4vd29ya2VyLWhhbmRsZXIvaW5kZXguanNcIlxuXG4vKipcbiAqIERlZmluZXMgdGhpcyB0eXBlZGVmLlxuICogQHR5cGVkZWYge3tzdGFydDogKCkgPT4gUHJvbWlzZTx2b2lkPiwgc3RvcDogKCkgPT4gUHJvbWlzZTx2b2lkPn19IERldmVsb3BtZW50UmVsb2FkZXJMaWtlICovXG4vKipcbiAqIERlZmluZXMgdGhpcyB0eXBlZGVmLlxuICogQHR5cGVkZWYgeyhhcmdzOiB7Y29uZmlndXJhdGlvbjogaW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0LCBvbldlYnNvY2tldFNlc3Npb25Pd25lZDogKGFyZ3M6IHtzZXNzaW9uSWQ6IHN0cmluZywgd29ya2VySGFuZGxlcjogV29ya2VySGFuZGxlcn0pID0+IHZvaWQsIG9uV2Vic29ja2V0U2Vzc2lvblJlbGVhc2VkOiAoYXJnczoge3Nlc3Npb25JZDogc3RyaW5nLCB3b3JrZXJIYW5kbGVyOiBXb3JrZXJIYW5kbGVyfSkgPT4gdm9pZCwgb25Xb3JrZXJTdG9wcGVkOiAoYXJnczoge3dvcmtlckhhbmRsZXI6IFdvcmtlckhhbmRsZXJ9KSA9PiB2b2lkLCB3b3JrZXJDb3VudDogbnVtYmVyfSkgPT4gKFdvcmtlckhhbmRsZXIgfCBJblByb2Nlc3NIYW5kbGVyKX0gV29ya2VySGFuZGxlckZhY3RvcnkgKi9cblxuLyoqXG4gKiBSdW5zIG5vcm1hbGl6ZSB3b3JrZXIgY291bnQuXG4gKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMgb2JqZWN0LlxuICogQHBhcmFtIHtudW1iZXJ9IFthcmdzLm1heFdvcmtlcnNdIC0gQmFja3dhcmQtY29tcGF0aWJsZSB3b3JrZXIgY291bnQgYWxpYXMuXG4gKiBAcGFyYW0ge251bWJlcn0gW2FyZ3Mud29ya2Vyc10gLSBDb25maWd1cmVkIHdvcmtlciBjb3VudC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBhcmdzLmRlZmF1bHRXb3JrZXJDb3VudCAtIFByb2Nlc3MtYXZhaWxhYmxlIENQVSBjb3VudC5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IC0gTm9ybWFsaXplZCB3b3JrZXIgY291bnQuXG4gKi9cbmZ1bmN0aW9uIG5vcm1hbGl6ZVdvcmtlckNvdW50KHtkZWZhdWx0V29ya2VyQ291bnQsIG1heFdvcmtlcnMsIHdvcmtlcnN9KSB7XG4gIGNvbnN0IHdvcmtlckNvdW50ID0gd29ya2VycyA/PyBtYXhXb3JrZXJzID8/IGRlZmF1bHRXb3JrZXJDb3VudFxuXG4gIGlmICghTnVtYmVyLmlzSW50ZWdlcih3b3JrZXJDb3VudCkgfHwgd29ya2VyQ291bnQgPCAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiSFRUUCBzZXJ2ZXIgd29ya2VycyBtdXN0IGJlIGEgcG9zaXRpdmUgaW50ZWdlclwiKVxuICB9XG5cbiAgcmV0dXJuIHdvcmtlckNvdW50XG59XG5cbmNvbnN0IE1BWF9JTklUSUFMX1JFUVVFU1RfSEVBREVSX0JZVEVTID0gNjQgKiAxMDI0XG5jb25zdCBXRUJTT0NLRVRfU0VTU0lPTl9ST1VUSU5HX1BBUkFNRVRFUiA9IFwidmVsb2Npb3VzU2Vzc2lvbklkXCJcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVmVsb2Npb3VzSHR0cFNlcnZlciB7XG4gIGNsaWVudENvdW50ID0gMFxuICBfc3RhcnRpbmcgPSBmYWxzZVxuXG4gIC8qKlxuICAgKiBOYXJyb3dzIHRoZSBydW50aW1lIHZhbHVlIHRvIHRoZSBkb2N1bWVudGVkIHR5cGUuXG4gICAqIEB0eXBlIHtEZXZlbG9wbWVudFJlbG9hZGVyIHwgRGV2ZWxvcG1lbnRSZWxvYWRlckxpa2UgfCB1bmRlZmluZWR9ICovXG4gIGRldmVsb3BtZW50UmVsb2FkZXJcblxuICAvKipcbiAgICogTmFycm93cyB0aGUgcnVudGltZSB2YWx1ZSB0byB0aGUgZG9jdW1lbnRlZCB0eXBlLlxuICAgKiBAdHlwZSB7aW1wb3J0KFwibmV0XCIpLlNlcnZlciB8IHVuZGVmaW5lZH0gKi9cbiAgbmV0U2VydmVyXG5cbiAgLyoqXG4gICAqIE5hcnJvd3MgdGhlIHJ1bnRpbWUgdmFsdWUgdG8gdGhlIGRvY3VtZW50ZWQgdHlwZS5cbiAgICogQHR5cGUge1dvcmtlckhhbmRsZXJGYWN0b3J5IHwgdW5kZWZpbmVkfSAqL1xuICB3b3JrZXJIYW5kbGVyRmFjdG9yeVxuXG4gIC8qKlxuICAgKiBDbGllbnRzLlxuICAgKiBAdHlwZSB7UmVjb3JkPHN0cmluZywgU2VydmVyQ2xpZW50Pn0gICovXG4gIGNsaWVudHMgPSB7fVxuXG4gIC8qKlxuICAgKiBBY3RpdmUgc29ja2V0cy5cbiAgICogQHR5cGUge1NldDxpbXBvcnQoXCJuZXRcIikuU29ja2V0Pn0gKi9cbiAgX2FjdGl2ZVNvY2tldHMgPSBuZXcgU2V0KClcblxuICBldmVudHMgPSBuZXcgRXZlbnRFbWl0dGVyKClcbiAgd29ya2VyQ291bnQgPSAwXG5cbiAgLyoqXG4gICAqIFdvcmtlciBoYW5kbGVycy5cbiAgICogQHR5cGUge0FycmF5PFdvcmtlckhhbmRsZXIgfCBJblByb2Nlc3NIYW5kbGVyPn0gKi9cbiAgd29ya2VySGFuZGxlcnMgPSBbXVxuICBuZXh0V29ya2VySGFuZGxlckluZGV4ID0gMFxuICAvKiogV29ya2VyIG93bmVyc2hpcCBmb3IgbGl2ZSBvciBncmFjZS1wYXVzZWQgcmVzdW1hYmxlIFdlYlNvY2tldCBzZXNzaW9ucy4gKi9cbiAgd2Vic29ja2V0U2Vzc2lvbk93bmVycyA9IG5ldyBNYXAoKVxuXG4gIC8qKlxuICAgKiBSdW5zIGNvbnN0cnVjdG9yLlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMgb2JqZWN0LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2NvbmZpZ3VyYXRpb24uanNcIikuZGVmYXVsdH0gYXJncy5jb25maWd1cmF0aW9uIC0gQ29uZmlndXJhdGlvbiBpbnN0YW5jZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFthcmdzLmhvc3RdIC0gSG9zdC5cbiAgICogQHBhcmFtIHtib29sZWFufSBbYXJncy5pblByb2Nlc3NdIC0gUnVuIEhUVFAgaGFuZGxlcnMgaW4gdGhlIG1haW4gdGhyZWFkIGluc3RlYWQgb2Ygd29ya2VyIHRocmVhZHMuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJncy5wb3J0XSAtIFBvcnQuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJncy5tYXhXb3JrZXJzXSAtIE1heCB3b3JrZXJzLlxuICAgKiBAcGFyYW0ge251bWJlcn0gW2FyZ3Mud29ya2Vyc10gLSBXb3JrZXIgaGFuZGxlcnMgdG8gc3RhcnQuXG4gICAqIEBwYXJhbSB7KCkgPT4gbnVtYmVyfSBbYXJncy5hdmFpbGFibGVQYXJhbGxlbGlzbV0gLSBDUFUgYXZhaWxhYmlsaXR5IG93bmVyIHNlYW0uXG4gICAqIEBwYXJhbSB7KGFyZ3M6IHtjb25maWd1cmF0aW9uOiBpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHQsIG9uUmVsb2FkOiAoYXJnczoge2NoYW5nZWRQYXRoOiBzdHJpbmd9KSA9PiBQcm9taXNlPHZvaWQ+fSkgPT4ge3N0YXJ0OiAoKSA9PiBQcm9taXNlPHZvaWQ+LCBzdG9wOiAoKSA9PiBQcm9taXNlPHZvaWQ+fX0gW2FyZ3MuZGV2ZWxvcG1lbnRSZWxvYWRlckZhY3RvcnldIC0gRGV2ZWxvcG1lbnQgcmVsb2FkZXIgZmFjdG9yeS5cbiAgICogQHBhcmFtIHtXb3JrZXJIYW5kbGVyRmFjdG9yeX0gW2FyZ3Mud29ya2VySGFuZGxlckZhY3RvcnldIC0gV29ya2VyIGhhbmRsZXIgZmFjdG9yeS5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHthdmFpbGFibGVQYXJhbGxlbGlzbSA9IG9zLmF2YWlsYWJsZVBhcmFsbGVsaXNtLCBjb25maWd1cmF0aW9uLCBkZXZlbG9wbWVudFJlbG9hZGVyRmFjdG9yeSwgaG9zdCwgaW5Qcm9jZXNzLCBtYXhXb3JrZXJzLCBwb3J0LCB3b3JrZXJIYW5kbGVyRmFjdG9yeSwgd29ya2Vyc30pIHtcbiAgICB0aGlzLmNvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uXG4gICAgdGhpcy5kZXZlbG9wbWVudFJlbG9hZGVyRmFjdG9yeSA9IGRldmVsb3BtZW50UmVsb2FkZXJGYWN0b3J5XG4gICAgdGhpcy53b3JrZXJIYW5kbGVyRmFjdG9yeSA9IHdvcmtlckhhbmRsZXJGYWN0b3J5XG4gICAgdGhpcy5pblByb2Nlc3MgPSBpblByb2Nlc3MgfHwgZmFsc2VcbiAgICB0aGlzLmxvZ2dlciA9IG5ldyBMb2dnZXIodGhpcylcbiAgICB0aGlzLmhvc3QgPSBob3N0ID8/IFwiMC4wLjAuMFwiXG4gICAgdGhpcy5wb3J0ID0gcG9ydCA/PyAzMDA2XG4gICAgdGhpcy53b3JrZXJzID0gbm9ybWFsaXplV29ya2VyQ291bnQoe2RlZmF1bHRXb3JrZXJDb3VudDogYXZhaWxhYmxlUGFyYWxsZWxpc20oKSwgbWF4V29ya2Vycywgd29ya2Vyc30pXG4gICAgdGhpcy5lZmZlY3RpdmVXb3JrZXJzID0gdGhpcy5pblByb2Nlc3MgJiYgd29ya2VycyA9PT0gdW5kZWZpbmVkICYmIG1heFdvcmtlcnMgPT09IHVuZGVmaW5lZCA/IDEgOiB0aGlzLndvcmtlcnNcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHN0YXJ0LlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNvbXBsZXRlLlxuICAgKi9cbiAgYXN5bmMgc3RhcnQoKSB7XG4gICAgaWYgKHRoaXMuX3N0YXJ0aW5nKSB0aHJvdyBuZXcgRXJyb3IoXCJWZWxvY2lvdXMgSFRUUCBzZXJ2ZXIgaXMgYWxyZWFkeSBzdGFydGluZ1wiKVxuICAgIGlmICh0aGlzLmlzQWN0aXZlKCkpIHRocm93IG5ldyBFcnJvcihcIlZlbG9jaW91cyBIVFRQIHNlcnZlciBpcyBhbHJlYWR5IHJ1bm5pbmdcIilcblxuICAgIHRoaXMuX3N0YXJ0aW5nID0gdHJ1ZVxuICAgIGNvbnN0IHN0YXJ0dXBTdGF0ZSA9IHRoaXMuX2NhcHR1cmVTdGFydHVwU3RhdGUoKVxuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuX2Vuc3VyZVdvcmtlcnMoKVxuICAgICAgYXdhaXQgdGhpcy5fc3RhcnREZXZlbG9wbWVudFJlbG9hZGVyKClcbiAgICAgIC8qKlxuICAgICAgICogTmV0IHNlcnZlci5cbiAgICAgICAqIEB0eXBlIHtpbXBvcnQoXCJuZXRcIikuU2VydmVyfSAqL1xuICAgICAgY29uc3QgbmV0U2VydmVyID0gbmV3IE5ldC5TZXJ2ZXIoKVxuICAgICAgdGhpcy5uZXRTZXJ2ZXIgPSBuZXRTZXJ2ZXJcbiAgICAgIG5ldFNlcnZlci5vbihcImNsb3NlXCIsIHRoaXMub25DbG9zZSlcbiAgICAgIG5ldFNlcnZlci5vbihcImNvbm5lY3Rpb25cIiwgdGhpcy5vbkNvbm5lY3Rpb24pXG4gICAgICBuZXRTZXJ2ZXIub24oXCJlcnJvclwiLCB0aGlzLm9uU2VydmVyRXJyb3IpXG4gICAgICBhd2FpdCB0aGlzLl9uZXRTZXJ2ZXJMaXN0ZW4oKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBhd2FpdCB0aGlzLl9zdG9wU3RhcnR1cFJlc291cmNlcyhzdGFydHVwU3RhdGUpXG4gICAgICB0aHJvdyBlcnJvclxuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLl9zdGFydGluZyA9IGZhbHNlXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgY2FwdHVyZSBzdGFydHVwIHN0YXRlLlxuICAgKiBAcmV0dXJucyB7e2RldmVsb3BtZW50UmVsb2FkZXI6IERldmVsb3BtZW50UmVsb2FkZXIgfCBEZXZlbG9wbWVudFJlbG9hZGVyTGlrZSB8IHVuZGVmaW5lZCwgbmV0U2VydmVyOiBpbXBvcnQoXCJuZXRcIikuU2VydmVyIHwgdW5kZWZpbmVkLCB3b3JrZXJIYW5kbGVyczogQXJyYXk8V29ya2VySGFuZGxlciB8IEluUHJvY2Vzc0hhbmRsZXI+fX0gLSBTdGFydHVwIHN0YXRlLlxuICAgKi9cbiAgX2NhcHR1cmVTdGFydHVwU3RhdGUoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRldmVsb3BtZW50UmVsb2FkZXI6IHRoaXMuZGV2ZWxvcG1lbnRSZWxvYWRlcixcbiAgICAgIG5ldFNlcnZlcjogdGhpcy5uZXRTZXJ2ZXIsXG4gICAgICB3b3JrZXJIYW5kbGVyczogWy4uLnRoaXMud29ya2VySGFuZGxlcnNdXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgc3RvcCBzdGFydHVwIHJlc291cmNlcy5cbiAgICogQHBhcmFtIHtSZXR1cm5UeXBlPFZlbG9jaW91c0h0dHBTZXJ2ZXJbXCJfY2FwdHVyZVN0YXJ0dXBTdGF0ZVwiXT59IHN0YXJ0dXBTdGF0ZSAtIFN0YXRlIGNhcHR1cmVkIGJlZm9yZSBzdGFydHVwLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNsZWFudXAgaXMgY29tcGxldGUuXG4gICAqL1xuICBhc3luYyBfc3RvcFN0YXJ0dXBSZXNvdXJjZXMoc3RhcnR1cFN0YXRlKSB7XG4gICAgLyoqXG4gICAgICogU3RhcnR1cCBuZXQgc2VydmVyLlxuICAgICAqIEB0eXBlIHtpbXBvcnQoXCJuZXRcIikuU2VydmVyIHwgdW5kZWZpbmVkfSAqL1xuICAgIGNvbnN0IHN0YXJ0dXBOZXRTZXJ2ZXIgPSB0aGlzLm5ldFNlcnZlclxuXG4gICAgaWYgKHRoaXMuZGV2ZWxvcG1lbnRSZWxvYWRlciAmJiB0aGlzLmRldmVsb3BtZW50UmVsb2FkZXIgIT09IHN0YXJ0dXBTdGF0ZS5kZXZlbG9wbWVudFJlbG9hZGVyKSB7XG4gICAgICBhd2FpdCB0aGlzLmRldmVsb3BtZW50UmVsb2FkZXIuc3RvcCgpXG4gICAgfVxuXG4gICAgaWYgKHN0YXJ0dXBOZXRTZXJ2ZXIgJiYgc3RhcnR1cE5ldFNlcnZlciAhPT0gc3RhcnR1cFN0YXRlLm5ldFNlcnZlcikge1xuICAgICAgYXdhaXQgdGhpcy5zdG9wU2VydmVyKHN0YXJ0dXBOZXRTZXJ2ZXIpXG4gICAgfVxuXG4gICAgY29uc3Qgc3RhcnR1cFdvcmtlckhhbmRsZXJzID0gdGhpcy53b3JrZXJIYW5kbGVycy5maWx0ZXIoKHdvcmtlckhhbmRsZXIpID0+ICFzdGFydHVwU3RhdGUud29ya2VySGFuZGxlcnMuaW5jbHVkZXMod29ya2VySGFuZGxlcikpXG5cbiAgICBhd2FpdCBQcm9taXNlLmFsbChzdGFydHVwV29ya2VySGFuZGxlcnMubWFwKChoYW5kbGVyKSA9PiBoYW5kbGVyLnN0b3AoKSkpXG5cbiAgICB0aGlzLmRldmVsb3BtZW50UmVsb2FkZXIgPSBzdGFydHVwU3RhdGUuZGV2ZWxvcG1lbnRSZWxvYWRlclxuICAgIHRoaXMubmV0U2VydmVyID0gc3RhcnR1cFN0YXRlLm5ldFNlcnZlclxuICAgIHRoaXMud29ya2VySGFuZGxlcnMgPSBzdGFydHVwU3RhdGUud29ya2VySGFuZGxlcnNcbiAgICB0aGlzLndlYnNvY2tldFNlc3Npb25Pd25lcnMuY2xlYXIoKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgbmV0IHNlcnZlciBsaXN0ZW4uXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gY29tcGxldGUuXG4gICAqL1xuICBfbmV0U2VydmVyTGlzdGVuKCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBpZiAoIXRoaXMubmV0U2VydmVyKSB0aHJvdyBuZXcgRXJyb3IoXCJObyBuZXRTZXJ2ZXJcIilcblxuICAgICAgLyoqXG4gICAgICAgKiBPbiBsaXN0ZW4gZXJyb3IuXG4gICAgICAgKiBAcGFyYW0ge0Vycm9yfSBlcnJvciAtIExpc3RlbiBlcnJvci5cbiAgICAgICAqL1xuICAgICAgY29uc3Qgb25MaXN0ZW5FcnJvciA9IChlcnJvcikgPT4ge1xuICAgICAgICB0aGlzLm5ldFNlcnZlcj8ub2ZmKFwiZXJyb3JcIiwgb25MaXN0ZW5FcnJvcilcbiAgICAgICAgcmVqZWN0KGVycm9yKVxuICAgICAgfVxuXG4gICAgICB0cnkge1xuICAgICAgICB0aGlzLm5ldFNlcnZlci5vbmNlKFwiZXJyb3JcIiwgb25MaXN0ZW5FcnJvcilcbiAgICAgICAgdGhpcy5uZXRTZXJ2ZXIubGlzdGVuKHRoaXMucG9ydCwgdGhpcy5ob3N0LCAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5uZXRTZXJ2ZXI/Lm9mZihcImVycm9yXCIsIG9uTGlzdGVuRXJyb3IpXG4gICAgICAgICAgdGhpcy5sb2dnZXIuZGVidWcoYFZlbG9jaW91cyBsaXN0ZW5pbmcgb24gJHt0aGlzLmhvc3R9OiR7dGhpcy5wb3J0fWApXG4gICAgICAgICAgcmVzb2x2ZSh1bmRlZmluZWQpXG4gICAgICAgIH0pXG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICByZWplY3QoZXJyb3IpXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGVuc3VyZSB3b3JrZXJzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNvbXBsZXRlLlxuICAgKi9cbiAgYXN5bmMgX2Vuc3VyZVdvcmtlcnMoKSB7XG4gICAgd2hpbGUgKHRoaXMud29ya2VySGFuZGxlcnMubGVuZ3RoIDwgdGhpcy5lZmZlY3RpdmVXb3JrZXJzKSB7XG4gICAgICBhd2FpdCB0aGlzLnNwYXduV29ya2VyKClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyBpcyBhY3RpdmUuXG4gICAqIEByZXR1cm5zIHtib29sZWFufSAtIFdoZXRoZXIgYWN0aXZlLlxuICAgKi9cbiAgaXNBY3RpdmUoKSB7XG4gICAgaWYgKHRoaXMubmV0U2VydmVyKSB7XG4gICAgICByZXR1cm4gdGhpcy5uZXRTZXJ2ZXIubGlzdGVuaW5nXG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICAvKipcbiAgICogUnVucyBnZXQgZGVidWcgc25hcHNob3QuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pj59IC0gSFRUUCBzZXJ2ZXIgd29ya2VyIGRpYWdub3N0aWNzLlxuICAgKi9cbiAgYXN5bmMgZ2V0RGVidWdTbmFwc2hvdCgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgYWN0aXZlOiB0aGlzLmlzQWN0aXZlKCksXG4gICAgICBhY3RpdmVTb2NrZXRDb3VudDogdGhpcy5fYWN0aXZlU29ja2V0cy5zaXplLFxuICAgICAgY2xpZW50Q291bnQ6IE9iamVjdC5rZXlzKHRoaXMuY2xpZW50cykubGVuZ3RoLFxuICAgICAgY29uZmlndXJlZFdvcmtlckNvdW50OiB0aGlzLndvcmtlcnMsXG4gICAgICBlZmZlY3RpdmVXb3JrZXJDb3VudDogdGhpcy5lZmZlY3RpdmVXb3JrZXJzLFxuICAgICAgaW5Qcm9jZXNzOiB0aGlzLmluUHJvY2VzcyxcbiAgICAgIHdvcmtlckNvdW50OiB0aGlzLndvcmtlckhhbmRsZXJzLmxlbmd0aCxcbiAgICAgIHdvcmtlcnM6IGF3YWl0IFByb21pc2UuYWxsKHRoaXMud29ya2VySGFuZGxlcnMubWFwKChoYW5kbGVyKSA9PiB0aGlzLndvcmtlckRlYnVnU25hcHNob3QoaGFuZGxlcikpKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHdvcmtlciBkZWJ1ZyBzbmFwc2hvdC5cbiAgICogQHBhcmFtIHtXb3JrZXJIYW5kbGVyIHwgSW5Qcm9jZXNzSGFuZGxlcn0gd29ya2VySGFuZGxlciAtIFdvcmtlciBoYW5kbGVyIHRvIGluc3BlY3QuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pj59IFdvcmtlciBkZWJ1ZyBzbmFwc2hvdC5cbiAgICovXG4gIGFzeW5jIHdvcmtlckRlYnVnU25hcHNob3Qod29ya2VySGFuZGxlcikge1xuICAgIGlmICh3b3JrZXJIYW5kbGVyIGluc3RhbmNlb2YgV29ya2VySGFuZGxlcikgcmV0dXJuIGF3YWl0IHdvcmtlckhhbmRsZXIuZ2V0RGVidWdTbmFwc2hvdCgpXG4gICAgaWYgKHdvcmtlckhhbmRsZXIgaW5zdGFuY2VvZiBJblByb2Nlc3NIYW5kbGVyKSByZXR1cm4gdGhpcy5pblByb2Nlc3NXb3JrZXJEZWJ1Z1NuYXBzaG90KHdvcmtlckhhbmRsZXIpXG5cbiAgICByZXR1cm4ge2FjdGl2ZTogZmFsc2UsIGVycm9yOiBcIlVua25vd24gd29ya2VyIGhhbmRsZXIgdHlwZVwifVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgaW4gcHJvY2VzcyB3b3JrZXIgZGVidWcgc25hcHNob3QuXG4gICAqIEBwYXJhbSB7SW5Qcm9jZXNzSGFuZGxlcn0gd29ya2VySGFuZGxlciAtIEluLXByb2Nlc3Mgd29ya2VyIGhhbmRsZXIgdG8gaW5zcGVjdC5cbiAgICogQHJldHVybnMge1JlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+Pn0gV29ya2VyIGRlYnVnIHNuYXBzaG90LlxuICAgKi9cbiAgaW5Qcm9jZXNzV29ya2VyRGVidWdTbmFwc2hvdCh3b3JrZXJIYW5kbGVyKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGFjdGl2ZTogdHJ1ZSxcbiAgICAgIGNsaWVudENvdW50OiBPYmplY3Qua2V5cyh3b3JrZXJIYW5kbGVyLmNsaWVudHMpLmxlbmd0aCxcbiAgICAgIHNuYXBzaG90OiB3b3JrZXJIYW5kbGVyLmNvbmZpZ3VyYXRpb24uZ2V0TG9jYWxEZWJ1Z1NuYXBzaG90KCksXG4gICAgICB3b3JrZXJDb3VudDogd29ya2VySGFuZGxlci53b3JrZXJDb3VudFxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHN0b3AgY2xpZW50cy5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjb21wbGV0ZS5cbiAgICovXG4gIGFzeW5jIHN0b3BDbGllbnRzKCkge1xuICAgIGNvbnN0IHByb21pc2VzID0gW11cblxuICAgIGZvciAoY29uc3QgY2xpZW50Q291bnQgaW4gdGhpcy5jbGllbnRzKSB7XG4gICAgICBjb25zdCBjbGllbnQgPSB0aGlzLmNsaWVudHNbY2xpZW50Q291bnRdXG5cbiAgICAgIHByb21pc2VzLnB1c2goY2xpZW50LmVuZCgpKVxuICAgIH1cblxuICAgIGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgc3RvcCBzZXJ2ZXIuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwibmV0XCIpLlNlcnZlciB8IHVuZGVmaW5lZH0gW25ldFNlcnZlcl0gLSBTZXJ2ZXIgdG8gc3RvcC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjb21wbGV0ZS5cbiAgICovXG4gIHN0b3BTZXJ2ZXIobmV0U2VydmVyID0gdGhpcy5uZXRTZXJ2ZXIpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgaWYgKCFuZXRTZXJ2ZXIgfHwgIW5ldFNlcnZlci5saXN0ZW5pbmcpIHtcbiAgICAgICAgcmVzb2x2ZSh1bmRlZmluZWQpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBpZiAobmV0U2VydmVyID09PSB0aGlzLm5ldFNlcnZlcikge1xuICAgICAgICAvLyBGb3JjZS1jbG9zZSBsaW5nZXJpbmcgc29ja2V0cyAoZS5nLiBXZWJTb2NrZXQgdXBncmFkZVxuICAgICAgICAvLyBjb25uZWN0aW9ucyBtaWQtY2xvc2UtaGFuZHNoYWtlKSBzbyB0aGUgcG9ydCBpcyByZWxlYXNlZFxuICAgICAgICAvLyBpbW1lZGlhdGVseSBpbnN0ZWFkIG9mIHdhaXRpbmcgZm9yIGdyYWNlZnVsIGRyYWluLlxuICAgICAgICBmb3IgKGNvbnN0IHNvY2tldCBvZiB0aGlzLl9hY3RpdmVTb2NrZXRzKSB7XG4gICAgICAgICAgc29ja2V0LmRlc3Ryb3koKVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fYWN0aXZlU29ja2V0cy5jbGVhcigpXG4gICAgICB9XG5cbiAgICAgIG5ldFNlcnZlci5jbG9zZSgoZXJyb3IpID0+IHtcbiAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgcmVqZWN0KGVycm9yKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc29sdmUodW5kZWZpbmVkKVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogUnVucyBzdG9wLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNvbXBsZXRlLlxuICAgKi9cbiAgYXN5bmMgc3RvcCgpIHtcbiAgICB0aGlzLl9zdG9wcGluZyA9IHRydWVcbiAgICBhd2FpdCB0aGlzLmRldmVsb3BtZW50UmVsb2FkZXI/LnN0b3AoKVxuICAgIHRoaXMuZGV2ZWxvcG1lbnRSZWxvYWRlciA9IHVuZGVmaW5lZFxuICAgIGF3YWl0IHRoaXMuc3RvcENsaWVudHMoKVxuICAgIGF3YWl0IHRoaXMuc3RvcFNlcnZlcigpXG5cbiAgICBjb25zdCBzdG9wVGFza3MgPSB0aGlzLndvcmtlckhhbmRsZXJzLm1hcCgoaGFuZGxlcikgPT4gaGFuZGxlci5zdG9wKCkpXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoc3RvcFRhc2tzKVxuICAgIHRoaXMud29ya2VySGFuZGxlcnMgPSBbXVxuICAgIHRoaXMud2Vic29ja2V0U2Vzc2lvbk93bmVycy5jbGVhcigpXG4gIH1cblxuICAvKipcbiAgICogT24gY2xvc2UuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIG9uQ2xvc2UgPSAoKSA9PiB7XG4gICAgdGhpcy5ldmVudHMuZW1pdChcImNsb3NlXCIpXG4gIH1cblxuICAvKipcbiAgICogT24gc2VydmVyIGVycm9yLlxuICAgKiBAcGFyYW0ge0Vycm9yfSBlcnJvciAtIFNlcnZlciBzb2NrZXQgZXJyb3IuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIG9uU2VydmVyRXJyb3IgPSAoZXJyb3IpID0+IHtcbiAgICB0aGlzLmxvZ2dlci5lcnJvcihgVmVsb2Npb3VzIEhUVFAgc2VydmVyIHNvY2tldCBlcnJvciBvbiAke3RoaXMuaG9zdH06JHt0aGlzLnBvcnR9YCwgZXJyb3IpXG4gIH1cblxuICAvKipcbiAgICogT24gY29ubmVjdGlvbi5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCJuZXRcIikuU29ja2V0fSBzb2NrZXQgLSBTb2NrZXQgaW5zdGFuY2UuXG4gICAqIEByZXR1cm5zIHt2b2lkfSAtIE5vIHJldHVybiB2YWx1ZS5cbiAgICovXG4gIG9uQ29ubmVjdGlvbiA9IChzb2NrZXQpID0+IHtcbiAgICBjb25zdCBjbGllbnRDb3VudCA9IHRoaXMuY2xpZW50Q291bnRcblxuICAgIHRoaXMuX2FjdGl2ZVNvY2tldHMuYWRkKHNvY2tldClcbiAgICBzb2NrZXQub25jZShcImNsb3NlXCIsICgpID0+IHRoaXMuX2FjdGl2ZVNvY2tldHMuZGVsZXRlKHNvY2tldCkpXG5cbiAgICB0aGlzLmxvZ2dlci5kZWJ1ZygoKSA9PiBbXCJOZXcgY2xpZW50XCIsIHtcbiAgICAgIGNsaWVudENvdW50LFxuICAgICAgcmVtb3RlQWRkcmVzczogc29ja2V0LnJlbW90ZUFkZHJlc3MsXG4gICAgICByZW1vdGVGYW1pbHk6IHNvY2tldC5yZW1vdGVGYW1pbHksXG4gICAgICByZW1vdGVQb3J0OiBzb2NrZXQucmVtb3RlUG9ydFxuICAgIH1dKVxuICAgIHRoaXMuY2xpZW50Q291bnQrK1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGNsaWVudCA9IG5ldyBTZXJ2ZXJDbGllbnQoe1xuICAgICAgICBjbGllbnRDb3VudCxcbiAgICAgICAgY29uZmlndXJhdGlvbjogdGhpcy5jb25maWd1cmF0aW9uLFxuICAgICAgICBzb2NrZXRcbiAgICAgIH0pXG5cbiAgICAgIGNsaWVudC5ldmVudHMub24oXCJjbG9zZVwiLCB0aGlzLm9uQ2xpZW50Q2xvc2UpXG4gICAgICB0aGlzLmNsaWVudHNbY2xpZW50Q291bnRdID0gY2xpZW50XG4gICAgICB0aGlzLnJvdXRlQ2xpZW50QWZ0ZXJJbml0aWFsUm91dGluZ0RhdGEoY2xpZW50KVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihgRmFpbGVkIHRvIGluaXRpYWxpemUgY2xpZW50ICR7Y2xpZW50Q291bnR9IG9uIG5ldyBjb25uZWN0aW9uYCwgZXJyb3IpXG4gICAgICBzb2NrZXQuZGVzdHJveSgpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1ZmZlcnMgb25seSB0aGUgYm91bmRlZCBpbml0aWFsIHJlcXVlc3QgZGF0YSBuZWVkZWQgdG8gcmVjb2duaXplIGFcbiAgICogV2ViU29ja2V0IHJlc3VtZSByb3V0aW5nIGhpbnQsIHRoZW4gcmVwbGF5cyBpdCB0byB0aGUgc2VsZWN0ZWQgd29ya2VyLlxuICAgKiBAcGFyYW0ge1NlcnZlckNsaWVudH0gY2xpZW50IC0gVW5hc3NpZ25lZCBzb2NrZXQgY2xpZW50LlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIHJvdXRlQ2xpZW50QWZ0ZXJJbml0aWFsUm91dGluZ0RhdGEoY2xpZW50KSB7XG4gICAgY29uc3Qge3NvY2tldH0gPSBjbGllbnRcbiAgICAvKiogQHR5cGUge0J1ZmZlcltdfSAqL1xuICAgIGNvbnN0IGNodW5rcyA9IFtdXG4gICAgbGV0IGJ5dGVMZW5ndGggPSAwXG4gICAgY29uc3QgY2xlYW51cCA9ICgpID0+IHtcbiAgICAgIHNvY2tldC5vZmYoXCJkYXRhXCIsIG9uRGF0YSlcbiAgICAgIHNvY2tldC5vZmYoXCJjbG9zZVwiLCBjbGVhbnVwKVxuICAgIH1cbiAgICBjb25zdCBvbkRhdGEgPSAoLyoqIEB0eXBlIHtCdWZmZXJ9ICovIGNodW5rKSA9PiB7XG4gICAgICBjaHVua3MucHVzaChjaHVuaylcbiAgICAgIGJ5dGVMZW5ndGggKz0gY2h1bmsubGVuZ3RoXG4gICAgICBjb25zdCBpbml0aWFsUmVxdWVzdCA9IEJ1ZmZlci5jb25jYXQoY2h1bmtzLCBieXRlTGVuZ3RoKVxuXG4gICAgICBpZiAodGhpcy5pbml0aWFsUmVxdWVzdE5lZWRzTW9yZVJvdXRpbmdEYXRhKGluaXRpYWxSZXF1ZXN0KSAmJiBieXRlTGVuZ3RoIDwgTUFYX0lOSVRJQUxfUkVRVUVTVF9IRUFERVJfQllURVMpIHJldHVyblxuXG4gICAgICBjbGVhbnVwKClcbiAgICAgIHRoaXMuYXNzaWduQ2xpZW50VG9Xb3JrZXIoY2xpZW50LCBpbml0aWFsUmVxdWVzdClcbiAgICB9XG5cbiAgICBzb2NrZXQub24oXCJkYXRhXCIsIG9uRGF0YSlcbiAgICBzb2NrZXQub25jZShcImNsb3NlXCIsIGNsZWFudXApXG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIHdoZXRoZXIgdGhlIGJ1ZmZlcmVkIGluaXRpYWwgSFRUUCBoZWFkZXJzIGFyZSBjb21wbGV0ZS5cbiAgICogQHBhcmFtIHtCdWZmZXJ9IGluaXRpYWxSZXF1ZXN0IC0gQnVmZmVyZWQgaW5pdGlhbCByZXF1ZXN0IGJ5dGVzLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBXaGV0aGVyIGEgaGVhZGVyIHRlcm1pbmF0b3IgaXMgcHJlc2VudC5cbiAgICovXG4gIGluaXRpYWxSZXF1ZXN0SGVhZGVyc0NvbXBsZXRlKGluaXRpYWxSZXF1ZXN0KSB7XG4gICAgcmV0dXJuIGluaXRpYWxSZXF1ZXN0LmluY2x1ZGVzKFwiXFxyXFxuXFxyXFxuXCIpIHx8IGluaXRpYWxSZXF1ZXN0LmluY2x1ZGVzKFwiXFxuXFxuXCIpXG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIHdoZXRoZXIgYSBwb3NzaWJsZSByZXN1bWFibGUgV2ViU29ja2V0IHJlcXVlc3Qgc3RpbGwgbmVlZHMgaGVhZGVycy5cbiAgICogT3JkaW5hcnkgYW5kIG1hbGZvcm1lZCByZXF1ZXN0cyBjYW4gcmVhY2ggdGhlIGV4aXN0aW5nIHJlcXVlc3QgcGFyc2VyIGFzXG4gICAqIHNvb24gYXMgdGhlaXIgZmlyc3QgbGluZSBpcyBjb21wbGV0ZS5cbiAgICogQHBhcmFtIHtCdWZmZXJ9IGluaXRpYWxSZXF1ZXN0IC0gQnVmZmVyZWQgaW5pdGlhbCByZXF1ZXN0IGJ5dGVzLlxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBXaGV0aGVyIG1vcmUgcm91dGluZyBkYXRhIGlzIHJlcXVpcmVkLlxuICAgKi9cbiAgaW5pdGlhbFJlcXVlc3ROZWVkc01vcmVSb3V0aW5nRGF0YShpbml0aWFsUmVxdWVzdCkge1xuICAgIGlmICh0aGlzLmluaXRpYWxSZXF1ZXN0SGVhZGVyc0NvbXBsZXRlKGluaXRpYWxSZXF1ZXN0KSkgcmV0dXJuIGZhbHNlXG5cbiAgICBjb25zdCBsaW5lRW5kID0gaW5pdGlhbFJlcXVlc3QuaW5kZXhPZihcIlxcblwiKVxuXG4gICAgaWYgKGxpbmVFbmQgPT09IC0xKSByZXR1cm4gdHJ1ZVxuXG4gICAgY29uc3QgcmVxdWVzdExpbmUgPSBpbml0aWFsUmVxdWVzdC5zdWJhcnJheSgwLCBsaW5lRW5kKS50b1N0cmluZyhcImxhdGluMVwiKS5yZXBsYWNlKC9cXHIkLywgXCJcIilcbiAgICBjb25zdCByZXF1ZXN0TGluZU1hdGNoID0gcmVxdWVzdExpbmUubWF0Y2goL15HRVQgKFteIF0rKSBIVFRQXFwvW14gXSskLylcblxuICAgIGlmICghcmVxdWVzdExpbmVNYXRjaCkgcmV0dXJuIGZhbHNlXG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVxdWVzdFVybCA9IG5ldyBVUkwocmVxdWVzdExpbmVNYXRjaFsxXSwgXCJodHRwOi8vdmVsb2Npb3VzLmludmFsaWRcIilcblxuICAgICAgcmV0dXJuIHJlcXVlc3RVcmwuc2VhcmNoUGFyYW1zLmhhcyhXRUJTT0NLRVRfU0VTU0lPTl9ST1VUSU5HX1BBUkFNRVRFUilcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBc3NpZ25zIGEgYnVmZmVyZWQgY2xpZW50IGFuZCByZXBsYXlzIHRoZSBleGFjdCBieXRlcyBpbnRvIGl0cyB3b3JrZXIuXG4gICAqIEBwYXJhbSB7U2VydmVyQ2xpZW50fSBjbGllbnQgLSBDbGllbnQgYXdhaXRpbmcgYXNzaWdubWVudC5cbiAgICogQHBhcmFtIHtCdWZmZXJ9IGluaXRpYWxSZXF1ZXN0IC0gSW5pdGlhbCByZXF1ZXN0IGJ5dGVzLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIGFzc2lnbkNsaWVudFRvV29ya2VyKGNsaWVudCwgaW5pdGlhbFJlcXVlc3QpIHtcbiAgICBpZiAoY2xpZW50LnNvY2tldC5kZXN0cm95ZWQpIHJldHVyblxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHdvcmtlckhhbmRsZXIgPSB0aGlzLndvcmtlckhhbmRsZXJGb3JJbml0aWFsUmVxdWVzdChpbml0aWFsUmVxdWVzdClcblxuICAgICAgdGhpcy5sb2dnZXIuZGVidWcoYEdhdmUgY2xpZW50ICR7Y2xpZW50LmNsaWVudENvdW50fSB0byB3b3JrZXIgJHt3b3JrZXJIYW5kbGVyLndvcmtlckNvdW50fWApXG4gICAgICB3b3JrZXJIYW5kbGVyLmFkZFNvY2tldENvbm5lY3Rpb24oY2xpZW50KVxuICAgICAgY2xpZW50Lm9uU29ja2V0RGF0YShpbml0aWFsUmVxdWVzdClcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoYEZhaWxlZCB0byBhc3NpZ24gY2xpZW50ICR7Y2xpZW50LmNsaWVudENvdW50fSB0byBhIHdvcmtlcmAsIGVycm9yKVxuICAgICAgY2xpZW50LmRlc3Ryb3koZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yIDogbmV3IEVycm9yKFwiRmFpbGVkIHRvIGFzc2lnbiBIVFRQIGNsaWVudCB0byB3b3JrZXJcIiwge2NhdXNlOiBlcnJvcn0pKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZWxlY3RzIHRoZSBvd25lciBvZiBhIHJlc3VtYWJsZSBXZWJTb2NrZXQgc2Vzc2lvbiBvciB0aGUgbmV4dCBvcmRpbmFyeSB3b3JrZXIuXG4gICAqIEBwYXJhbSB7QnVmZmVyfSBpbml0aWFsUmVxdWVzdCAtIEluaXRpYWwgSFRUUCByZXF1ZXN0IGhlYWRlcnMuXG4gICAqIEByZXR1cm5zIHtXb3JrZXJIYW5kbGVyIHwgSW5Qcm9jZXNzSGFuZGxlcn0gLSBTZWxlY3RlZCB3b3JrZXIuXG4gICAqL1xuICB3b3JrZXJIYW5kbGVyRm9ySW5pdGlhbFJlcXVlc3QoaW5pdGlhbFJlcXVlc3QpIHtcbiAgICBjb25zdCBzZXNzaW9uSWQgPSB0aGlzLndlYnNvY2tldFJlc3VtZVNlc3Npb25JZChpbml0aWFsUmVxdWVzdClcblxuICAgIGlmIChzZXNzaW9uSWQpIHtcbiAgICAgIGNvbnN0IG93bmVyID0gdGhpcy53ZWJzb2NrZXRTZXNzaW9uT3duZXJzLmdldChzZXNzaW9uSWQpXG5cbiAgICAgIGlmIChvd25lciAmJiB0aGlzLndvcmtlckhhbmRsZXJzLmluY2x1ZGVzKG93bmVyKSkgcmV0dXJuIG93bmVyXG4gICAgICBpZiAob3duZXIpIHRoaXMud2Vic29ja2V0U2Vzc2lvbk93bmVycy5kZWxldGUoc2Vzc2lvbklkKVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLndvcmtlckhhbmRsZXJUb1VzZSgpXG4gIH1cblxuICAvKipcbiAgICogUmVhZHMgdGhlIHJlc3VtYWJsZSBXZWJTb2NrZXQgc2Vzc2lvbiByb3V0aW5nIGhpbnQgZnJvbSBhbiB1cGdyYWRlIHJlcXVlc3QuXG4gICAqIEBwYXJhbSB7QnVmZmVyfSBpbml0aWFsUmVxdWVzdCAtIEluaXRpYWwgSFRUUCByZXF1ZXN0IGhlYWRlcnMuXG4gICAqIEByZXR1cm5zIHtzdHJpbmcgfCB1bmRlZmluZWR9IC0gU2Vzc2lvbiBpZGVudGl0eSwgaWYgcHJlc2VudCBvbiBhIFdlYlNvY2tldCB1cGdyYWRlLlxuICAgKi9cbiAgd2Vic29ja2V0UmVzdW1lU2Vzc2lvbklkKGluaXRpYWxSZXF1ZXN0KSB7XG4gICAgY29uc3QgaGVhZGVyRW5kID0gaW5pdGlhbFJlcXVlc3QuaW5kZXhPZihcIlxcclxcblxcclxcblwiKVxuICAgIGNvbnN0IGZhbGxiYWNrSGVhZGVyRW5kID0gaGVhZGVyRW5kID09PSAtMSA/IGluaXRpYWxSZXF1ZXN0LmluZGV4T2YoXCJcXG5cXG5cIikgOiBoZWFkZXJFbmRcblxuICAgIGlmIChmYWxsYmFja0hlYWRlckVuZCA9PT0gLTEpIHJldHVyblxuXG4gICAgY29uc3QgbGluZXMgPSBpbml0aWFsUmVxdWVzdC5zdWJhcnJheSgwLCBmYWxsYmFja0hlYWRlckVuZCkudG9TdHJpbmcoXCJsYXRpbjFcIikuc3BsaXQoL1xccj9cXG4vKVxuICAgIGNvbnN0IFttZXRob2QsIHJlcXVlc3RUYXJnZXRdID0gbGluZXNbMF0/LnNwbGl0KFwiIFwiKSB8fCBbXVxuXG4gICAgaWYgKG1ldGhvZCAhPT0gXCJHRVRcIiB8fCAhcmVxdWVzdFRhcmdldCkgcmV0dXJuXG5cbiAgICAvKiogQHR5cGUge01hcDxzdHJpbmcsIHN0cmluZz59ICovXG4gICAgY29uc3QgaGVhZGVycyA9IG5ldyBNYXAoKVxuXG4gICAgZm9yIChjb25zdCBsaW5lIG9mIGxpbmVzLnNsaWNlKDEpKSB7XG4gICAgICBjb25zdCBzZXBhcmF0b3JJbmRleCA9IGxpbmUuaW5kZXhPZihcIjpcIilcblxuICAgICAgaWYgKHNlcGFyYXRvckluZGV4ID09PSAtMSkgY29udGludWVcblxuICAgICAgaGVhZGVycy5zZXQobGluZS5zbGljZSgwLCBzZXBhcmF0b3JJbmRleCkudHJpbSgpLnRvTG93ZXJDYXNlKCksIGxpbmUuc2xpY2Uoc2VwYXJhdG9ySW5kZXggKyAxKS50cmltKCkudG9Mb3dlckNhc2UoKSlcbiAgICB9XG5cbiAgICBpZiAoaGVhZGVycy5nZXQoXCJ1cGdyYWRlXCIpICE9PSBcIndlYnNvY2tldFwiIHx8ICFoZWFkZXJzLmdldChcImNvbm5lY3Rpb25cIik/LnNwbGl0KFwiLFwiKS5tYXAoKHZhbHVlKSA9PiB2YWx1ZS50cmltKCkpLmluY2x1ZGVzKFwidXBncmFkZVwiKSkgcmV0dXJuXG5cbiAgICBjb25zdCBzZXNzaW9uSWQgPSBuZXcgVVJMKHJlcXVlc3RUYXJnZXQsIFwiaHR0cDovL3ZlbG9jaW91cy5pbnZhbGlkXCIpLnNlYXJjaFBhcmFtcy5nZXQoV0VCU09DS0VUX1NFU1NJT05fUk9VVElOR19QQVJBTUVURVIpXG5cbiAgICByZXR1cm4gc2Vzc2lvbklkIHx8IHVuZGVmaW5lZFxuICB9XG5cbiAgLyoqXG4gICAqIFJlY29yZHMgdGhlIGxpdmUgd29ya2VyIG93bmVyIGZvciBhIHJlc3VtYWJsZSBzZXNzaW9uLlxuICAgKiBAcGFyYW0ge3tzZXNzaW9uSWQ6IHN0cmluZywgd29ya2VySGFuZGxlcjogV29ya2VySGFuZGxlciB8IEluUHJvY2Vzc0hhbmRsZXJ9fSBhcmdzIC0gT3duZXJzaGlwIGNsYWltLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIGNsYWltV2Vic29ja2V0U2Vzc2lvbih7c2Vzc2lvbklkLCB3b3JrZXJIYW5kbGVyfSkge1xuICAgIGlmICghdGhpcy53b3JrZXJIYW5kbGVycy5pbmNsdWRlcyh3b3JrZXJIYW5kbGVyKSkgcmV0dXJuXG4gICAgdGhpcy53ZWJzb2NrZXRTZXNzaW9uT3duZXJzLnNldChzZXNzaW9uSWQsIHdvcmtlckhhbmRsZXIpXG4gIH1cblxuICAvKipcbiAgICogUmVsZWFzZXMgYSBzZXNzaW9uIG9ubHkgd2hlbiB0aGUgcmVsZWFzaW5nIHdvcmtlciBzdGlsbCBvd25zIGl0LlxuICAgKiBAcGFyYW0ge3tzZXNzaW9uSWQ6IHN0cmluZywgd29ya2VySGFuZGxlcjogV29ya2VySGFuZGxlciB8IEluUHJvY2Vzc0hhbmRsZXJ9fSBhcmdzIC0gT3duZXJzaGlwIHJlbGVhc2UuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgcmVsZWFzZVdlYnNvY2tldFNlc3Npb24oe3Nlc3Npb25JZCwgd29ya2VySGFuZGxlcn0pIHtcbiAgICBpZiAodGhpcy53ZWJzb2NrZXRTZXNzaW9uT3duZXJzLmdldChzZXNzaW9uSWQpID09PSB3b3JrZXJIYW5kbGVyKSB0aGlzLndlYnNvY2tldFNlc3Npb25Pd25lcnMuZGVsZXRlKHNlc3Npb25JZClcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWxlYXNlcyBldmVyeSBzZXNzaW9uIG93bmVkIGJ5IGEgd29ya2VyIGxlYXZpbmcgc2VydmljZS5cbiAgICogQHBhcmFtIHtXb3JrZXJIYW5kbGVyIHwgSW5Qcm9jZXNzSGFuZGxlcn0gd29ya2VySGFuZGxlciAtIFdvcmtlciBsZWF2aW5nIHNlcnZpY2UuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgcmVsZWFzZVdlYnNvY2tldFNlc3Npb25zRm9yV29ya2VyKHdvcmtlckhhbmRsZXIpIHtcbiAgICBmb3IgKGNvbnN0IFtzZXNzaW9uSWQsIG93bmVyXSBvZiB0aGlzLndlYnNvY2tldFNlc3Npb25Pd25lcnMpIHtcbiAgICAgIGlmIChvd25lciA9PT0gd29ya2VySGFuZGxlcikgdGhpcy53ZWJzb2NrZXRTZXNzaW9uT3duZXJzLmRlbGV0ZShzZXNzaW9uSWQpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE9uIGNsaWVudCBjbG9zZS5cbiAgICogQHBhcmFtIHtTZXJ2ZXJDbGllbnR9IGNsaWVudCAtIENsaWVudCBpbnN0YW5jZS5cbiAgICogQHJldHVybnMge3ZvaWR9IC0gTm8gcmV0dXJuIHZhbHVlLlxuICAgKi9cbiAgb25DbGllbnRDbG9zZSA9IChjbGllbnQpID0+IHtcbiAgICBjb25zdCBjbGllbnRDb3VudCA9IGRpZ2coY2xpZW50LCBcImNsaWVudENvdW50XCIpXG4gICAgY29uc3Qgb2xkQ2xpZW50c0xlbmd0aCA9IE9iamVjdC5rZXlzKHRoaXMuY2xpZW50cykubGVuZ3RoXG5cbiAgICBkZWxldGUgdGhpcy5jbGllbnRzW2NsaWVudENvdW50XVxuXG4gICAgY29uc3QgbmV3Q2xpZW50c0xlbmd0aCA9IE9iamVjdC5rZXlzKHRoaXMuY2xpZW50cykubGVuZ3RoXG5cbiAgICBpZiAobmV3Q2xpZW50c0xlbmd0aCAhPSAob2xkQ2xpZW50c0xlbmd0aCAtIDEpKSB7XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihgRXhwZWN0ZWQgY2xpZW50IHRvIGhhdmUgYmVlbiByZW1vdmVkIGJ1dCBsZW5ndGggZGlkbid0IGNoYW5nZSBmcm9tICR7b2xkQ2xpZW50c0xlbmd0aH0gdG8gJHtvbGRDbGllbnRzTGVuZ3RoIC0gMX1gKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHNwYXduIHdvcmtlci5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBjb21wbGV0ZS5cbiAgICovXG4gIGFzeW5jIHNwYXduV29ya2VyKCkge1xuICAgIGNvbnN0IHdvcmtlckhhbmRsZXIgPSBhd2FpdCB0aGlzLl9idWlsZFdvcmtlckhhbmRsZXIoKVxuXG4gICAgdGhpcy53b3JrZXJIYW5kbGVycy5wdXNoKHdvcmtlckhhbmRsZXIpXG4gIH1cblxuICAvKipcbiAgICogUnVucyBidWlsZCB3b3JrZXIgaGFuZGxlcnMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPEFycmF5PFdvcmtlckhhbmRsZXIgfCBJblByb2Nlc3NIYW5kbGVyPj59IC0gU3RhcnRlZCB3b3JrZXIgaGFuZGxlcnMuXG4gICAqL1xuICBhc3luYyBfYnVpbGRXb3JrZXJIYW5kbGVycygpIHtcbiAgICAvKipcbiAgICAgKiBXb3JrZXIgaGFuZGxlcnMuXG4gICAgICogQHR5cGUge0FycmF5PFdvcmtlckhhbmRsZXIgfCBJblByb2Nlc3NIYW5kbGVyPn0gKi9cbiAgICBjb25zdCB3b3JrZXJIYW5kbGVycyA9IFtdXG5cbiAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgdGhpcy5lZmZlY3RpdmVXb3JrZXJzOyBpbmRleCArPSAxKSB7XG4gICAgICB3b3JrZXJIYW5kbGVycy5wdXNoKGF3YWl0IHRoaXMuX2J1aWxkV29ya2VySGFuZGxlcigpKVxuICAgIH1cblxuICAgIHJldHVybiB3b3JrZXJIYW5kbGVyc1xuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgYnVpbGQgd29ya2VyIGhhbmRsZXIuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFdvcmtlckhhbmRsZXIgfCBJblByb2Nlc3NIYW5kbGVyPn0gLSBTdGFydGVkIHdvcmtlciBoYW5kbGVyLlxuICAgKi9cbiAgYXN5bmMgX2J1aWxkV29ya2VySGFuZGxlcigpIHtcbiAgICBjb25zdCB3b3JrZXJDb3VudCA9IHRoaXMud29ya2VyQ291bnRcblxuICAgIHRoaXMud29ya2VyQ291bnQrK1xuXG4gICAgY29uc3QgSGFuZGxlciA9IHRoaXMuaW5Qcm9jZXNzID8gSW5Qcm9jZXNzSGFuZGxlciA6IFdvcmtlckhhbmRsZXJcbiAgICBjb25zdCB3b3JrZXJIYW5kbGVyID0gdGhpcy53b3JrZXJIYW5kbGVyRmFjdG9yeVxuICAgICAgPyB0aGlzLndvcmtlckhhbmRsZXJGYWN0b3J5KHtcbiAgICAgICAgY29uZmlndXJhdGlvbjogdGhpcy5jb25maWd1cmF0aW9uLFxuICAgICAgICBvbldlYnNvY2tldFNlc3Npb25Pd25lZDogKHtzZXNzaW9uSWQsIHdvcmtlckhhbmRsZXJ9KSA9PiB0aGlzLmNsYWltV2Vic29ja2V0U2Vzc2lvbih7c2Vzc2lvbklkLCB3b3JrZXJIYW5kbGVyfSksXG4gICAgICAgIG9uV2Vic29ja2V0U2Vzc2lvblJlbGVhc2VkOiAoe3Nlc3Npb25JZCwgd29ya2VySGFuZGxlcn0pID0+IHRoaXMucmVsZWFzZVdlYnNvY2tldFNlc3Npb24oe3Nlc3Npb25JZCwgd29ya2VySGFuZGxlcn0pLFxuICAgICAgICBvbldvcmtlclN0b3BwZWQ6ICh7d29ya2VySGFuZGxlcn0pID0+IHRoaXMucmVsZWFzZVdlYnNvY2tldFNlc3Npb25zRm9yV29ya2VyKHdvcmtlckhhbmRsZXIpLFxuICAgICAgICB3b3JrZXJDb3VudFxuICAgICAgfSlcbiAgICAgIDogbmV3IEhhbmRsZXIoe1xuICAgICAgICBjb25maWd1cmF0aW9uOiB0aGlzLmNvbmZpZ3VyYXRpb24sXG4gICAgICAgIG9uV2Vic29ja2V0U2Vzc2lvbk93bmVkOiAoe3Nlc3Npb25JZCwgd29ya2VySGFuZGxlcn0pID0+IHRoaXMuY2xhaW1XZWJzb2NrZXRTZXNzaW9uKHtzZXNzaW9uSWQsIHdvcmtlckhhbmRsZXJ9KSxcbiAgICAgICAgb25XZWJzb2NrZXRTZXNzaW9uUmVsZWFzZWQ6ICh7c2Vzc2lvbklkLCB3b3JrZXJIYW5kbGVyfSkgPT4gdGhpcy5yZWxlYXNlV2Vic29ja2V0U2Vzc2lvbih7c2Vzc2lvbklkLCB3b3JrZXJIYW5kbGVyfSksXG4gICAgICAgIG9uV29ya2VyU3RvcHBlZDogKHt3b3JrZXJIYW5kbGVyfSkgPT4gdGhpcy5yZWxlYXNlV2Vic29ja2V0U2Vzc2lvbnNGb3JXb3JrZXIod29ya2VySGFuZGxlciksXG4gICAgICAgIHdvcmtlckNvdW50XG4gICAgICB9KVxuXG4gICAgYXdhaXQgd29ya2VySGFuZGxlci5zdGFydCgpXG5cbiAgICByZXR1cm4gd29ya2VySGFuZGxlclxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgd29ya2VyIGhhbmRsZXIgdG8gdXNlLlxuICAgKiBAcmV0dXJucyB7V29ya2VySGFuZGxlciB8IEluUHJvY2Vzc0hhbmRsZXJ9IC0gVGhlIHdvcmtlciBoYW5kbGVyIHRvIHVzZS5cbiAgICovXG4gIHdvcmtlckhhbmRsZXJUb1VzZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fbmV4dFJvdW5kUm9iaW5Xb3JrZXJIYW5kbGVyKClcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIG5leHQgcm91bmQgcm9iaW4gd29ya2VyIGhhbmRsZXIuXG4gICAqIEByZXR1cm5zIHtXb3JrZXJIYW5kbGVyIHwgSW5Qcm9jZXNzSGFuZGxlcn0gLSBUaGUgbmV4dCByb3VuZC1yb2JpbiB3b3JrZXIgaGFuZGxlci5cbiAgICovXG4gIF9uZXh0Um91bmRSb2JpbldvcmtlckhhbmRsZXIoKSB7XG4gICAgdGhpcy5sb2dnZXIuZGVidWcoYFdvcmtlciBoYW5kbGVycyBsZW5ndGg6ICR7dGhpcy53b3JrZXJIYW5kbGVycy5sZW5ndGh9YClcblxuICAgIGNvbnN0IHdvcmtlckhhbmRsZXJJbmRleCA9IHRoaXMubmV4dFdvcmtlckhhbmRsZXJJbmRleCAlIHRoaXMud29ya2VySGFuZGxlcnMubGVuZ3RoXG4gICAgY29uc3Qgd29ya2VySGFuZGxlciA9IHRoaXMud29ya2VySGFuZGxlcnNbd29ya2VySGFuZGxlckluZGV4XVxuXG4gICAgaWYgKCF3b3JrZXJIYW5kbGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIHdvcmtlckhhbmRsZXIgYnkgdGhhdCBudW1iZXI6ICR7d29ya2VySGFuZGxlckluZGV4fWApXG4gICAgfVxuXG4gICAgdGhpcy5uZXh0V29ya2VySGFuZGxlckluZGV4ICs9IDFcblxuICAgIHJldHVybiB3b3JrZXJIYW5kbGVyXG4gIH1cblxuICAvKipcbiAgICogUnVucyBzaG91bGQgdXNlIGRldmVsb3BtZW50IGhvdCByZWxvYWQuXG4gICAqIEByZXR1cm5zIHtib29sZWFufSAtIFdoZXRoZXIgZGV2ZWxvcG1lbnQgd29ya2VyIGhvdCByZWxvYWQgc2hvdWxkIHJ1bi5cbiAgICovXG4gIHNob3VsZFVzZURldmVsb3BtZW50SG90UmVsb2FkKCkge1xuICAgIHJldHVybiAhdGhpcy5pblByb2Nlc3MgJiYgdGhpcy5jb25maWd1cmF0aW9uLmdldEVudmlyb25tZW50KCkgPT09IFwiZGV2ZWxvcG1lbnRcIlxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgc3RhcnQgZGV2ZWxvcG1lbnQgcmVsb2FkZXIuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gd2F0Y2hlciBzZXR1cCBmaW5pc2hlcy5cbiAgICovXG4gIGFzeW5jIF9zdGFydERldmVsb3BtZW50UmVsb2FkZXIoKSB7XG4gICAgaWYgKCF0aGlzLnNob3VsZFVzZURldmVsb3BtZW50SG90UmVsb2FkKCkpIHJldHVyblxuICAgIGlmICh0aGlzLmRldmVsb3BtZW50UmVsb2FkZXIpIHJldHVyblxuXG4gICAgY29uc3QgY3JlYXRlRGV2ZWxvcG1lbnRSZWxvYWRlciA9IHRoaXMuZGV2ZWxvcG1lbnRSZWxvYWRlckZhY3RvcnlcbiAgICAgIHx8ICgoYXJncykgPT4gbmV3IERldmVsb3BtZW50UmVsb2FkZXIoYXJncykpXG5cbiAgICB0aGlzLmRldmVsb3BtZW50UmVsb2FkZXIgPSBjcmVhdGVEZXZlbG9wbWVudFJlbG9hZGVyKHtcbiAgICAgIGNvbmZpZ3VyYXRpb246IHRoaXMuY29uZmlndXJhdGlvbixcbiAgICAgIG9uUmVsb2FkOiBhc3luYyAoe2NoYW5nZWRQYXRofSkgPT4ge1xuICAgICAgICBhd2FpdCB0aGlzLmxvZ2dlci5pbmZvKGBEZXZlbG9wbWVudCBob3QgcmVsb2FkIGRldGVjdGVkIGNoYW5nZSBpbiAke2NoYW5nZWRQYXRofWApXG4gICAgICAgIGF3YWl0IHRoaXMucmVsb2FkV29ya2Vyc0ZvckRldmVsb3BtZW50KClcbiAgICAgIH1cbiAgICB9KVxuXG4gICAgYXdhaXQgdGhpcy5kZXZlbG9wbWVudFJlbG9hZGVyLnN0YXJ0KClcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHJlbG9hZCB3b3JrZXJzIGZvciBkZXZlbG9wbWVudC5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiB3b3JrZXJzIGhhdmUgYmVlbiByZWZyZXNoZWQuXG4gICAqL1xuICBhc3luYyByZWxvYWRXb3JrZXJzRm9yRGV2ZWxvcG1lbnQoKSB7XG4gICAgaWYgKHRoaXMuX3N0b3BwaW5nKSByZXR1cm5cblxuICAgIGlmICh0aGlzLl9yZWxvYWRpbmdXb3JrZXJzRm9yRGV2ZWxvcG1lbnQpIHtcbiAgICAgIHRoaXMuX3JlbG9hZFdvcmtlcnNGb3JEZXZlbG9wbWVudFF1ZXVlZCA9IHRydWVcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHRoaXMuX3JlbG9hZGluZ1dvcmtlcnNGb3JEZXZlbG9wbWVudCA9IHRydWVcblxuICAgIHRyeSB7XG4gICAgICBkbyB7XG4gICAgICAgIHRoaXMuX3JlbG9hZFdvcmtlcnNGb3JEZXZlbG9wbWVudFF1ZXVlZCA9IGZhbHNlXG5cbiAgICAgICAgY29uc3Qgb2xkV29ya2VySGFuZGxlcnMgPSBbLi4udGhpcy53b3JrZXJIYW5kbGVyc11cbiAgICAgICAgY29uc3QgbmV3V29ya2VySGFuZGxlcnMgPSBhd2FpdCB0aGlzLl9idWlsZFdvcmtlckhhbmRsZXJzKClcblxuICAgICAgICB0aGlzLndvcmtlckhhbmRsZXJzID0gbmV3V29ya2VySGFuZGxlcnNcbiAgICAgICAgdGhpcy5uZXh0V29ya2VySGFuZGxlckluZGV4ID0gMFxuICAgICAgICBmb3IgKGNvbnN0IHdvcmtlckhhbmRsZXIgb2Ygb2xkV29ya2VySGFuZGxlcnMpIHRoaXMucmVsZWFzZVdlYnNvY2tldFNlc3Npb25zRm9yV29ya2VyKHdvcmtlckhhbmRsZXIpXG5cbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwob2xkV29ya2VySGFuZGxlcnMubWFwKCh3b3JrZXJIYW5kbGVyKSA9PiB3b3JrZXJIYW5kbGVyLnN0b3AoKSkpXG4gICAgICB9IHdoaWxlICh0aGlzLl9yZWxvYWRXb3JrZXJzRm9yRGV2ZWxvcG1lbnRRdWV1ZWQgJiYgIXRoaXMuX3N0b3BwaW5nKVxuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLl9yZWxvYWRpbmdXb3JrZXJzRm9yRGV2ZWxvcG1lbnQgPSBmYWxzZVxuICAgIH1cbiAgfVxufVxuIl19
|
|
@@ -9,6 +9,17 @@ export default class VelociousHttpServerWorker {
|
|
|
9
9
|
clients: Record<number, import("../server-client.js").default>;
|
|
10
10
|
logger: Logger;
|
|
11
11
|
workerCount: number;
|
|
12
|
+
onWebsocketSessionOwned: ((args: {
|
|
13
|
+
sessionId: string;
|
|
14
|
+
workerHandler: VelociousHttpServerWorker;
|
|
15
|
+
}) => void) | undefined;
|
|
16
|
+
onWebsocketSessionReleased: ((args: {
|
|
17
|
+
sessionId: string;
|
|
18
|
+
workerHandler: VelociousHttpServerWorker;
|
|
19
|
+
}) => void) | undefined;
|
|
20
|
+
onWorkerStopped: ((args: {
|
|
21
|
+
workerHandler: VelociousHttpServerWorker;
|
|
22
|
+
}) => void) | undefined;
|
|
12
23
|
workerStarted: boolean;
|
|
13
24
|
_stopping: boolean;
|
|
14
25
|
_debugRequestId: number;
|
|
@@ -30,10 +41,24 @@ export default class VelociousHttpServerWorker {
|
|
|
30
41
|
* @param {object} args - Options object.
|
|
31
42
|
* @param {import("../../configuration.js").default} args.configuration - Configuration instance.
|
|
32
43
|
* @param {number} args.workerCount - Worker count.
|
|
44
|
+
* @param {(args: {sessionId: string, workerHandler: VelociousHttpServerWorker}) => void} [args.onWebsocketSessionOwned] - Session ownership callback.
|
|
45
|
+
* @param {(args: {sessionId: string, workerHandler: VelociousHttpServerWorker}) => void} [args.onWebsocketSessionReleased] - Session ownership release callback.
|
|
46
|
+
* @param {(args: {workerHandler: VelociousHttpServerWorker}) => void} [args.onWorkerStopped] - Worker lifecycle callback.
|
|
33
47
|
*/
|
|
34
|
-
constructor({ configuration, workerCount }: {
|
|
48
|
+
constructor({ configuration, onWebsocketSessionOwned, onWebsocketSessionReleased, onWorkerStopped, workerCount }: {
|
|
35
49
|
configuration: import("../../configuration.js").default;
|
|
36
50
|
workerCount: number;
|
|
51
|
+
onWebsocketSessionOwned?: (args: {
|
|
52
|
+
sessionId: string;
|
|
53
|
+
workerHandler: VelociousHttpServerWorker;
|
|
54
|
+
}) => void;
|
|
55
|
+
onWebsocketSessionReleased?: (args: {
|
|
56
|
+
sessionId: string;
|
|
57
|
+
workerHandler: VelociousHttpServerWorker;
|
|
58
|
+
}) => void;
|
|
59
|
+
onWorkerStopped?: (args: {
|
|
60
|
+
workerHandler: VelociousHttpServerWorker;
|
|
61
|
+
}) => void;
|
|
37
62
|
});
|
|
38
63
|
start(): Promise<any>;
|
|
39
64
|
_spawnWorker(): Promise<void>;
|
|
@@ -76,6 +101,7 @@ export default class VelociousHttpServerWorker {
|
|
|
76
101
|
* @param {number} [data.transferId] - File transfer id.
|
|
77
102
|
* @param {boolean} [data.websocketFrame] - Whether output is a completed WebSocket frame.
|
|
78
103
|
* @param {string} [data.channel] - Channel name.
|
|
104
|
+
* @param {string} [data.sessionId] - WebSocket session identity.
|
|
79
105
|
* @param {number} [data.requestId] - Debug request id.
|
|
80
106
|
* @param {Record<string, ReturnType<typeof JSON.parse>>} [data.snapshot] - Worker debug snapshot.
|
|
81
107
|
* @param {ReturnType<typeof JSON.parse>} [data.payload] - Payload data.
|
|
@@ -92,6 +118,7 @@ export default class VelociousHttpServerWorker {
|
|
|
92
118
|
transferId?: number;
|
|
93
119
|
websocketFrame?: boolean;
|
|
94
120
|
channel?: string;
|
|
121
|
+
sessionId?: string;
|
|
95
122
|
requestId?: number;
|
|
96
123
|
snapshot?: Record<string, ReturnType<typeof JSON.parse>>;
|
|
97
124
|
payload?: ReturnType<typeof JSON.parse>;
|