@dbx-tools/appkit-lakebox 0.0.0-stage → 0.9.132

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 (55) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +197 -2
  3. package/index.ts +32 -0
  4. package/lib/index.d.ts +28 -0
  5. package/lib/index.js +26 -0
  6. package/lib/src/_package.d.ts +2 -0
  7. package/lib/src/_package.js +11 -0
  8. package/lib/src/_resource-registry.d.ts +41 -0
  9. package/lib/src/_resource-registry.js +128 -0
  10. package/lib/src/_service-snapshots.d.ts +55 -0
  11. package/lib/src/_service-snapshots.js +65 -0
  12. package/lib/src/config.d.ts +40 -0
  13. package/lib/src/config.js +86 -0
  14. package/lib/src/desktop.d.ts +6 -0
  15. package/lib/src/desktop.js +88 -0
  16. package/lib/src/metrics.d.ts +59 -0
  17. package/lib/src/metrics.js +151 -0
  18. package/lib/src/plugin.d.ts +259 -0
  19. package/lib/src/plugin.js +329 -0
  20. package/lib/src/routes.d.ts +75 -0
  21. package/lib/src/routes.js +441 -0
  22. package/lib/src/runtime.d.ts +154 -0
  23. package/lib/src/runtime.js +760 -0
  24. package/lib/src/services.d.ts +101 -0
  25. package/lib/src/services.js +188 -0
  26. package/lib/src/skills.d.ts +5 -0
  27. package/lib/src/skills.js +21 -0
  28. package/lib/src/user.d.ts +46 -0
  29. package/lib/src/user.js +76 -0
  30. package/lib/src/workspace.d.ts +43 -0
  31. package/lib/src/workspace.js +138 -0
  32. package/lib/tsconfig.tsbuildinfo +1 -0
  33. package/package.json +167 -4
  34. package/scripts/desktop-prerequisites.sh +66 -0
  35. package/scripts/desktop-session.sh +307 -0
  36. package/scripts/lakebox-admin.sh +234 -0
  37. package/scripts/lakebox-service.py +449 -0
  38. package/skills/html-page/SKILL.md +40 -0
  39. package/skills/jupyter-lab/SKILL.md +32 -0
  40. package/skills/lakebox-showcase/SKILL.md +66 -0
  41. package/skills/network-speed-test/SKILL.md +29 -0
  42. package/skills/realtime-whiteboard/SKILL.md +28 -0
  43. package/src/_package.ts +11 -0
  44. package/src/_resource-registry.ts +160 -0
  45. package/src/_service-snapshots.ts +84 -0
  46. package/src/config.ts +128 -0
  47. package/src/desktop.ts +97 -0
  48. package/src/metrics.ts +178 -0
  49. package/src/plugin.ts +446 -0
  50. package/src/routes.ts +524 -0
  51. package/src/runtime.ts +952 -0
  52. package/src/services.ts +239 -0
  53. package/src/skills.ts +23 -0
  54. package/src/user.ts +88 -0
  55. package/src/workspace.ts +185 -0
