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.
Files changed (81) hide show
  1. package/README.md +15 -3
  2. package/build/background-jobs/job-runner.js +9 -1
  3. package/build/background-jobs/local-dispatcher.js +23 -1
  4. package/build/background-jobs/main.js +6 -4
  5. package/build/background-jobs/perform-job.js +10 -1
  6. package/build/background-jobs/platform-job.js +62 -0
  7. package/build/background-jobs/runtime.js +6 -3
  8. package/build/background-jobs/types.js +8 -0
  9. package/build/background-jobs/worker.js +3 -1
  10. package/build/database/pool/async-tracked-multi-connection.js +46 -9
  11. package/build/database/pool/base.js +3 -0
  12. package/build/database/pool/checkout-timeout-error.js +16 -0
  13. package/build/http-client/websocket-client.js +52 -0
  14. package/build/http-server/client/index.js +6 -0
  15. package/build/http-server/client/websocket-session.js +30 -0
  16. package/build/http-server/index.js +202 -38
  17. package/build/http-server/worker-handler/index.js +15 -1
  18. package/build/http-server/worker-handler/worker-thread.js +8 -0
  19. package/build/src/background-jobs/job-runner.d.ts.map +1 -1
  20. package/build/src/background-jobs/job-runner.js +10 -2
  21. package/build/src/background-jobs/local-dispatcher.d.ts.map +1 -1
  22. package/build/src/background-jobs/local-dispatcher.js +24 -2
  23. package/build/src/background-jobs/main.d.ts.map +1 -1
  24. package/build/src/background-jobs/main.js +7 -5
  25. package/build/src/background-jobs/perform-job.d.ts +5 -1
  26. package/build/src/background-jobs/perform-job.d.ts.map +1 -1
  27. package/build/src/background-jobs/perform-job.js +11 -2
  28. package/build/src/background-jobs/platform-job.d.ts +34 -0
  29. package/build/src/background-jobs/platform-job.d.ts.map +1 -1
  30. package/build/src/background-jobs/platform-job.js +56 -1
  31. package/build/src/background-jobs/runtime.d.ts.map +1 -1
  32. package/build/src/background-jobs/runtime.js +7 -4
  33. package/build/src/background-jobs/types.d.ts +30 -0
  34. package/build/src/background-jobs/types.d.ts.map +1 -1
  35. package/build/src/background-jobs/types.js +9 -1
  36. package/build/src/background-jobs/worker.d.ts.map +1 -1
  37. package/build/src/background-jobs/worker.js +4 -2
  38. package/build/src/database/pool/async-tracked-multi-connection.d.ts +22 -2
  39. package/build/src/database/pool/async-tracked-multi-connection.d.ts.map +1 -1
  40. package/build/src/database/pool/async-tracked-multi-connection.js +44 -10
  41. package/build/src/database/pool/base.d.ts +15 -0
  42. package/build/src/database/pool/base.d.ts.map +1 -1
  43. package/build/src/database/pool/base.js +4 -1
  44. package/build/src/database/pool/checkout-timeout-error.d.ts +13 -0
  45. package/build/src/database/pool/checkout-timeout-error.d.ts.map +1 -0
  46. package/build/src/database/pool/checkout-timeout-error.js +15 -0
  47. package/build/src/http-client/websocket-client.d.ts +18 -0
  48. package/build/src/http-client/websocket-client.d.ts.map +1 -1
  49. package/build/src/http-client/websocket-client.js +48 -1
  50. package/build/src/http-server/client/index.d.ts.map +1 -1
  51. package/build/src/http-server/client/index.js +7 -1
  52. package/build/src/http-server/client/websocket-session.d.ts +6 -0
  53. package/build/src/http-server/client/websocket-session.d.ts.map +1 -1
  54. package/build/src/http-server/client/websocket-session.js +27 -1
  55. package/build/src/http-server/index.d.ts +82 -10
  56. package/build/src/http-server/index.d.ts.map +1 -1
  57. package/build/src/http-server/index.js +186 -33
  58. package/build/src/http-server/worker-handler/index.d.ts +28 -1
  59. package/build/src/http-server/worker-handler/index.d.ts.map +1 -1
  60. package/build/src/http-server/worker-handler/index.js +23 -2
  61. package/build/src/http-server/worker-handler/worker-thread.d.ts.map +1 -1
  62. package/build/src/http-server/worker-handler/worker-thread.js +7 -1
  63. package/build/tsconfig.tsbuildinfo +1 -1
  64. package/package.json +1 -1
  65. package/src/background-jobs/job-runner.js +9 -1
  66. package/src/background-jobs/local-dispatcher.js +23 -1
  67. package/src/background-jobs/main.js +6 -4
  68. package/src/background-jobs/perform-job.js +10 -1
  69. package/src/background-jobs/platform-job.js +62 -0
  70. package/src/background-jobs/runtime.js +6 -3
  71. package/src/background-jobs/types.js +8 -0
  72. package/src/background-jobs/worker.js +3 -1
  73. package/src/database/pool/async-tracked-multi-connection.js +46 -9
  74. package/src/database/pool/base.js +3 -0
  75. package/src/database/pool/checkout-timeout-error.js +16 -0
  76. package/src/http-client/websocket-client.js +52 -0
  77. package/src/http-server/client/index.js +6 -0
  78. package/src/http-server/client/websocket-session.js +30 -0
  79. package/src/http-server/index.js +202 -38
  80. package/src/http-server/worker-handler/index.js +15 -1
  81. 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 ?? 1;
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
- * Sticky worker handlers.
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.stickyWorkerHandlers.clear();
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.workers) {
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.stickyWorkerHandlers.clear();
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.workers; index += 1) {
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({ configuration: this.configuration, workerCount })
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({ stickyKey } = {}) {
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
- this.stickyWorkerHandlers.clear();
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>;