@@ -0,0 +1,760 @@
1
+ import { createHash } from "node:crypto";
2
+ import { exec } from "@dbx-tools/core";
3
+ import { SshKeyStore } from "@dbx-tools/lakebox/key-store";
4
+ import { ensureLakeboxRunning, ensureLakeboxStopped, lakeboxIdleTimeoutSeconds, normalizeLakeboxStatus, } from "@dbx-tools/lakebox/lifecycle";
5
+ import { isLakeboxUnavailable, LakeboxApiError, LakeboxClient, } from "@dbx-tools/lakebox/rest";
6
+ import { SshCommand, SshSession } from "@dbx-tools/lakebox/session";
7
+ import { errorUtils, log } from "@dbx-tools/shared-core";
8
+ import { LAKEBOX_BUILT_IN_SERVICES, lakeboxBuiltInServiceNameSchema, lakeboxCommandRequestSchema, lakeboxServiceLogsRequestSchema, } from "@dbx-tools/shared-lakebox";
9
+ import { readPackageResource } from "./_package.js";
10
+ import { stoppedSnapshotServices } from "./_service-snapshots.js";
11
+ import { LakeboxMetrics } from "./metrics.js";
12
+ import { LakeboxRouteRegistry } from "./routes.js";
13
+ import { builtInDefinition, idleBuiltInService, imageDefinition, LakeboxControllerServiceSchema, serviceRoute, toLakeboxService, } from "./services.js";
14
+ import { LAKEBOX_RUNTIME_ROOT, lakeboxUser } from "./user.js";
15
+ const ADMIN_SCRIPT = readPackageResource("scripts", "lakebox-admin.sh");
16
+ const HELPERS = {
17
+ "lakebox-service": readPackageResource("scripts", "lakebox-service.py"),
18
+ "desktop-session": readPackageResource("scripts", "desktop-session.sh"),
19
+ "desktop-prerequisites": readPackageResource("scripts", "desktop-prerequisites.sh"),
20
+ };
21
+ const CONTROLLER = `${LAKEBOX_RUNTIME_ROOT}/bin/lakebox-service`;
22
+ const ENTRY_TTL_MS = 5_000;
23
+ const SETUP_TIMEOUT_MS = 600_000;
24
+ const METRICS_LEASE_MS = 60_000;
25
+ const IDLE_CHECK_MS = 30_000;
26
+ const SSH_KEY_OWNER = "app-service-principal";
27
+ const LEGACY_NAME = /^dbx-(?!lakebox-)[a-z]+-[a-z]+-[0-9a-f]{8}(?:_uid_[A-Za-z0-9_-]+_exp_[0-9]+)?$/;
28
+ const LEGACY_SCHEMA_PREFIX = "dbx_tools_databricks_sandbox";
29
+ const logger = log.logger("appkit-lakebox:runtime");
30
+ /**
31
+ * Owns the single lazily created Lakebox of one application.
32
+ *
33
+ * Every Databricks Lakebox REST call uses the app service principal supplied
34
+ * through {@link initialize}; request identity only selects the internal Linux
35
+ * account. Each authenticated identity maps through one FNV-1a hash to a locked
36
+ * account, persistent home, route segment, and service ports. Lifecycle and
37
+ * per-boot bootstrap are serialized in-process; the persistent resource
38
+ * registry serializes first creation across replicas.
39
+ */
40
+ export class LakeboxRuntime {
41
+ config;
42
+ routes;
43
+ metrics;
44
+ keys;
45
+ stopParentTerminationSignal;
46
+ shutdownController = new AbortController();
47
+ api;
48
+ identity = () => undefined;
49
+ /** In-memory identities of routed users; never persisted. */
50
+ routedIdentities = new Map();
51
+ cached;
52
+ boot;
53
+ /** Last boot that completed runtime bootstrap and produced a metrics sample. */
54
+ readyBootKey;
55
+ converging;
56
+ waking;
57
+ metricsLease;
58
+ idleTimer;
59
+ lastActivity = Date.now();
60
+ activeCommands = 0;
61
+ /** Last service states per user hash, kept after an idle session release. */
62
+ lastServices = new Map();
63
+ lastServicesObservedAt = new Map();
64
+ resourceRegistry;
65
+ serviceSnapshots;
66
+ closing;
67
+ /** Creates a runtime from resolved plugin configuration. */
68
+ constructor(config) {
69
+ this.config = config;
70
+ this.keys = new SshKeyStore(config.keyDirectory);
71
+ this.routes = new LakeboxRouteRegistry(config.routePrefix, {
72
+ user: (headers) => {
73
+ const identity = this.identity(headers);
74
+ if (!identity)
75
+ return undefined;
76
+ const user = this.user(identity);
77
+ this.routedIdentities.set(user.hash, identity);
78
+ return user;
79
+ },
80
+ resolve: (user, service) => this.resolveRoute(user, service),
81
+ unavailable: (user, service) => this.markUnavailable(user, service),
82
+ });
83
+ this.metrics = new LakeboxMetrics((signal) => this.readMetrics(signal), config.metricsIntervalSeconds * 1_000);
84
+ this.stopParentTerminationSignal = exec.onParentTerminationSignal(() => this.routes.beginShutdown());
85
+ }
86
+ /**
87
+ * Supplies app service-principal credentials and the request identity
88
+ * resolver used by routes.
89
+ */
90
+ initialize(auth, identity, serviceSnapshots, resourceRegistry) {
91
+ this.api = new LakeboxClient(auth);
92
+ if (identity)
93
+ this.identity = identity;
94
+ if (serviceSnapshots)
95
+ this.serviceSnapshots = serviceSnapshots;
96
+ if (resourceRegistry)
97
+ this.resourceRegistry = resourceRegistry;
98
+ }
99
+ /** Derives the Lakebox account for one authenticated identity. */
100
+ user(identity) {
101
+ return lakeboxUser(identity, this.config.routePrefix);
102
+ }
103
+ /** Summarizes the app Lakebox for one user without creating it. */
104
+ async summary(identity, signal) {
105
+ const user = this.user(identity);
106
+ const base = { auto: this.config.auto, name: "Lakebox", user };
107
+ let entry;
108
+ try {
109
+ entry = await this.entry(signal, true);
110
+ }
111
+ catch (error) {
112
+ if (isLakeboxUnavailable(error)) {
113
+ return {
114
+ ...base,
115
+ supported: false,
116
+ status: "missing",
117
+ services: [],
118
+ servicesStale: false,
119
+ canStart: false,
120
+ canStop: false,
121
+ };
122
+ }
123
+ throw error;
124
+ }
125
+ const platformStatus = entry ? normalizeLakeboxStatus(entry.status) : "missing";
126
+ const status = this.productStatus(entry, platformStatus);
127
+ if (entry && platformStatus === "running" && status === "starting") {
128
+ this.wake(() => this.ready());
129
+ }
130
+ const listing = await this.serviceListing(identity, user, entry, status, signal);
131
+ return {
132
+ ...base,
133
+ supported: true,
134
+ status,
135
+ ...(entry ? { id: entry.sandboxId } : {}),
136
+ ...(lakeboxIdleTimeoutSeconds(entry?.idleTimeout) !== undefined
137
+ ? { idleTimeoutSeconds: lakeboxIdleTimeoutSeconds(entry?.idleTimeout) }
138
+ : {}),
139
+ services: listing.services,
140
+ servicesStale: listing.stale,
141
+ ...(listing.observedAt ? { servicesObservedAt: listing.observedAt } : {}),
142
+ canStart: status !== "running" && status !== "starting",
143
+ canStop: status === "running" || status === "starting",
144
+ };
145
+ }
146
+ /** Creates the Lakebox when needed, starts it, and restores saved services. */
147
+ async start(signal) {
148
+ await this.ready(signal, true);
149
+ }
150
+ /** Stops the shared Lakebox for every user. Files and saved services persist. */
151
+ async stop(signal) {
152
+ const entry = await this.entry(signal, true);
153
+ if (!entry)
154
+ return;
155
+ await this.discardBoot();
156
+ await ensureLakeboxStopped(this.client(), entry, signal);
157
+ this.cached = undefined;
158
+ }
159
+ /** Permanently deletes the managed Lakebox and every user's files. */
160
+ async delete(signal) {
161
+ const entry = await this.entry(signal, true);
162
+ if (!entry)
163
+ return false;
164
+ await this.discardBoot();
165
+ await this.client().delete(entry.sandboxId, signal);
166
+ await this.resources().clear(this.client());
167
+ this.readyBootKey = undefined;
168
+ this.cached = { at: Date.now() };
169
+ return true;
170
+ }
171
+ /**
172
+ * Runs one command as the user's account, creating or starting the Lakebox
173
+ * when `auto` is enabled.
174
+ */
175
+ execute(identity, input, signal) {
176
+ const request = lakeboxCommandRequestSchema.parse(input);
177
+ const timeoutMs = request.timeoutMs ?? this.config.commandTimeoutMs;
178
+ const user = this.user(identity);
179
+ return new SshCommand(request.command, request.args, { timeoutMs, signal }, async (execution) => {
180
+ const boot = await this.readyUser(user, identity, execution.signal);
181
+ this.activeCommands += 1;
182
+ try {
183
+ return await execution.follow(boot.session.execute(request.command, request.args, {
184
+ user,
185
+ ...(request.cwd ? { cwd: request.cwd } : {}),
186
+ ...(request.env ? { env: request.env } : {}),
187
+ timeoutMs,
188
+ signal: execution.signal,
189
+ }));
190
+ }
191
+ finally {
192
+ this.activeCommands -= 1;
193
+ this.touch();
194
+ }
195
+ });
196
+ }
197
+ /** Lists the user's services, including idle built-ins. Never creates the Lakebox. */
198
+ async listServices(identity, signal) {
199
+ const user = this.user(identity);
200
+ const entry = await this.entry(signal);
201
+ const status = entry ? normalizeLakeboxStatus(entry.status) : "missing";
202
+ return (await this.serviceListing(identity, user, entry, status, signal)).services;
203
+ }
204
+ /** Creates or replaces one image service and waits until it is ready or failed. */
205
+ async createService(identity, input, signal) {
206
+ const user = this.user(identity);
207
+ const definition = imageDefinition(input, user);
208
+ const boot = await this.readyUser(user, identity, signal);
209
+ await this.controller(boot, user, "put", [encode(definition)], signal);
210
+ return this.runService(boot, user, definition, signal);
211
+ }
212
+ /** Starts a saved service or a built-in and waits until it is ready or failed. */
213
+ async startService(identity, name, signal) {
214
+ const user = this.user(identity);
215
+ const boot = await this.readyUser(user, identity, signal);
216
+ const builtIn = lakeboxBuiltInServiceNameSchema.safeParse(name);
217
+ if (builtIn.success) {
218
+ const definition = builtInDefinition(builtIn.data, user);
219
+ await this.controller(boot, user, "put", [encode(definition)], signal);
220
+ return this.runService(boot, user, definition, signal);
221
+ }
222
+ const saved = (await this.refreshServices(boot, user, identity, signal)).get(name);
223
+ if (!saved)
224
+ throw new Error(`Lakebox service ${name} does not exist`);
225
+ return this.runService(boot, user, saved.definition, signal);
226
+ }
227
+ /** Stops one running service without removing its definition. */
228
+ async stopService(identity, name, signal) {
229
+ const user = this.user(identity);
230
+ const boot = await this.readyUser(user, identity, signal);
231
+ const stopped = LakeboxControllerServiceSchema.parse(await this.controller(boot, user, "stop", [name], signal));
232
+ this.cacheService(boot, user, stopped);
233
+ return toLakeboxService(stopped, user, this.config.routePrefix);
234
+ }
235
+ /** Stops and deletes one saved service. Mounted home directories are preserved. */
236
+ async removeService(identity, name, signal) {
237
+ const user = this.user(identity);
238
+ const boot = await this.readyUser(user, identity, signal);
239
+ const result = (await this.controller(boot, user, "remove", [name], signal));
240
+ if (result.removed === true)
241
+ await this.refreshServices(boot, user, identity, signal);
242
+ return result.removed === true;
243
+ }
244
+ /** Reads a bounded tail of one service log. */
245
+ async serviceLogs(identity, input, signal) {
246
+ const request = lakeboxServiceLogsRequestSchema.parse(input);
247
+ const user = this.user(identity);
248
+ const entry = await this.entry(signal);
249
+ if (!entry || normalizeLakeboxStatus(entry.status) !== "running")
250
+ return { log: "" };
251
+ const boot = await this.readyUser(user, identity, signal);
252
+ const result = (await this.controller(boot, user, "logs", [request.name, String(request.maxLines), String(request.maxChars)], signal));
253
+ return { log: result.log ?? "" };
254
+ }
255
+ /**
256
+ * Returns recent metrics and keeps sampling for one lease interval. Sampling
257
+ * runs only while the Lakebox runs and a caller is watching, so metrics never
258
+ * keep an otherwise idle Lakebox awake.
259
+ */
260
+ async metricsResponse(signal) {
261
+ const entry = await this.entry(signal);
262
+ const platformStatus = entry ? normalizeLakeboxStatus(entry.status) : "missing";
263
+ if (platformStatus !== "running") {
264
+ this.metrics.stop();
265
+ return { status: platformStatus, series: [] };
266
+ }
267
+ if (!entry || !this.boot || this.boot.key !== this.bootKey(entry)) {
268
+ this.metrics.stop();
269
+ this.wake(() => this.ready());
270
+ return { status: "starting", series: [] };
271
+ }
272
+ this.leaseMetrics();
273
+ return {
274
+ status: this.productStatus(entry, platformStatus),
275
+ series: [...this.metrics.series()],
276
+ };
277
+ }
278
+ /** Subscribes to metrics snapshots while the Lakebox runs. */
279
+ subscribeMetrics(listener) {
280
+ this.metrics.on("snapshot", listener);
281
+ if (this.boot?.key === this.readyBootKey)
282
+ this.metrics.start();
283
+ return () => {
284
+ this.metrics.off("snapshot", listener);
285
+ this.leaseMetrics();
286
+ };
287
+ }
288
+ /**
289
+ * Deletes legacy per-user Lakeboxes and drops legacy ownership schemas.
290
+ *
291
+ * There is no migration: the earlier one-machine-per-user model is removed.
292
+ * The managed app Lakebox and Lakeboxes with other names are never touched.
293
+ */
294
+ async cleanupLegacy(pool, signal) {
295
+ try {
296
+ const entries = await this.client().list(signal);
297
+ await Promise.all(entries
298
+ .filter((entry) => entry.name && LEGACY_NAME.test(entry.name))
299
+ .map(async (entry) => {
300
+ await this.client().delete(entry.sandboxId, signal);
301
+ logger.info("deleted legacy per-user Lakebox", {
302
+ id: entry.sandboxId,
303
+ name: entry.name,
304
+ });
305
+ }));
306
+ }
307
+ catch (error) {
308
+ if (!isLakeboxUnavailable(error)) {
309
+ logger.warn("legacy Lakebox cleanup failed", { error: errorUtils.toError(error) });
310
+ }
311
+ }
312
+ if (!pool)
313
+ return;
314
+ try {
315
+ const schemas = await pool.query("SELECT nspname FROM pg_namespace WHERE nspname = $1 OR starts_with(nspname, $2)", [LEGACY_SCHEMA_PREFIX, `${LEGACY_SCHEMA_PREFIX}_`]);
316
+ for (const row of schemas.rows) {
317
+ const schema = String(row.nspname);
318
+ await pool.query(`DROP SCHEMA IF EXISTS "${schema.replaceAll('"', '""')}" CASCADE`);
319
+ logger.info("dropped legacy Lakebox ownership schema", { schema });
320
+ }
321
+ }
322
+ catch (error) {
323
+ logger.warn("legacy ownership schema cleanup failed", { error: errorUtils.toError(error) });
324
+ }
325
+ }
326
+ /** Cancels in-flight work before teardown. */
327
+ abortActiveOperations() {
328
+ if (!this.shutdownController.signal.aborted)
329
+ this.shutdownController.abort();
330
+ }
331
+ /** Closes routes, metrics, and the SSH session without changing the Lakebox. */
332
+ close() {
333
+ this.abortActiveOperations();
334
+ this.routes.beginShutdown();
335
+ this.closing ??= (async () => {
336
+ try {
337
+ if (this.metricsLease)
338
+ clearTimeout(this.metricsLease);
339
+ this.metrics.stop();
340
+ await this.routes.close();
341
+ await this.boot?.session.close();
342
+ this.boot = undefined;
343
+ }
344
+ finally {
345
+ this.stopParentTerminationSignal();
346
+ }
347
+ })();
348
+ return this.closing;
349
+ }
350
+ client() {
351
+ if (!this.api)
352
+ throw new Error("The Lakebox runtime has no app service-principal credentials");
353
+ return this.api;
354
+ }
355
+ resources() {
356
+ if (!this.resourceRegistry)
357
+ throw new Error("The Lakebox runtime has no resource registry");
358
+ return this.resourceRegistry;
359
+ }
360
+ /** Returns the managed Lakebox entry, cached briefly to keep routes cheap. */
361
+ async entry(signal, fresh = false) {
362
+ if (!fresh && this.cached && Date.now() - this.cached.at < ENTRY_TTL_MS) {
363
+ return this.cached.entry;
364
+ }
365
+ const entry = await this.resources().read(this.client(), signal);
366
+ this.cached = { ...(entry ? { entry } : {}), at: Date.now() };
367
+ if (!entry || normalizeLakeboxStatus(entry.status) !== "running") {
368
+ this.readyBootKey = undefined;
369
+ }
370
+ if (this.boot && (!entry || this.bootKey(entry) !== this.boot.key))
371
+ await this.discardBoot();
372
+ return entry;
373
+ }
374
+ bootKey(entry) {
375
+ return `${entry.sandboxId}\0${entry.lastStartTime ?? ""}`;
376
+ }
377
+ productStatus(entry, status) {
378
+ return entry && status === "running" && this.readyBootKey !== this.bootKey(entry)
379
+ ? "starting"
380
+ : status;
381
+ }
382
+ /** Serializes create, start, connect, and bootstrap for the current boot. */
383
+ ready(signal, explicit = false) {
384
+ const current = this.boot;
385
+ if (current && this.cached?.entry && this.bootKey(this.cached.entry) === current.key) {
386
+ if (Date.now() - this.cached.at < ENTRY_TTL_MS)
387
+ return Promise.resolve(current);
388
+ }
389
+ this.converging ??= this.converge(signal, explicit).finally(() => {
390
+ this.converging = undefined;
391
+ });
392
+ return this.converging;
393
+ }
394
+ async converge(signal, explicit) {
395
+ const operationSignal = signal
396
+ ? AbortSignal.any([signal, this.shutdownController.signal])
397
+ : this.shutdownController.signal;
398
+ let entry = await this.entry(operationSignal, true);
399
+ if (!entry || normalizeLakeboxStatus(entry.status) !== "running") {
400
+ if (!this.config.auto && !explicit) {
401
+ throw new Error(`Lakebox is ${entry ? entry.status : "not created"}; start it explicitly because auto is false`);
402
+ }
403
+ }
404
+ entry ??= await this.resources().getOrCreate(this.client(), operationSignal);
405
+ if (lakeboxIdleTimeoutSeconds(entry.idleTimeout) !== this.config.idleTimeoutSeconds) {
406
+ entry = await this.client().setIdleTimeout(entry.sandboxId, this.config.idleTimeoutSeconds, operationSignal);
407
+ }
408
+ entry = await ensureLakeboxRunning(this.client(), entry, operationSignal);
409
+ this.cached = { entry, at: Date.now() };
410
+ const key = this.bootKey(entry);
411
+ if (this.boot?.key === key)
412
+ return this.boot;
413
+ await this.discardBoot();
414
+ const session = await this.connect(entry, operationSignal);
415
+ const boot = {
416
+ key,
417
+ entry,
418
+ session,
419
+ users: new Map(),
420
+ services: new Map(),
421
+ starting: new Map(),
422
+ };
423
+ try {
424
+ const restored = await this.bootstrap(session, operationSignal);
425
+ this.metrics.stop();
426
+ this.metrics.seed((await this.admin(session, ["metrics"], operationSignal)).stdout);
427
+ this.boot = boot;
428
+ this.readyBootKey = key;
429
+ this.watchIdle();
430
+ if (this.metrics.listenerCount("snapshot") > 0)
431
+ this.metrics.start();
432
+ for (const hash of restored)
433
+ void this.restoreUser(boot, hash);
434
+ return boot;
435
+ }
436
+ catch (error) {
437
+ await session.close();
438
+ throw error;
439
+ }
440
+ }
441
+ async connect(entry, signal) {
442
+ const api = this.client();
443
+ const scope = await api.workspaceScope();
444
+ const key = await this.keys.ensureRegistered(api, SSH_KEY_OWNER, signal);
445
+ const gatewayHost = entry.gatewayHost ?? key.gatewayHost;
446
+ if (!gatewayHost)
447
+ throw new Error("Databricks Lakebox did not return an SSH gateway host");
448
+ const port = this.config.gatewayPort;
449
+ const knownHost = await this.keys.knownHost(scope, SSH_KEY_OWNER, gatewayHost, port);
450
+ const session = new SshSession({
451
+ host: gatewayHost,
452
+ port,
453
+ username: entry.sandboxId,
454
+ privateKey: key.privateKey,
455
+ privateKeyPath: key.privateKeyPath,
456
+ knownHostsPath: this.keys.knownHostsPath(scope, SSH_KEY_OWNER, gatewayHost, port),
457
+ connectTimeoutMs: this.config.connectTimeoutMs,
458
+ sshTransport: this.config.sshTransport,
459
+ ssh2Patch: this.config.ssh2Patch,
460
+ ...(knownHost ? { knownHost } : {}),
461
+ rememberHost: (fingerprint, hostKey) => this.keys.rememberHost(scope, SSH_KEY_OWNER, gatewayHost, port, fingerprint, hostKey),
462
+ });
463
+ try {
464
+ await session.connect();
465
+ return session;
466
+ }
467
+ catch (error) {
468
+ await session.close();
469
+ throw error;
470
+ }
471
+ }
472
+ /** Runs the fixed privileged bootstrap and returns the restored user hashes. */
473
+ async bootstrap(session, signal) {
474
+ const helpers = Object.entries(HELPERS).map(([name, content]) => `${name}=${Buffer.from(content).toString("base64")}`);
475
+ const result = await this.admin(session, ["bootstrap", ...helpers], signal);
476
+ return result.stdout
477
+ .split("\n")
478
+ .filter((line) => line.startsWith("__LAKEBOX_USER__="))
479
+ .map((line) => line.slice("__LAKEBOX_USER__=".length).trim());
480
+ }
481
+ async admin(session, args, signal) {
482
+ const encoded = Buffer.from(ADMIN_SCRIPT).toString("base64");
483
+ const result = await session.executePrivileged("sh", ["-c", `printf %s '${encoded}' | base64 -d | sh -s -- ${args.map(shellQuote).join(" ")}`], { timeoutMs: SETUP_TIMEOUT_MS, ...(signal ? { signal } : {}) }).result;
484
+ if (!result.success) {
485
+ throw new Error(`Lakebox ${args[0]} failed: ${result.stderr.trim() || result.stdout.trim() || `exit ${result.exitCode}`}`);
486
+ }
487
+ return result;
488
+ }
489
+ /** Marks activity, readies the current boot, and converges the user's account. */
490
+ async readyUser(user, identity, signal) {
491
+ this.touch();
492
+ const boot = await this.ready(signal);
493
+ await this.convergeUser(boot, user, identity, signal);
494
+ return boot;
495
+ }
496
+ /** Creates or verifies the user's account once per boot. */
497
+ convergeUser(boot, user, identity, signal) {
498
+ let converged = boot.users.get(user.hash);
499
+ if (!converged) {
500
+ const digest = createHash("sha256").update(identity.trim().toLowerCase()).digest("hex");
501
+ converged = this.admin(boot.session, ["ensure-user", user.hash, String(user.uid), digest], signal).then(() => undefined);
502
+ boot.users.set(user.hash, converged);
503
+ converged.catch(() => boot.users.delete(user.hash));
504
+ }
505
+ return converged;
506
+ }
507
+ async restoreUser(boot, hash) {
508
+ const user = { name: `lakebox-${hash}`, home: `/home/lakebox-${hash}` };
509
+ boot.users.set(hash, Promise.resolve());
510
+ try {
511
+ const result = await boot.session.execute("python3", [CONTROLLER, "start-all"], {
512
+ user,
513
+ timeoutMs: SETUP_TIMEOUT_MS,
514
+ signal: this.shutdownController.signal,
515
+ }).result;
516
+ if (!result.success)
517
+ throw new Error(result.stderr.trim() || `exit ${result.exitCode}`);
518
+ }
519
+ catch (error) {
520
+ if (this.shutdownController.signal.aborted)
521
+ return;
522
+ logger.warn("Lakebox service restore failed", {
523
+ user: hash,
524
+ error: errorUtils.toError(error),
525
+ });
526
+ }
527
+ }
528
+ async controller(boot, user, command, args, signal) {
529
+ const result = await boot.session.execute("python3", [CONTROLLER, command, ...args], {
530
+ user,
531
+ timeoutMs: SETUP_TIMEOUT_MS,
532
+ ...(signal ? { signal } : {}),
533
+ }).result;
534
+ if (!result.success) {
535
+ throw new Error(`Lakebox service ${command} failed: ${result.stderr.trim() || `exit ${result.exitCode}`}`);
536
+ }
537
+ return JSON.parse(result.stdout);
538
+ }
539
+ async runService(boot, user, definition, signal) {
540
+ const key = `${user.hash}\0${definition.name}`;
541
+ const pending = boot.starting.get(key);
542
+ if (pending)
543
+ return pending;
544
+ const operation = (async () => {
545
+ if (definition.kind === "desktop") {
546
+ boot.desktop ??= this.admin(boot.session, ["desktop-prerequisites"], signal).then(() => undefined);
547
+ boot.desktop.catch(() => {
548
+ boot.desktop = undefined;
549
+ });
550
+ await boot.desktop;
551
+ }
552
+ await this.admin(boot.session, ["allow-port", String(user.uid), String(definition.port)], signal);
553
+ const started = LakeboxControllerServiceSchema.parse(await this.controller(boot, user, "start", [definition.name], signal));
554
+ this.cacheService(boot, user, started);
555
+ return toLakeboxService(started, user, this.config.routePrefix);
556
+ })().finally(() => boot.starting.delete(key));
557
+ boot.starting.set(key, operation);
558
+ return operation;
559
+ }
560
+ async refreshServices(boot, user, identity, signal) {
561
+ await this.convergeUser(boot, user, identity, signal);
562
+ const response = (await this.controller(boot, user, "list", [], signal));
563
+ const services = new Map((response.services ?? []).map((service) => {
564
+ const parsed = LakeboxControllerServiceSchema.parse(service);
565
+ return [parsed.name, parsed];
566
+ }));
567
+ boot.services.set(user.hash, services);
568
+ this.lastServices.set(user.hash, services);
569
+ const observedAt = new Date().toISOString();
570
+ this.lastServicesObservedAt.set(user.hash, observedAt);
571
+ await this.persistServiceSnapshot(boot.entry, user, services, observedAt);
572
+ return services;
573
+ }
574
+ cacheService(boot, user, service) {
575
+ const services = boot.services.get(user.hash) ?? new Map();
576
+ services.set(service.name, service);
577
+ boot.services.set(user.hash, services);
578
+ this.lastServices.set(user.hash, services);
579
+ const observedAt = new Date().toISOString();
580
+ this.lastServicesObservedAt.set(user.hash, observedAt);
581
+ void this.persistServiceSnapshot(boot.entry, user, services, observedAt);
582
+ }
583
+ async serviceListing(identity, user, entry, status, signal) {
584
+ if (!entry || status === "missing") {
585
+ return { services: this.idleServices(user), stale: false };
586
+ }
587
+ if (status === "running" && this.boot?.key === this.bootKey(entry)) {
588
+ const services = await this.refreshServices(this.boot, user, identity, signal);
589
+ return { services: this.withBuiltIns(user, services), stale: false };
590
+ }
591
+ const memory = this.lastServices.get(user.hash);
592
+ if (memory) {
593
+ const observedAt = this.lastServicesObservedAt.get(user.hash);
594
+ const services = status === "running"
595
+ ? memory
596
+ : stoppedSnapshotServices({
597
+ observedAt: observedAt ?? new Date().toISOString(),
598
+ definitions: [...memory.values()].map((service) => service.definition),
599
+ });
600
+ return {
601
+ services: this.withBuiltIns(user, services),
602
+ stale: true,
603
+ ...(observedAt ? { observedAt } : {}),
604
+ };
605
+ }
606
+ const snapshot = await this.serviceSnapshots?.read(entry.sandboxId, user.hash);
607
+ return snapshot
608
+ ? {
609
+ services: this.withBuiltIns(user, stoppedSnapshotServices(snapshot)),
610
+ stale: true,
611
+ observedAt: snapshot.observedAt,
612
+ }
613
+ : { services: this.idleServices(user), stale: true };
614
+ }
615
+ async persistServiceSnapshot(entry, user, services, observedAt) {
616
+ await this.serviceSnapshots?.write(entry.sandboxId, user.hash, {
617
+ observedAt,
618
+ definitions: [...services.values()].map((service) => service.definition),
619
+ });
620
+ }
621
+ withBuiltIns(user, services) {
622
+ const builtIns = LAKEBOX_BUILT_IN_SERVICES.map(({ name }) => {
623
+ const saved = services.get(name);
624
+ return saved
625
+ ? toLakeboxService(saved, user, this.config.routePrefix)
626
+ : idleBuiltInService(name, user, this.config.routePrefix);
627
+ });
628
+ const custom = [...services.values()]
629
+ .filter((service) => !LAKEBOX_BUILT_IN_SERVICES.some(({ name }) => name === service.name))
630
+ .map((service) => toLakeboxService(service, user, this.config.routePrefix));
631
+ return [...builtIns, ...custom];
632
+ }
633
+ idleServices(user) {
634
+ return LAKEBOX_BUILT_IN_SERVICES.map(({ name }) => idleBuiltInService(name, user, this.config.routePrefix));
635
+ }
636
+ /** Resolves one routed request, waking the Lakebox or service in the background. */
637
+ async resolveRoute(user, name) {
638
+ this.touch();
639
+ const entry = await this.entry();
640
+ const running = entry && normalizeLakeboxStatus(entry.status) === "running";
641
+ const boot = this.boot;
642
+ if (!running || !boot || boot.key !== this.bootKey(entry)) {
643
+ if (!this.config.auto)
644
+ return { kind: "missing" };
645
+ this.wake(() => this.ready());
646
+ return { kind: "loading" };
647
+ }
648
+ const identity = this.routedIdentities.get(user.hash);
649
+ if (!identity)
650
+ return { kind: "missing" };
651
+ let service = boot.services.get(user.hash)?.get(name);
652
+ if (!service)
653
+ service = (await this.refreshServices(boot, user, identity)).get(name);
654
+ const builtIn = lakeboxBuiltInServiceNameSchema.safeParse(name);
655
+ if (!service && !builtIn.success)
656
+ return { kind: "missing" };
657
+ if (service?.state === "ready") {
658
+ return { kind: "ready", session: boot.session, route: serviceRoute(service.definition) };
659
+ }
660
+ if (service?.state === "error" && !boot.starting.has(`${user.hash}\0${name}`)) {
661
+ return { kind: "failed", message: service.error ?? "the service failed to start" };
662
+ }
663
+ const definition = service?.definition ?? builtInDefinition(builtIn.data, user);
664
+ this.wake(async () => {
665
+ if (!service)
666
+ await this.controller(boot, user, "put", [encode(definition)]);
667
+ await this.runService(boot, user, definition);
668
+ });
669
+ return { kind: "loading" };
670
+ }
671
+ markUnavailable(user, name) {
672
+ this.boot?.services.get(user.hash)?.delete(name);
673
+ this.cached = undefined;
674
+ }
675
+ wake(action) {
676
+ if (this.waking)
677
+ return;
678
+ this.waking = action()
679
+ .catch((error) => logger.warn("Lakebox wake failed", { error: errorUtils.toError(error) }))
680
+ .finally(() => {
681
+ this.waking = undefined;
682
+ });
683
+ }
684
+ async readMetrics(signal) {
685
+ const boot = this.boot;
686
+ if (!boot)
687
+ throw new Error("Lakebox is not running");
688
+ try {
689
+ return (await this.admin(boot.session, ["metrics"], signal)).stdout;
690
+ }
691
+ catch (error) {
692
+ this.cached = undefined;
693
+ throw error;
694
+ }
695
+ }
696
+ leaseMetrics() {
697
+ if (!this.boot)
698
+ return;
699
+ this.metrics.start();
700
+ if (this.metricsLease)
701
+ clearTimeout(this.metricsLease);
702
+ this.metricsLease = setTimeout(() => {
703
+ if (this.metrics.listenerCount("snapshot") === 0)
704
+ this.metrics.stop();
705
+ }, METRICS_LEASE_MS);
706
+ this.metricsLease.unref?.();
707
+ }
708
+ /**
709
+ * Releases the SSH session after the idle timeout without commands, service
710
+ * operations, routed traffic, open streams, or metrics watchers. An open
711
+ * session counts as activity for the platform watchdog, so releasing it lets
712
+ * the platform stop the Lakebox after its own idle timeout. The next request
713
+ * reconnects.
714
+ */
715
+ watchIdle() {
716
+ if (this.idleTimer)
717
+ clearInterval(this.idleTimer);
718
+ this.idleTimer = setInterval(() => {
719
+ const idleMs = Date.now() - this.lastActivity;
720
+ if (!this.boot ||
721
+ this.converging ||
722
+ idleMs < this.config.idleTimeoutSeconds * 1_000 ||
723
+ this.activeCommands > 0 ||
724
+ this.boot.starting.size > 0 ||
725
+ this.routes.activeConnections() > 0 ||
726
+ this.metrics.listenerCount("snapshot") > 0) {
727
+ if (this.routes.activeConnections() > 0 || this.activeCommands > 0)
728
+ this.touch();
729
+ return;
730
+ }
731
+ logger.info("releasing idle Lakebox session", { idleSeconds: Math.round(idleMs / 1_000) });
732
+ void this.discardBoot();
733
+ }, IDLE_CHECK_MS);
734
+ this.idleTimer.unref?.();
735
+ }
736
+ touch() {
737
+ this.lastActivity = Date.now();
738
+ }
739
+ async discardBoot() {
740
+ if (this.idleTimer)
741
+ clearInterval(this.idleTimer);
742
+ this.idleTimer = undefined;
743
+ const boot = this.boot;
744
+ this.boot = undefined;
745
+ this.metrics.stop();
746
+ await this.routes.closeBridges();
747
+ await boot?.session.close().catch(() => undefined);
748
+ }
749
+ }
750
+ function encode(definition) {
751
+ return Buffer.from(JSON.stringify(definition)).toString("base64");
752
+ }
753
+ function shellQuote(value) {
754
+ return `'${value.replaceAll("'", "'\\''")}'`;
755
+ }
756
+ /** Returns whether an error means the managed Lakebox no longer exists. */
757
+ export function isLakeboxMissing(error) {
758
+ return error instanceof LakeboxApiError && error.status === 404;
759
+ }
760
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVudGltZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydW50aW1lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFekMsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMzRCxPQUFPLEVBQ0wsb0JBQW9CLEVBQ3BCLG9CQUFvQixFQUNwQix5QkFBeUIsRUFDekIsc0JBQXNCLEdBQ3ZCLE1BQU0sOEJBQThCLENBQUM7QUFDdEMsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixlQUFlLEVBQ2YsYUFBYSxHQUdkLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNwRSxPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3pELE9BQU8sRUFDTCx5QkFBeUIsRUFDekIsK0JBQStCLEVBQy9CLDJCQUEyQixFQUMzQiwrQkFBK0IsR0FXaEMsTUFBTSwyQkFBMkIsQ0FBQztBQUNuQyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFcEQsT0FBTyxFQUEyQix1QkFBdUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRTNGLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDOUMsT0FBTyxFQUFFLG9CQUFvQixFQUErQixNQUFNLGFBQWEsQ0FBQztBQUNoRixPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLGtCQUFrQixFQUNsQixlQUFlLEVBQ2YsOEJBQThCLEVBQzlCLFlBQVksRUFDWixnQkFBZ0IsR0FHakIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLG9CQUFvQixFQUFFLFdBQVcsRUFBRSxNQUFNLFdBQVcs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VUFBVSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDcEUsQ0FBQztBQUVELFNBQVMsVUFBVSxDQUFDLEtBQWE7SUFDL0IsT0FBTyxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUM7QUFDL0MsQ0FBQztBQUVELDJFQUEyRTtBQUMzRSxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsS0FBYztJQUM3QyxPQUFPLEtBQUssWUFBWSxlQUFlLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxHQUFHLENBQUM7QUFDbEUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNyZWF0ZUhhc2ggfSBmcm9tIFwibm9kZTpjcnlwdG9cIjtcbmltcG9ydCB0eXBlIHsgSW5jb21pbmdIdHRwSGVhZGVycyB9IGZyb20gXCJub2RlOmh0dHBcIjtcbmltcG9ydCB7IGV4ZWMgfSBmcm9tIFwiQGRieC10b29scy9jb3JlXCI7XG5pbXBvcnQgeyBTc2hLZXlTdG9yZSB9IGZyb20gXCJAZGJ4LXRvb2xzL2xha2Vib3gva2V5LXN0b3JlXCI7XG5pbXBvcnQge1xuICBlbnN1cmVMYWtlYm94UnVubmluZyxcbiAgZW5zdXJlTGFrZWJveFN0b3BwZWQsXG4gIGxha2Vib3hJZGxlVGltZW91dFNlY29uZHMsXG4gIG5vcm1hbGl6ZUxha2Vib3hTdGF0dXMsXG59IGZyb20gXCJAZGJ4LXRvb2xzL2xha2Vib3gvbGlmZWN5Y2xlXCI7XG5pbXBvcnQge1xuICBpc0xha2Vib3hVbmF2YWlsYWJsZSxcbiAgTGFrZWJveEFwaUVycm9yLFxuICBMYWtlYm94Q2xpZW50LFxuICB0eXBlIExha2Vib3hBdXRoLFxuICB0eXBlIExha2Vib3hFbnRyeSxcbn0gZnJvbSBcIkBkYngtdG9vbHMvbGFrZWJveC9yZXN0XCI7XG5pbXBvcnQgeyBTc2hDb21tYW5kLCBTc2hTZXNzaW9uIH0gZnJvbSBcIkBkYngtdG9vbHMvbGFrZWJveC9zZXNzaW9uXCI7XG5pbXBvcnQgeyBlcnJvclV0aWxzLCBsb2cgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHtcbiAgTEFLRUJPWF9CVUlMVF9JTl9TRVJWSUNFUyxcbiAgbGFrZWJveEJ1aWx0SW5TZXJ2aWNlTmFtZVNjaGVtYSxcbiAgbGFrZWJveENvbW1hbmRSZXF1ZXN0U2NoZW1hLFxuICBsYWtlYm94U2VydmljZUxvZ3NSZXF1ZXN0U2NoZW1hLFxuICB0eXBlIENyZWF0ZUxha2Vib3hTZXJ2aWNlUmVxdWVzdCxcbiAgdHlwZSBMYWtlYm94QnVpbHRJblNlcnZpY2VOYW1lLFxuICB0eXBlIExha2Vib3hDb21tYW5kUmVxdWVzdCxcbiAgdHlwZSBMYWtlYm94TWV0cmljc1Jlc3BvbnNlLFxuICB0eXBlIExha2Vib3hNZXRyaWNzU25hcHNob3QsXG4gIHR5cGUgTGFrZWJveFNlcnZpY2UsXG4gIHR5cGUgTGFrZWJveFNlcnZpY2VMb2dzUmVxdWVzdCxcbiAgdHlwZSBMYWtlYm94U3RhdHVzLFxuICB0eXBlIExha2Vib3hTdW1tYXJ5LFxuICB0eXBlIExha2Vib3hVc2VyLFxufSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtbGFrZWJveFwiO1xuaW1wb3J0IHsgcmVhZFBhY2thZ2VSZXNvdXJjZSB9IGZyb20gXCIuL19wYWNrYWdlLnRzXCI7XG5pbXBvcnQgeyBMYWtlYm94UmVzb3VyY2VSZWdpc3RyeSB9IGZyb20gXCIuL19yZXNvdXJjZS1yZWdpc3RyeS50c1wiO1xuaW1wb3J0IHsgTGFrZWJveFNlcnZpY2VTbmFwc2hvdHMsIHN0b3BwZWRTbmFwc2hvdFNlcnZpY2VzIH0gZnJvbSBcIi4vX3NlcnZpY2Utc25hcHNob3RzLnRzXCI7XG5pbXBvcnQgdHlwZSB7IFJlc29sdmVkTGFrZWJveFBsdWdpbkNvbmZpZyB9IGZyb20gXCIuL2NvbmZpZy50c1wiO1xuaW1wb3J0IHsgTGFrZWJveE1ldHJpY3MgfSBmcm9tIFwiLi9tZXRyaWNzLnRzXCI7XG5pbXBvcnQgeyBMYWtlYm94Um91dGVSZWdpc3RyeSwgdHlwZSBMYWtlYm94Um91dGVSZXNvbHV0aW9uIH0gZnJvbSBcIi4vcm91dGVzLnRzXCI7XG5pbXBvcnQge1xuICBidWlsdEluRGVmaW5pdGlvbixcbiAgaWRsZUJ1aWx0SW5TZXJ2aWNlLFxuICBpbWFnZURlZmluaXRpb24sXG4gIExha2Vib3hDb250cm9sbGVyU2VydmljZVNjaGVtYSxcbiAgc2VydmljZVJvdXRlLFxuICB0b0xha2Vib3hTZXJ2aWNlLFxuICB0eXBlIExha2Vib3hDb250cm9sbGVyRGVmaW5pdGlvbixcbiAgdHlwZSBMYWtlYm94Q29udHJvbGxlclNlcnZpY2UsXG59IGZyb20gXCIuL3NlcnZpY2VzLnRzXCI7XG5pbXBvcnQgeyBMQUtFQk9YX1JVTlRJTUVfUk9PVCwgbGFrZWJveFVzZXIgfSBmcm9tIFwiLi91c2VyLnRzXCI7XG5cbmNvbnN0IEFETUlOX1NDUklQVCA9IHJlYWRQYWNrYWdlUmVzb3VyY2UoXCJzY3JpcHRzXCIsIFwibGFrZWJveC1hZG1pbi5zaFwiKTtcbmNvbnN0IEhFTFBFUlMgPSB7XG4gIFwibGFrZWJveC1zZXJ2aWNlXCI6IHJlYWRQYWNrYWdlUmVzb3VyY2UoXCJzY3JpcHRzXCIsIFwibGFrZWJveC1zZXJ2aWNlLnB5XCIpLFxuICBcImRlc2t0b3Atc2Vzc2lvblwiOiByZWFkUGFja2FnZVJlc291cmNlKFwic2NyaXB0c1wiLCBcImRlc2t0b3Atc2Vzc2lvbi5zaFwiKSxcbiAgXCJkZXNrdG9wLXByZXJlcXVpc2l0ZXNcIjogcmVhZFBhY2thZ2VSZXNvdXJjZShcInNjcmlwdHNcIiwgXCJkZXNrdG9wLXByZXJlcXVpc2l0ZXMuc2hcIiksXG59IGFzIGNvbnN0O1xuY29uc3QgQ09OVFJPTExFUiA9IGAke0xBS0VCT1hfUlVOVElNRV9ST09UfS9iaW4vbGFrZWJveC1zZXJ2aWNlYDtcbmNvbnN0IEVOVFJZX1RUTF9NUyA9IDVfMDAwO1xuY29uc3QgU0VUVVBfVElNRU9VVF9NUyA9IDYwMF8wMDA7XG5jb25zdCBNRVRSSUNTX0xFQVNFX01TID0gNjBfMDAwO1xuY29uc3QgSURMRV9DSEVDS19NUyA9IDMwXzAwMDtcbmNvbnN0IFNTSF9LRVlfT1dORVIgPSBcImFwcC1zZXJ2aWNlLXByaW5jaXBhbFwiO1xuY29uc3QgTEVHQUNZX05BTUUgPVxuICAvXmRieC0oPyFsYWtlYm94LSlbYS16XSstW2Etel0rLVswLTlhLWZdezh9KD86X3VpZF9bQS1aYS16MC05Xy1dK19leHBfWzAtOV0rKT8kLztcbmNvbnN0IExFR0FDWV9TQ0hFTUFfUFJFRklYID0gXCJkYnhfdG9vbHNfZGF0YWJyaWNrc19zYW5kYm94XCI7XG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwiYXBwa2l0LWxha2Vib3g6cnVudGltZVwiKTtcblxuLyoqIFJlc29sdmVzIHRoZSBhdXRoZW50aWNhdGVkIGlkZW50aXR5IGZvciByYXcgcmVxdWVzdCBoZWFkZXJzLiAqL1xuZXhwb3J0IHR5cGUgTGFrZWJveElkZW50aXR5UmVzb2x2ZXIgPSAoaGVhZGVyczogSW5jb21pbmdIdHRwSGVhZGVycykgPT4gc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4vKiogTWluaW1hbCBMYWtlYmFzZSBwb29sIHVzZWQgdG8gZHJvcCBsZWdhY3kgb3duZXJzaGlwIHNjaGVtYXMuICovXG5leHBvcnQgaW50ZXJmYWNlIExha2Vib3hMZWdhY3lQb29sIHtcbiAgcXVlcnkoc3FsOiBzdHJpbmcsIHZhbHVlcz86IHVua25vd25bXSk6IFByb21pc2U8eyByb3dzOiBBcnJheTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4gfT47XG59XG5cbmludGVyZmFjZSBCb290IHtcbiAga2V5OiBzdHJpbmc7XG4gIGVudHJ5OiBMYWtlYm94RW50cnk7XG4gIHNlc3Npb246IFNzaFNlc3Npb247XG4gIHVzZXJzOiBNYXA8c3RyaW5nLCBQcm9taXNlPHZvaWQ+PjtcbiAgc2VydmljZXM6IE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIExha2Vib3hDb250cm9sbGVyU2VydmljZT4+O1xuICBzdGFydGluZzogTWFwPHN0cmluZywgUHJvbWlzZTxMYWtlYm94U2VydmljZT4+O1xuICBkZXNrdG9wPzogUHJvbWlzZTx2b2lkPjtcbn1cblxuaW50ZXJmYWNlIFNlcnZpY2VMaXN0aW5nIHtcbiAgc2VydmljZXM6IExha2Vib3hTZXJ2aWNlW107XG4gIHN0YWxlOiBib29sZWFuO1xuICBvYnNlcnZlZEF0Pzogc3RyaW5nO1xufVxuXG4vKipcbiAqIE93bnMgdGhlIHNpbmdsZSBsYXppbHkgY3JlYXRlZCBMYWtlYm94IG9mIG9uZSBhcHBsaWNhdGlvbi5cbiAqXG4gKiBFdmVyeSBEYXRhYnJpY2tzIExha2Vib3ggUkVTVCBjYWxsIHVzZXMgdGhlIGFwcCBzZXJ2aWNlIHByaW5jaXBhbCBzdXBwbGllZFxuICogdGhyb3VnaCB7QGxpbmsgaW5pdGlhbGl6ZX07IHJlcXVlc3QgaWRlbnRpdHkgb25seSBzZWxlY3RzIHRoZSBpbnRlcm5hbCBMaW51eFxuICogYWNjb3VudC4gRWFjaCBhdXRoZW50aWNhdGVkIGlkZW50aXR5IG1hcHMgdGhyb3VnaCBvbmUgRk5WLTFhIGhhc2ggdG8gYSBsb2NrZWRcbiAqIGFjY291bnQsIHBlcnNpc3RlbnQgaG9tZSwgcm91dGUgc2VnbWVudCwgYW5kIHNlcnZpY2UgcG9ydHMuIExpZmVjeWNsZSBhbmRcbiAqIHBlci1ib290IGJvb3RzdHJhcCBhcmUgc2VyaWFsaXplZCBpbi1wcm9jZXNzOyB0aGUgcGVyc2lzdGVudCByZXNvdXJjZVxuICogcmVnaXN0cnkgc2VyaWFsaXplcyBmaXJzdCBjcmVhdGlvbiBhY3Jvc3MgcmVwbGljYXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBMYWtlYm94UnVudGltZSB7XG4gIHJlYWRvbmx5IHJvdXRlczogTGFrZWJveFJvdXRlUmVnaXN0cnk7XG4gIHJlYWRvbmx5IG1ldHJpY3M6IExha2Vib3hNZXRyaWNzO1xuICBwcml2YXRlIHJlYWRvbmx5IGtleXM6IFNzaEtleVN0b3JlO1xuICBwcml2YXRlIHJlYWRvbmx5IHN0b3BQYXJlbnRUZXJtaW5hdGlvblNpZ25hbDogKCkgPT4gdm9pZDtcbiAgcHJpdmF0ZSByZWFkb25seSBzaHV0ZG93bkNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gIHByaXZhdGUgYXBpPzogTGFrZWJveENsaWVudDtcbiAgcHJpdmF0ZSBpZGVudGl0eTogTGFrZWJveElkZW50aXR5UmVzb2x2ZXIgPSAoKSA9PiB1bmRlZmluZWQ7XG4gIC8qKiBJbi1tZW1vcnkgaWRlbnRpdGllcyBvZiByb3V0ZWQgdXNlcnM7IG5ldmVyIHBlcnNpc3RlZC4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSByb3V0ZWRJZGVudGl0aWVzID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcbiAgcHJpdmF0ZSBjYWNoZWQ/OiB7IGVudHJ5PzogTGFrZWJveEVudHJ5OyBhdDogbnVtYmVyIH07XG4gIHByaXZhdGUgYm9vdD86IEJvb3Q7XG4gIC8qKiBMYXN0IGJvb3QgdGhhdCBjb21wbGV0ZWQgcnVudGltZSBib290c3RyYXAgYW5kIHByb2R1Y2VkIGEgbWV0cmljcyBzYW1wbGUuICovXG4gIHByaXZhdGUgcmVhZHlCb290S2V5Pzogc3RyaW5nO1xuICBwcml2YXRlIGNvbnZlcmdpbmc/OiBQcm9taXNlPEJvb3Q+O1xuICBwcml2YXRlIHdha2luZz86IFByb21pc2U8dW5rbm93bj47XG4gIHByaXZhdGUgbWV0cmljc0xlYXNlPzogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD47XG4gIHByaXZhdGUgaWRsZVRpbWVyPzogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0SW50ZXJ2YWw+O1xuICBwcml2YXRlIGxhc3RBY3Rpdml0eSA9IERhdGUubm93KCk7XG4gIHByaXZhdGUgYWN0aXZlQ29tbWFuZHMgPSAwO1xuICAvKiogTGFzdCBzZXJ2aWNlIHN0YXRlcyBwZXIgdXNlciBoYXNoLCBrZXB0IGFmdGVyIGFuIGlkbGUgc2Vzc2lvbiByZWxlYXNlLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGxhc3RTZXJ2aWNlcyA9IG5ldyBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBMYWtlYm94Q29udHJvbGxlclNlcnZpY2U+PigpO1xuICBwcml2YXRlIHJlYWRvbmx5IGxhc3RTZXJ2aWNlc09ic2VydmVkQXQgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICBwcml2YXRlIHJlc291cmNlUmVnaXN0cnk/OiBMYWtlYm94UmVzb3VyY2VSZWdpc3RyeTtcbiAgcHJpdmF0ZSBzZXJ2aWNlU25hcHNob3RzPzogTGFrZWJveFNlcnZpY2VTbmFwc2hvdHM7XG4gIHByaXZhdGUgY2xvc2luZz86IFByb21pc2U8dm9pZD47XG5cbiAgLyoqIENyZWF0ZXMgYSBydW50aW1lIGZyb20gcmVzb2x2ZWQgcGx1Z2luIGNvbmZpZ3VyYXRpb24uICovXG4gIGNvbnN0cnVjdG9yKHJlYWRvbmx5IGNvbmZpZzogUmVzb2x2ZWRMYWtlYm94UGx1Z2luQ29uZmlnKSB7XG4gICAgdGhpcy5rZXlzID0gbmV3IFNzaEtleVN0b3JlKGNvbmZpZy5rZXlEaXJlY3RvcnkpO1xuICAgIHRoaXMucm91dGVzID0gbmV3IExha2Vib3hSb3V0ZVJlZ2lzdHJ5KGNvbmZpZy5yb3V0ZVByZWZpeCwge1xuICAgICAgdXNlcjogKGhlYWRlcnMpID0+IHtcbiAgICAgICAgY29uc3QgaWRlbnRpdHkgPSB0aGlzLmlkZW50aXR5KGhlYWRlcnMpO1xuICAgICAgICBpZiAoIWlkZW50aXR5KSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCB1c2VyID0gdGhpcy51c2VyKGlkZW50aXR5KTtcbiAgICAgICAgdGhpcy5yb3V0ZWRJZGVudGl0aWVzLnNldCh1c2VyLmhhc2gsIGlkZW50aXR5KTtcbiAgICAgICAgcmV0dXJuIHVzZXI7XG4gICAgICB9LFxuICAgICAgcmVzb2x2ZTogKHVzZXIsIHNlcnZpY2UpID0+IHRoaXMucmVzb2x2ZVJvdXRlKHVzZXIsIHNlcnZpY2UpLFxuICAgICAgdW5hdmFpbGFibGU6ICh1c2VyLCBzZXJ2aWNlKSA9PiB0aGlzLm1hcmtVbmF2YWlsYWJsZSh1c2VyLCBzZXJ2aWNlKSxcbiAgICB9KTtcbiAgICB0aGlzLm1ldHJpY3MgPSBuZXcgTGFrZWJveE1ldHJpY3MoXG4gICAgICAoc2lnbmFsKSA9PiB0aGlzLnJlYWRNZXRyaWNzKHNpZ25hbCksXG4gICAgICBjb25maWcubWV0cmljc0ludGVydmFsU2Vjb25kcyAqIDFfMDAwLFxuICAgICk7XG4gICAgdGhpcy5zdG9wUGFyZW50VGVybWluYXRpb25TaWduYWwgPSBleGVjLm9uUGFyZW50VGVybWluYXRpb25TaWduYWwoKCkgPT5cbiAgICAgIHRoaXMucm91dGVzLmJlZ2luU2h1dGRvd24oKSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFN1cHBsaWVzIGFwcCBzZXJ2aWNlLXByaW5jaXBhbCBjcmVkZW50aWFscyBhbmQgdGhlIHJlcXVlc3QgaWRlbnRpdHlcbiAgICogcmVzb2x2ZXIgdXNlZCBieSByb3V0ZXMuXG4gICAqL1xuICBpbml0aWFsaXplKFxuICAgIGF1dGg6IExha2Vib3hBdXRoLFxuICAgIGlkZW50aXR5PzogTGFrZWJveElkZW50aXR5UmVzb2x2ZXIsXG4gICAgc2VydmljZVNuYXBzaG90cz86IExha2Vib3hTZXJ2aWNlU25hcHNob3RzLFxuICAgIHJlc291cmNlUmVnaXN0cnk/OiBMYWtlYm94UmVzb3VyY2VSZWdpc3RyeSxcbiAgKTogdm9pZCB7XG4gICAgdGhpcy5hcGkgPSBuZXcgTGFrZWJveENsaWVudChhdXRoKTtcbiAgICBpZiAoaWRlbnRpdHkpIHRoaXMuaWRlbnRpdHkgPSBpZGVudGl0eTtcbiAgICBpZiAoc2VydmljZVNuYXBzaG90cykgdGhpcy5zZXJ2aWNlU25hcHNob3RzID0gc2VydmljZVNuYXBzaG90cztcbiAgICBpZiAocmVzb3VyY2VSZWdpc3RyeSkgdGhpcy5yZXNvdXJjZVJlZ2lzdHJ5ID0gcmVzb3VyY2VSZWdpc3RyeTtcbiAgfVxuXG4gIC8qKiBEZXJpdmVzIHRoZSBMYWtlYm94IGFjY291bnQgZm9yIG9uZSBhdXRoZW50aWNhdGVkIGlkZW50aXR5LiAqL1xuICB1c2VyKGlkZW50aXR5OiBzdHJpbmcpOiBMYWtlYm94VXNlciB7XG4gICAgcmV0dXJuIGxha2Vib3hVc2VyKGlkZW50aXR5LCB0aGlzLmNvbmZpZy5yb3V0ZVByZWZpeCk7XG4gIH1cblxuICAvKiogU3VtbWFyaXplcyB0aGUgYXBwIExha2Vib3ggZm9yIG9uZSB1c2VyIHdpdGhvdXQgY3JlYXRpbmcgaXQuICovXG4gIGFzeW5jIHN1bW1hcnkoaWRlbnRpdHk6IHN0cmluZywgc2lnbmFsPzogQWJvcnRTaWduYWwpOiBQcm9taXNlPExha2Vib3hTdW1tYXJ5PiB7XG4gICAgY29uc3QgdXNlciA9IHRoaXMudXNlcihpZGVudGl0eSk7XG4gICAgY29uc3QgYmFzZSA9IHsgYXV0bzogdGhpcy5jb25maWcuYXV0bywgbmFtZTogXCJMYWtlYm94XCIsIHVzZXIgfTtcbiAgICBsZXQgZW50cnk6IExha2Vib3hFbnRyeSB8IHVuZGVmaW5lZDtcbiAgICB0cnkge1xuICAgICAgZW50cnkgPSBhd2FpdCB0aGlzLmVudHJ5KHNpZ25hbCwgdHJ1ZSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChpc0xha2Vib3hVbmF2YWlsYWJsZShlcnJvcikpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAuLi5iYXNlLFxuICAgICAgICAgIHN1cHBvcnRlZDogZmFsc2UsXG4gICAgICAgICAgc3RhdHVzOiBcIm1pc3NpbmdcIixcbiAgICAgICAgICBzZXJ2aWNlczogW10sXG4gICAgICAgICAgc2VydmljZXNTdGFsZTogZmFsc2UsXG4gICAgICAgICAgY2FuU3RhcnQ6IGZhbHNlLFxuICAgICAgICAgIGNhblN0b3A6IGZhbHNlLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICAgIGNvbnN0IHBsYXRmb3JtU3RhdHVzOiBMYWtlYm94U3RhdHVzID0gZW50cnkgPyBub3JtYWxpemVMYWtlYm94U3RhdHVzKGVudHJ5LnN0YXR1cykgOiBcIm1pc3NpbmdcIjtcbiAgICBjb25zdCBzdGF0dXMgPSB0aGlzLnByb2R1Y3RTdGF0dXMoZW50cnksIHBsYXRmb3JtU3RhdHVzKTtcbiAgICBpZiAoZW50cnkgJiYgcGxhdGZvcm1TdGF0dXMgPT09IFwicnVubmluZ1wiICYmIHN0YXR1cyA9PT0gXCJzdGFydGluZ1wiKSB7XG4gICAgICB0aGlzLndha2UoKCkgPT4gdGhpcy5yZWFkeSgpKTtcbiAgICB9XG4gICAgY29uc3QgbGlzdGluZyA9IGF3YWl0IHRoaXMuc2VydmljZUxpc3RpbmcoaWRlbnRpdHksIHVzZXIsIGVudHJ5LCBzdGF0dXMsIHNpZ25hbCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmJhc2UsXG4gICAgICBzdXBwb3J0ZWQ6IHRydWUsXG4gICAgICBzdGF0dXMsXG4gICAgICAuLi4oZW50cnkgPyB7IGlkOiBlbnRyeS5zYW5kYm94SWQgfSA6IHt9KSxcbiAgICAgIC4uLihsYWtlYm94SWRsZVRpbWVvdXRTZWNvbmRzKGVudHJ5Py5pZGxlVGltZW91dCkgIT09IHVuZGVmaW5lZFxuICAgICAgICA/IHsgaWRsZVRpbWVvdXRTZWNvbmRzOiBsYWtlYm94SWRsZVRpbWVvdXRTZWNvbmRzKGVudHJ5Py5pZGxlVGltZW91dCkgfVxuICAgICAgICA6IHt9KSxcbiAgICAgIHNlcnZpY2VzOiBsaXN0aW5nLnNlcnZpY2VzLFxuICAgICAgc2VydmljZXNTdGFsZTogbGlzdGluZy5zdGFsZSxcbiAgICAgIC4uLihsaXN0aW5nLm9ic2VydmVkQXQgPyB7IHNlcnZpY2VzT2JzZXJ2ZWRBdDogbGlzdGluZy5vYnNlcnZlZEF0IH0gOiB7fSksXG4gICAgICBjYW5TdGFydDogc3RhdHVzICE9PSBcInJ1bm5pbmdcIiAmJiBzdGF0dXMgIT09IFwic3RhcnRpbmdcIixcbiAgICAgIGNhblN0b3A6IHN0YXR1cyA9PT0gXCJydW5uaW5nXCIgfHwgc3RhdHVzID09PSBcInN0YXJ0aW5nXCIsXG4gICAgfTtcbiAgfVxuXG4gIC8qKiBDcmVhdGVzIHRoZSBMYWtlYm94IHdoZW4gbmVlZGVkLCBzdGFydHMgaXQsIGFuZCByZXN0b3JlcyBzYXZlZCBzZXJ2aWNlcy4gKi9cbiAgYXN5bmMgc3RhcnQoc2lnbmFsPzogQWJvcnRTaWduYWwpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLnJlYWR5KHNpZ25hbCwgdHJ1ZSk7XG4gIH1cblxuICAvKiogU3RvcHMgdGhlIHNoYXJlZCBMYWtlYm94IGZvciBldmVyeSB1c2VyLiBGaWxlcyBhbmQgc2F2ZWQgc2VydmljZXMgcGVyc2lzdC4gKi9cbiAgYXN5bmMgc3RvcChzaWduYWw/OiBBYm9ydFNpZ25hbCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGVudHJ5ID0gYXdhaXQgdGhpcy5lbnRyeShzaWduYWwsIHRydWUpO1xuICAgIGlmICghZW50cnkpIHJldHVybjtcbiAgICBhd2FpdCB0aGlzLmRpc2NhcmRCb290KCk7XG4gICAgYXdhaXQgZW5zdXJlTGFrZWJveFN0b3BwZWQodGhpcy5jbGllbnQoKSwgZW50cnksIHNpZ25hbCk7XG4gICAgdGhpcy5jYWNoZWQgPSB1bmRlZmluZWQ7XG4gIH1cblxuICAvKiogUGVybWFuZW50bHkgZGVsZXRlcyB0aGUgbWFuYWdlZCBMYWtlYm94IGFuZCBldmVyeSB1c2VyJ3MgZmlsZXMuICovXG4gIGFzeW5jIGRlbGV0ZShzaWduYWw/OiBBYm9ydFNpZ25hbCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IGVudHJ5ID0gYXdhaXQgdGhpcy5lbnRyeShzaWduYWwsIHRydWUpO1xuICAgIGlmICghZW50cnkpIHJldHVybiBmYWxzZTtcbiAgICBhd2FpdCB0aGlzLmRpc2NhcmRCb290KCk7XG4gICAgYXdhaXQgdGhpcy5jbGllbnQoKS5kZWxldGUoZW50cnkuc2FuZGJveElkLCBzaWduYWwpO1xuICAgIGF3YWl0IHRoaXMucmVzb3VyY2VzKCkuY2xlYXIodGhpcy5jbGllbnQoKSk7XG4gICAgdGhpcy5yZWFkeUJvb3RLZXkgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5jYWNoZWQgPSB7IGF0OiBEYXRlLm5vdygpIH07XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogUnVucyBvbmUgY29tbWFuZCBhcyB0aGUgdXNlcidzIGFjY291bnQsIGNyZWF0aW5nIG9yIHN0YXJ0aW5nIHRoZSBMYWtlYm94XG4gICAqIHdoZW4gYGF1dG9gIGlzIGVuYWJsZWQuXG4gICAqL1xuICBleGVjdXRlKGlkZW50aXR5OiBzdHJpbmcsIGlucHV0OiBMYWtlYm94Q29tbWFuZFJlcXVlc3QsIHNpZ25hbD86IEFib3J0U2lnbmFsKTogU3NoQ29tbWFuZCB7XG4gICAgY29uc3QgcmVxdWVzdCA9IGxha2Vib3hDb21tYW5kUmVxdWVzdFNjaGVtYS5wYXJzZShpbnB1dCk7XG4gICAgY29uc3QgdGltZW91dE1zID0gcmVxdWVzdC50aW1lb3V0TXMgPz8gdGhpcy5jb25maWcuY29tbWFuZFRpbWVvdXRNcztcbiAgICBjb25zdCB1c2VyID0gdGhpcy51c2VyKGlkZW50aXR5KTtcbiAgICByZXR1cm4gbmV3IFNzaENvbW1hbmQoXG4gICAgICByZXF1ZXN0LmNvbW1hbmQsXG4gICAgICByZXF1ZXN0LmFyZ3MsXG4gICAgICB7IHRpbWVvdXRNcywgc2lnbmFsIH0sXG4gICAgICBhc3luYyAoZXhlY3V0aW9uKSA9PiB7XG4gICAgICAgIGNvbnN0IGJvb3QgPSBhd2FpdCB0aGlzLnJlYWR5VXNlcih1c2VyLCBpZGVudGl0eSwgZXhlY3V0aW9uLnNpZ25hbCk7XG4gICAgICAgIHRoaXMuYWN0aXZlQ29tbWFuZHMgKz0gMTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gYXdhaXQgZXhlY3V0aW9uLmZvbGxvdyhcbiAgICAgICAgICAgIGJvb3Quc2Vzc2lvbi5leGVjdXRlKHJlcXVlc3QuY29tbWFuZCwgcmVxdWVzdC5hcmdzLCB7XG4gICAgICAgICAgICAgIHVzZXIsXG4gICAgICAgICAgICAgIC4uLihyZXF1ZXN0LmN3ZCA/IHsgY3dkOiByZXF1ZXN0LmN3ZCB9IDoge30pLFxuICAgICAgICAgICAgICAuLi4ocmVxdWVzdC5lbnYgPyB7IGVudjogcmVxdWVzdC5lbnYgfSA6IHt9KSxcbiAgICAgICAgICAgICAgdGltZW91dE1zLFxuICAgICAgICAgICAgICBzaWduYWw6IGV4ZWN1dGlvbi5zaWduYWwsXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICApO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgIHRoaXMuYWN0aXZlQ29tbWFuZHMgLT0gMTtcbiAgICAgICAgICB0aGlzLnRvdWNoKCk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBMaXN0cyB0aGUgdXNlcidzIHNlcnZpY2VzLCBpbmNsdWRpbmcgaWRsZSBidWlsdC1pbnMuIE5ldmVyIGNyZWF0ZXMgdGhlIExha2Vib3guICovXG4gIGFzeW5jIGxpc3RTZXJ2aWNlcyhpZGVudGl0eTogc3RyaW5nLCBzaWduYWw/OiBBYm9ydFNpZ25hbCk6IFByb21pc2U8TGFrZWJveFNlcnZpY2VbXT4ge1xuICAgIGNvbnN0IHVzZXIgPSB0aGlzLnVzZXIoaWRlbnRpdHkpO1xuICAgIGNvbnN0IGVudHJ5ID0gYXdhaXQgdGhpcy5lbnRyeShzaWduYWwpO1xuICAgIGNvbnN0IHN0YXR1czogTGFrZWJveFN0YXR1cyA9IGVudHJ5ID8gbm9ybWFsaXplTGFrZWJveFN0YXR1cyhlbnRyeS5zdGF0dXMpIDogXCJtaXNzaW5nXCI7XG4gICAgcmV0dXJuIChhd2FpdCB0aGlzLnNlcnZpY2VMaXN0aW5nKGlkZW50aXR5LCB1c2VyLCBlbnRyeSwgc3RhdHVzLCBzaWduYWwpKS5zZXJ2aWNlcztcbiAgfVxuXG4gIC8qKiBDcmVhdGVzIG9yIHJlcGxhY2VzIG9uZSBpbWFnZSBzZXJ2aWNlIGFuZCB3YWl0cyB1bnRpbCBpdCBpcyByZWFkeSBvciBmYWlsZWQuICovXG4gIGFzeW5jIGNyZWF0ZVNlcnZpY2UoXG4gICAgaWRlbnRpdHk6IHN0cmluZyxcbiAgICBpbnB1dDogQ3JlYXRlTGFrZWJveFNlcnZpY2VSZXF1ZXN0LFxuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsLFxuICApOiBQcm9taXNlPExha2Vib3hTZXJ2aWNlPiB7XG4gICAgY29uc3QgdXNlciA9IHRoaXMudXNlcihpZGVudGl0eSk7XG4gICAgY29uc3QgZGVmaW5pdGlvbiA9IGltYWdlRGVmaW5pdGlvbihpbnB1dCwgdXNlcik7XG4gICAgY29uc3QgYm9vdCA9IGF3YWl0IHRoaXMucmVhZHlVc2VyKHVzZXIsIGlkZW50aXR5LCBzaWduYWwpO1xuICAgIGF3YWl0IHRoaXMuY29udHJvbGxlcihib290LCB1c2VyLCBcInB1dFwiLCBbZW5jb2RlKGRlZmluaXRpb24pXSwgc2lnbmFsKTtcbiAgICByZXR1cm4gdGhpcy5ydW5TZXJ2aWNlKGJvb3QsIHVzZXIsIGRlZmluaXRpb24sIHNpZ25hbCk7XG4gIH1cblxuICAvKiogU3RhcnRzIGEgc2F2ZWQgc2VydmljZSBvciBhIGJ1aWx0LWluIGFuZCB3YWl0cyB1bnRpbCBpdCBpcyByZWFkeSBvciBmYWlsZWQuICovXG4gIGFzeW5jIHN0YXJ0U2VydmljZShcbiAgICBpZGVudGl0eTogc3RyaW5nLFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbCxcbiAgKTogUHJvbWlzZTxMYWtlYm94U2VydmljZT4ge1xuICAgIGNvbnN0IHVzZXIgPSB0aGlzLnVzZXIoaWRlbnRpdHkpO1xuICAgIGNvbnN0IGJvb3QgPSBhd2FpdCB0aGlzLnJlYWR5VXNlcih1c2VyLCBpZGVudGl0eSwgc2lnbmFsKTtcbiAgICBjb25zdCBidWlsdEluID0gbGFrZWJveEJ1aWx0SW5TZXJ2aWNlTmFtZVNjaGVtYS5zYWZlUGFyc2UobmFtZSk7XG4gICAgaWYgKGJ1aWx0SW4uc3VjY2Vzcykge1xuICAgICAgY29uc3QgZGVmaW5pdGlvbiA9IGJ1aWx0SW5EZWZpbml0aW9uKGJ1aWx0SW4uZGF0YSwgdXNlcik7XG4gICAgICBhd2FpdCB0aGlzLmNvbnRyb2xsZXIoYm9vdCwgdXNlciwgXCJwdXRcIiwgW2VuY29kZShkZWZpbml0aW9uKV0sIHNpZ25hbCk7XG4gICAgICByZXR1cm4gdGhpcy5ydW5TZXJ2aWNlKGJvb3QsIHVzZXIsIGRlZmluaXRpb24sIHNpZ25hbCk7XG4gICAgfVxuICAgIGNvbnN0IHNhdmVkID0gKGF3YWl0IHRoaXMucmVmcmVzaFNlcnZpY2VzKGJvb3QsIHVzZXIsIGlkZW50aXR5LCBzaWduYWwpKS5nZXQobmFtZSk7XG4gICAgaWYgKCFzYXZlZCkgdGhyb3cgbmV3IEVycm9yKGBMYWtlYm94IHNlcnZpY2UgJHtuYW1lfSBkb2VzIG5vdCBleGlzdGApO1xuICAgIHJldHVybiB0aGlzLnJ1blNlcnZpY2UoYm9vdCwgdXNlciwgc2F2ZWQuZGVmaW5pdGlvbiwgc2lnbmFsKTtcbiAgfVxuXG4gIC8qKiBTdG9wcyBvbmUgcnVubmluZyBzZXJ2aWNlIHdpdGhvdXQgcmVtb3ZpbmcgaXRzIGRlZmluaXRpb24uICovXG4gIGFzeW5jIHN0b3BTZXJ2aWNlKGlkZW50aXR5OiBzdHJpbmcsIG5hbWU6IHN0cmluZywgc2lnbmFsPzogQWJvcnRTaWduYWwpOiBQcm9taXNlPExha2Vib3hTZXJ2aWNlPiB7XG4gICAgY29uc3QgdXNlciA9IHRoaXMudXNlcihpZGVudGl0eSk7XG4gICAgY29uc3QgYm9vdCA9IGF3YWl0IHRoaXMucmVhZHlVc2VyKHVzZXIsIGlkZW50aXR5LCBzaWduYWwpO1xuICAgIGNvbnN0IHN0b3BwZWQgPSBMYWtlYm94Q29udHJvbGxlclNlcnZpY2VTY2hlbWEucGFyc2UoXG4gICAgICBhd2FpdCB0aGlzLmNvbnRyb2xsZXIoYm9vdCwgdXNlciwgXCJzdG9wXCIsIFtuYW1lXSwgc2lnbmFsKSxcbiAgICApO1xuICAgIHRoaXMuY2FjaGVTZXJ2aWNlKGJvb3QsIHVzZXIsIHN0b3BwZWQpO1xuICAgIHJldHVybiB0b0xha2Vib3hTZXJ2aWNlKHN0b3BwZWQsIHVzZXIsIHRoaXMuY29uZmlnLnJvdXRlUHJlZml4KTtcbiAgfVxuXG4gIC8qKiBTdG9wcyBhbmQgZGVsZXRlcyBvbmUgc2F2ZWQgc2VydmljZS4gTW91bnRlZCBob21lIGRpcmVjdG9yaWVzIGFyZSBwcmVzZXJ2ZWQuICovXG4gIGFzeW5jIHJlbW92ZVNlcnZpY2UoaWRlbnRpdHk6IHN0cmluZywgbmFtZTogc3RyaW5nLCBzaWduYWw/OiBBYm9ydFNpZ25hbCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IHVzZXIgPSB0aGlzLnVzZXIoaWRlbnRpdHkpO1xuICAgIGNvbnN0IGJvb3QgPSBhd2FpdCB0aGlzLnJlYWR5VXNlcih1c2VyLCBpZGVudGl0eSwgc2lnbmFsKTtcbiAgICBjb25zdCByZXN1bHQgPSAoYXdhaXQgdGhpcy5jb250cm9sbGVyKGJvb3QsIHVzZXIsIFwicmVtb3ZlXCIsIFtuYW1lXSwgc2lnbmFsKSkgYXMge1xuICAgICAgcmVtb3ZlZD86IGJvb2xlYW47XG4gICAgfTtcbiAgICBpZiAocmVzdWx0LnJlbW92ZWQgPT09IHRydWUpIGF3YWl0IHRoaXMucmVmcmVzaFNlcnZpY2VzKGJvb3QsIHVzZXIsIGlkZW50aXR5LCBzaWduYWwpO1xuICAgIHJldHVybiByZXN1bHQucmVtb3ZlZCA9PT0gdHJ1ZTtcbiAgfVxuXG4gIC8qKiBSZWFkcyBhIGJvdW5kZWQgdGFpbCBvZiBvbmUgc2VydmljZSBsb2cuICovXG4gIGFzeW5jIHNlcnZpY2VMb2dzKFxuICAgIGlkZW50aXR5OiBzdHJpbmcsXG4gICAgaW5wdXQ6IExha2Vib3hTZXJ2aWNlTG9nc1JlcXVlc3QsXG4gICAgc2lnbmFsPzogQWJvcnRTaWduYWwsXG4gICk6IFByb21pc2U8eyBsb2c6IHN0cmluZyB9PiB7XG4gICAgY29uc3QgcmVxdWVzdCA9IGxha2Vib3hTZXJ2aWNlTG9nc1JlcXVlc3RTY2hlbWEucGFyc2UoaW5wdXQpO1xuICAgIGNvbnN0IHVzZXIgPSB0aGlzLnVzZXIoaWRlbnRpdHkpO1xuICAgIGNvbnN0IGVudHJ5ID0gYXdhaXQgdGhpcy5lbnRyeShzaWduYWwpO1xuICAgIGlmICghZW50cnkgfHwgbm9ybWFsaXplTGFrZWJveFN0YXR1cyhlbnRyeS5zdGF0dXMpICE9PSBcInJ1bm5pbmdcIikgcmV0dXJuIHsgbG9nOiBcIlwiIH07XG4gICAgY29uc3QgYm9vdCA9IGF3YWl0IHRoaXMucmVhZHlVc2VyKHVzZXIsIGlkZW50aXR5LCBzaWduYWwpO1xuICAgIGNvbnN0IHJlc3VsdCA9IChhd2FpdCB0aGlzLmNvbnRyb2xsZXIoXG4gICAgICBib290LFxuICAgICAgdXNlcixcbiAgICAgIFwibG9nc1wiLFxuICAgICAgW3JlcXVlc3QubmFtZSwgU3RyaW5nKHJlcXVlc3QubWF4TGluZXMpLCBTdHJpbmcocmVxdWVzdC5tYXhDaGFycyldLFxuICAgICAgc2lnbmFsLFxuICAgICkpIGFzIHsgbG9nPzogc3RyaW5nIH07XG4gICAgcmV0dXJuIHsgbG9nOiByZXN1bHQubG9nID8/IFwiXCIgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHJlY2VudCBtZXRyaWNzIGFuZCBrZWVwcyBzYW1wbGluZyBmb3Igb25lIGxlYXNlIGludGVydmFsLiBTYW1wbGluZ1xuICAgKiBydW5zIG9ubHkgd2hpbGUgdGhlIExha2Vib3ggcnVucyBhbmQgYSBjYWxsZXIgaXMgd2F0Y2hpbmcsIHNvIG1ldHJpY3MgbmV2ZXJcbiAgICoga2VlcCBhbiBvdGhlcndpc2UgaWRsZSBMYWtlYm94IGF3YWtlLlxuICAgKi9cbiAgYXN5bmMgbWV0cmljc1Jlc3BvbnNlKHNpZ25hbD86IEFib3J0U2lnbmFsKTogUHJvbWlzZTxMYWtlYm94TWV0cmljc1Jlc3BvbnNlPiB7XG4gICAgY29uc3QgZW50cnkgPSBhd2FpdCB0aGlzLmVudHJ5KHNpZ25hbCk7XG4gICAgY29uc3QgcGxhdGZvcm1TdGF0dXM6IExha2Vib3hTdGF0dXMgPSBlbnRyeSA/IG5vcm1hbGl6ZUxha2Vib3hTdGF0dXMoZW50cnkuc3RhdHVzKSA6IFwibWlzc2luZ1wiO1xuICAgIGlmIChwbGF0Zm9ybVN0YXR1cyAhPT0gXCJydW5uaW5nXCIpIHtcbiAgICAgIHRoaXMubWV0cmljcy5zdG9wKCk7XG4gICAgICByZXR1cm4geyBzdGF0dXM6IHBsYXRmb3JtU3RhdHVzLCBzZXJpZXM6IFtdIH07XG4gICAgfVxuICAgIGlmICghZW50cnkgfHwgIXRoaXMuYm9vdCB8fCB0aGlzLmJvb3Qua2V5ICE9PSB0aGlzLmJvb3RLZXkoZW50cnkpKSB7XG4gICAgICB0aGlzLm1ldHJpY3Muc3RvcCgpO1xuICAgICAgdGhpcy53YWtlKCgpID0+IHRoaXMucmVhZHkoKSk7XG4gICAgICByZXR1cm4geyBzdGF0dXM6IFwic3RhcnRpbmdcIiwgc2VyaWVzOiBbXSB9O1xuICAgIH1cbiAgICB0aGlzLmxlYXNlTWV0cmljcygpO1xuICAgIHJldHVybiB7XG4gICAgICBzdGF0dXM6IHRoaXMucHJvZHVjdFN0YXR1cyhlbnRyeSwgcGxhdGZvcm1TdGF0dXMpLFxuICAgICAgc2VyaWVzOiBbLi4udGhpcy5tZXRyaWNzLnNlcmllcygpXSxcbiAgICB9O1xuICB9XG5cbiAgLyoqIFN1YnNjcmliZXMgdG8gbWV0cmljcyBzbmFwc2hvdHMgd2hpbGUgdGhlIExha2Vib3ggcnVucy4gKi9cbiAgc3Vic2NyaWJlTWV0cmljcyhsaXN0ZW5lcjogKHNuYXBzaG90OiBMYWtlYm94TWV0cmljc1NuYXBzaG90KSA9PiB2b2lkKTogKCkgPT4gdm9pZCB7XG4gICAgdGhpcy5tZXRyaWNzLm9uKFwic25hcHNob3RcIiwgbGlzdGVuZXIpO1xuICAgIGlmICh0aGlzLmJvb3Q/LmtleSA9PT0gdGhpcy5yZWFkeUJvb3RLZXkpIHRoaXMubWV0cmljcy5zdGFydCgpO1xuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICB0aGlzLm1ldHJpY3Mub2ZmKFwic25hcHNob3RcIiwgbGlzdGVuZXIpO1xuICAgICAgdGhpcy5sZWFzZU1ldHJpY3MoKTtcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZXMgbGVnYWN5IHBlci11c2VyIExha2Vib3hlcyBhbmQgZHJvcHMgbGVnYWN5IG93bmVyc2hpcCBzY2hlbWFzLlxuICAgKlxuICAgKiBUaGVyZSBpcyBubyBtaWdyYXRpb246IHRoZSBlYXJsaWVyIG9uZS1tYWNoaW5lLXBlci11c2VyIG1vZGVsIGlzIHJlbW92ZWQuXG4gICAqIFRoZSBtYW5hZ2VkIGFwcCBMYWtlYm94IGFuZCBMYWtlYm94ZXMgd2l0aCBvdGhlciBuYW1lcyBhcmUgbmV2ZXIgdG91Y2hlZC5cbiAgICovXG4gIGFzeW5jIGNsZWFudXBMZWdhY3kocG9vbD86IExha2Vib3hMZWdhY3lQb29sLCBzaWduYWw/OiBBYm9ydFNpZ25hbCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBlbnRyaWVzID0gYXdhaXQgdGhpcy5jbGllbnQoKS5saXN0KHNpZ25hbCk7XG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgZW50cmllc1xuICAgICAgICAgIC5maWx0ZXIoKGVudHJ5KSA9PiBlbnRyeS5uYW1lICYmIExFR0FDWV9OQU1FLnRlc3QoZW50cnkubmFtZSkpXG4gICAgICAgICAgLm1hcChhc3luYyAoZW50cnkpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY2xpZW50KCkuZGVsZXRlKGVudHJ5LnNhbmRib3hJZCwgc2lnbmFsKTtcbiAgICAgICAgICAgIGxvZ2dlci5pbmZvKFwiZGVsZXRlZCBsZWdhY3kgcGVyLXVzZXIgTGFrZWJveFwiLCB7XG4gICAgICAgICAgICAgIGlkOiBlbnRyeS5zYW5kYm94SWQsXG4gICAgICAgICAgICAgIG5hbWU6IGVudHJ5Lm5hbWUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmICghaXNMYWtlYm94VW5hdmFpbGFibGUoZXJyb3IpKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKFwibGVnYWN5IExha2Vib3ggY2xlYW51cCBmYWlsZWRcIiwgeyBlcnJvcjogZXJyb3JVdGlscy50b0Vycm9yKGVycm9yKSB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFwb29sKSByZXR1cm47XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHNjaGVtYXMgPSBhd2FpdCBwb29sLnF1ZXJ5KFxuICAgICAgICBcIlNFTEVDVCBuc3BuYW1lIEZST00gcGdfbmFtZXNwYWNlIFdIRVJFIG5zcG5hbWUgPSAkMSBPUiBzdGFydHNfd2l0aChuc3BuYW1lLCAkMilcIixcbiAgICAgICAgW0xFR0FDWV9TQ0hFTUFfUFJFRklYLCBgJHtMRUdBQ1lfU0NIRU1BX1BSRUZJWH1fYF0sXG4gICAgICApO1xuICAgICAgZm9yIChjb25zdCByb3cgb2Ygc2NoZW1hcy5yb3dzKSB7XG4gICAgICAgIGNvbnN0IHNjaGVtYSA9IFN0cmluZyhyb3cubnNwbmFtZSk7XG4gICAgICAgIGF3YWl0IHBvb2wucXVlcnkoYERST1AgU0NIRU1BIElGIEVYSVNUUyBcIiR7c2NoZW1hLnJlcGxhY2VBbGwoJ1wiJywgJ1wiXCInKX1cIiBDQVNDQURFYCk7XG4gICAgICAgIGxvZ2dlci5pbmZvKFwiZHJvcHBlZCBsZWdhY3kgTGFrZWJveCBvd25lcnNoaXAgc2NoZW1hXCIsIHsgc2NoZW1hIH0pO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIud2FybihcImxlZ2FjeSBvd25lcnNoaXAgc2NoZW1hIGNsZWFudXAgZmFpbGVkXCIsIHsgZXJyb3I6IGVycm9yVXRpbHMudG9FcnJvcihlcnJvcikgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqIENhbmNlbHMgaW4tZmxpZ2h0IHdvcmsgYmVmb3JlIHRlYXJkb3duLiAqL1xuICBhYm9ydEFjdGl2ZU9wZXJhdGlvbnMoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnNodXRkb3duQ29udHJvbGxlci5zaWduYWwuYWJvcnRlZCkgdGhpcy5zaHV0ZG93bkNvbnRyb2xsZXIuYWJvcnQoKTtcbiAgfVxuXG4gIC8qKiBDbG9zZXMgcm91dGVzLCBtZXRyaWNzLCBhbmQgdGhlIFNTSCBzZXNzaW9uIHdpdGhvdXQgY2hhbmdpbmcgdGhlIExha2Vib3guICovXG4gIGNsb3NlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuYWJvcnRBY3RpdmVPcGVyYXRpb25zKCk7XG4gICAgdGhpcy5yb3V0ZXMuYmVnaW5TaHV0ZG93bigpO1xuICAgIHRoaXMuY2xvc2luZyA/Pz0gKGFzeW5jICgpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGlmICh0aGlzLm1ldHJpY3NMZWFzZSkgY2xlYXJUaW1lb3V0KHRoaXMubWV0cmljc0xlYXNlKTtcbiAgICAgICAgdGhpcy5tZXRyaWNzLnN0b3AoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5yb3V0ZXMuY2xvc2UoKTtcbiAgICAgICAgYXdhaXQgdGhpcy5ib290Py5zZXNzaW9uLmNsb3NlKCk7XG4gICAgICAgIHRoaXMuYm9vdCA9IHVuZGVmaW5lZDtcbiAgICAgIH0gZmluYWxseSB7XG4gICAgICAgIHRoaXMuc3RvcFBhcmVudFRlcm1pbmF0aW9uU2lnbmFsKCk7XG4gICAgICB9XG4gICAgfSkoKTtcbiAgICByZXR1cm4gdGhpcy5jbG9zaW5nO1xuICB9XG5cbiAgcHJpdmF0ZSBjbGllbnQoKTogTGFrZWJveENsaWVudCB7XG4gICAgaWYgKCF0aGlzLmFwaSkgdGhyb3cgbmV3IEVycm9yKFwiVGhlIExha2Vib3ggcnVudGltZSBoYXMgbm8gYXBwIHNlcnZpY2UtcHJpbmNpcGFsIGNyZWRlbnRpYWxzXCIpO1xuICAgIHJldHVybiB0aGlzLmFwaTtcbiAgfVxuXG4gIHByaXZhdGUgcmVzb3VyY2VzKCk6IExha2Vib3hSZXNvdXJjZVJlZ2lzdHJ5IHtcbiAgICBpZiAoIXRoaXMucmVzb3VyY2VSZWdpc3RyeSkgdGhyb3cgbmV3IEVycm9yKFwiVGhlIExha2Vib3ggcnVudGltZSBoYXMgbm8gcmVzb3VyY2UgcmVnaXN0cnlcIik7XG4gICAgcmV0dXJuIHRoaXMucmVzb3VyY2VSZWdpc3RyeTtcbiAgfVxuXG4gIC8qKiBSZXR1cm5zIHRoZSBtYW5hZ2VkIExha2Vib3ggZW50cnksIGNhY2hlZCBicmllZmx5IHRvIGtlZXAgcm91dGVzIGNoZWFwLiAqL1xuICBwcml2YXRlIGFzeW5jIGVudHJ5KHNpZ25hbD86IEFib3J0U2lnbmFsLCBmcmVzaCA9IGZhbHNlKTogUHJvbWlzZTxMYWtlYm94RW50cnkgfCB1bmRlZmluZWQ+IHtcbiAgICBpZiAoIWZyZXNoICYmIHRoaXMuY2FjaGVkICYmIERhdGUubm93KCkgLSB0aGlzLmNhY2hlZC5hdCA8IEVOVFJZX1RUTF9NUykge1xuICAgICAgcmV0dXJuIHRoaXMuY2FjaGVkLmVudHJ5O1xuICAgIH1cbiAgICBjb25zdCBlbnRyeSA9IGF3YWl0IHRoaXMucmVzb3VyY2VzKCkucmVhZCh0aGlzLmNsaWVudCgpLCBzaWduYWwpO1xuICAgIHRoaXMuY2FjaGVkID0geyAuLi4oZW50cnkgPyB7IGVudHJ5IH0gOiB7fSksIGF0OiBEYXRlLm5vdygpIH07XG4gICAgaWYgKCFlbnRyeSB8fCBub3JtYWxpemVMYWtlYm94U3RhdHVzKGVudHJ5LnN0YXR1cykgIT09IFwicnVubmluZ1wiKSB7XG4gICAgICB0aGlzLnJlYWR5Qm9vdEtleSA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgaWYgKHRoaXMuYm9vdCAmJiAoIWVudHJ5IHx8IHRoaXMuYm9vdEtleShlbnRyeSkgIT09IHRoaXMuYm9vdC5rZXkpKSBhd2FpdCB0aGlzLmRpc2NhcmRCb290KCk7XG4gICAgcmV0dXJuIGVudHJ5O1xuICB9XG5cbiAgcHJpdmF0ZSBib290S2V5KGVudHJ5OiBMYWtlYm94RW50cnkpOiBzdHJpbmcge1xuICAgIHJldHVybiBgJHtlbnRyeS5zYW5kYm94SWR9XFwwJHtlbnRyeS5sYXN0U3RhcnRUaW1lID8/IFwiXCJ9YDtcbiAgfVxuXG4gIHByaXZhdGUgcHJvZHVjdFN0YXR1cyhlbnRyeTogTGFrZWJveEVudHJ5IHwgdW5kZWZpbmVkLCBzdGF0dXM6IExha2Vib3hTdGF0dXMpOiBMYWtlYm94U3RhdHVzIHtcbiAgICByZXR1cm4gZW50cnkgJiYgc3RhdHVzID09PSBcInJ1bm5pbmdcIiAmJiB0aGlzLnJlYWR5Qm9vdEtleSAhPT0gdGhpcy5ib290S2V5KGVudHJ5KVxuICAgICAgPyBcInN0YXJ0aW5nXCJcbiAgICAgIDogc3RhdHVzO1xuICB9XG5cbiAgLyoqIFNlcmlhbGl6ZXMgY3JlYXRlLCBzdGFydCwgY29ubmVjdCwgYW5kIGJvb3RzdHJhcCBmb3IgdGhlIGN1cnJlbnQgYm9vdC4gKi9cbiAgcHJpdmF0ZSByZWFkeShzaWduYWw/OiBBYm9ydFNpZ25hbCwgZXhwbGljaXQgPSBmYWxzZSk6IFByb21pc2U8Qm9vdD4ge1xuICAgIGNvbnN0IGN1cnJlbnQgPSB0aGlzLmJvb3Q7XG4gICAgaWYgKGN1cnJlbnQgJiYgdGhpcy5jYWNoZWQ/LmVudHJ5ICYmIHRoaXMuYm9vdEtleSh0aGlzLmNhY2hlZC5lbnRyeSkgPT09IGN1cnJlbnQua2V5KSB7XG4gICAgICBpZiAoRGF0ZS5ub3coKSAtIHRoaXMuY2FjaGVkLmF0IDwgRU5UUllfVFRMX01TKSByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGN1cnJlbnQpO1xuICAgIH1cbiAgICB0aGlzLmNvbnZlcmdpbmcgPz89IHRoaXMuY29udmVyZ2Uoc2lnbmFsLCBleHBsaWNpdCkuZmluYWxseSgoKSA9PiB7XG4gICAgICB0aGlzLmNvbnZlcmdpbmcgPSB1bmRlZmluZWQ7XG4gICAgfSk7XG4gICAgcmV0dXJuIHRoaXMuY29udmVyZ2luZztcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY29udmVyZ2Uoc2lnbmFsOiBBYm9ydFNpZ25hbCB8IHVuZGVmaW5lZCwgZXhwbGljaXQ6IGJvb2xlYW4pOiBQcm9taXNlPEJvb3Q+IHtcbiAgICBjb25zdCBvcGVyYXRpb25TaWduYWwgPSBzaWduYWxcbiAgICAgID8gQWJvcnRTaWduYWwuYW55KFtzaWduYWwsIHRoaXMuc2h1dGRvd25Db250cm9sbGVyLnNpZ25hbF0pXG4gICAgICA6IHRoaXMuc2h1dGRvd25Db250cm9sbGVyLnNpZ25hbDtcbiAgICBsZXQgZW50cnkgPSBhd2FpdCB0aGlzLmVudHJ5KG9wZXJhdGlvblNpZ25hbCwgdHJ1ZSk7XG4gICAgaWYgKCFlbnRyeSB8fCBub3JtYWxpemVMYWtlYm94U3RhdHVzKGVudHJ5LnN0YXR1cykgIT09IFwicnVubmluZ1wiKSB7XG4gICAgICBpZiAoIXRoaXMuY29uZmlnLmF1dG8gJiYgIWV4cGxpY2l0KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgTGFrZWJveCBpcyAke2VudHJ5ID8gZW50cnkuc3RhdHVzIDogXCJub3QgY3JlYXRlZFwifTsgc3RhcnQgaXQgZXhwbGljaXRseSBiZWNhdXNlIGF1dG8gaXMgZmFsc2VgLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgICBlbnRyeSA/Pz0gYXdhaXQgdGhpcy5yZXNvdXJjZXMoKS5nZXRPckNyZWF0ZSh0aGlzLmNsaWVudCgpLCBvcGVyYXRpb25TaWduYWwpO1xuICAgIGlmIChsYWtlYm94SWRsZVRpbWVvdXRTZWNvbmRzKGVudHJ5LmlkbGVUaW1lb3V0KSAhPT0gdGhpcy5jb25maWcuaWRsZVRpbWVvdXRTZWNvbmRzKSB7XG4gICAgICBlbnRyeSA9IGF3YWl0IHRoaXMuY2xpZW50KCkuc2V0SWRsZVRpbWVvdXQoXG4gICAgICAgIGVudHJ5LnNhbmRib3hJZCxcbiAgICAgICAgdGhpcy5jb25maWcuaWRsZVRpbWVvdXRTZWNvbmRzLFxuICAgICAgICBvcGVyYXRpb25TaWduYWwsXG4gICAgICApO1xuICAgIH1cbiAgICBlbnRyeSA9IGF3YWl0IGVuc3VyZUxha2Vib3hSdW5uaW5nKHRoaXMuY2xpZW50KCksIGVudHJ5LCBvcGVyYXRpb25TaWduYWwpO1xuICAgIHRoaXMuY2FjaGVkID0geyBlbnRyeSwgYXQ6IERhdGUubm93KCkgfTtcbiAgICBjb25zdCBrZXkgPSB0aGlzLmJvb3RLZXkoZW50cnkpO1xuICAgIGlmICh0aGlzLmJvb3Q/LmtleSA9PT0ga2V5KSByZXR1cm4gdGhpcy5ib290O1xuICAgIGF3YWl0IHRoaXMuZGlzY2FyZEJvb3QoKTtcbiAgICBjb25zdCBzZXNzaW9uID0gYXdhaXQgdGhpcy5jb25uZWN0KGVudHJ5LCBvcGVyYXRpb25TaWduYWwpO1xuICAgIGNvbnN0IGJvb3Q6IEJvb3QgPSB7XG4gICAgICBrZXksXG4gICAgICBlbnRyeSxcbiAgICAgIHNlc3Npb24sXG4gICAgICB1c2VyczogbmV3IE1hcCgpLFxuICAgICAgc2VydmljZXM6IG5ldyBNYXAoKSxcbiAgICAgIHN0YXJ0aW5nOiBuZXcgTWFwKCksXG4gICAgfTtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdG9yZWQgPSBhd2FpdCB0aGlzLmJvb3RzdHJhcChzZXNzaW9uLCBvcGVyYXRpb25TaWduYWwpO1xuICAgICAgdGhpcy5tZXRyaWNzLnN0b3AoKTtcbiAgICAgIHRoaXMubWV0cmljcy5zZWVkKChhd2FpdCB0aGlzLmFkbWluKHNlc3Npb24sIFtcIm1ldHJpY3NcIl0sIG9wZXJhdGlvblNpZ25hbCkpLnN0ZG91dCk7XG4gICAgICB0aGlzLmJvb3QgPSBib290O1xuICAgICAgdGhpcy5yZWFkeUJvb3RLZXkgPSBrZXk7XG4gICAgICB0aGlzLndhdGNoSWRsZSgpO1xuICAgICAgaWYgKHRoaXMubWV0cmljcy5saXN0ZW5lckNvdW50KFwic25hcHNob3RcIikgPiAwKSB0aGlzLm1ldHJpY3Muc3RhcnQoKTtcbiAgICAgIGZvciAoY29uc3QgaGFzaCBvZiByZXN0b3JlZCkgdm9pZCB0aGlzLnJlc3RvcmVVc2VyKGJvb3QsIGhhc2gpO1xuICAgICAgcmV0dXJuIGJvb3Q7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGF3YWl0IHNlc3Npb24uY2xvc2UoKTtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY29ubmVjdChlbnRyeTogTGFrZWJveEVudHJ5LCBzaWduYWw6IEFib3J0U2lnbmFsKTogUHJvbWlzZTxTc2hTZXNzaW9uPiB7XG4gICAgY29uc3QgYXBpID0gdGhpcy5jbGllbnQoKTtcbiAgICBjb25zdCBzY29wZSA9IGF3YWl0IGFwaS53b3Jrc3BhY2VTY29wZSgpO1xuICAgIGNvbnN0IGtleSA9IGF3YWl0IHRoaXMua2V5cy5lbnN1cmVSZWdpc3RlcmVkKGFwaSwgU1NIX0tFWV9PV05FUiwgc2lnbmFsKTtcbiAgICBjb25zdCBnYXRld2F5SG9zdCA9IGVudHJ5LmdhdGV3YXlIb3N0ID8/IGtleS5nYXRld2F5SG9zdDtcbiAgICBpZiAoIWdhdGV3YXlIb3N0KSB0aHJvdyBuZXcgRXJyb3IoXCJEYXRhYnJpY2tzIExha2Vib3ggZGlkIG5vdCByZXR1cm4gYW4gU1NIIGdhdGV3YXkgaG9zdFwiKTtcbiAgICBjb25zdCBwb3J0ID0gdGhpcy5jb25maWcuZ2F0ZXdheVBvcnQ7XG4gICAgY29uc3Qga25vd25Ib3N0ID0gYXdhaXQgdGhpcy5rZXlzLmtub3duSG9zdChzY29wZSwgU1NIX0tFWV9PV05FUiwgZ2F0ZXdheUhvc3QsIHBvcnQpO1xuICAgIGNvbnN0IHNlc3Npb24gPSBuZXcgU3NoU2Vzc2lvbih7XG4gICAgICBob3N0OiBnYXRld2F5SG9zdCxcbiAgICAgIHBvcnQsXG4gICAgICB1c2VybmFtZTogZW50cnkuc2FuZGJveElkLFxuICAgICAgcHJpdmF0ZUtleToga2V5LnByaXZhdGVLZXksXG4gICAgICBwcml2YXRlS2V5UGF0aDoga2V5LnByaXZhdGVLZXlQYXRoLFxuICAgICAga25vd25Ib3N0c1BhdGg6IHRoaXMua2V5cy5rbm93bkhvc3RzUGF0aChzY29wZSwgU1NIX0tFWV9PV05FUiwgZ2F0ZXdheUhvc3QsIHBvcnQpLFxuICAgICAgY29ubmVjdFRpbWVvdXRNczogdGhpcy5jb25maWcuY29ubmVjdFRpbWVvdXRNcyxcbiAgICAgIHNzaFRyYW5zcG9ydDogdGhpcy5jb25maWcuc3NoVHJhbnNwb3J0LFxuICAgICAgc3NoMlBhdGNoOiB0aGlzLmNvbmZpZy5zc2gyUGF0Y2gsXG4gICAgICAuLi4oa25vd25Ib3N0ID8geyBrbm93bkhvc3QgfSA6IHt9KSxcbiAgICAgIHJlbWVtYmVySG9zdDogKGZpbmdlcnByaW50LCBob3N0S2V5KSA9PlxuICAgICAgICB0aGlzLmtleXMucmVtZW1iZXJIb3N0KHNjb3BlLCBTU0hfS0VZX09XTkVSLCBnYXRld2F5SG9zdCwgcG9ydCwgZmluZ2VycHJpbnQsIGhvc3RLZXkpLFxuICAgIH0pO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBzZXNzaW9uLmNvbm5lY3QoKTtcbiAgICAgIHJldHVybiBzZXNzaW9uO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBhd2FpdCBzZXNzaW9uLmNsb3NlKCk7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH1cblxuICAvKiogUnVucyB0aGUgZml4ZWQgcHJpdmlsZWdlZCBib290c3RyYXAgYW5kIHJldHVybnMgdGhlIHJlc3RvcmVkIHVzZXIgaGFzaGVzLiAqL1xuICBwcml2YXRlIGFzeW5jIGJvb3RzdHJhcChzZXNzaW9uOiBTc2hTZXNzaW9uLCBzaWduYWw6IEFib3J0U2lnbmFsKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIGNvbnN0IGhlbHBlcnMgPSBPYmplY3QuZW50cmllcyhIRUxQRVJTKS5tYXAoXG4gICAgICAoW25hbWUsIGNvbnRlbnRdKSA9PiBgJHtuYW1lfT0ke0J1ZmZlci5mcm9tKGNvbnRlbnQpLnRvU3RyaW5nKFwiYmFzZTY0XCIpfWAsXG4gICAgKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmFkbWluKHNlc3Npb24sIFtcImJvb3RzdHJhcFwiLCAuLi5oZWxwZXJzXSwgc2lnbmFsKTtcbiAgICByZXR1cm4gcmVzdWx0LnN0ZG91dFxuICAgICAgLnNwbGl0KFwiXFxuXCIpXG4gICAgICAuZmlsdGVyKChsaW5lKSA9PiBsaW5lLnN0YXJ0c1dpdGgoXCJfX0xBS0VCT1hfVVNFUl9fPVwiKSlcbiAgICAgIC5tYXAoKGxpbmUpID0+IGxpbmUuc2xpY2UoXCJfX0xBS0VCT1hfVVNFUl9fPVwiLmxlbmd0aCkudHJpbSgpKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYWRtaW4oXG4gICAgc2Vzc2lvbjogU3NoU2Vzc2lvbixcbiAgICBhcmdzOiByZWFkb25seSBzdHJpbmdbXSxcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbCxcbiAgKTogUHJvbWlzZTx7IHN0ZG91dDogc3RyaW5nIH0+IHtcbiAgICBjb25zdCBlbmNvZGVkID0gQnVmZmVyLmZyb20oQURNSU5fU0NSSVBUKS50b1N0cmluZyhcImJhc2U2NFwiKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzZXNzaW9uLmV4ZWN1dGVQcml2aWxlZ2VkKFxuICAgICAgXCJzaFwiLFxuICAgICAgW1wiLWNcIiwgYHByaW50ZiAlcyAnJHtlbmNvZGVkfScgfCBiYXNlNjQgLWQgfCBzaCAtcyAtLSAke2FyZ3MubWFwKHNoZWxsUXVvdGUpLmpvaW4oXCIgXCIpfWBdLFxuICAgICAgeyB0aW1lb3V0TXM6IFNFVFVQX1RJTUVPVVRfTVMsIC4uLihzaWduYWwgPyB7IHNpZ25hbCB9IDoge30pIH0sXG4gICAgKS5yZXN1bHQ7XG4gICAgaWYgKCFyZXN1bHQuc3VjY2Vzcykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgTGFrZWJveCAke2FyZ3NbMF19IGZhaWxlZDogJHtyZXN1bHQuc3RkZXJyLnRyaW0oKSB8fCByZXN1bHQuc3Rkb3V0LnRyaW0oKSB8fCBgZXhpdCAke3Jlc3VsdC5leGl0Q29kZX1gfWAsXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqIE1hcmtzIGFjdGl2aXR5LCByZWFkaWVzIHRoZSBjdXJyZW50IGJvb3QsIGFuZCBjb252ZXJnZXMgdGhlIHVzZXIncyBhY2NvdW50LiAqL1xuICBwcml2YXRlIGFzeW5jIHJlYWR5VXNlcihcbiAgICB1c2VyOiBMYWtlYm94VXNlcixcbiAgICBpZGVudGl0eTogc3RyaW5nLFxuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsLFxuICApOiBQcm9taXNlPEJvb3Q+IHtcbiAgICB0aGlzLnRvdWNoKCk7XG4gICAgY29uc3QgYm9vdCA9IGF3YWl0IHRoaXMucmVhZHkoc2lnbmFsKTtcbiAgICBhd2FpdCB0aGlzLmNvbnZlcmdlVXNlcihib290LCB1c2VyLCBpZGVudGl0eSwgc2lnbmFsKTtcbiAgICByZXR1cm4gYm9vdDtcbiAgfVxuXG4gIC8qKiBDcmVhdGVzIG9yIHZlcmlmaWVzIHRoZSB1c2VyJ3MgYWNjb3VudCBvbmNlIHBlciBib290LiAqL1xuICBwcml2YXRlIGNvbnZlcmdlVXNlcihcbiAgICBib290OiBCb290LFxuICAgIHVzZXI6IExha2Vib3hVc2VyLFxuICAgIGlkZW50aXR5OiBzdHJpbmcsXG4gICAgc2lnbmFsPzogQWJvcnRTaWduYWwsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxldCBjb252ZXJnZWQgPSBib290LnVzZXJzLmdldCh1c2VyLmhhc2gpO1xuICAgIGlmICghY29udmVyZ2VkKSB7XG4gICAgICBjb25zdCBkaWdlc3QgPSBjcmVhdGVIYXNoKFwic2hhMjU2XCIpLnVwZGF0ZShpZGVudGl0eS50cmltKCkudG9Mb3dlckNhc2UoKSkuZGlnZXN0KFwiaGV4XCIpO1xuICAgICAgY29udmVyZ2VkID0gdGhpcy5hZG1pbihcbiAgICAgICAgYm9vdC5zZXNzaW9uLFxuICAgICAgICBbXCJlbnN1cmUtdXNlclwiLCB1c2VyLmhhc2gsIFN0cmluZyh1c2VyLnVpZCksIGRpZ2VzdF0sXG4gICAgICAgIHNpZ25hbCxcbiAgICAgICkudGhlbigoKSA9PiB1bmRlZmluZWQpO1xuICAgICAgYm9vdC51c2Vycy5zZXQodXNlci5oYXNoLCBjb252ZXJnZWQpO1xuICAgICAgY29udmVyZ2VkLmNhdGNoKCgpID0+IGJvb3QudXNlcnMuZGVsZXRlKHVzZXIuaGFzaCkpO1xuICAgIH1cbiAgICByZXR1cm4gY29udmVyZ2VkO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZXN0b3JlVXNlcihib290OiBCb290LCBoYXNoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB1c2VyID0geyBuYW1lOiBgbGFrZWJveC0ke2hhc2h9YCwgaG9tZTogYC9ob21lL2xha2Vib3gtJHtoYXNofWAgfTtcbiAgICBib290LnVzZXJzLnNldChoYXNoLCBQcm9taXNlLnJlc29sdmUoKSk7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGJvb3Quc2Vzc2lvbi5leGVjdXRlKFwicHl0aG9uM1wiLCBbQ09OVFJPTExFUiwgXCJzdGFydC1hbGxcIl0sIHtcbiAgICAgICAgdXNlcixcbiAgICAgICAgdGltZW91dE1zOiBTRVRVUF9USU1FT1VUX01TLFxuICAgICAgICBzaWduYWw6IHRoaXMuc2h1dGRvd25Db250cm9sbGVyLnNpZ25hbCxcbiAgICAgIH0pLnJlc3VsdDtcbiAgICAgIGlmICghcmVzdWx0LnN1Y2Nlc3MpIHRocm93IG5ldyBFcnJvcihyZXN1bHQuc3RkZXJyLnRyaW0oKSB8fCBgZXhpdCAke3Jlc3VsdC5leGl0Q29kZX1gKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKHRoaXMuc2h1dGRvd25Db250cm9sbGVyLnNpZ25hbC5hYm9ydGVkKSByZXR1cm47XG4gICAgICBsb2dnZXIud2FybihcIkxha2Vib3ggc2VydmljZSByZXN0b3JlIGZhaWxlZFwiLCB7XG4gICAgICAgIHVzZXI6IGhhc2gsXG4gICAgICAgIGVycm9yOiBlcnJvclV0aWxzLnRvRXJyb3IoZXJyb3IpLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBjb250cm9sbGVyKFxuICAgIGJvb3Q6IEJvb3QsXG4gICAgdXNlcjogTGFrZWJveFVzZXIsXG4gICAgY29tbWFuZDogc3RyaW5nLFxuICAgIGFyZ3M6IHJlYWRvbmx5IHN0cmluZ1tdLFxuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsLFxuICApOiBQcm9taXNlPHVua25vd24+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBib290LnNlc3Npb24uZXhlY3V0ZShcInB5dGhvbjNcIiwgW0NPTlRST0xMRVIsIGNvbW1hbmQsIC4uLmFyZ3NdLCB7XG4gICAgICB1c2VyLFxuICAgICAgdGltZW91dE1zOiBTRVRVUF9USU1FT1VUX01TLFxuICAgICAgLi4uKHNpZ25hbCA/IHsgc2lnbmFsIH0gOiB7fSksXG4gICAgfSkucmVzdWx0O1xuICAgIGlmICghcmVzdWx0LnN1Y2Nlc3MpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYExha2Vib3ggc2VydmljZSAke2NvbW1hbmR9IGZhaWxlZDogJHtyZXN1bHQuc3RkZXJyLnRyaW0oKSB8fCBgZXhpdCAke3Jlc3VsdC5leGl0Q29kZX1gfWAsXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gSlNPTi5wYXJzZShyZXN1bHQuc3Rkb3V0KSBhcyB1bmtub3duO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBydW5TZXJ2aWNlKFxuICAgIGJvb3Q6IEJvb3QsXG4gICAgdXNlcjogTGFrZWJveFVzZXIsXG4gICAgZGVmaW5pdGlvbjogTGFrZWJveENvbnRyb2xsZXJEZWZpbml0aW9uLFxuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsLFxuICApOiBQcm9taXNlPExha2Vib3hTZXJ2aWNlPiB7XG4gICAgY29uc3Qga2V5ID0gYCR7dXNlci5oYXNofVxcMCR7ZGVmaW5pdGlvbi5uYW1lfWA7XG4gICAgY29uc3QgcGVuZGluZyA9IGJvb3Quc3RhcnRpbmcuZ2V0KGtleSk7XG4gICAgaWYgKHBlbmRpbmcpIHJldHVybiBwZW5kaW5nO1xuICAgIGNvbnN0IG9wZXJhdGlvbiA9IChhc3luYyAoKSA9PiB7XG4gICAgICBpZiAoZGVmaW5pdGlvbi5raW5kID09PSBcImRlc2t0b3BcIikge1xuICAgICAgICBib290LmRlc2t0b3AgPz89IHRoaXMuYWRtaW4oYm9vdC5zZXNzaW9uLCBbXCJkZXNrdG9wLXByZXJlcXVpc2l0ZXNcIl0sIHNpZ25hbCkudGhlbihcbiAgICAgICAgICAoKSA9PiB1bmRlZmluZWQsXG4gICAgICAgICk7XG4gICAgICAgIGJvb3QuZGVza3RvcC5jYXRjaCgoKSA9PiB7XG4gICAgICAgICAgYm9vdC5kZXNrdG9wID0gdW5kZWZpbmVkO1xuICAgICAgICB9KTtcbiAgICAgICAgYXdhaXQgYm9vdC5kZXNrdG9wO1xuICAgICAgfVxuICAgICAgYXdhaXQgdGhpcy5hZG1pbihcbiAgICAgICAgYm9vdC5zZXNzaW9uLFxuICAgICAgICBbXCJhbGxvdy1wb3J0XCIsIFN0cmluZyh1c2VyLnVpZCksIFN0cmluZyhkZWZpbml0aW9uLnBvcnQpXSxcbiAgICAgICAgc2lnbmFsLFxuICAgICAgKTtcbiAgICAgIGNvbnN0IHN0YXJ0ZWQgPSBMYWtlYm94Q29udHJvbGxlclNlcnZpY2VTY2hlbWEucGFyc2UoXG4gICAgICAgIGF3YWl0IHRoaXMuY29udHJvbGxlcihib290LCB1c2VyLCBcInN0YXJ0XCIsIFtkZWZpbml0aW9uLm5hbWVdLCBzaWduYWwpLFxuICAgICAgKTtcbiAgICAgIHRoaXMuY2FjaGVTZXJ2aWNlKGJvb3QsIHVzZXIsIHN0YXJ0ZWQpO1xuICAgICAgcmV0dXJuIHRvTGFrZWJveFNlcnZpY2Uoc3RhcnRlZCwgdXNlciwgdGhpcy5jb25maWcucm91dGVQcmVmaXgpO1xuICAgIH0pKCkuZmluYWxseSgoKSA9PiBib290LnN0YXJ0aW5nLmRlbGV0ZShrZXkpKTtcbiAgICBib290LnN0YXJ0aW5nLnNldChrZXksIG9wZXJhdGlvbik7XG4gICAgcmV0dXJuIG9wZXJhdGlvbjtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcmVmcmVzaFNlcnZpY2VzKFxuICAgIGJvb3Q6IEJvb3QsXG4gICAgdXNlcjogTGFrZWJveFVzZXIsXG4gICAgaWRlbnRpdHk6IHN0cmluZyxcbiAgICBzaWduYWw/OiBBYm9ydFNpZ25hbCxcbiAgKTogUHJvbWlzZTxNYXA8c3RyaW5nLCBMYWtlYm94Q29udHJvbGxlclNlcnZpY2U+PiB7XG4gICAgYXdhaXQgdGhpcy5jb252ZXJnZVVzZXIoYm9vdCwgdXNlciwgaWRlbnRpdHksIHNpZ25hbCk7XG4gICAgY29uc3QgcmVzcG9uc2UgPSAoYXdhaXQgdGhpcy5jb250cm9sbGVyKGJvb3QsIHVzZXIsIFwibGlzdFwiLCBbXSwgc2lnbmFsKSkgYXMge1xuICAgICAgc2VydmljZXM/OiB1bmtub3duW107XG4gICAgfTtcbiAgICBjb25zdCBzZXJ2aWNlcyA9IG5ldyBNYXAoXG4gICAgICAocmVzcG9uc2Uuc2VydmljZXMgPz8gW10pLm1hcCgoc2VydmljZSkgPT4ge1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBMYWtlYm94Q29udHJvbGxlclNlcnZpY2VTY2hlbWEucGFyc2Uoc2VydmljZSk7XG4gICAgICAgIHJldHVybiBbcGFyc2VkLm5hbWUsIHBhcnNlZF0gYXMgY29uc3Q7XG4gICAgICB9KSxcbiAgICApO1xuICAgIGJvb3Quc2VydmljZXMuc2V0KHVzZXIuaGFzaCwgc2VydmljZXMpO1xuICAgIHRoaXMubGFzdFNlcnZpY2VzLnNldCh1c2VyLmhhc2gsIHNlcnZpY2VzKTtcbiAgICBjb25zdCBvYnNlcnZlZEF0ID0gbmV3IERhdGUoKS50b0lTT1N0cmluZygpO1xuICAgIHRoaXMubGFzdFNlcnZpY2VzT2JzZXJ2ZWRBdC5zZXQodXNlci5oYXNoLCBvYnNlcnZlZEF0KTtcbiAgICBhd2FpdCB0aGlzLnBlcnNpc3RTZXJ2aWNlU25hcHNob3QoYm9vdC5lbnRyeSwgdXNlciwgc2VydmljZXMsIG9ic2VydmVkQXQpO1xuICAgIHJldHVybiBzZXJ2aWNlcztcbiAgfVxuXG4gIHByaXZhdGUgY2FjaGVTZXJ2aWNlKGJvb3Q6IEJvb3QsIHVzZXI6IExha2Vib3hVc2VyLCBzZXJ2aWNlOiBMYWtlYm94Q29udHJvbGxlclNlcnZpY2UpOiB2b2lkIHtcbiAgICBjb25zdCBzZXJ2aWNlcyA9IGJvb3Quc2VydmljZXMuZ2V0KHVzZXIuaGFzaCkgPz8gbmV3IE1hcDxzdHJpbmcsIExha2Vib3hDb250cm9sbGVyU2VydmljZT4oKTtcbiAgICBzZXJ2aWNlcy5zZXQoc2VydmljZS5uYW1lLCBzZXJ2aWNlKTtcbiAgICBib290LnNlcnZpY2VzLnNldCh1c2VyLmhhc2gsIHNlcnZpY2VzKTtcbiAgICB0aGlzLmxhc3RTZXJ2aWNlcy5zZXQodXNlci5oYXNoLCBzZXJ2aWNlcyk7XG4gICAgY29uc3Qgb2JzZXJ2ZWRBdCA9IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKTtcbiAgICB0aGlzLmxhc3RTZXJ2aWNlc09ic2VydmVkQXQuc2V0KHVzZXIuaGFzaCwgb2JzZXJ2ZWRBdCk7XG4gICAgdm9pZCB0aGlzLnBlcnNpc3RTZXJ2aWNlU25hcHNob3QoYm9vdC5lbnRyeSwgdXNlciwgc2VydmljZXMsIG9ic2VydmVkQXQpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzZXJ2aWNlTGlzdGluZyhcbiAgICBpZGVudGl0eTogc3RyaW5nLFxuICAgIHVzZXI6IExha2Vib3hVc2VyLFxuICAgIGVudHJ5OiBMYWtlYm94RW50cnkgfCB1bmRlZmluZWQsXG4gICAgc3RhdHVzOiBMYWtlYm94U3RhdHVzLFxuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsLFxuICApOiBQcm9taXNlPFNlcnZpY2VMaXN0aW5nPiB7XG4gICAgaWYgKCFlbnRyeSB8fCBzdGF0dXMgPT09IFwibWlzc2luZ1wiKSB7XG4gICAgICByZXR1cm4geyBzZXJ2aWNlczogdGhpcy5pZGxlU2VydmljZXModXNlciksIHN0YWxlOiBmYWxzZSB9O1xuICAgIH1cbiAgICBpZiAoc3RhdHVzID09PSBcInJ1bm5pbmdcIiAmJiB0aGlzLmJvb3Q/LmtleSA9PT0gdGhpcy5ib290S2V5KGVudHJ5KSkge1xuICAgICAgY29uc3Qgc2VydmljZXMgPSBhd2FpdCB0aGlzLnJlZnJlc2hTZXJ2aWNlcyh0aGlzLmJvb3QsIHVzZXIsIGlkZW50aXR5LCBzaWduYWwpO1xuICAgICAgcmV0dXJuIHsgc2VydmljZXM6IHRoaXMud2l0aEJ1aWx0SW5zKHVzZXIsIHNlcnZpY2VzKSwgc3RhbGU6IGZhbHNlIH07XG4gICAgfVxuICAgIGNvbnN0IG1lbW9yeSA9IHRoaXMubGFzdFNlcnZpY2VzLmdldCh1c2VyLmhhc2gpO1xuICAgIGlmIChtZW1vcnkpIHtcbiAgICAgIGNvbnN0IG9ic2VydmVkQXQgPSB0aGlzLmxhc3RTZXJ2aWNlc09ic2VydmVkQXQuZ2V0KHVzZXIuaGFzaCk7XG4gICAgICBjb25zdCBzZXJ2aWNlcyA9XG4gICAgICAgIHN0YXR1cyA9PT0gXCJydW5uaW5nXCJcbiAgICAgICAgICA/IG1lbW9yeVxuICAgICAgICAgIDogc3RvcHBlZFNuYXBzaG90U2VydmljZXMoe1xuICAgICAgICAgICAgICBvYnNlcnZlZEF0OiBvYnNlcnZlZEF0ID8/IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgICAgICAgZGVmaW5pdGlvbnM6IFsuLi5tZW1vcnkudmFsdWVzKCldLm1hcCgoc2VydmljZSkgPT4gc2VydmljZS5kZWZpbml0aW9uKSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc2VydmljZXM6IHRoaXMud2l0aEJ1aWx0SW5zKHVzZXIsIHNlcnZpY2VzKSxcbiAgICAgICAgc3RhbGU6IHRydWUsXG4gICAgICAgIC4uLihvYnNlcnZlZEF0ID8geyBvYnNlcnZlZEF0IH0gOiB7fSksXG4gICAgICB9O1xuICAgIH1cbiAgICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IHRoaXMuc2VydmljZVNuYXBzaG90cz8ucmVhZChlbnRyeS5zYW5kYm94SWQsIHVzZXIuaGFzaCk7XG4gICAgcmV0dXJuIHNuYXBzaG90XG4gICAgICA/IHtcbiAgICAgICAgICBzZXJ2aWNlczogdGhpcy53aXRoQnVpbHRJbnModXNlciwgc3RvcHBlZFNuYXBzaG90U2VydmljZXMoc25hcHNob3QpKSxcbiAgICAgICAgICBzdGFsZTogdHJ1ZSxcbiAgICAgICAgICBvYnNlcnZlZEF0OiBzbmFwc2hvdC5vYnNlcnZlZEF0LFxuICAgICAgICB9XG4gICAgICA6IHsgc2VydmljZXM6IHRoaXMuaWRsZVNlcnZpY2VzKHVzZXIpLCBzdGFsZTogdHJ1ZSB9O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBwZXJzaXN0U2VydmljZVNuYXBzaG90KFxuICAgIGVudHJ5OiBMYWtlYm94RW50cnksXG4gICAgdXNlcjogTGFrZWJveFVzZXIsXG4gICAgc2VydmljZXM6IFJlYWRvbmx5TWFwPHN0cmluZywgTGFrZWJveENvbnRyb2xsZXJTZXJ2aWNlPixcbiAgICBvYnNlcnZlZEF0OiBzdHJpbmcsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuc2VydmljZVNuYXBzaG90cz8ud3JpdGUoZW50cnkuc2FuZGJveElkLCB1c2VyLmhhc2gsIHtcbiAgICAgIG9ic2VydmVkQXQsXG4gICAgICBkZWZpbml0aW9uczogWy4uLnNlcnZpY2VzLnZhbHVlcygpXS5tYXAoKHNlcnZpY2UpID0+IHNlcnZpY2UuZGVmaW5pdGlvbiksXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHdpdGhCdWlsdElucyhcbiAgICB1c2VyOiBMYWtlYm94VXNlcixcbiAgICBzZXJ2aWNlczogUmVhZG9ubHlNYXA8c3RyaW5nLCBMYWtlYm94Q29udHJvbGxlclNlcnZpY2U+LFxuICApOiBMYWtlYm94U2VydmljZVtdIHtcbiAgICBjb25zdCBidWlsdElucyA9IExBS0VCT1hfQlVJTFRfSU5fU0VSVklDRVMubWFwKCh7IG5hbWUgfSkgPT4ge1xuICAgICAgY29uc3Qgc2F2ZWQgPSBzZXJ2aWNlcy5nZXQobmFtZSk7XG4gICAgICByZXR1cm4gc2F2ZWRcbiAgICAgICAgPyB0b0xha2Vib3hTZXJ2aWNlKHNhdmVkLCB1c2VyLCB0aGlzLmNvbmZpZy5yb3V0ZVByZWZpeClcbiAgICAgICAgOiBpZGxlQnVpbHRJblNlcnZpY2UobmFtZSwgdXNlciwgdGhpcy5jb25maWcucm91dGVQcmVmaXgpO1xuICAgIH0pO1xuICAgIGNvbnN0IGN1c3RvbSA9IFsuLi5zZXJ2aWNlcy52YWx1ZXMoKV1cbiAgICAgIC5maWx0ZXIoKHNlcnZpY2UpID0+ICFMQUtFQk9YX0JVSUxUX0lOX1NFUlZJQ0VTLnNvbWUoKHsgbmFtZSB9KSA9PiBuYW1lID09PSBzZXJ2aWNlLm5hbWUpKVxuICAgICAgLm1hcCgoc2VydmljZSkgPT4gdG9MYWtlYm94U2VydmljZShzZXJ2aWNlLCB1c2VyLCB0aGlzLmNvbmZpZy5yb3V0ZVByZWZpeCkpO1xuICAgIHJldHVybiBbLi4uYnVpbHRJbnMsIC4uLmN1c3RvbV07XG4gIH1cblxuICBwcml2YXRlIGlkbGVTZXJ2aWNlcyh1c2VyOiBMYWtlYm94VXNlcik6IExha2Vib3hTZXJ2aWNlW10ge1xuICAgIHJldHVybiBMQUtFQk9YX0JVSUxUX0lOX1NFUlZJQ0VTLm1hcCgoeyBuYW1lIH0pID0+XG4gICAgICBpZGxlQnVpbHRJblNlcnZpY2UobmFtZSBhcyBMYWtlYm94QnVpbHRJblNlcnZpY2VOYW1lLCB1c2VyLCB0aGlzLmNvbmZpZy5yb3V0ZVByZWZpeCksXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBSZXNvbHZlcyBvbmUgcm91dGVkIHJlcXVlc3QsIHdha2luZyB0aGUgTGFrZWJveCBvciBzZXJ2aWNlIGluIHRoZSBiYWNrZ3JvdW5kLiAqL1xuICBwcml2YXRlIGFzeW5jIHJlc29sdmVSb3V0ZSh1c2VyOiBMYWtlYm94VXNlciwgbmFtZTogc3RyaW5nKTogUHJvbWlzZTxMYWtlYm94Um91dGVSZXNvbHV0aW9uPiB7XG4gICAgdGhpcy50b3VjaCgpO1xuICAgIGNvbnN0IGVudHJ5ID0gYXdhaXQgdGhpcy5lbnRyeSgpO1xuICAgIGNvbnN0IHJ1bm5pbmcgPSBlbnRyeSAmJiBub3JtYWxpemVMYWtlYm94U3RhdHVzKGVudHJ5LnN0YXR1cykgPT09IFwicnVubmluZ1wiO1xuICAgIGNvbnN0IGJvb3QgPSB0aGlzLmJvb3Q7XG4gICAgaWYgKCFydW5uaW5nIHx8ICFib290IHx8IGJvb3Qua2V5ICE9PSB0aGlzLmJvb3RLZXkoZW50cnkpKSB7XG4gICAgICBpZiAoIXRoaXMuY29uZmlnLmF1dG8pIHJldHVybiB7IGtpbmQ6IFwibWlzc2luZ1wiIH07XG4gICAgICB0aGlzLndha2UoKCkgPT4gdGhpcy5yZWFkeSgpKTtcbiAgICAgIHJldHVybiB7IGtpbmQ6IFwibG9hZGluZ1wiIH07XG4gICAgfVxuICAgIGNvbnN0IGlkZW50aXR5ID0gdGhpcy5yb3V0ZWRJZGVudGl0aWVzLmdldCh1c2VyLmhhc2gpO1xuICAgIGlmICghaWRlbnRpdHkpIHJldHVybiB7IGtpbmQ6IFwibWlzc2luZ1wiIH07XG4gICAgbGV0IHNlcnZpY2UgPSBib290LnNlcnZpY2VzLmdldCh1c2VyLmhhc2gpPy5nZXQobmFtZSk7XG4gICAgaWYgKCFzZXJ2aWNlKSBzZXJ2aWNlID0gKGF3YWl0IHRoaXMucmVmcmVzaFNlcnZpY2VzKGJvb3QsIHVzZXIsIGlkZW50aXR5KSkuZ2V0KG5hbWUpO1xuICAgIGNvbnN0IGJ1aWx0SW4gPSBsYWtlYm94QnVpbHRJblNlcnZpY2VOYW1lU2NoZW1hLnNhZmVQYXJzZShuYW1lKTtcbiAgICBpZiAoIXNlcnZpY2UgJiYgIWJ1aWx0SW4uc3VjY2VzcykgcmV0dXJuIHsga2luZDogXCJtaXNzaW5nXCIgfTtcbiAgICBpZiAoc2VydmljZT8uc3RhdGUgPT09IFwicmVhZHlcIikge1xuICAgICAgcmV0dXJuIHsga2luZDogXCJyZWFkeVwiLCBzZXNzaW9uOiBib290LnNlc3Npb24sIHJvdXRlOiBzZXJ2aWNlUm91dGUoc2VydmljZS5kZWZpbml0aW9uKSB9O1xuICAgIH1cbiAgICBpZiAoc2VydmljZT8uc3RhdGUgPT09IFwiZXJyb3JcIiAmJiAhYm9vdC5zdGFydGluZy5oYXMoYCR7dXNlci5oYXNofVxcMCR7bmFtZX1gKSkge1xuICAgICAgcmV0dXJuIHsga2luZDogXCJmYWlsZWRcIiwgbWVzc2FnZTogc2VydmljZS5lcnJvciA/PyBcInRoZSBzZXJ2aWNlIGZhaWxlZCB0byBzdGFydFwiIH07XG4gICAgfVxuICAgIGNvbnN0IGRlZmluaXRpb24gPSBzZXJ2aWNlPy5kZWZpbml0aW9uID8/IGJ1aWx0SW5EZWZpbml0aW9uKGJ1aWx0SW4uZGF0YSEsIHVzZXIpO1xuICAgIHRoaXMud2FrZShhc3luYyAoKSA9PiB7XG4gICAgICBpZiAoIXNlcnZpY2UpIGF3YWl0IHRoaXMuY29udHJvbGxlcihib290LCB1c2VyLCBcInB1dFwiLCBbZW5jb2RlKGRlZmluaXRpb24pXSk7XG4gICAgICBhd2FpdCB0aGlzLnJ1blNlcnZpY2UoYm9vdCwgdXNlciwgZGVmaW5pdGlvbik7XG4gICAgfSk7XG4gICAgcmV0dXJuIHsga2luZDogXCJsb2FkaW5nXCIgfTtcbiAgfVxuXG4gIHByaXZhdGUgbWFya1VuYXZhaWxhYmxlKHVzZXI6IExha2Vib3hVc2VyLCBuYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmJvb3Q/LnNlcnZpY2VzLmdldCh1c2VyLmhhc2gpPy5kZWxldGUobmFtZSk7XG4gICAgdGhpcy5jYWNoZWQgPSB1bmRlZmluZWQ7XG4gIH1cblxuICBwcml2YXRlIHdha2UoYWN0aW9uOiAoKSA9PiBQcm9taXNlPHVua25vd24+KTogdm9pZCB7XG4gICAgaWYgKHRoaXMud2FraW5nKSByZXR1cm47XG4gICAgdGhpcy53YWtpbmcgPSBhY3Rpb24oKVxuICAgICAgLmNhdGNoKChlcnJvcikgPT4gbG9nZ2VyLndhcm4oXCJMYWtlYm94IHdha2UgZmFpbGVkXCIsIHsgZXJyb3I6IGVycm9yVXRpbHMudG9FcnJvcihlcnJvcikgfSkpXG4gICAgICAuZmluYWxseSgoKSA9PiB7XG4gICAgICAgIHRoaXMud2FraW5nID0gdW5kZWZpbmVkO1xuICAgICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlYWRNZXRyaWNzKHNpZ25hbDogQWJvcnRTaWduYWwpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IGJvb3QgPSB0aGlzLmJvb3Q7XG4gICAgaWYgKCFib290KSB0aHJvdyBuZXcgRXJyb3IoXCJMYWtlYm94IGlzIG5vdCBydW5uaW5nXCIpO1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gKGF3YWl0IHRoaXMuYWRtaW4oYm9vdC5zZXNzaW9uLCBbXCJtZXRyaWNzXCJdLCBzaWduYWwpKS5zdGRvdXQ7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMuY2FjaGVkID0gdW5kZWZpbmVkO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBsZWFzZU1ldHJpY3MoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmJvb3QpIHJldHVybjtcbiAgICB0aGlzLm1ldHJpY3Muc3RhcnQoKTtcbiAgICBpZiAodGhpcy5tZXRyaWNzTGVhc2UpIGNsZWFyVGltZW91dCh0aGlzLm1ldHJpY3NMZWFzZSk7XG4gICAgdGhpcy5tZXRyaWNzTGVhc2UgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGlmICh0aGlzLm1ldHJpY3MubGlzdGVuZXJDb3VudChcInNuYXBzaG90XCIpID09PSAwKSB0aGlzLm1ldHJpY3Muc3RvcCgpO1xuICAgIH0sIE1FVFJJQ1NfTEVBU0VfTVMpO1xuICAgIHRoaXMubWV0cmljc0xlYXNlLnVucmVmPy4oKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWxlYXNlcyB0aGUgU1NIIHNlc3Npb24gYWZ0ZXIgdGhlIGlkbGUgdGltZW91dCB3aXRob3V0IGNvbW1hbmRzLCBzZXJ2aWNlXG4gICAqIG9wZXJhdGlvbnMsIHJvdXRlZCB0cmFmZmljLCBvcGVuIHN0cmVhbXMsIG9yIG1ldHJpY3Mgd2F0Y2hlcnMuIEFuIG9wZW5cbiAgICogc2Vzc2lvbiBjb3VudHMgYXMgYWN0aXZpdHkgZm9yIHRoZSBwbGF0Zm9ybSB3YXRjaGRvZywgc28gcmVsZWFzaW5nIGl0IGxldHNcbiAgICogdGhlIHBsYXRmb3JtIHN0b3AgdGhlIExha2Vib3ggYWZ0ZXIgaXRzIG93biBpZGxlIHRpbWVvdXQuIFRoZSBuZXh0IHJlcXVlc3RcbiAgICogcmVjb25uZWN0cy5cbiAgICovXG4gIHByaXZhdGUgd2F0Y2hJZGxlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmlkbGVUaW1lcikgY2xlYXJJbnRlcnZhbCh0aGlzLmlkbGVUaW1lcik7XG4gICAgdGhpcy5pZGxlVGltZXIgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICBjb25zdCBpZGxlTXMgPSBEYXRlLm5vdygpIC0gdGhpcy5sYXN0QWN0aXZpdHk7XG4gICAgICBpZiAoXG4gICAgICAgICF0aGlzLmJvb3QgfHxcbiAgICAgICAgdGhpcy5jb252ZXJnaW5nIHx8XG4gICAgICAgIGlkbGVNcyA8IHRoaXMuY29uZmlnLmlkbGVUaW1lb3V0U2Vjb25kcyAqIDFfMDAwIHx8XG4gICAgICAgIHRoaXMuYWN0aXZlQ29tbWFuZHMgPiAwIHx8XG4gICAgICAgIHRoaXMuYm9vdC5zdGFydGluZy5zaXplID4gMCB8fFxuICAgICAgICB0aGlzLnJvdXRlcy5hY3RpdmVDb25uZWN0aW9ucygpID4gMCB8fFxuICAgICAgICB0aGlzLm1ldHJpY3MubGlzdGVuZXJDb3VudChcInNuYXBzaG90XCIpID4gMFxuICAgICAgKSB7XG4gICAgICAgIGlmICh0aGlzLnJvdXRlcy5hY3RpdmVDb25uZWN0aW9ucygpID4gMCB8fCB0aGlzLmFjdGl2ZUNvbW1hbmRzID4gMCkgdGhpcy50b3VjaCgpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBsb2dnZXIuaW5mbyhcInJlbGVhc2luZyBpZGxlIExha2Vib3ggc2Vzc2lvblwiLCB7IGlkbGVTZWNvbmRzOiBNYXRoLnJvdW5kKGlkbGVNcyAvIDFfMDAwKSB9KTtcbiAgICAgIHZvaWQgdGhpcy5kaXNjYXJkQm9vdCgpO1xuICAgIH0sIElETEVfQ0hFQ0tfTVMpO1xuICAgIHRoaXMuaWRsZVRpbWVyLnVucmVmPy4oKTtcbiAgfVxuXG4gIHByaXZhdGUgdG91Y2goKTogdm9pZCB7XG4gICAgdGhpcy5sYXN0QWN0aXZpdHkgPSBEYXRlLm5vdygpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBkaXNjYXJkQm9vdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5pZGxlVGltZXIpIGNsZWFySW50ZXJ2YWwodGhpcy5pZGxlVGltZXIpO1xuICAgIHRoaXMuaWRsZVRpbWVyID0gdW5kZWZpbmVkO1xuICAgIGNvbnN0IGJvb3QgPSB0aGlzLmJvb3Q7XG4gICAgdGhpcy5ib290ID0gdW5kZWZpbmVkO1xuICAgIHRoaXMubWV0cmljcy5zdG9wKCk7XG4gICAgYXdhaXQgdGhpcy5yb3V0ZXMuY2xvc2VCcmlkZ2VzKCk7XG4gICAgYXdhaXQgYm9vdD8uc2Vzc2lvbi5jbG9zZSgpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW5jb2RlKGRlZmluaXRpb246IExha2Vib3hDb250cm9sbGVyRGVmaW5pdGlvbik6IHN0cmluZyB7XG4gIHJldHVybiBCdWZmZXIuZnJvbShKU09OLnN0cmluZ2lmeShkZWZpbml0aW9uKSkudG9TdHJpbmcoXCJiYXNlNjRcIik7XG59XG5cbmZ1bmN0aW9uIHNoZWxsUXVvdGUodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgJyR7dmFsdWUucmVwbGFjZUFsbChcIidcIiwgXCInXFxcXCcnXCIpfSdgO1xufVxuXG4vKiogUmV0dXJucyB3aGV0aGVyIGFuIGVycm9yIG1lYW5zIHRoZSBtYW5hZ2VkIExha2Vib3ggbm8gbG9uZ2VyIGV4aXN0cy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0xha2Vib3hNaXNzaW5nKGVycm9yOiB1bmtub3duKTogYm9vbGVhbiB7XG4gIHJldHVybiBlcnJvciBpbnN0YW5jZW9mIExha2Vib3hBcGlFcnJvciAmJiBlcnJvci5zdGF0dXMgPT09IDQwNDtcbn1cbiJdfQ==